161 KiB
Датасет астероидов¶
Выведем записи и столбцы
import pandas as pd
df_subset = pd.read_csv("..//..//static//csv//neo.csv")
df = df_subset.head(15000)
print(df.columns)
df.head()
Бизнес-цели:¶
- Повышение безопасности планеты от потенциальных угроз космических объектов.
- Оптимизация исследования космических объектов для использования в коммерческих или исследовательских миссиях.
Цели технического проекта:¶
Для 1-й бизнес-цели:
- Создать веб-приложение или API, которое принимает параметры объекта и прогнозирует, опасен ли он для Земли.
- Модель может использоваться в системах мониторинга космических объектов для предоставления оперативных оценок и предупреждений.
- Включение автоматической системы оповещения для НАСА и других космических агентств с обновлениями по объектам, представляющим угрозу.
Для 2-й бизнес-цели:
- Разработка модели, которая позволяет астрономам и специалистам по космосу загружать данные о новых объектах и получать предсказания о расстоянии их ближайшего сближения с Землей.
- Создание системы мониторинга с графическим интерфейсом, отображающим траектории движения объектов и предполагаемые даты и расстояния их ближайших подходов.
- Реализация системы оповещений на основе пороговых значений расстояний для идентификации особо опасных сближений.
Проверим датасет на пропущенные значения:
for i in df.columns:
null_rate = df[i].isnull().sum() / len(df) * 100
print(f'{i} Процент пустых значений: %{null_rate:.2f}')
print(df.isnull().sum())
df.isnull().any()
Нулевых значений нет
Разобьём набор на 3 классических выборки: обучающую, тестовую и контрольную
from sklearn.model_selection import train_test_split
df = df.dropna()
df = df.drop_duplicates()
X = df.drop(columns=['absolute_magnitude'])
y = df['absolute_magnitude']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=42)
print("Размер обучающей выборки:", X_train.shape)
print("Размер контрольной выборки:", X_val.shape)
print("Размер тестовой выборки:", X_test.shape)
Построим несколько столбчатых диаграмм для визуализации распределения:
import matplotlib.pyplot as plt
import seaborn as sns
train_data = pd.DataFrame({'absolute_magnitude': y_train})
val_data = pd.DataFrame({'absolute_magnitude': y_val})
test_data = pd.DataFrame({'absolute_magnitude': y_test})
sns.histplot(train_data['absolute_magnitude'], kde=True)
plt.title('Распределение absolute_magnitude в обучающей выборке')
plt.show()
sns.histplot(val_data['absolute_magnitude'], kde=True)
plt.title('Распределение absolute_magnitude в контрольной выборке')
plt.show()
sns.histplot(test_data['absolute_magnitude'], kde=True)
plt.title('Распределение absolute_magnitude в тестовой выборке')
plt.show()
Конструирование признаков¶
Унитарное кодирование
Унитарное кодирование категориальных признаков (one-hot encoding). Преобразуем категориальные признаки в бинарные векторы.
from sklearn.preprocessing import OneHotEncoder
df = pd.read_csv("..//..//static//csv//neo.csv")
categorical_columns = ['orbiting_body', 'sentry_object']
df_encoded = pd.get_dummies(df, columns=categorical_columns)
print(df_encoded.head())
Дискретизация числовых признаков
Процесс преобразования непрерывных числовых значений в дискретные категории или интервалы (бины).
import pandas as pd
df['miss_distance_binned'] = pd.cut(df['miss_distance'], bins=5)
df['absolute_magnitude_binned'] = pd.qcut(df['absolute_magnitude'], q=4)
print(df[['miss_distance', 'miss_distance_binned']].head())
print(df[['absolute_magnitude', 'absolute_magnitude_binned']].head())
Ручной синтез
Создание новых признаков на основе экспертных знаний и логики предметной области. В нашем случае можно задействовать расстояния объекта от Земли и скорость движения объекта, синтезировав новый признак - "скорость в сравнении с расстоянием". Этот признак показывает, что объект может быть более опасным, если его скорость велика, а расстояние до Земли — маленькое.
# Создание нового признака 'Speed VS Distance'
df['high_risk'] = ((df['miss_distance'] < threshold_distance) & (df['relative_velocity'] > threshold_velocity)).astype(int)
Масштабирование признаков
Процесс преобразования числовых признаков таким образом, чтобы они имели одинаковый масштаб. Это важно для многих алгоритмов машинного обучения, которые чувствительны к масштабу признаков, таких как линейная регрессия, метод опорных векторов (SVM) и нейронные сети.
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# Пример масштабирования числовых признаков
numerical_features = ['miss_distance', 'absolute_magnitude']
scaler = StandardScaler()
df_encoded[numerical_features] = scaler.fit_transform(df_encoded[numerical_features])
df_encoded[numerical_features] = scaler.transform(df_encoded[numerical_features])
df_encoded[numerical_features] = scaler.transform(df_encoded[numerical_features])
import pandas as pd
import featuretools as ft
from sklearn.model_selection import train_test_split
df = pd.read_csv("..//..//static//csv//neo.csv")
df['id'] = range(1, len(df) + 1)
df = df.drop_duplicates()
es = ft.EntitySet(id='objects_data')
es = es.add_dataframe(
dataframe_name='objects',
dataframe=df,
index='id'
)
feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='objects', max_depth=1)
print(feature_matrix.head())
train_data, test_data = train_test_split(df, test_size=0.3, random_state=42)
val_data, test_data = train_test_split(test_data, test_size=0.5, random_state=42)
val_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=val_data['id'])
test_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=test_data['id'])
print(val_feature_matrix.head())
print(test_feature_matrix.head())
Оценка качества каждого набора признаков¶
Представим основные оценки качества наборов признаков:
Предсказательная способность Метрики: RMSE, MAE, R²
Методы: Обучение модели на обучающей выборке и оценка на контрольной и тестовой выборках.
Скорость вычисления
Методы: Измерение времени выполнения генерации признаков и обучения модели.
Надежность
Методы: Кросс-валидация, анализ чувствительности модели к изменениям в данных.
Корреляция
Методы: Анализ корреляционной матрицы признаков, удаление мультиколлинеарных признаков.
Цельность
Методы: Проверка логической связи между признаками и целевой переменной, интерпретация результатов модели.
import time
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
X = feature_matrix.drop('absolute_magnitude', axis=1)
y = feature_matrix['absolute_magnitude']
X = pd.get_dummies(X, drop_first=True)
X.fillna(X.median(), inplace=True)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
model = LinearRegression()
start_time = time.time()
model.fit(X_train, y_train)
train_time = time.time() - start_time
predictions = model.predict(X_val)
mse = mean_squared_error(y_val, predictions)
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_absolute_error
from sklearn.model_selection import cross_val_score
feature_matrix = feature_matrix.dropna()
val_feature_matrix = val_feature_matrix.dropna()
test_feature_matrix = test_feature_matrix.dropna()
X_train = feature_matrix.drop('absolute_magnitude', axis=1)
y_train = feature_matrix['absolute_magnitude']
X_val = val_feature_matrix.drop('absolute_magnitude', axis=1)
y_val = val_feature_matrix['absolute_magnitude']
X_test = test_feature_matrix.drop('absolute_magnitude', axis=1)
y_test = test_feature_matrix['absolute_magnitude']
X_test = X_test.reindex(columns=X_train.columns, fill_value=0)
X = pd.get_dummies(X, drop_first=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = RandomForestRegressor(random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, y_pred, squared=False)
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
print()
print(f"RMSE: {rmse}")
print(f"R²: {r2}")
print(f"MAE: {mae} \n")
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")
feature_importances = model.feature_importances_
feature_names = X_train.columns
y_train_pred = model.predict(X_train)
rmse_train = mean_squared_error(y_train, y_train_pred, squared=False)
r2_train = r2_score(y_train, y_train_pred)
mae_train = mean_absolute_error(y_train, y_train_pred)
print(f"Train RMSE: {rmse_train}")
print(f"Train R²: {r2_train}")
print(f"Train MAE: {mae_train}")
print()