SciKit Learn的R平方与Pearson相关系数的平方非常不同

4

我有两个类似于numpy数组的东西:

a = np.array([32.0, 25.97, 26.78, 35.85, 30.17, 29.87, 30.45, 31.93, 30.65, 35.49, 
              28.3, 35.24, 35.98, 38.84, 27.97, 26.98, 25.98, 34.53, 40.39, 36.3])

b = np.array([28.778585, 31.164268, 24.690865, 33.523693, 29.272448, 28.39742,
              28.950092, 29.701189, 29.179174, 30.94298 , 26.05434 , 31.793175,
              30.382706, 32.135723, 28.018875, 25.659306, 27.232124, 28.295502,
              33.081223, 30.312504])

当我使用SciKit Learn计算R-squared时,得到的值与我先计算Pearson相关系数再平方结果完全不同:
sk_r2 = sklearn.metrics.r2_score(a, b)
print('SciKit R2: {:0.5f}\n'.format(sk_r2))

pearson_r = scipy.stats.pearsonr(a, b)
print('Pearson R: ', pearson_r)
print('Pearson R squared: ', pearson_r[0]**2)

结果为:
SciKit R2:0.15913

Pearson R:(0.7617075766854164,9.534162339384296e-05)
Pearson R平方:0.5801984323799696

我意识到,对于拟合不良的模型,R平方值有时可能为负(https://stats.stackexchange.com/questions/12900/when-is-r-squared-negative),因此Pearson相关系数的平方并不总是等于R平方。然而,我认为对于正R平方值,它总是等于Pearson相关系数的平方?这些R平方值为什么如此不同?

2个回答

10
Pearson相关系数R和决定系数R平方是两个完全不同的统计量。
您可以参考以下网址: https://en.wikipedia.org/wiki/Pearson_correlation_coefficienthttps://en.wikipedia.org/wiki/Coefficient_of_determination

更新

Pearson相关系数r是衡量两个变量之间线性关系的统计量,其公式如下: enter image description here 其中bar xbar y分别为样本的均值。
而决定系数R2是衡量拟合优度的统计量,其公式如下: enter image description here 其中hat y为预测的y值,bar y为样本的均值。
因此,
  1. 它们衡量的是不同的东西
  2. r**2不等于R2,因为它们的公式完全不同

更新2

只有在用线性模型计算变量(如y)和预测变量hat y的Pearson相关系数r时,r**2才等于R2
我们可以使用您提供的两个数组来进行示例演示。
import numpy as np
import pandas as pd
import scipy.stats as sps
import statsmodels.api as sm
from sklearn.metrics import r2_score as R2
import matplotlib.pyplot as plt

a = np.array([32.0, 25.97, 26.78, 35.85, 30.17, 29.87, 30.45, 31.93, 30.65, 35.49, 
              28.3, 35.24, 35.98, 38.84, 27.97, 26.98, 25.98, 34.53, 40.39, 36.3])

b = np.array([28.778585, 31.164268, 24.690865, 33.523693, 29.272448, 28.39742,
              28.950092, 29.701189, 29.179174, 30.94298 , 26.05434 , 31.793175,
              30.382706, 32.135723, 28.018875, 25.659306, 27.232124, 28.295502,
              33.081223, 30.312504])

df = pd.DataFrame({
    'x': a,
    'y': b,
})

df.plot(x='x', y='y', marker='.', ls='none', legend=False);

在此输入图片描述

现在我们要拟合一个线性回归模型。

mod = sm.OLS.from_formula('y ~ x', data=df)
mod_fit = mod.fit()
print(mod_fit.summary())

输出

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.580
Model:                            OLS   Adj. R-squared:                  0.557
Method:                 Least Squares   F-statistic:                     24.88
Date:                Mon, 29 Mar 2021   Prob (F-statistic):           9.53e-05
Time:                        14:12:15   Log-Likelihood:                -36.562
No. Observations:                  20   AIC:                             77.12
Df Residuals:                      18   BIC:                             79.12
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     16.0814      2.689      5.979      0.000      10.431      21.732
x              0.4157      0.083      4.988      0.000       0.241       0.591
==============================================================================
Omnibus:                        6.882   Durbin-Watson:                   3.001
Prob(Omnibus):                  0.032   Jarque-Bera (JB):                4.363
Skew:                           0.872   Prob(JB):                        0.113
Kurtosis:                       4.481   Cond. No.                         245.
==============================================================================

计算r**2R2,我们可以看到在这种情况下它们是相等的。

predicted_y = mod_fit.predict(df.x)
print("R2 :", R2(df.y, predicted_y))
print("r^2:", sps.pearsonr(df.y, predicted_y)[0]**2)

输出

R2 : 0.5801984323799696
r^2: 0.5801984323799696

你做的 R2(df.x, df.y) 不可能等于我们计算的值,因为你使用了一个独立的 x 和因变量 y 之间拟合程度的度量。相反,我们用 y 和预测值的 y,同时使用 rR2


请仔细阅读问题。我并不是直接比较皮尔逊相关系数和R平方。我是在比较皮尔逊相关系数的平方(pearson_r[0]**2)与R平方。对于一个正的R平方值,这两者应该相等。 - daragh
我已经更新了答案,并附上了详细的解释。 - Max Pierini
这完全是不正确的。在只有一个预测变量的简单线性回归中,R2 = r2 = Corr(x,y)**2。请参考此链接:https://economictheoryblog.com/2014/11/05/proof/ - daragh
2
我解释得更详细了,希望现在清楚了 :-) - Max Pierini

2
我也曾经处于同样的情况。对我来说,当我将scikit-learn中的R平方与R caret包中计算的R平方进行比较时,就会出现这种情况。
R caret包中的R平方或者在你的情况下是在scipy.stats.pearsonr中,按定义是“Pearson R”的平方。它是一种相关性度量。请参阅其定义here(按定义可能介于零和1之间)。
然而,scikit-learn中的R平方是一种准确度度量,您可以在其user guide中查看其定义。(按定义可能介于-Inf和1之间)。
最重要的是,不要进行比较。它们是不同的度量。

请仔细阅读问题。我并不是直接比较皮尔逊相关系数和R平方。我是在比较皮尔逊相关系数的平方(pearson_r[0]**2)与R平方。对于一个正的R平方值,这两者应该相等。 - daragh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接