Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Scikit学习返回的确定系数(R^2)值小于-1_Python_Statistics_Scikit Learn - Fatal编程技术网

Python Scikit学习返回的确定系数(R^2)值小于-1

Python Scikit学习返回的确定系数(R^2)值小于-1,python,statistics,scikit-learn,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 产生 [ 0.00000000e+00 0.00000000e+00 -8.27299054e+02 -5.80431382e+

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

fire = load_data()
regr = linear_model.LinearRegression()
scores = cross_validation.cross_val_score(regr, fire.data, fire.target, cv=10, scoring='r2')
print scores
产生

[  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]

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

没有理由
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')
这将导致负
r^2

In [23]: scores
Out[23]: 
array([-240.17927358,   -5.51819556,  -14.06815196,  -67.87003867,
    -64.14367035])
现在重要的问题是,这是因为线性模型在数据中找不到任何东西,还是因为在数据预处理过程中可能会有其他固定的东西。您是否尝试过将列缩放为均值0和方差1?您可以使用
sklearn.preprocessing.StandardScaler
完成此操作。事实上,您应该通过使用
sklearn.pipeline.pipeline
StandardScaler
LinearRegression
连接到管道中来创建一个新的估计器。
接下来,您可能需要尝试岭回归。

R²=1-RSS/TSS,其中RSS是残差平方和∑(y-f(x))²和TSS是平方和的总和∑(y-平均值(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

仅仅因为
R^2
可以是负数并不意味着它应该是负数

可能性1:代码中存在错误。

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

r2_score(y_true, y_pred) # Correct!
r2_score(y_pred, y_true) # Incorrect!!!!
可能性2:小数据集

如果R^2为负值,还可以检查是否过度拟合。请记住,
cross\u validation.cross\u val\u score()
不会随机搅乱您的输入,因此,如果无意中对样本进行了排序(例如,按日期),则您可能会在每个折叠上构建模型,而这些模型不会预测其他折叠

尝试减少功能的数量,增加样本的数量,并减少折叠的数量(如果您使用的是
交叉验证
)。虽然这里没有官方规则,但您的
m x n
数据集(其中
m
是样本数,
n
是特征数)的形状应为

m > n^2
当您使用交叉验证,并以
f
作为折叠数时,您应该将

m/f > n^2

如果得到负回归r^2分数,请确保在拟合/评分模型之前从数据集中删除任何唯一标识符(如“id”或“rownum”)。简单的检查,但它会为您节省一些头痛的时间。

谢谢您的帮助。我知道R^2可以是负数,但我认为它应该是有界于区间[-1,1]。不是这样吗?R^2在1.0以上有界,但在1.0以下没有界。相关性总是在-1和1之间。仅仅因为
R^2
可以是负的,并不意味着我们应该期望它是负的。请参阅下面我的答案,了解
R^2
可能为负值的原因以及如何修复它们。确切地说,模型必须是“足够错误的”,如果您选择了完全不对应的对象,这并不难。要使
线性回归发生这种情况,请,你的模型一定很糟糕,每次预测一个简单的平均值会更好。通常这意味着您的模型过于合适。有关更多详细信息,请参见下面的答案,或者尝试将
cv
设置为较小的数字。查找bug的最佳方法。负R^2绝对值得调查!然而,即使你做的每件事都是正确的,R^2仍然可以是负的,因为纯粹的随机性。事实上,使用线性预测器的预测R^2在高斯噪声(即预测器无法预测的数据)上的零分布为负。(估计的平均值将是错误的,即不是0,斜率也几乎肯定不是0)@Eikenberg true,但我相信在大多数情况下,它将是略微负的。我发现这个问题的原因是因为我得到了一个大约为
-0.99的
R^2
,结果我只是在
r2\u分数中翻转了y\u true和y\u pred。我想很多用户都会有类似的愚蠢错误。是的,有趣的观察!事实上,如果预测的方差小于目标值(通常情况下,如果涉及加性噪声),这将使R^2任意降低。很高兴在这里写下这篇文章,它可以让很多人花更少的时间来处理这类错误。正如在这里发布的,这是一个相反的问题,在修复了R^2之后,这是有意义的。我一直在绘制图表,这些图表显示出明显的关系,所以我挠头。非常感谢。