Как я могу убедиться в своем значении R^2?

Вопрос или проблема

У меня есть набор данных с 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 ), следуйте этим рекомендациям:

  1. Понимание ( R^2 ): Коэффициент ( R^2 ) показывает, какую долю дисперсии зависимой переменной объясняют независимые переменные. Высокое значение ( R^2 ) может указывать на то, что ваша модель хорошо подгоняет данные, однако это не всегда гарантирует ее качество или применимость.

  2. Использование скорректированного ( R^2 ): Как упоминалось, скорректированный ( R^2 ) дает более точное представление о качестве модели с учетом количества предикторов и объема выборки. Если значение скорректированного ( R^2 ) значительно ниже обычного ( R^2 ), это может быть признаком переобучения модели.

  3. Анализ p-значений: Важно также проверить p-значения ваших предикторов. Они помогут определить, являются ли ваши независимые переменные статистически значимыми. Высокие p-значения (обычно выше 0.05) могут указывать на то, что предикторы не влияют на зависимую переменную, и их использование может вводить шум в модель.

  4. Перекрестная проверка: Используйте перекрестную проверку для оценки стабильности модели. Это метод позволяет убедиться, что модель не основана на особенностях конкретной выборки данных. Конкретно, выполните k-кратную перекрестную проверку и оцените стабильные значения ( R^2 ).

  5. Диагностика регрессии: Проведите регрессионную диагностику для выявления возможных проблем с моделью, таких как гетероскедастичность или мультиколлинеарность. Используйте такие визуализации, как остаточные графики и графики плотности, чтобы узнать, корректно ли модель описывает данные.

  6. Проверка на переобучение: Высокий коэффициент ( R^2 ) может быть признаком переобучения, особенно если он значительно отличается на обучающем наборе данных и тестовой выборке. Убедитесь, что производительность вашей модели на тестовом наборе данных не оказывается значительно хуже.

  7. Сравнение с другими моделями: Рассмотрите возможность использования разных моделей (например, линейной регрессии) для сравнения результатов. Это даст вам понимание того, насколько хорошо ваша модель 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())

В результате выполнения данного кода вы получите информацию о вашей модели и ее надежности, что поможет вам сделать обоснованный вывод о ваших результатах.

Оцените материал
Добавить комментарий

Капча загружается...