为什么`sklearn`和`statsmodels`实现OLS回归会给出不同的R ^ 2?

abu*_*kaj 10 python linear-regression python-3.x scikit-learn statsmodels

我意外地注意到,当不适合拦截时,OLS模型由R ^ 2 实现sklearnstatsmodels产生不同的R ^ 2值.否则他们似乎工作正常.以下代码产生:

import numpy as np
import sklearn
import statsmodels
import sklearn.linear_model as sl
import statsmodels.api as sm

np.random.seed(42)

N=1000
X = np.random.normal(loc=1, size=(N, 1))
Y = 2 * X.flatten() + 4 + np.random.normal(size=N)

sklernIntercept=sl.LinearRegression(fit_intercept=True).fit(X, Y)
sklernNoIntercept=sl.LinearRegression(fit_intercept=False).fit(X, Y)
statsmodelsIntercept = sm.OLS(Y, sm.add_constant(X))
statsmodelsNoIntercept = sm.OLS(Y, X)

print(sklernIntercept.score(X, Y), statsmodelsIntercept.fit().rsquared)
print(sklernNoIntercept.score(X, Y), statsmodelsNoIntercept.fit().rsquared)

print(sklearn.__version__, statsmodels.__version__)
Run Code Online (Sandbox Code Playgroud)

打印:

0.78741906105 0.78741906105
-0.950825182861 0.783154483028
0.19.1 0.8.0
Run Code Online (Sandbox Code Playgroud)

差异来自哪里?

问题不同于不同的线性回归系数与statsmodels和sklearn,因为那里sklearn.linear_model.LinearModel(有截距)适合X准备的statsmodels.api.OLS.

问题不同于 Statsmodels:计算拟合值和R平方, 因为它解决了两个Python包(statsmodelsscikit-learn)之间的差异,而链接问题是关于statsmodels和常见的R ^ 2定义.他们都回答了相同的答案,但是这个问题在这里已经讨论过了:相同的答案是否意味着问题应该重复关闭?

abu*_*kaj 2

statsmodels正如 @user333700 在评论中指出的,R^2 的 OLS 定义在' 实现中与scikit-learn'中不同。

来自的文档RegressionResults(重点是我的):

平方

具有截距的模型的 R 平方。如果模型中包含常量,则此处定义为 1 - ssr/centered_tss;如果省略常量,则定义为 1 - ssr/uncentered_tss

来自文档LinearRegression.score()

分数(X,y,样本权重=无)

返回预测的确定系数 R^2。

系数 R^2 定义为 (1 - u/v),其中 u 是残差

平方和 ((y_true - y_pred) ** 2).sum() 和 v 是总平方和 ((y_true - y_true.mean()) ** 2).sum()。最好的可能分数是 1.0,它可以是负值(因为模型可以任意变差)。始终预测 y 期望值(不考虑输入特征)的常量模型将获得 0.0 的 R^2 分数。