为何Statsmodels OLS与Numpy矩阵代数OLS结果不一致?
为什么手动Numpy矩阵OLS与Statsmodels OLS结果不一致?
一、示例中X.T@X不可逆的原因
你的示例数据里,X的第二列是第一列的2倍(X[:,1] = 2 * X[:,0]),这意味着X的列存在完全多重共线性,导致X.T@X成为奇异矩阵,无法求逆。
而Statsmodels的OLS遇到完全共线性时,会自动识别并丢弃冗余自变量(比如示例中的第二列),因此能正常输出系数。你可以通过results.model.exog_names查看哪些变量被保留。
二、实际数据中系数差异显著的常见原因
1. 截距项处理不一致
Statsmodels的sm.OLS(y, X)默认不会自动添加截距项,只有通过sm.add_constant(X)给X加上常数列后,才会拟合截距。如果手动计算和Statsmodels在截距项的处理上不一致,结果必然不同:
- 若手动方法没加常数列,但Statsmodels加了;
- 或手动加了常数列,Statsmodels没加;
要让两者结果一致,需保持截距处理统一:
无截距的一致写法
# Numpy手动计算 coeff_np = np.linalg.inv(X.T@X)@X.T@y # Statsmodels model = sm.OLS(y, X) results = model.fit() coeff_sm = results.params
带截距的一致写法
# Numpy手动计算(添加常数列) X_with_const = np.hstack([np.ones((X.shape[0], 1)), X]) coeff_np = np.linalg.inv(X_with_const.T@X_with_const)@X_with_const.T@y # Statsmodels(添加常数列) X_with_const = sm.add_constant(X) model = sm.OLS(y, X_with_const) results = model.fit() coeff_sm = results.params
2. 数值稳定性差异
直接用np.linalg.inv(X.T@X)@X.T@y计算OLS系数的数值稳定性极差,尤其是当X.T@X的条件数很大(即自变量存在近似共线性)时,求逆操作会放大计算误差,导致结果偏离真实值。
Statsmodels内部采用QR分解或**奇异值分解(SVD)**求解OLS,这些方法在数值稳定性上远优于直接求逆,能有效降低近似共线性带来的误差。
如果想用Numpy实现更稳定的OLS计算,推荐使用np.linalg.lstsq(内部同样基于QR/SVD),结果会和Statsmodels更接近:
coeff_np, _, _, _ = np.linalg.lstsq(X, y, rcond=None)
3. 其他潜在因素
- 数据预处理差异:手动方法和Statsmodels是否对数据做了相同的标准化、中心化处理;
- 缺失值/异常值:Statsmodels默认会处理缺失值,而手动方法需自行处理,若数据存在缺失值但处理不一致,会导致结果差异;
- 权重设置:若Statsmodels中指定了
weights参数,而手动方法未考虑权重,结果也会不同。
内容的提问来源于stack exchange,提问作者firstname
相关产品推荐
相关产品推荐

