为啥 `sklearn` 和 `statsmodels` 的 OLS 回归实现给出不同的 R^2?
Posted
技术标签:
【中文标题】为啥 `sklearn` 和 `statsmodels` 的 OLS 回归实现给出不同的 R^2?【英文标题】:Why `sklearn` and `statsmodels` implementation of OLS regression give different R^2?为什么 `sklearn` 和 `statsmodels` 的 OLS 回归实现给出不同的 R^2? 【发布时间】:2018-07-27 17:25:25 【问题描述】:我偶然注意到,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.72... 与 0.78... 完全不同... 始终播种随机数据以获得可重复性:np.random.seed(###)
.
没有截距会改变 statsmodels 中 R2 的定义。见***.com/questions/29664471/… 和***.com/questions/24851787/…
@Parfait 同意了。在这种特殊情况下,我省略了种子,因为样本非常大,并且每次运行的结果都不同。但是为了正确起见,我更新了示例。
@user333700 你可以给出这个答案吗?我愿意接受。
【参考方案1】:
正如 cmets 中的 @user333700 所指出的,statsmodels
' 实现中 R^2 的 OLS 定义与 scikit-learn
's 中的不同。
来自documentation of RegressionResults
class(强调我的):
平方
具有截距的模型的 R 平方。这在这里定义为 1 - s-s-r/centered_tss 如果常量包含在模型中并且 1 - s-s-r/uncentered_tss 如果常量被省略.
来自documentation of LinearRegression.score()
:
score(X, y, sample_weight=None)
返回系数 确定预测的R^2。
系数R^2定义为(1 - u/v),其中u为残差
平方和 ((y_true - y_pred) ** 2).sum() 和 v 是总和 平方数 ((y_true - y_true.mean()) ** 2).sum()。最好的 score 是 1.0,它可以是负数(因为模型可以 任意更坏)。始终预测预期的常数模型 y 的值,忽略输入特征,将得到 R^2 分数 0.0.
【讨论】:
以上是关于为啥 `sklearn` 和 `statsmodels` 的 OLS 回归实现给出不同的 R^2?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 `sklearn` 和 `statsmodels` 的 OLS 回归实现给出不同的 R^2?
为啥 sklearn 和 numpy 不同意 PCA 的乘法分量?
为啥 auc 与 sklearn 和 R 的逻辑回归如此不同
为啥我在 python 的 sklearn 中使用管道和没有管道得到不同的值
为啥 CPU(使用 SKLearn)和 GPU(使用 RAPID)上的 RandomForestClassifier 获得不同的分数,非常不同?