为什么 statsmodels.api.OLS 会过度报告 r 平方值?

机器算法验证 多重回归 scikit-学习 r平方 统计模型
2022-03-13 01:07:32

statsmodels.api.OLS用来拟合具有 4 个输入特征的线性回归模型。

数据的形状是:

X_train.shape, y_train.shape  

Out[]: ((350, 4), (350,))

然后我拟合模型并以 3 种不同的方式计算 r 平方值:

import statsmodels.api as sm
import sklearn

ols = sm.OLS(y_train, X_train).fit()

y_pred = ols.predict(X_train)
res = y_train - y_pred

ss_tot = np.sum( (y_train - y_train.mean())**2 )
ss_res = np.sum( (y_train - y_pred)**2 )

(1 - ss_res/ss_tot), sklearn.metrics.r2_score(y_train, y_pred), ols.rsquared

Out[]: (0.91923900248372292, 0.91923900248372292, 0.99795455683297096)

手动计算的 r 平方值与来自的值sklearn.metrics.r2_score完全匹配。
然而,这个ols.rsquared价值似乎被高估了。

为什么会这样?如何statsmodels计算 rsquared 值?

1个回答

这在技术上并不是一个错误statsmodels而是因为默认情况下statsmodels.OLS不会将截距/常数项添加到回归方程的右侧——您必须明确添加它。相反,(以及绝大多数其他回归程序)默认添加常量/截距项,除非它被明确禁止。sklearn

要将截距项添加到statsmodels,请使用以下内容:

ols = sm.OLS(y_train, sm.add_constant(X_train)).fit()

省略截距的原因改变了R2这是一个不同的定义R2没有截距时使用。

我们可以查看平时R2作为两个模型 A 和 B 之间误差平方和的比例减少。

A: Yi=β0+β1Xi+ei
B: Yi=β0+ei
换句话说,我们比较了模型的性能,包括X作为预测器与仅预测所有观察值的恒定值(样本均值)的模型。

当拦截β0从模型 A 中省略以形成一个新模型 - 将其称为模型 C - 将其与简化模型 B 进行比较不再有意义(B 嵌套在 A 中,但未嵌套在 C 中)。所以我们改为调整计算R2因此可以将其视为 C 与新模型 D 之间的比较

C: Yi=β1Xi+ei
D: Yi=0+ei
换句话说,我们将仅斜率模型与仅对所有观测值进行恒定预测为 0 的模型进行比较。这常常自相矛盾地导致R2甚至比以前更高,但这只是因为简化的参考模型 D 在大多数应用程序中是荒谬的。

在以下主题中进一步讨论了此问题和相关问题:

去除统计上显着的截距项增加R2在线性模型中

当在线性回归中强制截距为 0 是可接受/可取的

什么时候可以删除线性回归模型中的截距?