{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Лабораторная работа 3." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Определение бизнес и технических целей\n", "1. Прогнозирование цены автомобиля\n", "Бизнес-цель: Оптимизация ценовой политики.\n", "Техническая цель: Построение модели прогнозирования цены.\n", "\n", "Конструирование признаков:\n", "Объем двигателя:\n", "\n", "Извлечь числовую часть из столбца Engine volume (например, 3.5).\n", "Добавить бинарный признак: наличие турбонаддува (Turbo).\n", "Возраст автомобиля:\n", "\n", "Вычислить возраст автомобиля как разницу между текущим годом и Prod. year.\n", "Привод (Drive wheels):\n", "\n", "Закодировать тип привода (например, 4x4, Front, Rear) с помощью One-Hot Encoding.\n", "Категория автомобиля (Category):\n", "\n", "Преобразовать категорию в числовые признаки с помощью One-Hot Encoding.\n", "Технические характеристики:\n", "\n", "Нормализовать числовые параметры, такие как пробег (Mileage) и количество цилиндров (Cylinders).\n", "Состояние интерьера:\n", "\n", "Закодировать признак наличия кожаного салона (Leather interior) как бинарный.\n", "\n", "2. Классификация популярности автомобиля\n", "Бизнес-цель: Изучение предпочтений клиентов.\n", "Техническая цель: Определение популярности автомобилей.\n", "\n", "Конструирование признаков:\n", "Рейтинг безопасности:\n", "\n", "Использовать количество подушек безопасности (Airbags) для создания индикатора безопасности автомобиля.\n", "Тип топлива:\n", "\n", "Закодировать Fuel type как категориальный признак (например, Petrol, Diesel, Hybrid).\n", "Цвет автомобиля:\n", "\n", "Создать признак редкости цвета на основе частоты его встречаемости в данных.\n", "Стоимость обслуживания:\n", "\n", "Преобразовать Levy в числовой признак и обработать пропущенные значения (например, заменить на среднее/медианное значение).\n", "Сегмент рынка:\n", "\n", "Объединить категории автомобилей (например, Jeep, Hatchback) в несколько сегментов (премиум, эконом, компакт).\n", "Особенности привода:\n", "\n", "Создать бинарные признаки, указывающие на тип управления (Left wheel/Right-hand drive)." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "((11542, 215), (3847, 215), (3848, 215), (11542,), (3847,), (3848,))" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.model_selection import train_test_split\n", "import pandas as pd\n", "\n", "data = pd.read_csv(\"car_price_prediction.csv\")\n", "# Preparing the data by removing unnecessary columns and handling categorical data\n", "data_cleaned = data.copy()\n", "\n", "# Converting \"Levy\" and \"Mileage\" to numeric (handling non-numeric values like '-')\n", "data_cleaned[\"Levy\"] = pd.to_numeric(data_cleaned[\"Levy\"], errors=\"coerce\")\n", "data_cleaned[\"Mileage\"] = (\n", " data_cleaned[\"Mileage\"].str.replace(\" km\", \"\").str.replace(\" \", \"\").astype(float)\n", ")\n", "\n", "# Dropping columns that are identifiers or too detailed for prediction (like ID, Model)\n", "data_cleaned = data_cleaned.drop([\"ID\", \"Model\"], axis=1)\n", "\n", "# Encoding categorical columns\n", "categorical_cols = data_cleaned.select_dtypes(include=\"object\").columns\n", "data_encoded = pd.get_dummies(data_cleaned, columns=categorical_cols, drop_first=True)\n", "\n", "# Splitting the data into features (X) and target (y)\n", "X = data_encoded.drop(\"Price\", axis=1)\n", "y = data_encoded[\"Price\"]\n", "\n", "# Splitting into training, validation, and testing datasets\n", "X_train, X_temp, y_train, y_temp = train_test_split(\n", " X, y, test_size=0.4, random_state=42\n", ") # 60% training data\n", "X_val, X_test, y_val, y_test = train_test_split(\n", " X_temp, y_temp, test_size=0.5, random_state=42\n", ") # 20% validation, 20% testing\n", "\n", "# Displaying the sizes of the datasets\n", "X_train.shape, X_val.shape, X_test.shape, y_train.shape, y_val.shape, y_test.shape" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
PriceLevyManufacturerLeather interiorEngine volumeMileageCylindersGear box typeDoorsAirbags...Fuel type_LPGFuel type_PetrolFuel type_Plug-in HybridWheel_Right-hand driveCar ageCar age binsMileage binsTurboSafety ratingColor rarity
0133281.065632LEXUSYes1.357980-0.0278131.180937Automatic04-May12...FalseFalseFalseFalse1511-20High00.7500.197120
1166210.240688CHEVROLETNo0.788363-0.0276891.180937Tiptronic04-May8...FalseTrueFalseFalse1411-20Very High00.5000.261631
28467NaNHONDANo-1.148338-0.027524-0.485866Variator04-May2...FalseTrueFalseTrue1911-20Very High00.1250.261631
33607-0.097084FORDYes0.218745-0.028165-0.485866Automatic04-May0...FalseFalseFalseFalse1411-20High00.0000.233352
411726-0.997809HONDAYes-1.148338-0.029757-0.485866Automatic04-May4...FalseTrueFalseFalse1111-20Medium00.2500.197120
\n", "

5 rows × 35 columns

\n", "
" ], "text/plain": [ " Price Levy Manufacturer Leather interior Engine volume Mileage \\\n", "0 13328 1.065632 LEXUS Yes 1.357980 -0.027813 \n", "1 16621 0.240688 CHEVROLET No 0.788363 -0.027689 \n", "2 8467 NaN HONDA No -1.148338 -0.027524 \n", "3 3607 -0.097084 FORD Yes 0.218745 -0.028165 \n", "4 11726 -0.997809 HONDA Yes -1.148338 -0.029757 \n", "\n", " Cylinders Gear box type Doors Airbags ... Fuel type_LPG \\\n", "0 1.180937 Automatic 04-May 12 ... False \n", "1 1.180937 Tiptronic 04-May 8 ... False \n", "2 -0.485866 Variator 04-May 2 ... False \n", "3 -0.485866 Automatic 04-May 0 ... False \n", "4 -0.485866 Automatic 04-May 4 ... False \n", "\n", " Fuel type_Petrol Fuel type_Plug-in Hybrid Wheel_Right-hand drive \\\n", "0 False False False \n", "1 True False False \n", "2 True False True \n", "3 False False False \n", "4 True False False \n", "\n", " Car age Car age bins Mileage bins Turbo Safety rating Color rarity \n", "0 15 11-20 High 0 0.750 0.197120 \n", "1 14 11-20 Very High 0 0.500 0.261631 \n", "2 19 11-20 Very High 0 0.125 0.261631 \n", "3 14 11-20 High 0 0.000 0.233352 \n", "4 11 11-20 Medium 0 0.250 0.197120 \n", "\n", "[5 rows x 35 columns]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "import pandas as pd\n", "from sklearn.preprocessing import MinMaxScaler, StandardScaler\n", "\n", "# Копия исходного набора данных\n", "features_data = data_cleaned.copy()\n", "\n", "# --- 1. Унитарное кодирование категориальных признаков ---\n", "# Кодирование категориальных переменных\n", "categorical_columns = [\"Drive wheels\", \"Category\", \"Fuel type\", \"Wheel\"]\n", "features_data = pd.get_dummies(\n", " features_data, columns=categorical_columns, drop_first=True\n", ")\n", "\n", "# --- 2. Дискретизация числовых признаков ---\n", "# Пример: Дискретизация возраста автомобиля\n", "current_year = 2025\n", "features_data[\"Car age\"] = current_year - features_data[\"Prod. year\"]\n", "features_data[\"Car age bins\"] = pd.cut(\n", " features_data[\"Car age\"],\n", " bins=[0, 5, 10, 20, 50],\n", " labels=[\"0-5\", \"6-10\", \"11-20\", \"21+\"],\n", ")\n", "\n", "# Дискретизация пробега\n", "features_data[\"Mileage bins\"] = pd.qcut(\n", " features_data[\"Mileage\"].fillna(0),\n", " q=4,\n", " labels=[\"Low\", \"Medium\", \"High\", \"Very High\"],\n", ")\n", "\n", "# --- 3. «Ручной» синтез признаков ---\n", "# Индикатор турбонаддува\n", "features_data[\"Turbo\"] = (\n", " features_data[\"Engine volume\"].str.contains(\"Turbo\").astype(int)\n", ") # Индикатор турбонаддува\n", "features_data[\"Engine volume\"] = features_data[\"Engine volume\"].str.replace(\n", " \" Turbo\", \"\"\n", ") # Убираем текст 'Turbo'\n", "features_data[\"Engine volume\"] = features_data[\"Engine volume\"].astype(\n", " float\n", ") # Преобразуем в float\n", "# Рейтинг безопасности\n", "features_data[\"Safety rating\"] = (\n", " features_data[\"Airbags\"] / features_data[\"Airbags\"].max()\n", ")\n", "\n", "# Редкость цвета\n", "color_frequency = features_data[\"Color\"].value_counts(normalize=True)\n", "features_data[\"Color rarity\"] = features_data[\"Color\"].map(color_frequency)\n", "\n", "# --- 4. Масштабирование признаков ---\n", "# Масштабирование числовых признаков с использованием нормализации (Min-Max Scaling)\n", "scaler_minmax = MinMaxScaler()\n", "numerical_features = [\"Mileage\", \"Engine volume\", \"Cylinders\", \"Levy\"]\n", "features_data[numerical_features] = scaler_minmax.fit_transform(\n", " features_data[numerical_features]\n", ")\n", "\n", "# Стандартизация (Standard Scaling) для числовых признаков\n", "scaler_standard = StandardScaler()\n", "features_data[numerical_features] = scaler_standard.fit_transform(\n", " features_data[numerical_features]\n", ")\n", "\n", "# --- Удаление ненужных столбцов ---\n", "columns_to_drop = [\"Prod. year\", \"Color\"] # Удаление лишних столбцов\n", "features_data = features_data.drop(columns=columns_to_drop)\n", "\n", "# Просмотр итогового набора данных\n", "features_data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Оценка набора признаков по следующим критериям: предсказательная способность, скорость вычисления, надежность, корреляция и цельность.\n", "\n", " Предсказательная способность:\n", "1. Код приводит к созданию большого числа новых признаков, что может повысить предсказательную способность модели, если эти признаки действительно значимы для задачи.\n", "Например, создание индикатора турбонаддува, рейтинга безопасности и редкости цвета может улучшить способность модели делать точные предсказания.\n", "Однако важно проверить, что эти признаки не приводят к переобучению.\n", "\n", "2. Скорость вычисления:\n", "Операции, такие как кодирование категориальных признаков, дискретизация и масштабирование, могут замедлить процесс при больших наборах данных.\n", "Особое внимание стоит уделить масштабированию, так как оно требует времени на преобразование значений, особенно если количество числовых признаков велико.\n", "Признаки, полученные в результате ручного синтеза, такие как \"Turbo\", могут быть быстрыми для вычислений, но создание новых бинарных признаков увеличивает размер данных, что может замедлить вычисления.\n", "\n", "3. Надежность:\n", "Признаки, созданные вручную, такие как \"Turbo\" и \"Safety rating\", могут быть более устойчивыми, так как они не зависят от структуры данных, а только от специфической логики.\n", "Однако, например, дискретизация и кодирование категориальных переменных могут изменить поведение модели при изменении данных (например, когда в новых данных появляются новые категории).\n", "\n", "4. Корреляция:\n", "Кодирование категориальных признаков создаст новые столбцы, и важно будет проверить корреляцию между этими новыми признаками, чтобы избежать избыточности.\n", "Признаки, такие как возраст автомобиля и пробег, могут быть взаимосвязаны, что может потребовать дополнительных шагов для уменьшения корреляции (например, PCA или исключение одного из признаков).\n", "\n", "5. Целостность:\n", "Код также не учитывает пропуски в данных (например, в столбцах \"Mileage\" или \"Engine volume\"). Эти пропуски могут повлиять на результат и должны быть обработаны до начала других этапов.\n", "Например, при дискретизации пробега (pd.qcut()) используется .fillna(0), что может быть не оптимальным способом заполнения пропусков, так как это может привести к искажению данных." ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.5" } }, "nbformat": 4, "nbformat_minor": 2 }