使用scipy.stats和statsmodels计算线性回归时结果不同

5 投票
2 回答
3409 浏览
提问于 2025-04-18 08:21

我在用这两个库进行普通最小二乘法(OLS)拟合时,得到了不同的r^2值(决定系数),我搞不清楚为什么会这样。(为了方便你,去掉了一些空格)

In [1]: import pandas as pd       
In [2]: import numpy as np
In [3]: import statsmodels.api as sm
In [4]: import scipy.stats
In [5]: np.random.seed(100)
In [6]: x = np.linspace(0, 10, 100) + 5*np.random.randn(100)
In [7]: y = np.arange(100)

In [8]: slope, intercept, r, p, std_err = scipy.stats.linregress(x, y)

In [9]: r**2
Out[9]: 0.22045988449873671

In [10]: model = sm.OLS(y, x)
In [11]: est = model.fit()

In [12]: est.rsquared
Out[12]: 0.5327910685035413

这是怎么回事呢?我真搞不明白!是不是哪里出错了?

2 个回答

3

这不是对原问题的回答,因为原问题已经有了答案。

关于没有常数项的回归中的R平方。

一个问题是,没有截距的回归没有R平方的标准定义。

简单来说,R平方是用来衡量模型拟合效果的一个指标。在有截距的模型中,R平方是通过比较完整模型和只有截距的模型来计算的。如果完整模型没有截距,那么R平方的标准定义可能会产生一些奇怪的结果,比如负的R平方。

在没有常数项的回归中,传统的定义是用因变量的总平方和来计算,而不是用去掉均值后的平方和。因此,有常数项和没有常数项的回归之间的R平方不能进行有意义的比较。

例如,关于如何在没有常数项的回归中“正确”处理R平方的问题,触发了statsmodels的变化:https://github.com/statsmodels/statsmodels/issues/785

1

0.2205这个数字来自一个模型,这个模型里还有一个截距项——如果去掉这个截距,结果就是0.5328。

简单来说,一个软件包是在做y = bx的模型,而另一个软件包(很贴心地)假设你还想要一个截距项,也就是y = a + bx
【注意:这样做的好处是,如果不加这个假设,每次你想做回归分析的时候,就得把x和一列全是1的数字绑定在一起,否则模型可能会有偏差。】

想了解更多,可以看看这篇文章,里面有更详细的讨论。

祝你好运!

撰写回答