为什么确定系数 R² 的实施会产生不同的结果?
Why do coefficient of determination, R², implementations produce different results?
在尝试实现 python 计算决定系数 R² 的函数时,我注意到我得到的结果截然不同,具体取决于我使用的计算顺序。
wikipedia page on R² 对如何计算 R² 给出了看似非常清晰的解释。我对维基页面上所说内容的 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 尝试此方法时,此函数生成的 R² 值为-0.00301.
但是,this Whosebug post discussing how to calculate R² 接受的答案给出了以下定义:
def calcR2_Whosebug(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²。
此外,在同一个 Whosebug post 中,很多人似乎赞成使用 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² 的正确方法是什么?
定义
这是一种经常导致误解的符号滥用。您正在比较两个不同的系数:
- Coefficient of determination(通常表示为
R^2
),它不仅可以用于线性回归,还可以用于任何 OLS 回归(OLS 是关于拟合参数而不是函数本身的线性);
- Pearson Correlation Coefficient(平方时通常记为
r
或 r^2
)仅用于线性回归。
如果你仔细阅读维基百科页面上的决定系数的介绍,你会看到那里有讨论,它开始如下:
There are several definitions of R2 that are only sometimes
equivalent.
MCVE
您可以确认这些分数的经典实施 return 预期结果:
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
)returns的决定系数,可以确认return和[=22=一样]:
metrics.r2_score(yn, yh) # 0.9265536406736125
另一方面 scipy.stats.linregress return 的相关系数(仅对线性回归有效):
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
在尝试实现 python 计算决定系数 R² 的函数时,我注意到我得到的结果截然不同,具体取决于我使用的计算顺序。
wikipedia page on R² 对如何计算 R² 给出了看似非常清晰的解释。我对维基页面上所说内容的 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 尝试此方法时,此函数生成的 R² 值为-0.00301.
但是,this Whosebug post discussing how to calculate R² 接受的答案给出了以下定义:
def calcR2_Whosebug(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²。
此外,在同一个 Whosebug post 中,很多人似乎赞成使用 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² 的正确方法是什么?
定义
这是一种经常导致误解的符号滥用。您正在比较两个不同的系数:
- Coefficient of determination(通常表示为
R^2
),它不仅可以用于线性回归,还可以用于任何 OLS 回归(OLS 是关于拟合参数而不是函数本身的线性); - Pearson Correlation Coefficient(平方时通常记为
r
或r^2
)仅用于线性回归。
如果你仔细阅读维基百科页面上的决定系数的介绍,你会看到那里有讨论,它开始如下:
There are several definitions of R2 that are only sometimes equivalent.
MCVE
您可以确认这些分数的经典实施 return 预期结果:
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
)returns的决定系数,可以确认return和[=22=一样]:
metrics.r2_score(yn, yh) # 0.9265536406736125
另一方面 scipy.stats.linregress return 的相关系数(仅对线性回归有效):
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