Оценка моделей машинного обучения¶
Правильная оценка моделей — ключевой этап в машинном обучении, определяющий качество и надежность ваших предсказаний.
1. Метрики для классификации¶
Основные метрики¶
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# Accuracy (точность) - доля правильных ответов
accuracy = accuracy_score(y_true, y_pred)
# Precision (точность положительного класса)
precision = precision_score(y_true, y_pred)
# Recall (полнота) - доля найденных положительных
recall = recall_score(y_true, y_pred)
# F1-score - гармоническое среднее precision и recall
f1 = f1_score(y_true, y_pred)
Матрица ошибок (Confusion Matrix)¶
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
cm = confusion_matrix(y_true, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot()
plt.show()
# Расшифровка:
# TN | FP
# FN | TP
ROC-AUC и PR-AUC¶
from sklearn.metrics import roc_curve, auc, precision_recall_curve, roc_auc_score
# ROC кривая
fpr, tpr, thresholds = roc_curve(y_true, y_scores)
roc_auc = auc(fpr, tpr)
# Построение ROC кривой
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'ROC curve (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--', label='Random')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.show()
# ROC-AUC score
roc_auc = roc_auc_score(y_true, y_scores)
# Precision-Recall кривая (для несбалансированных данных)
precision, recall, thresholds = precision_recall_curve(y_true, y_scores)
pr_auc = auc(recall, precision)
Логарифмические потери (Log Loss)¶
from sklearn.metrics import log_loss
# Для бинарной классификации
logloss = log_loss(y_true, y_scores)
# Для многоклассовой
logloss = log_loss(y_true, y_scores_proba, labels=[0, 1, 2])
Метрики для многоклассовой классификации¶
from sklearn.metrics import classification_report
# Полный отчет по всем классам
print(classification_report(y_true, y_pred, digits=4))
# Средние значения
# macro - простое среднее по классам
# weighted - среднее с учетом поддержки классов
# micro - глобальный подсчет TP, FP, FN
precision_macro = precision_score(y_true, y_pred, average='macro')
precision_weighted = precision_score(y_true, y_pred, average='weighted')
Cohen's Kappa¶
from sklearn.metrics import cohen_kappa_score
# Учет случайного угадывания
kappa = cohen_kappa_score(y_true, y_pred)
# Интерпретация:
# < 0 - хуже случайного
# 0-0.2 - слабое согласие
# 0.2-0.4 - умеренное
# 0.4-0.6 - хорошее
# 0.6-0.8 - очень хорошее
# 0.8-1 - почти идеальное
2. Метрики для регрессии¶
Mean Absolute Error (MAE)¶
from sklearn.metrics import mean_absolute_error
mae = mean_absolute_error(y_true, y_pred)
# Интерпретация: средняя величина ошибки в единицах целевой переменной
Mean Squared Error (MSE) и RMSE¶
from sklearn.metrics import mean_squared_error
mse = mean_squared_error(y_true, y_pred)
rmse = mean_squared_error(y_true, y_pred, squared=False)
# MSE сильнее штрафует за большие ошибки
# RMSE интерпретируется в тех же единицах, что и y
R² (Коэффициент детерминации)¶
from sklearn.metrics import r2_score
r2 = r2_score(y_true, y_pred)
# Интерпретация:
# 1 - идеальная модель
# 0 - модель не лучше константы (среднего)
# < 0 - модель хуже константы
Mean Absolute Percentage Error (MAPE)¶
def mape(y_true, y_pred):
"""Средняя абсолютная процентная ошибка"""
mask = y_true != 0
return np.mean(np.abs((y_true[mask] - y_pred[mask]) / y_true[mask])) * 100
mape_value = mape(y_true, y_pred)
# Интерпретация: средняя ошибка в процентах
Symmetric MAPE (sMAPE)¶
def smape(y_true, y_pred):
"""Симметричная MAPE"""
denominator = (np.abs(y_true) + np.abs(y_pred)) / 2
mask = denominator != 0
return np.mean(np.abs(y_true[mask] - y_pred[mask]) / denominator[mask]) * 100
smape_value = smape(y_true, y_pred)
3. Валидация моделей¶
Train/Test Split¶
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,
stratify=y # Для сохранения распределения классов
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
K-Fold Cross-Validation¶
from sklearn.model_selection import cross_val_score, KFold
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kf, scoring='accuracy')
print(f"Mean accuracy: {scores.mean():.3f} (+/- {scores.std():.3f})")
print(f"Scores: {scores}")
Stratified K-Fold¶
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=skf, scoring='f1')
Leave-One-Out (LOO)¶
from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
scores = cross_val_score(model, X, y, cv=loo)
# Дорого вычислительно, но дает наименее смещенную оценку
Time Series Split¶
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(X):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
# Важно: нет перемешивания, тест всегда после train
4. Анализ ошибок¶
Learning Curves¶
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
train_sizes, train_scores, test_scores = learning_curve(
model, X, y, cv=5, scoring='accuracy',
train_sizes=np.linspace(0.1, 1.0, 10),
n_jobs=-1
)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_mean, 'o-', label='Train')
plt.fill_between(train_sizes, train_mean - train_std, train_mean + train_std, alpha=0.15)
plt.plot(train_sizes, test_mean, 'o-', label='Test')
plt.fill_between(train_sizes, test_mean - test_std, test_mean + test_std, alpha=0.15)
plt.xlabel('Training Size')
plt.ylabel('Score')
plt.legend()
plt.grid(True)
plt.show()
Validation Curves¶
from sklearn.model_selection import validation_curve
param_range = [1, 10, 50, 100, 200]
train_scores, test_scores = validation_curve(
RandomForestClassifier(), X, y,
param_name='n_estimators', param_range=param_range,
cv=5, scoring='accuracy', n_jobs=-1
)
# Анализ переобучения/недообучения
Анализ ошибочных предсказаний¶
# Найти примеры, где модель ошиблась
errors = y_pred != y_true
error_indices = np.where(errors)[0]
# Проанализировать характерные ошибки
for idx in error_indices[:10]:
print(f"True: {y_true[idx]}, Predicted: {y_pred[idx]}")
# Можно вывести сами данные или изображения
5. Сравнение моделей¶
Статистические тесты¶
from scipy import stats
# paired t-test для сравнения двух моделей
t_stat, p_value = stats.ttest_rel(scores_model1, scores_model2)
if p_value < 0.05:
print("Модели статистически различаются")
else:
print("Различия незначимы")
McNemar's Test¶
from statsmodels.stats.contingency_tables import mcnemar
# Таблица сопряженности ошибок
table = [[sum((p1==y) & (p2==y)), sum((p1==y) & (p2!=y))],
[sum((p1!=y) & (p2==y)), sum((p1!=y) & (p2!=y))]]
result = mcnemar(table, exact=True)
print(f"p-value: {result.pvalue}")
6. Базовые модели (Baselines)¶
Dummy Classifier¶
from sklearn.dummy import DummyClassifier
# Стратегии:
# - most_frequent: всегда предсказывает самый частый класс
# - stratified: случайное предсказание по распределению
# - uniform: равномерное случайное предсказание
# - constant: всегда предсказывает заданный класс
dummy = DummyClassifier(strategy='most_frequent')
dummy.fit(X_train, y_train)
baseline_score = dummy.score(X_test, y_test)
print(f"Baseline accuracy: {baseline_score:.3f}")
Dummy Regressor¶
from sklearn.dummy import DummyRegressor
# Стратегии:
# - mean: всегда предсказывает среднее
# - median: всегда предсказывает медиану
# - quantile: предсказывает квантиль
# - constant: всегда предсказывает константу
dummy = DummyRegressor(strategy='mean')
dummy.fit(X_train, y_train)
baseline_r2 = dummy.score(X_test, y_test)
print(f"Baseline R²: {baseline_r2:.3f}")
Чек-лист оценки модели¶
- Выбрать подходящие метрики для задачи
- Использовать кросс-валидацию
- Сравнить с baseline моделью
- Проверить на переобучение (learning curves)
- Проанализировать ошибочные предсказания
- Проверить стабильность на разных фолдах
- Оценить калибровку вероятностей (если нужно)
Рекомендации¶
- Всегда сравнивайте с baseline — ваша модель должна быть лучше простого правила
- Используйте несколько метрик — одна метрика может вводить в заблуждение
- Кросс-валидация обязательна — особенно на маленьких датасетах
- Анализируйте ошибки — это даст идеи для улучшения
- Учитывайте бизнес-контекст — выбирайте метрики, важные для задачи