pred_analytics/Lab3.ipynb
2025-01-13 14:42:39 +04:00

456 lines
21 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Price</th>\n",
" <th>Levy</th>\n",
" <th>Manufacturer</th>\n",
" <th>Leather interior</th>\n",
" <th>Engine volume</th>\n",
" <th>Mileage</th>\n",
" <th>Cylinders</th>\n",
" <th>Gear box type</th>\n",
" <th>Doors</th>\n",
" <th>Airbags</th>\n",
" <th>...</th>\n",
" <th>Fuel type_LPG</th>\n",
" <th>Fuel type_Petrol</th>\n",
" <th>Fuel type_Plug-in Hybrid</th>\n",
" <th>Wheel_Right-hand drive</th>\n",
" <th>Car age</th>\n",
" <th>Car age bins</th>\n",
" <th>Mileage bins</th>\n",
" <th>Turbo</th>\n",
" <th>Safety rating</th>\n",
" <th>Color rarity</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>13328</td>\n",
" <td>1.065632</td>\n",
" <td>LEXUS</td>\n",
" <td>Yes</td>\n",
" <td>1.357980</td>\n",
" <td>-0.027813</td>\n",
" <td>1.180937</td>\n",
" <td>Automatic</td>\n",
" <td>04-May</td>\n",
" <td>12</td>\n",
" <td>...</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>15</td>\n",
" <td>11-20</td>\n",
" <td>High</td>\n",
" <td>0</td>\n",
" <td>0.750</td>\n",
" <td>0.197120</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>16621</td>\n",
" <td>0.240688</td>\n",
" <td>CHEVROLET</td>\n",
" <td>No</td>\n",
" <td>0.788363</td>\n",
" <td>-0.027689</td>\n",
" <td>1.180937</td>\n",
" <td>Tiptronic</td>\n",
" <td>04-May</td>\n",
" <td>8</td>\n",
" <td>...</td>\n",
" <td>False</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>14</td>\n",
" <td>11-20</td>\n",
" <td>Very High</td>\n",
" <td>0</td>\n",
" <td>0.500</td>\n",
" <td>0.261631</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>8467</td>\n",
" <td>NaN</td>\n",
" <td>HONDA</td>\n",
" <td>No</td>\n",
" <td>-1.148338</td>\n",
" <td>-0.027524</td>\n",
" <td>-0.485866</td>\n",
" <td>Variator</td>\n",
" <td>04-May</td>\n",
" <td>2</td>\n",
" <td>...</td>\n",
" <td>False</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>True</td>\n",
" <td>19</td>\n",
" <td>11-20</td>\n",
" <td>Very High</td>\n",
" <td>0</td>\n",
" <td>0.125</td>\n",
" <td>0.261631</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3607</td>\n",
" <td>-0.097084</td>\n",
" <td>FORD</td>\n",
" <td>Yes</td>\n",
" <td>0.218745</td>\n",
" <td>-0.028165</td>\n",
" <td>-0.485866</td>\n",
" <td>Automatic</td>\n",
" <td>04-May</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>14</td>\n",
" <td>11-20</td>\n",
" <td>High</td>\n",
" <td>0</td>\n",
" <td>0.000</td>\n",
" <td>0.233352</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>11726</td>\n",
" <td>-0.997809</td>\n",
" <td>HONDA</td>\n",
" <td>Yes</td>\n",
" <td>-1.148338</td>\n",
" <td>-0.029757</td>\n",
" <td>-0.485866</td>\n",
" <td>Automatic</td>\n",
" <td>04-May</td>\n",
" <td>4</td>\n",
" <td>...</td>\n",
" <td>False</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>11</td>\n",
" <td>11-20</td>\n",
" <td>Medium</td>\n",
" <td>0</td>\n",
" <td>0.250</td>\n",
" <td>0.197120</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 35 columns</p>\n",
"</div>"
],
"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
}