128 KiB
128 KiB
In [1]:
import pandas as pd
df = pd.read_csv("..//static//csv//car_price_prediction.csv", sep=",")
In [2]:
df.head()
Out[2]:
Бизнес-цели¶
- Задача регрессии: Построить модель для предсказания цены автомобиля (
Price
) на основе его характеристик. - Задача классификации: Определить категорию автомобиля (
Category
) по характеристикам.
Ввиду того что я первый раз обучаю модель прогнозируемое качество предсказания - не выше 50 %
In [3]:
df.dtypes
Out[3]:
небольшая обработка данных¶
In [4]:
Q1 = df['Price'].quantile(0.25)
Q3 = df['Price'].quantile(0.75)
IQR = Q3 - Q1
df = df[(df['Price'] >= Q1 - 1.5 * IQR) & (df['Price'] <= Q3 + 1.5 * IQR)]
In [5]:
df['Levy']=pd.to_numeric(df['Levy'],errors='coerce')
In [6]:
df['Mileage'] = df['Mileage'].str.replace(' km', '').str.replace(',', '')
df['Mileage'] = df['Mileage'].astype(int)
In [7]:
import re
df['Engine volume'] = df['Engine volume'].apply(lambda x: float(re.match(r'\d+(\.\d+)?', x).group()) if isinstance(x, str) else x)
In [8]:
df.drop_duplicates(inplace=True)
In [9]:
# Разделим данные на признаки и целевые переменные
X = df.drop(columns=['Price','ID']) # Признаки
y = df['Price'] # Целевая переменная для регрессии
In [10]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
наполняем пайплайн обработчиками¶
In [11]:
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
# Определение числовых и категориальных столбцов
numeric_features = ['Prod. year', 'Engine volume', 'Mileage', 'Cylinders', 'Airbags']
categorical_features = ['Manufacturer', 'Model', 'Category', 'Fuel type',
'Gear box type', 'Drive wheels', 'Doors',
'Wheel', 'Color']
# Обработка числовых данных
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')), # Заполнение пропусков медианой
('scaler', StandardScaler()) # Нормализация данных
])
# Обработка категориальных данных
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')), # Заполнение пропусков модой
('onehot', OneHotEncoder(handle_unknown='ignore')) # Преобразование в One-Hot Encoding
])
# Комбинированный трансформер
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features), # Применяем числовую обработку
('cat', categorical_transformer, categorical_features) # Применяем категориальную обработку
]
)
In [12]:
X_transformed = preprocessor.fit_transform(X)
print(f"Transformed feature shape: {X_transformed.shape}")
посмотрим результат пайплайна¶
In [13]:
# Получим имена категориальных признаков после OneHotEncoder
categorical_feature_names = preprocessor.named_transformers_['cat']['onehot'].get_feature_names_out(categorical_features)
# Объединим их с именами числовых признаков
feature_names = list(numeric_features) + list(categorical_feature_names)
# Создадим DataFrame для преобразованных данных
X_transformed_df = pd.DataFrame(X_transformed.toarray() if hasattr(X_transformed, 'toarray') else X_transformed, columns=feature_names)
# Выведем пример 5 строк
X_transformed_df
Out[13]:
обучим 3 разные модели с применением RandomizedSearchCV(для подора гиперпараметров)¶
In [14]:
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import matplotlib.pyplot as plt
random_state = 42
# Модели и параметры
models_regression = {
"LinearRegression": LinearRegression(),
"RandomForestRegressor": RandomForestRegressor(random_state=random_state),
"GradientBoostingRegressor": GradientBoostingRegressor(random_state=random_state)
}
param_grids_regression = {
"LinearRegression": {},
"RandomForestRegressor": {
'model__n_estimators': [50, 100, 200],
'model__max_depth': [None, 10, 20],
},
"GradientBoostingRegressor": {
'model__n_estimators': [50, 100, 200],
'model__learning_rate': [0.01, 0.1, 0.2],
'model__max_depth': [3, 5, 10]
}
}
# Результаты
results_regression = {}
# Перебор моделей
for name, model in models_regression.items():
print(f"Training {name}...")
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
param_grid = param_grids_regression[name]
grid_search = RandomizedSearchCV(pipeline, param_grid, cv=5, scoring='neg_mean_absolute_error', n_jobs=-1)
grid_search.fit(X_train, y_train)
# Лучшая модель
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
# Метрики
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
# Сохранение результатов
results_regression[name] = {
"Best Params": grid_search.best_params_,
"MAE": mae,
"RMSE": rmse,
"R2": r2
}
# Печать результатов
for name, metrics in results_regression.items():
print(f"\nModel: {name}")
for metric, value in metrics.items():
print(f"{metric}: {value}")
In [15]:
# Импортируем pandas для работы с таблицами
import pandas as pd
# Формируем таблицу метрик
reg_metrics = pd.DataFrame.from_dict(results_regression, orient="index")[
["MAE", "RMSE", "R2"]
]
# Визуализация результатов с помощью стилизации
styled_metrics = (
reg_metrics.sort_values(by="RMSE")
.style.background_gradient(cmap="viridis", low=1, high=0.3, subset=["RMSE", "MAE"])
.background_gradient(cmap="plasma", low=0.3, high=1, subset=["R2"])
)
styled_metrics
Out[15]:
невероятно¶
Модель может что-то даже предсказать, с погрешностью в 3к$ конечно и ошибкой 70% но всё же. Я думал и 50% не будет. Возможно если сузить сильнее входные данные, потому что выбросы очень большие, результат будет лучше. Линейная регрессия кстати вообще не справилась с данными а вот 2 другие ещё более менее
приступим к задаче классификации¶
In [16]:
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, f1_score
X = df.drop(columns=['Leather interior','ID']) # Признаки
# Целевая переменная для классификации
y_class = df['Leather interior'].map({'Yes': 1, 'No': 0}) # Преобразуем в 0/1
# Разделение данных
X_train_clf, X_test_clf, y_train_clf, y_test_clf = train_test_split(X, y_class, test_size=0.2, random_state=42)
# Модели и параметры
models_classification = {
"LogisticRegression": LogisticRegression(max_iter=1000),
"RandomForestClassifier": RandomForestClassifier(random_state=42),
"KNN": KNeighborsClassifier()
}
param_grids_classification = {
"LogisticRegression": {
'model__C': [0.1, 1, 10]
},
"RandomForestClassifier": {
"model__n_estimators": [10, 20, 30, 40, 50, 100, 150, 200, 250, 500],
"model__max_features": ["sqrt", "log2", 2],
"model__max_depth": [2, 3, 4, 5, 6, 7, 8, 9 ,10, 20],
"model__criterion": ["gini", "entropy", "log_loss"],
},
"KNN": {
'model__n_neighbors': [3, 5, 7, 9, 11],
'model__weights': ['uniform', 'distance']
}
}
# Результаты
results_classification = {}
# Перебор моделей
for name, model in models_classification.items():
print(f"Training {name}...")
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
param_grid = param_grids_classification[name]
grid_search = RandomizedSearchCV(pipeline, param_grid, cv=5, scoring='f1', n_jobs=-1)
grid_search.fit(X_train_clf, y_train_clf)
# Лучшая модель
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test_clf)
# Метрики
acc = accuracy_score(y_test_clf, y_pred)
f1 = f1_score(y_test_clf, y_pred)
# Вычисление матрицы ошибок
c_matrix = confusion_matrix(y_test_clf, y_pred)
# Сохранение результатов
results_classification[name] = {
"Best Params": grid_search.best_params_,
"Accuracy": acc,
"F1 Score": f1,
"Confusion_matrix": c_matrix
}
# Печать результатов
for name, metrics in results_classification.items():
print(f"\nModel: {name}")
for metric, value in metrics.items():
print(f"{metric}: {value}")
отресуем красивые квадратики¶
In [17]:
from sklearn.metrics import ConfusionMatrixDisplay
num_models = len(results_classification)
num_rows = (num_models // 2) + (num_models % 2) # Количество строк для подграфиков
_, ax = plt.subplots(num_rows, 2, figsize=(12, 10), sharex=False, sharey=False)
for index, (name, metrics) in enumerate(results_classification.items()):
c_matrix = metrics["Confusion_matrix"]
disp = ConfusionMatrixDisplay(
confusion_matrix=c_matrix, display_labels=["No", "Yes"]
).plot(ax=ax.flat[index])
disp.ax_.set_title(name)
# Корректировка расположения графиков
plt.subplots_adjust(top=1, bottom=0, hspace=0.4, wspace=0.1)
plt.show()
In [18]:
import pandas as pd
# Формируем таблицу метрик классификации
clf_metrics = pd.DataFrame.from_dict(results_classification, orient="index")[["Accuracy", "F1 Score"]]
# Визуализация результатов с помощью стилизации
styled_metrics_clf = (
clf_metrics.sort_values(by="F1 Score", ascending=False) # Сортировка по F1 Score
.style.background_gradient(cmap="viridis", low=0, high=1, subset=["F1 Score", "Accuracy"]) # Стилизация столбцов
.background_gradient(cmap="plasma", low=0.3, high=1, subset=["Accuracy"])
)
styled_metrics_clf
Out[18]:
В итоге KNN и LogisticRegression выдали точность в 90% что я считаю весьма неплохо. RandomForestClassifier близко, но не так хорошо