175 KiB
175 KiB
In [12]:
import pandas as pd
df = pd.read_csv("..//static//csv//car_price_prediction.csv", sep=",")
df.columns
Out[12]:
определение бизнесцелей:
- Прогнозирование цены автомобиля.
- Оценка факторов, влияющих на цену автомобиля.
Определение целей технического проекта:
- Построить модель машинного обучения для регрессии, которая будет прогнозировать стоимость автомобиля на основе предоставленных данных о его характеристиках.
- Провести анализ данных для выявления ключевых факторов, влияющих на стоимость автомобиля.
преобразуем пробег в число
In [13]:
df['Mileage'] = df['Mileage'].str.replace(r'\D+', '', regex=True).astype(float)
посмотрим выбросы и усредним их:
In [14]:
numeric_columns = ['Price', 'Mileage']
for column in numeric_columns:
if pd.api.types.is_numeric_dtype(df[column]): # Проверяем, является ли колонка числовой
q1 = df[column].quantile(0.25) # Находим 1-й квартиль (Q1)
q3 = df[column].quantile(0.75) # Находим 3-й квартиль (Q3)
iqr = q3 - q1 # Вычисляем межквартильный размах (IQR)
# Определяем границы для выбросов
lower_bound = q1 - 1.5 * iqr # Нижняя граница
upper_bound = q3 + 1.5 * iqr # Верхняя граница
# Подсчитываем количество выбросов
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
outlier_count = outliers.shape[0]
# Устраняем выбросы: заменяем значения ниже нижней границы на саму нижнюю границу, а выше верхней — на верхнюю
df[column] = df[column].apply(lambda x: lower_bound if x < lower_bound else upper_bound if x > upper_bound else x)
print(f"Колонка {column}:")
print(f" Есть выбросы: {'Да' if outlier_count > 0 else 'Нет'}")
print(f" Количество выбросов: {outlier_count}")
print(f" Минимальное значение: {df[column].min()}")
print(f" Максимальное значение: {df[column].max()}")
print(f" 1-й квартиль (Q1): {q1}")
print(f" 3-й квартиль (Q3): {q3}\n")
превращаем тире во чтото
In [15]:
import numpy as np
# Замена прочерков "-" в столбце Levy на NaN
df['Levy'].replace("-", np.nan, inplace=True)
# Преобразование столбца Levy в числовой формат (если он был строковым)
df['Levy'] = pd.to_numeric(df['Levy'], errors='coerce')
# Заполнение пропусков в столбце Levy медианой
df['Levy'].fillna(df['Levy'].median(), inplace=True)
код конструирования полей, все номинальные превращаем в числовые
In [16]:
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
#Пример: Создание нового признака "Age" (возраст автомобиля)
df['Age'] = 2024 - df['Prod. year']
df['Leather Interior'] = df['Leather interior'].apply(lambda x: 1 if x == 'Yes' else 0)
# Удаление ненужного столбца 'Prod. year', так как он был использован для создания 'Age'
df.drop(columns=['Prod. year'], inplace=True)
df.drop(columns=['Leather interior'], inplace=True)
# Определение категориальных признаков для преобразования
categorical_columns = ['Manufacturer', 'Engine volume', 'Doors', 'Wheel', 'Category', 'Fuel type', 'Gear box type', 'Color', 'Drive wheels']
# Инициализация OneHotEncoder
encoder = OneHotEncoder(sparse_output=False, drop="first")
# Применение OneHotEncoder к выбранным категориальным признакам
encoded_values = encoder.fit_transform(df[categorical_columns])
# Получение имен новых закодированных столбцов
encoded_columns = encoder.get_feature_names_out(categorical_columns)
# Преобразование в DataFrame
encoded_values_df = pd.DataFrame(encoded_values, columns=encoded_columns)
# Объединение закодированных значений с оригинальным DataFrame, исключив исходные категориальные столбцы
df = df.drop(columns=categorical_columns)
df = pd.concat([df.reset_index(drop=True), encoded_values_df.reset_index(drop=True)], axis=1)
# Применение Label Encoding для столбца 'Model'
label_encoder = LabelEncoder()
df['Model'] = label_encoder.fit_transform(df['Model'])
print(df.head())
Создадим выборки данных. разбивать будем относительно параметра цены, ведь это тот самый параметр по которому наша выборка разбивается на классы. И собственно его нам и надо будет предсказывать
In [17]:
from sklearn.model_selection import train_test_split
# Выделение признаков (X) и целевой переменной (y)
X = df.drop(columns=['Price']) # Признаки
y = df['Price'] # Целевая переменная (цена автомобиля)
# Разделение данных на обучающую и временную выборки
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42)
# Разделение временной выборки на контрольную и тестовую выборки
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
# Проверка размеров выборок
print(f"Размер обучающей выборки: {X_train.shape}")
print(f"Размер контрольной выборки: {X_val.shape}")
print(f"Размер тестовой выборки: {X_test.shape}")
In [18]:
import seaborn as sns
import matplotlib.pyplot as plt
# Функция для оценки распределения цены
def plot_distribution(y_data, title):
plt.figure(figsize=(10, 6))
sns.histplot(y_data, kde=True, bins=50)
plt.title(title)
plt.xlabel('Price')
plt.ylabel('Frequency')
plt.grid(True)
plt.show()
# Оценка распределения цены в каждой выборке
plot_distribution(y_train, "Распределение цены в обучающей выборке")
plot_distribution(y_val, "Распределение цены в контрольной выборке")
plot_distribution(y_test, "Распределение цены в тестовой выборке")
In [19]:
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# Предполагаем, что вы уже выделили ваши признаки X
# Применение нормировки Min-Max к всем числовым признакам
min_max_scaler = MinMaxScaler()
X_normalized = pd.DataFrame(min_max_scaler.fit_transform(X), columns=X.columns)
# Применение стандартизации к всем числовым признакам
standard_scaler = StandardScaler()
X_standardized = pd.DataFrame(standard_scaler.fit_transform(X), columns=X.columns)
# Проверка первых 5 строк после нормировки
print("Нормированные данные:")
print(X_normalized.head())
# Проверка первых 5 строк после стандартизации
print("\nСтандартизированные данные:")
print(X_standardized.head())
пример использование feature tools¶
попытаюсь вынести model в отдельную таблицу
In [20]:
pip install --upgrade featuretools
In [21]:
pip install --upgrade setuptools
In [27]:
import featuretools as ft
from woodwork.logical_types import Categorical, Integer
# Создание двух таблиц: одна с моделью, другая с остальными данными
model_df = df[['ID', 'Model']].drop_duplicates().reset_index(drop=True)
other_df = df.drop(columns=['Model'])
# Создание уникального идентификатора для связи
model_df['model_id'] = model_df.index
other_df['model_id'] = other_df['ID'].map(model_df.set_index('ID')['model_id'])
es = ft.EntitySet(id="orders")
es = es.add_dataframe(
dataframe_name="model_table",
dataframe=model_df,
index="model_id", # Индекс для уникальной идентификации моделей
logical_types={
"Model": Categorical # Определяем логический тип для модели
},
)
es = es.add_dataframe(
dataframe_name="car_features",
dataframe=other_df,
index="car_id", # Индекс для уникальной идентификации автомобилей
logical_types={
"Price": Integer, # Целевая переменная (цена)
"Mileage": Integer, # Пробег (числовой признак)
"model_id": Integer, # Пробег (числовой признак)
},
)
es = es.add_relationship("model_table", "model_id", "car_features", "model_id")
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_dataframe_name="car_features",
agg_primitives=["mean", "count", "mode", "any"],
trans_primitives=["hour", "weekday"],
max_depth=2,
)
feature_matrix
Out[27]: