【问题标题】:Why are my r^2 values so consistently negative?为什么我的 r^2 值一直是负数?
【发布时间】:2019-10-18 01:28:45
【问题描述】:

我不确定问题是出在我的回归估计模型上,还是出在我对 r^2 拟合度测量实际含义的理解上。我正在使用 scikit learn 和大约 11 个不同的回归估计器进行一个项目,以产生(粗略!)棒球幻想表现的预测。某些模型总是比其他模型表现更好(决策树回归和额外树回归产生最差的 r^2 分数,而 ElasticCV 和 LassoCV 产生最好的 r^2 分数,而且偶尔甚至可能是一个稍微正数!)。

如果一条水平线产生的 r^2 分数为 0,那么即使我所有的模型都毫无价值,并且实际上具有零预测值,并且完全随机地吐出数字,那么我不应该得到小的正数对于 r^2 有时,如果仅仅是出于愚蠢的运气?我使用的 11 个估计器中有 8 个,尽管在不同的数据集上运行了数百次,但从来没有为 r^2 产生过哪怕很小的正数。

我是否误解了 r^2 的工作原理?

我也没有在 sklearn 的 .score 函数中切换顺序。我已经仔细检查了很多次。当我以错误的方式放置 y_pred、y_true 的顺序时,它会产生非常负的 r^2 值(例如

事实确实如此,实际上让我更加困惑,这里的 r^2 是如何衡量适合度的,但我离题了...

## I don't know whether I'm supposed to include my df4 or even a
##sample, but suffice to say here is just a single row to show what
##kind of data we have.  It is all normalized and/or zscore'd
"""

>> print(df4.head(1))

        HomeAway  ParkFactor    Salary  HandedVs  Hand  oppoBullpen  \
Points                                                                       
3.0          1.0      -1.229 -0.122111       1.0          0.0     -0.90331   

        RibRunHistory  BibTibHistory  GrabBagHistory  oppoTotesRank  \
Points                                                                
3.0          0.964943       0.806874       -0.224993      -0.846859   

        oppoSwipesRank  oppoWalksRank      Temp    Precip  WindSpeed  \
Points                                                                 
3.0           -1.40371      -1.159115 -0.665324 -0.380048  -0.365671   

        WindDirection  oppoPositFantasy  oppoFantasy  
Points                                                
3.0          0.229944         -1.011505     0.919269  

"""



def ElasticNetValidation(df4):
    X = df4.values
    y = df4.index
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)

    ENTrain = ElasticNetCV(cv=20)
    ENTrain.fit(X_train, y_train)
    y_pred = ENTrain.predict(X_test)

    EN = ElasticNetCV(cv=20)
    ENModel = EN.fit(X, y)

    print('ElasticNet R^2: ' + str(r2_score(y_test, y_pred)))
    scores = cross_val_score(ENModel, X, y, cv=20)
    print("ElasticNet Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

    return ENModel

当我运行这个估计器以及我一直在试验的其他十个回归估计器时,我得到的 r2_score() 和 cross_val_score().mean() 几乎每次都显示负数。某些估计器总是产生甚至不接近于零的负分数(决策树回归器、额外树回归器)。某些估计器表现得更好,甚至有时会产生一个很小的正分数,尽管从不超过 0.01,甚至那些估计器(elasticCV、lassoCV、linearRegression)大多数时候都是负数,尽管只是略微负数。

即使我正在构建的这些模型很糟糕。假设它们是完全随机的,并且在涉及目标时没有任何预测能力:它不应该比普通水平线预测得​​更好吗?为什么一个不相关的模型预测比水平线更差?

【问题讨论】:

  • 尝试手动将 R 平方 (R2) 值计算为“R2 = 1.0 - (numpy.var(regression_error) / numpy.var(dependent_data))”并比较值。据我了解,除非回归存在问题,否则 R 平方值不应为负。

标签: scikit-learn regression linear-regression scoring performance-measuring


【解决方案1】:

您很可能遇到过拟合问题。正如您正确提到的,如果您的模型的性能比仅拟合截距项更差,则可能会出现负 R2 值。您的模型可能没有捕捉到任何“真实”的潜在依赖性,而只是拟合随机噪声。您正在一个小测试集上计算 R2 分数,很可能这种噪声拟合产生的结果始终比测试集上的简单截距项更差。

这是一个典型的偏差-方差权衡案例。您的模型具有低偏差和高方差,因此在测试数据上表现不佳。有些模型旨在减少过度拟合/方差,例如 Lasso 和 Elastic Net。这些模型实际上是您认为表现更好的模型之一。

为了让自己相信 sklearn 的 r2_score 函数可以正常工作并熟悉它,我建议您首先拟合仅根据训练数据预测您的模型(将 CV 省略为好吧)。在这种情况下,R2 永远不会是负数。还要确保您的模型包含截距项(如果可用)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    相关资源
    最近更新 更多