214 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)}')
mse, bias, variance = bias_variance_decomp(best_model, X_train.values, y_train.values, X_test.values, y_test.values, loss='mse', num_rounds=200, random_seed=123)
print("Смещение: ", bias)
print("Дисперсия: ", variance)
Гребневая регрессия¶
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)}')
mse, bias, variance = bias_variance_decomp(best_model, X_train.values, y_train.values, X_test.values, y_test.values, loss='mse', num_rounds=200, random_seed=123)
print("Смещение: ", bias)
print("Дисперсия: ", variance)
Гребневая регрессия показала почти такие же результаты, что и линейная регрессия
Метод градиентного бустинга (набор деревьев решений)¶
# Конвейер
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)
# Оценка смещения
bias = np.mean(y_cv_pred - y_train)
# Оценка дисперсии
variance = np.var(y_cv_pred)
print(f"Смещение: {bias}")
print(f"Дисперсия: {variance}")
Вывод:
Все 3 модели регрессии не показали необходимого уровня "погрешности". Это означает, что необходимо использовать более сложные модели или что по доступным данным нельзя достичь необходимой погрешности.
Из всех моделей градиентный бустинг показал самую низкую "погрешность"
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%