Статья Автор: Деникина Н.В., Деникин А.В.

Метрики качества

Метрики качества регрессии

После обучения модели возникает главный вопрос: насколько хорошо она работает? Для ответа используют метрики качества — числовые показатели, которые измеряют точность предсказаний.


Зачем нужны метрики?

Представьте, что вы построили две модели для предсказания цен квартир:

  • Модель 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% вариации цен. Это отличный результат!

Практические ориентиры:

Качество Комментарий
> 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
0.82 0.79
MAE 8500 руб 7200 руб
RMSE 12000 руб 15000 руб

Анализ:

  1. R²: Модель A лучше объясняет данные (0.82 > 0.79)
  2. MAE: Модель B в среднем ошибается меньше (7200 < 8500)
  3. 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}")

Резюме

Метрика Что измеряет Диапазон Интерпретация
Доля объяснённой вариации (-∞, 1] Чем ближе к 1, тем лучше
MAE Средняя ошибка [0, +∞) В единицах целевой переменной
RMSE Средняя ошибка (штраф за большие) [0, +∞) В единицах целевой переменной

Главное правило: Используйте несколько метрик вместе для полной картины!

Печать