Как посчитать adjusted R² в SQL
Содержание:
Зачем adjusted R2
R² растёт каждый раз, когда вы добавляете предиктор — даже если он мусорный. Это inflates ощущение «модель улучшилась». Adjusted R² корректирует на количество фичей: модель с большим количеством бесполезных переменных имеет более низкий adjusted R², даже если R² растёт.
Формула
adj_R² = 1 − (1 − R²) × (n − 1) / (n − p − 1)n— число наблюденийp— число предикторов (не считая intercept)
Если p = 0, adj_R² = R². Если p растёт без полезных эффектов, adj_R² падает.
Adjusted R2 в SQL
WITH stats AS (
SELECT
REGR_R2(y, x) AS r2,
COUNT(*) AS n,
1 AS p -- bivariate: только 1 predictor
FROM training_data
)
SELECT
r2,
n,
p,
1 - (1 - r2) * (n - 1)::NUMERIC / NULLIF(n - p - 1, 0) AS adjusted_r2
FROM stats;Для multivariate REGR_R2 не подходит — нужна Python. Но если есть готовый R² для multi-X модели:
WITH config AS (
SELECT 0.78 AS r2_multi, 500 AS n, 5 AS p
)
SELECT
r2_multi,
1 - (1 - r2_multi) * (n - 1)::NUMERIC / NULLIF(n - p - 1, 0) AS adjusted_r2
FROM config;Сравнение моделей
Удобно держать таблицу с метриками всех протестированных моделей:
SELECT
model_name,
r2,
n_predictors,
n_observations,
1 - (1 - r2) * (n_observations - 1)::NUMERIC
/ NULLIF(n_observations - n_predictors - 1, 0) AS adjusted_r2
FROM model_comparison
ORDER BY adjusted_r2 DESC;Модель с adj_R² 0.65 и 3 фичами лучше, чем модель с adj_R² 0.62 и 10 фичами — даже если её raw R² ниже.
R2 vs adjusted vs penalty
WITH versions AS (
SELECT
'simple' AS name, 0.50 AS r2, 100 AS n, 1 AS p
UNION ALL SELECT 'medium', 0.62, 100, 4
UNION ALL SELECT 'complex_useful', 0.75, 100, 8
UNION ALL SELECT 'overfit', 0.85, 100, 30
)
SELECT
name,
r2,
p,
1 - (1 - r2) * (n - 1)::NUMERIC / NULLIF(n - p - 1, 0) AS adj_r2,
r2 - (1 - (1 - r2) * (n - 1)::NUMERIC / NULLIF(n - p - 1, 0)) AS penalty
FROM versions
ORDER BY adj_r2 DESC;«Overfit» model с R² 0.85 и 30 предикторами имеет penalty 0.07 — adj_R² ≈ 0.78. Это всё ещё выше других, но если убрать 10 «случайных» предикторов и R² падает на 0.05 — penalty снизится больше.
Частые ошибки
Ошибка 1. n − p − 1 = 0. При p = n − 1 знаменатель = 0. Это «насыщенная» модель — все степени свободы исчерпаны. NULLIF лечит.
Ошибка 2. p включает intercept. В формуле p — число предикторов БЕЗ intercept. Если у вас 5 фичей + bias, p = 5, не 6.
Ошибка 3. Сравнивать adj_R² с разными samples. Adj_R² валиден для one dataset с разными моделями. Между samples — не очень.
Ошибка 4. Adj_R² < 0. Возможно, если модель хуже базовой (predicting mean). Сигнал, что что-то очень плохо.
Ошибка 5. Только adj_R² без cross-validation. Adj_R² на train не гарантирует generalization. Test R² + adj_R² оба.
Связанные темы
- Как посчитать r2 в SQL
- Как посчитать linear regression в SQL
- Как посчитать residuals в SQL
- Как посчитать correlation в SQL
FAQ
Adj R² < R²?
Да, всегда. Поправка вычитает penalty за предикторы.
Какой adj R² хороший?
Не отличается от R²: 0.5+ заметный сигнал, 0.7+ сильный.
Adjusted R² и BIC?
BIC жёстче штрафует за p. Используют для model selection.
Adjusted R² для logistic?
Pseudo-R² (McFadden, Cox-Snell) — другая концепция.
Можно ли adj R² для feature selection?
Можно. Stepwise — выбирают модель с максимальным adj_R².