使用WLS时statsmodels与自定义计算的R²值存在显著差异的问题
解决WLS模型下statsmodels与自定义R²差异的问题
嘿,这个问题我之前踩过坑!核心原因是statsmodels中WLS模型的R²计算采用了加权逻辑,而你的自定义函数大概率沿用了OLS的无权重公式,这就是两者结果差异极大的根源。
为什么会有差异?
- OLS的R²逻辑:我们常用的公式是
1 - (SS_res / SS_tot),其中SS_res是普通残差平方和,SS_tot是总离均差平方和(以样本均值为基准)。这时候自定义函数和statsmodels的计算逻辑完全一致,结果自然相同。 - WLS的R²逻辑:statsmodels默认计算的是加权版本的R²,它会用你指定的权重分别对残差和总平方和进行加权:
- 加权残差平方和:
sum(w * (y - y_pred)²) - 加权总平方和:
sum(w * (y - y_mean_weighted)²),这里的y_mean_weighted是加权均值,计算公式为sum(w*y)/sum(w)
- 加权残差平方和:
- 如果你自定义的函数还是直接计算无权重的
1 - (sum((y-y_pred)²)/sum((y-y_mean)²)),结果肯定和statsmodels的加权R²差很多。
修正自定义函数的示例代码
下面是一段可以和statsmodels结果对齐的自定义加权R²计算代码:
import statsmodels.api as sm import numpy as np # 模拟测试数据 np.random.seed(42) x = np.random.rand(100) y = 2*x + np.random.randn(100)*0.5 weights = np.random.rand(100)*2 + 0.5 # 生成随机权重 # 拟合WLS模型 X = sm.add_constant(x) wls_model = sm.WLS(y, X, weights=weights).fit() print("statsmodels WLS R²:", wls_model.rsquared) # 自定义加权R²计算函数 def weighted_r2(y_true, y_pred, weights): # 计算加权均值 y_weighted_mean = np.sum(weights * y_true) / np.sum(weights) # 加权残差平方和 ss_res_weighted = np.sum(weights * (y_true - y_pred)**2) # 加权总平方和 ss_tot_weighted = np.sum(weights * (y_true - y_weighted_mean)**2) return 1 - (ss_res_weighted / ss_tot_weighted) # 验证自定义结果 y_pred_wls = wls_model.predict(X) custom_r2 = weighted_r2(y, y_pred_wls, weights) print("自定义加权R²:", custom_r2)
运行这段代码后,你会发现两个R²结果完全一致。
额外注意事项
- statsmodels的WLS结果中还提供了
rsquared_adj(调整后加权R²),计算逻辑也是基于加权平方和的。 - 如果你非要计算无权重的R²,可以手动用OLS的公式,但这违背了加权回归的初衷——加权回归就是为了让权重高的样本对模型拟合产生更大影响,对应的R²也应该采用加权逻辑才有意义。
内容的提问来源于stack exchange,提问作者elvisching
相关产品推荐
相关产品推荐

