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

时间:2018-02-16 18:35:33

标签: python python-3.x scikit-learn linear-regression statsmodels

无意中我注意到,sklearnstatsmodels实施的OLS模型在不适合拦截时会产生不同的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__)

打印:

0.78741906105 0.78741906105
-0.950825182861 0.783154483028
0.19.1 0.8.0

差异来自哪里?

问题与Different Linear Regression Coefficients with statsmodels and sklearn不同,因为sklearn.linear_model.LinearModel(带截距)适合为statsmodels.api.OLS准备的X.

问题不同于 Statsmodels: Calculate fitted values and R squared 因为它解决了两个Python包(statsmodelsscikit-learn)之间的差异,而链接的问题是关于statsmodels和常见的R ^ 2定义。他们都用同样的答案回答,但这个问题在这里已经讨论过:Does the same answer imply that the questions should be closed as duplicate?

1 个答案:

答案 0 :(得分:0)

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

来自documentation of RegressionResults class(强调我的):

  

rsquared

     
    

带截距的模型的R平方。这在这里定义为1 -     ssr / centered_tss如果常量包含在模型中且 1 -     ssr / uncentered_tss如果省略常量

  

来自documentation of LinearRegression.score()

  

得分(X,y,sample_weight =无)

     
    

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

         

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

         

平方和((y_true - y_pred)** 2).sum()和v是总和     of square((y_true - y_true.mean())** 2).sum()。最好的     得分为1.0,它可以是负数(因为模型可以是     任意恶化)。一个始终预测预期的常数模型     y的值,忽略输入特征,得到R ^ 2得分     0.0。