sklearn的r2_score结果异常?与scipy计算结果不符求助
R²评分结果异常:sklearn r2_score与scipy linregress结果差异问题
模型拟合时使用sklearn.metrics.r2_score评估效果,部分数据组合下结果完全不符合预期:
- 给定参考值数组
ref与预测值数组pred,执行r2_score(ref,pred)得到结果0.05284238826655385 - 散点图显示二者线性相关性较好,预期R²约为0.9
- 使用
scipy.stats.linregress计算得到的r_value平方为0.8811870529781631,结果更合理 - 部分数据组合下
r2_score结果正常,求问题原因并验证结果
相关代码
ref = [14.44600051978183, 17.561804553460263, 19.261334026375774, 20.39435367498611, 14.44600051978183,16.712039817002506,18.15663986898069,19.544588938528356,16.712039817002506, 17.84505946561285,18.97807911422319, 20.111098762833524, 17.84505946561285, 18.893102640577414, 19.82784385068094, 20.960863499291282, 17.76008299196707, 18.97807911422319, 20.05444778040301, 20.960863499291282, 18.12831437776543, 19.261334026375774, 20.39435367498611, 20.960863499291282, 20.111098762833524, 21.15914193779809, 22.0, 22.377138060054207] pred = [13.12751026871668,16.234099798737148, 17.787394563747384, 18.5640419462525, 12.66840124840515, 15.666343879932109, 17.16531519569559, 18.66428651145907, 15.077797524003781, 16.520456140882633, 17.963114757761485, 19.405773374640333, 15.850036327506684, 17.23415013712082, 18.61826394673496, 20.002377756349095, 15.423479959829821, 16.770344482005054, 18.117209004180285, 19.464073526355516, 15.423479959829821, 16.770344482005054, 18.117209004180285, 19.464073526355516, 16.770344482005054, 18.117209004180285, 19.464073526355516, 20.137505787443132] from sklearn.metrics import r2_score print(r2_score(ref,pred)) # 输出:0.05284238826655385 import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=[16,10]) ax.scatter(ref, pred) ax.plot((12,24),(12,24),linewidth=.25,color="grey") import scipy _, _, r_value, _, _ = scipy.stats.linregress(ref, pred) print(r_value**2) # 输出:0.8811870529781631
问题原因与验证
1. 两个指标的本质差异
- sklearn的r2_score:计算的是决定系数,公式为:
$$R^2 = 1 - \frac{\sum (y_{true} - y_{pred})^2}{\sum (y_{true} - \bar{y}_{true})^2}$$
衡量模型预测值对真实值变异的解释能力,当预测存在系统性偏差(比如整体偏低、截距错误)时,即使线性相关性强,残差平方和会接近总平方和,导致R²接近0。 - scipy linregress的r²:是皮尔逊相关系数的平方,仅衡量两个变量之间的线性相关程度,不关心预测值是否完美匹配真实值的绝对水平。
2. 针对当前数据的验证
手动计算决定系数,结果与sklearn一致:
import numpy as np ref_arr = np.array(ref) pred_arr = np.array(pred) ss_res = np.sum((ref_arr - pred_arr)**2) # 残差平方和 ss_tot = np.sum((ref_arr - ref_arr.mean())**2) # 总平方和 r2_manual = 1 - ss_res / ss_tot print(r2_manual) # 输出:0.05284238826655385
观察数据可见:预测值pred整体比参考值ref偏低,尤其是高值区间(比如ref的22、22.37对应pred的19.46、20.14),导致残差平方和大幅增加;而ref的数值分布相对集中,总平方和较小,最终使得决定系数R²接近0。但二者的线性趋势一致,所以皮尔逊相关系数的平方仍保持较高水平。
内容的提问来源于stack exchange,提问作者Hu gePanic
相关产品推荐
相关产品推荐

