python - 为什么确定系数 R² 实现会产生不同的结果?
问题描述
在尝试实现用于计算决定系数 R² 的 python 函数时,我注意到根据我使用的计算顺序,我得到了截然不同的结果。
R² 上的维基百科页面对如何计算 R² 给出了看似非常清晰的解释。我对 wiki 页面上所说的内容的 numpy 解释如下:
def calcR2_wikipedia(y, yhat):
# Mean value of the observed data y.
y_mean = np.mean(y)
# Total sum of squares.
SS_tot = np.sum((y - y_mean)**2)
# Residual sum of squares.
SS_res = np.sum((y - yhat)**2)
# Coefficient of determination.
R2 = 1.0 - (SS_res / SS_tot)
return R2
当我使用目标向量y和模型估计向量yhat尝试此方法时,此函数产生 -0.00301 的 R² 值。
但是,从讨论如何计算 R²的这个 stackoverflow 帖子中接受的答案给出了以下定义:
def calcR2_stackOverflow(y, yhat):
SST = np.sum((y - np.mean(y))**2)
SSReg = np.sum((yhat - np.mean(y))**2)
R2 = SSReg/SST
return R2
使用与以前相同的y和yhat向量的方法,我现在得到 0.319 的 R²。
此外,在同一个 stackoverflow 帖子中,很多人似乎赞成使用 scipy 模块计算 R²,如下所示:
import scipy
slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(yhat, y)
R2 = r_value**2
在我的情况下产生0.261。
所以我的问题是:为什么从看似广为接受的来源产生的 R² 值彼此完全不同?计算两个向量之间的 R² 的正确方法是什么?
解决方案
定义
这是一种符号滥用,通常会导致误解。您正在比较两个不同的系数:
如果你仔细阅读维基百科页面上关于确定系数的介绍,你会看到那里有讨论,它的开头如下:
R2 有几个定义,它们只是有时是等价的。
MCVE
您可以确认这些分数的经典实现返回预期结果:
import numpy as np
import scipy
from sklearn import metrics
np.random.seed(12345)
x = np.linspace(-3, 3, 1001)
yh = np.polynomial.polynomial.polyval(x, [1, 2])
e = np.random.randn(x.size)
yn = yh + e
然后您的函数calcR2_wikipedia
( 0.9265536406736125
) 返回决定系数,可以确认它返回与sklearn.metrics.r2_score相同:
metrics.r2_score(yn, yh) # 0.9265536406736125
另一方面,scipy.stats.linregress返回相关系数(仅对线性回归有效):
slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(yh, yn)
r_value # 0.9625821384210018
您可以通过它的定义交叉确认:
C = np.cov(yh, yn)
C[1,0]/np.sqrt(C[0,0]*C[1,1]) # 0.9625821384210017
推荐阅读
- continuous-integration - 如何在不触发主分支的情况下在 bitbucket 的 2 个分支上测试作业?
- katacoda - 您如何避免登录新的 katacoda 场景
- tensorflow - 我有一个 hrnn 的名称和张量。无论如何我可以重建hrnn吗?
- asp.net - 使用 Asp.net Web 应用程序将 JWT 令牌存储在 Redis 缓存中
- datagrid - 在数据网格中隐藏/显示列:列不会自动调整大小
- javascript - JavaScript中带有嵌套while循环的无限for循环
- git - WSL1 上的 VSCode 未检测到 git repo
- python - 使用 mpiexec 时在 python 中向 .csv 文件添加行
- javascript - Highcharts Gantt - 如何为里程碑标记使用不同的形状?
- html - 粘性侧栏组件不会粘在顶部 - React + SCSS