215 KiB
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
from scipy import stats
from sklearn.compose import ColumnTransformer
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn import linear_model, tree, neighbors, ensemble, neural_network
df = pd.read_csv("..//static//csv//balanced_neo.csv")
1-я бизнес-цель (регрессия):¶
Предсказание скорости космического объекта для принятия решения о том, насколько опасным он может быть и стоит ли вести за ним наблюдения
Целевой признак: скорость космического объекта relative_velocity
Вход: минимальный радиус est_diameter_min, максимальный радиус est_diameter_max, яркость объекта absolute_magnitude, расстояние от Земли miss_distance
Достижимый уровень качества: предсказания должны иметь погрешность в среднем не более 10000 км/с. Для проверки будет использоваться метрика MAE (средняя абсолютная ошибка)
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.discriminant_analysis import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import roc_auc_score, confusion_matrix, accuracy_score
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
import seaborn as sns
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import mean_squared_error
import numpy as np
from sklearn import metrics
import sklearn.preprocessing as preproc
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_absolute_error
from mlxtend.evaluate import bias_variance_decomp
from sklearn.neural_network import MLPRegressor
# Загрузка данных
df = pd.read_csv("..//static//csv//balanced_neo.csv")
data = df[['est_diameter_min', 'est_diameter_max', 'absolute_magnitude', 'miss_distance', 'relative_velocity']]
X = data.drop('relative_velocity', axis=1)
y = data['relative_velocity']
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Преобразование числовых данных
#заполнение пустых значений медианой
num_imputer = SimpleImputer(strategy="median")
preprocessing_num = Pipeline(
[
("imputer", num_imputer)
]
)
#Категориальных данных нет, поэтому преобразовывать их не надо
# Общая предобработка (только числовые данные)
preprocessing = ColumnTransformer(
[
("nums", preprocessing_num, X.columns)
]
)
Линейная регрессия¶
pipeline_lin_reg = Pipeline([
('preprocessing', preprocessing),
('model', LinearRegression())]
)
# Определение сетки гиперпараметров (возможных знач-ий гиперпараметров) для перебора
param_grid = {
#как будут масштабироваться признаки
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None]
}
# Создание объекта GridSearchCV для поиска лучших гиперпараметров по сетке с максимальным знач-ием
# отрицательного корня из среднеквадратичной ошибки (отриц., чтобы искался не минимум, а максимум)
grid_search = GridSearchCV(pipeline_lin_reg, param_grid, cv=5, scoring='neg_root_mean_squared_error', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель лин. регрессии
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
# Оценка дисперсии и смещения
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
from sklearn.metrics import r2_score
print(f'R^2 = {r2_score(y_test, y_pred)}')
Гребневая регрессия¶
pipeline_ridge = Pipeline([
('preprocessing', preprocessing),
('model', Ridge())]
)
# Определение сетки гиперпараметров (возможных знач-ий гиперпараметров) для перебора
param_grid = {
#как будут масштабироваться признаки
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None],
#сила регуляризации
'model__alpha': [0, 0.5, 1.0, 1.5, 2.0, 5.0, 10.0]
}
# Создание объекта GridSearchCV для поиска лучших гиперпараметров по сетке с максимальным знач-ием
# отрицательного корня из среднеквадратичной ошибки (отриц., чтобы искался не минимум, а максимум)
grid_search = GridSearchCV(pipeline_ridge, param_grid, cv=5, scoring='neg_root_mean_squared_error', n_jobs=-1, verbose=0)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель регрессии
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
print(f'R^2 = {r2_score(y_test, y_pred)}')
Гребневая регрессия показала почти такие же результаты, что и линейная регрессия
Метод градиентного бустинга (набор деревьев решений)¶
# Конвейер
pipeline_grad = Pipeline([
('preprocessing', preprocessing),
('model', GradientBoostingRegressor())
])
# Определение сетки гиперпараметров
param_grid = {
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None],
'model__n_estimators': [100, 200, 300],
#Скорость обучения
'model__learning_rate': [0.1, 0.2],
#Максимальная глубина дерева
'model__max_depth': [3, 5, 7]
}
# Создание объекта GridSearchCV
grid_search = GridSearchCV(pipeline_grad, param_grid, cv=2, scoring='neg_root_mean_squared_error', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель случайного леса
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
# Получение предсказаний на кросс-валидации
y_cv_pred = cross_val_predict(best_model, X_train, y_train, cv=3)
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
print(f'R^2 = {r2_score(y_test, y_pred)}')
Вывод:
Все 3 модели регрессии не показали необходимого уровня "погрешности". Также у всех моделей большое значение смещения, т.е. эти модели для задачи слишком простые. Необходимо использовать более сложные модели. Также возможно, что по доступным в датасете данным нельзя достичь необходимой погрешности.
Также низкое значение метрики R^2 у всех моделей показывает, что эти модели плохо объясняют вариацию целевой переменной.
Из всех моделей градиентный бустинг показал самую низкую "погрешность"
2-я бизнес-цель (классификация):¶
Определение опасности космиеского объекта для увеличения безопасности Земли
Целевой признак: опасность объекта hazardous
Вход: минимальный радиус est_diameter_min, максимальный радиус est_diameter_max, яркость объекта absolute_magnitude, скорость relative_velocity
Достижимый уровень качества: необходимо, чтобы точность предсказания модели составляла не менее 90%. Для проверки этого будет использована метрика Accuracy
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.discriminant_analysis import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import roc_auc_score, confusion_matrix, accuracy_score
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
import seaborn as sns
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import mean_squared_error
import numpy as np
from sklearn import metrics
# Загрузка данных
df = pd.read_csv("..//static//csv//balanced_neo.csv")
data = df[['est_diameter_min', 'est_diameter_max', 'absolute_magnitude', 'relative_velocity', 'hazardous']]
X = data.drop('hazardous', axis=1)
y = data['hazardous']
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Преобразование числовых данных
num_imputer = SimpleImputer(strategy="median")
num_scaler = StandardScaler()
preprocessing_num = Pipeline(
[
("imputer", num_imputer),
("scaler", num_scaler),
]
)
# Общая предобработка (только числовые данные)
preprocessing = ColumnTransformer(
[
("nums", preprocessing_num, X.columns),
]
)
Логистическая регрессия¶
# Конвейер для логистической регрессии
pipeline_logreg = Pipeline([
('preprocessing', preprocessing),
('classifier', LogisticRegression())
])
# Определение сетки гиперпараметров (возможных знач-ий гиперпараметров) для перебора
param_grid = {
# Параметр регуляризации (сила регуляризации), чем меньше, тем сильнее регуляризация
'classifier__C': [0.1, 0.5, 1],
# Тип регуляризации (ф-ия штрафов)
'classifier__penalty': ['l1', 'l2'],
# Решатель (сам алгоритм?)
'classifier__solver': ['liblinear', 'saga']
}
# Создание объекта GridSearchCV для поиска лучших гиперпараметров по сетке с максимальным знач-ием ROC-кривой
grid_search = GridSearchCV(pipeline_logreg, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель логистической регрессии
best_model = grid_search.best_estimator_
# Использование и оценка лучшей логистической модели
y_pred_proba = best_model.predict_proba(X_test)[:, 1]
print(f'ROC у логистической регрессии = {roc_auc_score(y_test, y_pred_proba)}')
y_pred = best_model.predict(X_test)
print(f'Точность = {accuracy_score(y_test, y_pred)}')
fpr, tpr, _ = metrics.roc_curve(y_test, y_pred_proba)
# построение ROC кривой
plt.plot(fpr, tpr)
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
# Построение матрицы ошибок
conf_matrix = confusion_matrix(y_test, y_pred)
# Визуализация матрицы ошибок
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=['Предсказанный "безопасный"', 'Предсказанный "опасный"'],
yticklabels=['Действительно "безопасный"', 'Действительно "опасный"'])
plt.title('Confusion Matrix')
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
# Оценка дисперсии и смещения
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
Метод случаного леса (набор деревьев решений)¶
# Конвейер для случайного леса
pipeline_ranfor = Pipeline([
('preprocessing', preprocessing),
('classifier', RandomForestClassifier())
])
# Определение сетки гиперпараметров
param_grid = {
#Количество деревьев в лесу
'classifier__n_estimators': [50, 100, 200],
#Максимальная глубина дерева
'classifier__max_depth': [10, 20, 30],
#Минимальное количество образцов для листового узла
'classifier__min_samples_leaf': [1, 2, 4]
}
# Создание объекта GridSearchCV
grid_search = GridSearchCV(pipeline_ranfor, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель случайного леса
best_model = grid_search.best_estimator_
# Использование и оценка лучшей модели
y_pred_proba = best_model.predict_proba(X_test)[:, 1]
print(f'ROC у метода случайного леса = {roc_auc_score(y_test, y_pred_proba)}')
y_pred = best_model.predict(X_test)
print(f'Точность = {accuracy_score(y_test, y_pred)}')
fpr, tpr, _ = metrics.roc_curve(y_test, y_pred_proba)
# построение ROC кривой
plt.plot(fpr, tpr)
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
# Построение матрицы ошибок
conf_matrix = confusion_matrix(y_test, y_pred)
# Визуализация матрицы ошибок
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=['Предсказанный "безопасный"', 'Предсказанный "опасный"'],
yticklabels=['Действительно "безопасный"', 'Действительно "опасный"'])
plt.title('Confusion Matrix')
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
# Оценка дисперсии и смещения
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
Градиентный бустинг¶
# Конвейер
pipeline_grad = Pipeline([
('preprocessing', preprocessing),
('classifier', GradientBoostingClassifier())
])
# Определение сетки гиперпараметров
param_grid = {
'classifier__n_estimators': [100, 200, 300],
#Скорость обучения
'classifier__learning_rate': [0.1, 0.2],
#Максимальная глубина дерева
'classifier__max_depth': [3, 5, 7],
'classifier__subsample': [0.1, 0.5, 1.0],
}
# Создание объекта GridSearchCV
grid_search = GridSearchCV(pipeline_grad, param_grid, cv=2, scoring='roc_auc', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель
best_model = grid_search.best_estimator_
# Использование и оценка лучшей модели
y_pred_proba = best_model.predict_proba(X_test)[:, 1]
print(f'ROC у метода градиентного спуска = {roc_auc_score(y_test, y_pred_proba)}')
y_pred = best_model.predict(X_test)
print(f'Точность = {accuracy_score(y_test, y_pred)}')
fpr, tpr, _ = metrics.roc_curve(y_test, y_pred_proba)
# построение ROC кривой
plt.plot(fpr, tpr)
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
# Построение матрицы ошибок
conf_matrix = confusion_matrix(y_test, y_pred)
# Визуализация матрицы ошибок
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
xticklabels=['Предсказанный "безопасный"', 'Предсказанный "опасный"'],
yticklabels=['Действительно "безопасный"', 'Действительно "опасный"'])
plt.title('Confusion Matrix')
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
# Оценка дисперсии и смещения
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
Вывод:
Все модели классификации показали хорошие результаты, но лучший показатель точности у случайного леса. При этом все рассмотренные модели немного не дотянули до показателя точности в 90%. Дополнительая настройка гиперпараметров могла бы приблизить значение оценки ещё ближе к 90%