无意中我注意到,sklearn
和statsmodels
实施的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包(statsmodels
和scikit-learn
)之间的差异,而链接的问题是关于statsmodels
和常见的R ^ 2定义。他们都用同样的答案回答,但这个问题在这里已经讨论过:Does the same answer imply that the questions should be closed as duplicate?
答案 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。