Можно ли использовать метрику R^2 для обучения модели?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Использование R² как функции потерь при обучении модели
Это отличный вопрос, который касается глубокого понимания различий между метриками оценки и функциями потерь.
Краткий ответ: Технически можно, но нежелательно
Да, R² можно использовать как функцию потерь, но это редко делается и часто неоптимально. Давайте разберёмся, почему.
Что такое R²
Формула:
R² = 1 - (SS_res / SS_tot)
где:
SS_res = Σ(y_i - y_pred_i)² — сумма квадратов остатков
SS_tot = Σ(y_i - y_mean)² — общая сумма квадратов
R² показывает долю объяснённой дисперсии: какой процент вариации целевой переменной объясняет модель.
Почему R² не оптимальна как функция потерь
1. Зависимость от масштаба данных
R² зависит от y_mean (среднее значение целевой переменной), которое вычисляется по всему датасету. Это создаёт проблемы:
# Пример
y_true = [1, 2, 3, 4, 5]
y_pred = [1.1, 2.1, 2.9, 4.1, 4.9]
# R² = 0.98 (хорошо)
# Но если масштабировать данные
y_true_scaled = [100, 200, 300, 400, 500]
y_pred_scaled = [110, 210, 290, 410, 490]
# R² всё ещё = 0.98 (не изменилась!)
# Хотя абсолютная ошибка увеличилась в 100 раз
2. Сложность вычисления градиентов
У R² нелинейные и сложные зависимости через знаменатель (SS_tot). Вычисление градиентов:
# R² = 1 - SS_res / SS_tot
# dR²/dy_pred = -2(y_i - y_pred) / SS_tot + 2(y_i - y_pred)² * Σ(y - y_mean)² / SS_tot²
Это нестабильно и медленно конвергирует.
3. Отсутствие правильной инициализации
В начале обучения, когда модель даёт плохие предсказания, R² может быть даже отрицательным:
Если SS_res > SS_tot, то R² < 0
Оптимизатор может запутаться, какое направление улучшить.
4. Негладкое поведение
Функция R² не везде дифференцируема относительно y_pred. Небольшие изменения в предсказаниях могут привести к непропорциональным изменениям R².
Практическое сравнение
import numpy as np
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
import torch
import torch.optim as optim
# Данные
np.random.seed(42)
X = np.random.randn(100, 10)
y = 3 * X[:, 0] + 2 * X[:, 1] + np.random.randn(100) * 0.1
# Baseline: обучение с MSE (стандартный подход)
model_mse = LinearRegression()
model_mse.fit(X, y)
pred_mse = model_mse.predict(X)
r2_mse = r2_score(y, pred_mse) # ~0.995
# Попытка обучения с R² как loss
# (очень упрощённый пример, в реальности - ещё хуже)
def r2_loss(y_true, y_pred):
ss_res = torch.sum((y_true - y_pred)**2)
ss_tot = torch.sum((y_true - y_true.mean())**2)
r2 = 1 - (ss_res / ss_tot)
return -r2 # Минимизируем -R² (максимизируем R²)
# Обучение с R² обычно сложнее и медленнее сходится
Когда R² может быть полезна
1. Как вспомогательная функция потерь
Можно использовать взвешенную комбинацию:
# Multi-task learning
loss = mse_loss + 0.1 * (-r2_score) # Основной loss + штраф на R²
2. Для специфичных задач
Если вам критически важно именно объяснённая дисперсия (а не абсолютная ошибка), можно использовать, но обычно это не лучший вариант.
Правильный выбор функции потерь
Для регрессии:
| Функция потерь | Когда использовать |
|---|---|
| MSE/L2 | Стандартный выбор, гладкая, дифференцируемая |
| MAE/L1 | Устойчива к выбросам |
| Huber | Компромисс между MSE и MAE |
| Quantile | Если нужен конкретный квантиль |
| Custom loss | Если нужно штрафовать определённые типы ошибок |
Для оценки качества:
- R² — для интерпретации (доля объяснённой дисперсии)
- RMSE / MAE — для сравнения моделей
- MAPE — если нужны относительные ошибки
Итог
# ПРАВИЛЬНО: обучаем с MSE, оцениваем с R²
model = LinearRegression()
model.fit(X, y, loss='mse') # Обучение
metrics = {'r2': r2_score(y_val, y_pred), # Оценка
'rmse': np.sqrt(mean_squared_error(y_val, y_pred))}
# НЕПРАВИЛЬНО: обучаем с R²
model = LinearRegression()
model.fit(X, y, loss='r2') # Нестабильно, медленно конвергирует
Вывод: R² отлична как метрика оценки качества модели, но не подходит как функция потерь для оптимизации. Используйте MSE/MAE для обучения, а R² для оценки результатов.