"scikit-learn"的"r2_score"和R ^ 2计算之间存在显着的不匹配

Jua*_*oto 4 python numpy scikit-learn goodness-of-fit

为什么r2_scorescikit-learn中函数维基百科中描述的确定系数公式之间存在显着差异?哪个是正确的?


上下文

我正在使用Python 3.5来预测线性和二次模型,而我正在尝试的适合度的衡量标准之一是.但是,在测试时,维基百科中提供的r2_score指标scikit-learn与计算之间存在显着差异.


我在这里提供我的代码作为参考,它计算上面链接的维基百科页面中的示例.

from sklearn.metrics import r2_score
import numpy

y = [1, 2, 3, 4, 5]
f = [1.9, 3.7, 5.8, 8.0, 9.6]

# Convert to numpy array and ensure double precision to avoid single precision errors
observed = numpy.array(y, dtype=numpy.float64)
predicted = numpy.array(f, dtype=numpy.float64)

scipy_value = r2_score(observed, predicted)

>>> scipy_value: 

很明显,scipy计算值是-3.8699999999999992维基百科中的参考值0.998.

谢谢!

更新:这与关于如何在scikit-learn中计算R ^ 2的问题不同,我正在努力理解并澄清两种结果之间的差异.这个问题表明scikit中使用的公式与维基百科的公式相同,不应该导致不同的值.

更新#2:事实证明我在阅读维基百科文章的例子时犯了一个错误.下面的答案和评论提到我提供的示例是针对示例中(x,y)值的线性,最小二乘拟合.为此,维基百科的文章中的答案是正确的.为此,提供的R ^ 2 calue为0.998.对于两个向量之间的R ^ 2,scikit的答案也是正确的.非常感谢你的帮助!

Ran*_*ndy 6

引用的问题是正确的 - 如果您通过计算剩余的平方和和总平方和,则得到与sklearn相同的值:

In [85]: import numpy as np

In [86]: y = [1,2,3,4,5]

In [87]: f = [1.9, 3.7, 5.8, 8.0, 9.6]

In [88]: SSres = sum(map(lambda x: (x[0]-x[1])**2, zip(y, f)))

In [89]: SStot = sum([(x-np.mean(y))**2 for x in y])

In [90]: SSres, SStot
Out[90]: (48.699999999999996, 10.0)

In [91]: 1-(SSres/SStot)
Out[91]: -3.8699999999999992
Run Code Online (Sandbox Code Playgroud)

负值背后的想法是,如果你每次只预测平均值(这对应于r2 = 0),你就更接近实际值.

  • @JuanCarlosCoto没有,维基百科是正确的.维基百科文章指出,对于给定的`xy`数据拟合的线性最小二乘的"R ^ 2"是0.998.那里给出的数据不是'y`和`f`.请参阅我的回答. (2认同)

tmd*_*son 5

我认为您误解了维基百科。维基百科上的示例声明:

y=[1,2,3,4,5]
f=[1.9, 3.7, 5.8, 8.0, 9.6]
R^2 = 0.998
Run Code Online (Sandbox Code Playgroud)

相反,它表示R^2用于线性最小二乘法的拟合数据:

x=[1,2,3,4,5]
y=[1.9, 3.7, 5.8, 8.0, 9.6]
Run Code Online (Sandbox Code Playgroud)

等于 0.998

考虑一下此脚本,该脚本首先用于np.linalg.lstsq查找最小二乘拟合,然后使用这两种方法为这两种方法找到一个R^20.998的值:

import numpy as np
from sklearn.metrics import r2_score

x=np.arange(1,6,1)
y=np.array([1.9, 3.7, 5.8, 8.0, 9.6])

A=np.vstack([x, np.ones(len(x))]).T

# Use numpy's least squares function
m, c = np.linalg.lstsq(A, y)[0]

print m,c
# 1.97 -0.11

# Define the values of our least squares fit
f=m*x+c

print f
# [ 1.86  3.83  5.8   7.77  9.74]

# Calculate R^2 explicitly
yminusf2=(y-f)**2
sserr=sum(yminusf2)
mean=float(sum(y))/float(len(y))
yminusmean2=(y-mean)**2
sstot=sum(yminusmean2)
R2=1.-(sserr/sstot)

print R2
# 0.99766066838

# Use scikit
print r2_score(y,f)
# 0.99766066838

r2_score(y,f) == R2
# True
Run Code Online (Sandbox Code Playgroud)


Avi*_*ash 5

两种方法都使用相同的公式来计算 R 方。查看下面的代码:

    # Data
    X=np.array([1.9, 3.7, 5.8, 8.0, 9.6]).reshape(-1, 1)
    y=[1,2,3,4,5]

    # Import module
    from sklearn.linear_model import LinearRegression
    from sklearn.metrics import r2_score

    reg = LinearRegression().fit(X, y)

    # Predict the target variable
    y_pred=reg.predict(X)

    # R-Square fitness
    print('R-Square(metrics):', r2_score(y, y_pred))


    # R-Square using score method
    print('R-Sqaure(Score):',reg.score(X, y))
Run Code Online (Sandbox Code Playgroud)

输出: R 方(指标):0.9976606683804627 R 方(分数):0.9976606683804627