Вопрос или проблема
У меня есть набор данных с 10 столбцами и 158 строками. Я пытаюсь предсказать мой тестовый набор данных, который состоит из 1 столбца и 158 строк.
Я провел кросс-валидации, поиск по сетке и использовал алгоритм ElasticNet.
Также перед оценкой модели я проверяю коэффициент корреляции Пирсона между 10 столбцами, которые я использовал для тренировки, и другим 1 столбцом, который пытаюсь предсказать. Корреляция не хорошая, но когда я оцениваю модель, коэффициент R^2 близок к 0.98.
Как я могу убедиться, что этот результат достоверен? Потому что я не ожидал R^2 такого уровня. Это слишком высоко, чем я ожидал.
Спасибо заранее.
$ R^2 $ показывает, какая вариация вашей целевой переменной описывается независимыми переменными. Таким образом, их синергетический эффект может дать вам более хороший ответ, чем их корреляция. Лучше использовать $ R^2 $ с поправкой. Посмотрите на p-значения ваших переменных и подумайте о их реальной корреляции. Важны ли они в реальной жизни. Если у них есть какая-либо адекватная взаимосвязь, значит, ваша регрессия правильная.
Надеюсь, это поможет.
Попробуйте диагностику регрессии. Существует несколько методов, которые помогут вам лучше понять данные и модель. Попробуйте эту ссылку, перейдите на вкладку ресурсов и загрузите главу 6 – Диагностика проблем в линейных и обобщенных линейных моделях. Код написан на R. Однако вы можете найти эквивалент кода на Python.
Совместив следующее в вашем подходе, вы получите большее понимание о том, действительно ли ваш высокий $R²$ отражает хорошую модель или может вводить в заблуждение из-за факторов, таких как переобучение или несущественные признаки.
- Скорректированный $R²$ @Виталий Радченко предложил: Этот показатель поможет вам судить, не переобучается ли модель (если скорректированный $R²$ намного ниже обычного $R²$).
- p-значения: Проверяя p-значения ваших переменных, вы можете определить, являются ли признаки статистически значимыми или же они могут быть избыточными.
- Кросс-валидация: Этот процесс обеспечивает стабильную производительность модели на разных разбиениях данных, снижая риск переобучения.
import numpy as np
import pandas as pd
from sklearn.linear_model import ElasticNet, LinearRegression
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.metrics import r2_score
from sklearn.preprocessing import StandardScaler
import statsmodels.api as sm
import matplotlib.pyplot as plt
# Генерация примера набора данных (подкорректируйте под свой набор данных)
np.random.seed(42)
X = np.random.randn(158, 10) # 158 строк, 10 признаков
y = np.random.randn(158) # 158 строк, 1 целевая переменная
# Масштабирование признаков (важно для таких моделей, как ElasticNet)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Разделение на обучающую и тестовую выборки (вы также можете использовать кросс-валидацию напрямую)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# Определение модели ElasticNet
elasticnet = ElasticNet()
# Поиск по сетке для нахождения лучшего alpha и l1_ratio
param_grid = {'alpha': np.logspace(-3, 3, 7), 'l1_ratio': [0.1, 0.5, 0.9, 1]}
grid_search = GridSearchCV(elasticnet, param_grid, cv=5)
grid_search.fit(X_train, y_train)
# Лучшие параметры из поиска по сетке
print("Лучшие параметры из поиска по сетке:", grid_search.best_params_)
# Лучшая модель ElasticNet из поиска по сетке
best_model = grid_search.best_estimator_
# Оценка модели с помощью R²
y_pred = best_model.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"Коэффициент R² для тестовых данных: {r2}")
# Кросс-валидация для проверки стабильности
cv_scores = cross_val_score(best_model, X_scaled, y, cv=5, scoring='r2')
print(f"Кросс-валидированные R² оценки: {cv_scores}")
print(f"Средний R² по.foldам: {cv_scores.mean()}")
# Расчет скорректированного R²:
def adjusted_r2(r2, n, p):
"""Рассчитать скорректированный R²."""
return 1 - (1 - r2) * (n - 1) / (n - p - 1)
# Для расчета скорректированного R² нам нужно количество образцов (n) и признаков (p)
n = X_train.shape[0] # Количество образцов
p = X_train.shape[1] # Количество предикторов (признаков)
# Рассчитать скорректированный R²
adj_r2 = adjusted_r2(r2, n, p)
print(f"Скорректированный R²: {adj_r2}")
# Линейная регрессия для p-значений и дальнейшей диагностики
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
# Statsmodels для p-значений и резюме
X_train_with_const = sm.add_constant(X_train) # Добавить константу (перехват) для statsmodels
ols_model = sm.OLS(y_train, X_train_with_const).fit() # Подогнать модель
print(ols_model.summary()) # Печать резюме с p-значениями
вывод:
Лучшие параметры из поиска по сетке: {'alpha': 1.0, 'l1_ratio': 0.5}
Коэффициент R² для тестовых данных: -0.07902976206610557
Кросс-валидыционные R² оценки: [-0.10721625 -0.04982327 -0.00557496 -0.03379733 -0.01112718]
Средний R² по.foldам: -0.04150779846765138
Скорректированный R²: -0.17285843702837567
Результаты регрессии OLS
==============================================================================
Зависимая переменная: y R-квадрат: 0.057
Модель: OLS Скорректированный R-квадрат: -0.025
Метод: Метод наименьших квадратов F-статистика: 0.6946
Дата: Сб, 14 дек 2024 Вероятность (F-статистика): 0.728
Время: 04:07:21 Логарифм вероятности: -173.30
Количество наблюдений: 126 AIC: 368.6
Df Остаточные: 115 BIC: 399.8
Df Модель: 10
Тип ковариации: nonrobust
==============================================================================
коэффициент std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 0.1671 0.090 1.861 0.065 -0.011 0.345
x1 0.1301 0.088 1.481 0.141 -0.044 0.304
x2 0.0163 0.088 0.185 0.853 -0.157 0.190
x3 -0.0853 0.095 -0.899 0.370 -0.273 0.103
x4 0.0140 0.092 0.153 0.879 -0.167 0.195
x5 0.0579 0.088 0.658 0.512 -0.117 0.232
x6 -0.0268 0.092 -0.290 0.773 -0.210 0.156
x7 -0.0656 0.093 -0.709 0.480 -0.249 0.118
x8 0.1584 0.089 1.776 0.078 -0.018 0.335
x9 -0.0209 0.093 -0.225 0.823 -0.205 0.164
x10 -0.0342 0.091 -0.376 0.708 -0.215 0.146
==============================================================================
Omnibus: 1.535 Durbin-Watson: 1.901
Prob(Omnibus): 0.464 Jarque-Bera (JB): 1.113
Скошенность: -0.027 Prob(JB): 0.573
Эксцесс: 3.457 Cond. No. 1.48
==============================================================================
в сгенерированных данных я не вижу особой разницы для модели elasticnet
, но модель OLS
может быть переобучена.
$$R²_{adj.elasticnet}: -0.17 < R²=-0.07$$
$$R²_{adj.OLS}: -0.025 << R²=0.057$$
Ответ или решение
Чтобы убедиться в надежности вашего коэффициента детерминации ( R^2 ), следуйте этим рекомендациям:
-
Понимание ( R^2 ): Коэффициент ( R^2 ) показывает, какую долю дисперсии зависимой переменной объясняют независимые переменные. Высокое значение ( R^2 ) может указывать на то, что ваша модель хорошо подгоняет данные, однако это не всегда гарантирует ее качество или применимость.
-
Использование скорректированного ( R^2 ): Как упоминалось, скорректированный ( R^2 ) дает более точное представление о качестве модели с учетом количества предикторов и объема выборки. Если значение скорректированного ( R^2 ) значительно ниже обычного ( R^2 ), это может быть признаком переобучения модели.
-
Анализ p-значений: Важно также проверить p-значения ваших предикторов. Они помогут определить, являются ли ваши независимые переменные статистически значимыми. Высокие p-значения (обычно выше 0.05) могут указывать на то, что предикторы не влияют на зависимую переменную, и их использование может вводить шум в модель.
-
Перекрестная проверка: Используйте перекрестную проверку для оценки стабильности модели. Это метод позволяет убедиться, что модель не основана на особенностях конкретной выборки данных. Конкретно, выполните k-кратную перекрестную проверку и оцените стабильные значения ( R^2 ).
-
Диагностика регрессии: Проведите регрессионную диагностику для выявления возможных проблем с моделью, таких как гетероскедастичность или мультиколлинеарность. Используйте такие визуализации, как остаточные графики и графики плотности, чтобы узнать, корректно ли модель описывает данные.
-
Проверка на переобучение: Высокий коэффициент ( R^2 ) может быть признаком переобучения, особенно если он значительно отличается на обучающем наборе данных и тестовой выборке. Убедитесь, что производительность вашей модели на тестовом наборе данных не оказывается значительно хуже.
-
Сравнение с другими моделями: Рассмотрите возможность использования разных моделей (например, линейной регрессии) для сравнения результатов. Это даст вам понимание того, насколько хорошо ваша модель ElasticNet справляется по сравнению с другими подходами.
Для примерного кода на Python, который включает предложенные шаги, вы можете использовать модель ElasticNet, а также добавить линейную регрессию для сравнения результатов. Смотрите ниже:
import numpy as np
import pandas as pd
from sklearn.linear_model import ElasticNet, LinearRegression
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.metrics import r2_score
from sklearn.preprocessing import StandardScaler
import statsmodels.api as sm
# Пример генерации данных
np.random.seed(42)
X = np.random.randn(158, 10) # 158 строк, 10 признаков
y = np.random.randn(158) # 158 строк, 1 целевая переменная
# Масштабируем признаки
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# Настройка модели ElasticNet
elasticnet = ElasticNet()
param_grid = {'alpha': np.logspace(-3, 3, 7), 'l1_ratio': [0.1, 0.5, 0.9, 1]}
grid_search = GridSearchCV(elasticnet, param_grid, cv=5)
grid_search.fit(X_train, y_train)
# Результаты и оценка модели
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"R² на тестовых данных: {r2}")
# Перекрестная проверка
cv_scores = cross_val_score(best_model, X_scaled, y, cv=5, scoring='r2')
print(f"Перекрестная проверка R²: {cv_scores.mean()}")
# Расчет скорректированного R²
n = X_train.shape[0]
p = X_train.shape[1]
adj_r2 = 1 - (1 - r2) * (n - 1) / (n - p - 1)
print(f"Скорректированный R²: {adj_r2}")
# Модель OLS для диагностики
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
X_train_with_const = sm.add_constant(X_train) # Добавление константы
ols_model = sm.OLS(y_train, X_train_with_const).fit()
print(ols_model.summary())
В результате выполнения данного кода вы получите информацию о вашей модели и ее надежности, что поможет вам сделать обоснованный вывод о ваших результатах.