Метрики качества регрессии
После обучения модели возникает главный вопрос: насколько хорошо она работает? Для ответа используют метрики качества — числовые показатели, которые измеряют точность предсказаний.
Зачем нужны метрики?
Представьте, что вы построили две модели для предсказания цен квартир:
- Модель A предсказала: [3.0, 3.5, 4.2] млн руб.
- Модель B предсказала: [2.8, 3.6, 4.0] млн руб.
- Реальные цены: [3.0, 3.5, 4.0] млн руб.
Какая модель лучше? На глаз не очевидно. Метрики дают объективный ответ.
R² (коэффициент детерминации)
Что показывает?
R² показывает, какую долю вариации целевой переменной объясняет модель.
Формула:
R² = 1 - (SS_res / SS_tot)
где:
SS_res = Σ(yᵢ - ŷᵢ)² — сумма квадратов остатков (ошибок модели)
SS_tot = Σ(yᵢ - ȳ)² — общая сумма квадратов (вариация данных)
Диапазон значений:
| Значение |
Интерпретация |
| R² = 1.0 |
Идеальная модель — все предсказания точные |
| R² = 0.85 |
Модель объясняет 85% вариации данных |
| R² = 0.0 |
Модель не лучше, чем просто предсказывать среднее |
| R² < 0 |
Модель хуже, чем среднее! (это плохо) |
Практический пример:
from sklearn.metrics import r2_score
y_test = [3.0, 3.5, 4.0, 4.5, 5.0] # Реальные цены (млн руб.)
y_pred = [3.1, 3.4, 4.2, 4.3, 5.1] # Предсказания модели
r2 = r2_score(y_test, y_pred)
print(f"R² = {r2:.4f}") # R² = 0.9600
Интерпретация: Модель объясняет 96% вариации цен. Это отличный результат!
Практические ориентиры:
| R² |
Качество |
Комментарий |
| > 0.9 |
Отличное |
Для большинства задач — очень хорошо |
| 0.7 - 0.9 |
Хорошее |
Приемлемо для практики |
| 0.5 - 0.7 |
Удовлетворительное |
Модель работает, но есть куда расти |
| < 0.5 |
Слабое |
Нужно улучшать модель или данные |
⚠️ Важно: Границы условны! В некоторых сложных задачах R² = 0.6 — это успех.
Когда R² может быть отрицательным?
Это случается, когда модель предсказывает хуже, чем простое среднее:
y_test = [1, 2, 3]
y_pred = [10, 20, 30] # Совсем мимо!
r2 = r2_score(y_test, y_pred)
print(f"R² = {r2:.4f}") # R² = -89.5000
Отрицательный R² — сигнал, что с моделью что-то серьёзно не так.
MAE (Mean Absolute Error)
Что показывает?
MAE — это средняя абсолютная ошибка предсказания.
Формула:
MAE = (1/n) × Σ|yᵢ - ŷᵢ|
Главное преимущество:
Результат в тех же единицах, что и целевая переменная! Это делает MAE очень понятной метрикой.
Практический пример:
from sklearn.metrics import mean_absolute_error
y_test = [3000, 3500, 4000, 4500, 5000] # Цены в тыс. руб.
y_pred = [3100, 3400, 4200, 4300, 5100] # Предсказания
mae = mean_absolute_error(y_test, y_pred)
print(f"MAE = {mae:.2f} тыс. руб.") # MAE = 140.00 тыс. руб.
Интерпретация: В среднем модель ошибается на 140 тысяч рублей.
Когда использовать MAE?
✅ Когда важна интерпретируемость — легко объяснить заказчику
✅ Когда все ошибки одинаково важны
✅ Когда в данных есть выбросы (MAE к ним устойчива)
MSE и RMSE
MSE (Mean Squared Error)
Средняя квадратичная ошибка:
MSE = (1/n) × Σ(yᵢ - ŷᵢ)²
Проблема: Единицы измерения — квадраты исходных единиц.
Если цена в рублях, то MSE в рублях² — это бессмысленно для интерпретации.
RMSE (Root Mean Squared Error)
Корень из MSE — решает проблему единиц:
RMSE = √MSE = √[(1/n) × Σ(yᵢ - ŷᵢ)²]
Практический пример:
from sklearn.metrics import mean_squared_error
import numpy as np
y_test = [3000, 3500, 4000, 4500, 5000]
y_pred = [3100, 3400, 4200, 4300, 5100]
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
# Или в sklearn: rmse = mean_squared_error(y_test, y_pred, squared=False)
print(f"MSE = {mse:.2f}") # MSE = 22000.00
print(f"RMSE = {rmse:.2f} тыс. руб.") # RMSE = 148.32 тыс. руб.
MAE vs RMSE: в чём разница?
Ключевое отличие:
RMSE сильнее штрафует большие ошибки из-за возведения в квадрат.
Наглядный пример:
Представьте две модели с одинаковой суммой ошибок:
| Модель |
Ошибки |
MAE |
RMSE |
| A |
[2, 2, 2, 2] |
2.0 |
2.0 |
| B |
[0, 0, 0, 8] |
2.0 |
4.0 |
import numpy as np
errors_A = np.array([2, 2, 2, 2])
errors_B = np.array([0, 0, 0, 8])
print(f"Модель A: MAE={np.mean(np.abs(errors_A))}, RMSE={np.sqrt(np.mean(errors_A**2))}")
print(f"Модель B: MAE={np.mean(np.abs(errors_B))}, RMSE={np.sqrt(np.mean(errors_B**2))}")
# Модель A: MAE=2.0, RMSE=2.0
# Модель B: MAE=2.0, RMSE=4.0
Вывод:
- По MAE модели одинаковые
- По RMSE модель B хуже — у неё есть большая ошибка (8)
Когда что выбирать?
| Ситуация |
Выбор |
| Большие ошибки критичны (медицина, финансы) |
RMSE |
| Все ошибки равноценны |
MAE |
| Нужна простая интерпретация |
MAE |
| В данных много выбросов |
MAE (более устойчива) |
Сравнение моделей по метрикам
Пример анализа:
| Метрика |
Модель A |
Модель B |
| R² |
0.82 |
0.79 |
| MAE |
8500 руб |
7200 руб |
| RMSE |
12000 руб |
15000 руб |
Анализ:
- R²: Модель A лучше объясняет данные (0.82 > 0.79)
- MAE: Модель B в среднем ошибается меньше (7200 < 8500)
- RMSE: Модель A имеет меньше крупных ошибок (12000 < 15000)
Парадокс: Модель B имеет меньший MAE, но больший RMSE. Это значит, что она чаще делает небольшие ошибки, но иногда — очень большие.
Выбор: Зависит от задачи! Если большие ошибки критичны — выбираем A.
Диагностика переобучения
Идея:
Сравните метрики на обучающей и тестовой выборках:
# После обучения модели
train_r2 = model.score(X_train, y_train)
test_r2 = model.score(X_test, y_test)
print(f"R² на train: {train_r2:.4f}")
print(f"R² на test: {test_r2:.4f}")
Интерпретация:
| Результат |
Диагноз |
Что делать? |
| train ≈ test |
✅ Хорошее обобщение |
Всё отлично! |
| train >> test |
⚠️ Переобучение |
Упростить модель, добавить данных |
| train ≈ test, оба низкие |
❌ Недообучение |
Усложнить модель, добавить признаки |
Пример:
print(f"R² на train: 0.95")
print(f"R² на test: 0.72")
# Разница 0.23 — это много! Похоже на переобучение.
Использование в sklearn
Импорты:
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
import numpy as np
Вычисление всех метрик:
# После обучения модели
y_pred = model.predict(X_test)
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
print(f"R²: {r2:.4f}")
print(f"MAE: {mae:.2f}")
print(f"MSE: {mse:.2f}")
print(f"RMSE: {rmse:.2f}")
Быстрый способ для R²:
# Метод score() возвращает R²
score = model.score(X_test, y_test)
print(f"R² = {score:.4f}")
Резюме
| Метрика |
Что измеряет |
Диапазон |
Интерпретация |
| R² |
Доля объяснённой вариации |
(-∞, 1] |
Чем ближе к 1, тем лучше |
| MAE |
Средняя ошибка |
[0, +∞) |
В единицах целевой переменной |
| RMSE |
Средняя ошибка (штраф за большие) |
[0, +∞) |
В единицах целевой переменной |
Главное правило: Используйте несколько метрик вместе для полной картины!