Возможно, реальная проблема в таких случаях - убедиться, что вы сравниваете яблоки с яблоками.А в вашем случае кажется, что нет.Нашим лучшим другом всегда является соответствующая документация в сочетании с простыми экспериментами.Итак ...
Хотя LinearRegression()
(т. Е. Ваш 1-й квадрат R) Scikit-learn по умолчанию установлен на fit_intercept=True
( документы ), это не случай со статсмоделями 'OLS
(ваш 2-й R-квадрат);цитирование из документов :
Перехват не включен по умолчанию и должен быть добавлен пользователем.См. statsmodels.tools.add_constant
.
Имея в виду эту важную деталь, давайте проведем несколько простых экспериментов с фиктивными данными:
import numpy as np
import statsmodels.api as sm
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
# dummy data:
y = np.array([1,3,4,5,2,3,4])
X = np.array(range(1,8)).reshape(-1,1) # reshape to column
# scikit-learn:
lr = LinearRegression()
lr.fit(X,y)
# LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,
# normalize=False)
lr.score(X,y)
# 0.16118421052631582
y_pred=lr.predict(X)
r2_score(y, y_pred)
# 0.16118421052631582
# statsmodels
# first artificially add intercept to X, as advised in the docs:
X_ = sm.add_constant(X)
model = sm.OLS(y,X_) # X_ here
results = model.fit()
results.rsquared
# 0.16118421052631593
Для всех практических целей эти два значения R-Квадрат, полученный с помощью scikit-learn и statsmodels, идентичен .
Давайте сделаем еще один шаг и попробуем модель scikit-learn без перехвата, но где мы используем искусственно «перехваченные» данные X_
мы уже построили для использования со statsmodels:
lr2 = LinearRegression(fit_intercept=False)
lr2.fit(X_,y) # X_ here
# LinearRegression(copy_X=True, fit_intercept=False, n_jobs=None,
# normalize=False)
lr2.score(X_, y)
# 0.16118421052631593
y_pred2 = lr2.predict(X_)
r2_score(y, y_pred2)
# 0.16118421052631593
Опять R-квадрат идентичен с предыдущими значениями.
Итак, что происходит, когдамы «случайно» забываем учесть тот факт, что statsmodels OLS
устанавливается без перехвата?Давайте посмотрим:
model3 = sm.OLS(y,X) # X here, i.e. no intercept
results3 = model2.fit()
results3.rsquared
# 0.8058035714285714
Ну, R-квадрат 0,80 действительно очень далек от значения 0,16, возвращаемого моделью с перехватом, и, возможно, это именно то, что имеетслучилось в вашем случае.
Пока все хорошо, и я мог бы легко закончить ответ здесь;но действительно существует момент, когда этот гармоничный мир рушится: давайте посмотрим, что произойдет, когда мы подгоним обе модели без перехвата и с исходными данными X
, где мы не добавили искусственно никакого перехвата.Мы уже установили модель OLS
выше и получили R-квадрат 0,80;а как насчет аналогичной модели от scikit-learn?
# scikit-learn
lr3 = LinearRegression(fit_intercept=False)
lr3.fit(X,y) # X here
lr3.score(X,y)
# -0.4309210526315792
y_pred3 = lr3.predict(X)
r2_score(y, y_pred3)
# -0.4309210526315792
Упс ...!Какого черта ??
Кажется, что scikit-earn, когда вычисляет r2_score
, всегда предполагает перехват, либо явно в модели (fit_intercept=True
), либо неявно вданные (то, как мы создали X_
из X
выше, используя statsmodels 'add_constant
);Если немного покопаться в интернете, то вы увидите ветку Github (закрыта без исправления), где подтверждается, что ситуация действительно такая.
Позвольте мне уточнить, что расхождение, которое я описал выше, имеет ничего не имеет отношения к вашей проблеме: в вашем случае реальная проблема заключается в том, что вы фактически сравниваете яблоки (модель с перехватом) с апельсинами (модель без перехвата).
Итак, почему scikit-learn не только терпит неудачу в таком (по общему признанию edge ) случае, но даже когда факт возникает в проблеме Github, он фактически обрабатывается с равнодушным ?(Заметьте также, что разработчик ядра scikit-learn, отвечающий в вышеупомянутой ветке, случайно признает, что « Я не очень знаком со статистикой » ...).
Ответ идетнемного больше, чем проблемы кодирования, такие как те, о которых в основном говорит SO, но, возможно, здесь стоит немного остановиться.
Возможно, причина в том, что вся концепция R-квадрата на самом деле происходит непосредственно из мирастатистика, где акцент делается на интерпретативных моделях, и он мало используется в контексте машинного обучения, где акцент явно делается на прогнозирующих моделях;по крайней мере AFAIK, и помимо некоторых очень вводных курсов, я никогда (я имею в виду никогда ...) не видел проблемы прогнозирующего моделирования, где R-квадрат используется для любого вида оценки производительности;Также не случайно, что популярные машинные курсы , такие как Машинное обучение Эндрю Нг в Coursera, даже не удосужились об этом упомянуть.И, как отмечалось в ветке Github выше (выделение добавлено):
В частности, при использовании набора test мне немного неясно, что означает R ^ 2.
, с которым я, безусловно, согласен.
Что касается крайнего случая, рассмотренного выше (включать или не включать термин перехвата?), Я подозреваю, что это будет звучать действительно неуместно для современных практиков глубокого обучения, где эквивалентпересечение (параметры смещения) всегда включается по умолчанию в модели нейронной сети ...
См. принятый (и высоко оцененный) ответ в перекрестном утверждении вопроса Разница между statsmodel OLS и линейной регрессией scikit для более подробного обсуждения в этих последних строках ...