Scikit-learn返回小于-1的确定系数(R ^ 2)

rho*_*ron 14 python statistics scikit-learn

我正在做一个简单的线性模型.我有

fire = load_data()
regr = linear_model.LinearRegression()
scores = cross_validation.cross_val_score(regr, fire.data, fire.target, cv=10, scoring='r2')
print scores
Run Code Online (Sandbox Code Playgroud)

产量

[  0.00000000e+00   0.00000000e+00  -8.27299054e+02  -5.80431382e+00
  -1.04444147e-01  -1.19367785e+00  -1.24843536e+00  -3.39950443e-01
   1.95018287e-02  -9.73940970e-02]
Run Code Online (Sandbox Code Playgroud)

这怎么可能?当我对内置的糖尿病数据做同样的事情时,它的效果非常好,但对于我的数据,它会返回这些看似荒谬的结果.我做错了什么吗?

eic*_*erg 26

没有理由r^2不应该是否定的(尽管^2名称中有).这也在文档中说明.您可以r^2将模型拟合(在线性回归的上下文中,例如1阶(仿射)的模型)与0阶模型(仅拟合常数)进行比较,两者都是通过最小化平方损失.常数最小化平方误差的是平均值.由于您使用遗漏数据进行交叉验证,因此您的测试集的平均值可能会与训练集的平均值大不相同.仅这一点就可以在预测中产生更高的平方误差,而不仅仅是预测测试数据的平均值,从而导致负r^2分数.

在最坏的情况下,如果您的数据根本不能解释您的目标,那么这些分数可能会变得非常消极.尝试

import numpy as np
rng = np.random.RandomState(42)
X = rng.randn(100, 80)
y = rng.randn(100)  # y has nothing to do with X whatsoever
from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import cross_val_score
scores = cross_val_score(LinearRegression(), X, y, cv=5, scoring='r2')
Run Code Online (Sandbox Code Playgroud)

这应该导致负值r^2.

In [23]: scores
Out[23]: 
array([-240.17927358,   -5.51819556,  -14.06815196,  -67.87003867,
    -64.14367035])
Run Code Online (Sandbox Code Playgroud)

现在最重要的问题是,这是否是由于线性模型在您的数据中找不到任何内容,或者是在数据预处理中可能修复的其他内容.您是否尝试将列缩放为均值0和方差1?你可以使用sklearn.preprocessing.StandardScaler.事实上,您应该通过使用连接a StandardScaler和LinearRegression管道来创建新的估算器sklearn.pipeline.Pipeline.接下来,您可能想尝试Ridge回归.

  • R ^ 2的上限为1.0,但它不在下面.*相关*总是在-1和1之间. (6认同)

Fre*_*Foo 9

R²= 1 - RSS/TSS,其中RSS是残差平方和Σ(y - f(x))²,TSS是平方和的总和Σ(y - mean(y))².现在对于R²≥-1,需要RSS /TSS≤2,但是很容易构建一个不是这样的模型和数据集:

>>> x = np.arange(50, dtype=float)
>>> y = x
>>> def f(x): return -100
...
>>> rss = np.sum((y - f(x)) ** 2)
>>> tss = np.sum((y - y.mean()) ** 2)
>>> 1 - rss / tss
-74.430972388955581
Run Code Online (Sandbox Code Playgroud)


mgo*_*ser 7

仅仅因为R^2可能是负面的并不意味着它应该是.

可能性1:代码中的错误.

您应该仔细检查的常见错误是您正确传递参数:

r2_score(y_true, y_pred) # Correct!
r2_score(y_pred, y_true) # Incorrect!!!!
Run Code Online (Sandbox Code Playgroud)

可能性2:小数据集

如果你得到负R ^ 2,你也可以检查过度拟合.请记住,cross_validation.cross_val_score()不要随意改变您的输入,因此如果您的样本被无意排序(例如按日期),那么您可能会在每个折叠上构建模型,这些模型不能预测其他折叠.

尝试减少功能数量,增加样本数量,减少折叠次数(如果使用的话cross_validation).虽然这里没有官方规则,但您的m x n数据集(m样本数量和要素n数量)应该是一个形状

m > n^2
Run Code Online (Sandbox Code Playgroud)

当你使用交叉验证f作为折叠数时,你应该瞄准

m/f > n^2
Run Code Online (Sandbox Code Playgroud)

  • @eickenberg 是的,但我相信在大多数情况下它会略微负面。我真正发现这个问题的原因是因为我得到了一个大约为 -0.99 的 R^2,结果我只是简单地翻转了 r2_score 中的 y_true 和 y_pred。我想很多用户都会有类似的愚蠢错误。 (2认同)