Python 交叉验证给出负R2?

Python 交叉验证给出负R2?,python,scikit-learn,cross-validation,sklearn-pandas,goodness-of-fit,Python,Scikit Learn,Cross Validation,Sklearn Pandas,Goodness Of Fit,为了简单起见,我将500个样本划分为10000多行数据集。请将X和y复制并粘贴到IDE中 X= y= 初始化和培训: from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X, y) 交叉验证: from sklearn.model_selection import cross_val_score cross_val_score(model, X, y, cv=10,

为了简单起见,我将500个样本划分为10000多行数据集。请将X和y复制并粘贴到IDE中

X=

y=

初始化和培训:

from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X, y)
交叉验证:

from sklearn.model_selection import cross_val_score
cross_val_score(model, X, y, cv=10, scoring='r2').mean()
-0.3339677563815496(负R2?)

看看它是否接近模型的真实R2。我这样做:

from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=None, shuffle=False)

r2_score(y_test, model.predict_proba(X_test)[:,1], multioutput='variance_weighted')
0.32642659661798396

这个R2对于模型的拟合度来说更有意义,看起来两个R2只是一个+/-符号开关,但事实并非如此。在我使用更大样本的模型中,R2交叉值为-0.24,R2检验值为0.18。而且,当我添加一个似乎对模型有益的特性时,R2测试上升,R2交叉值下降


此外,如果您将LogisticRecession切换为LinearRecession,R2 cross val现在为正值,接近R2测试。是什么导致此问题?

R2可能为负值。以下段落摘自“确定系数”第页

有些情况下,R2的计算定义可能会产生负值,具体取决于使用的定义。当与相应结果进行比较的预测未通过使用这些数据的模型拟合程序得出时,可能会出现这种情况。即使使用了模型拟合程序,R2也可能为负,例如,在不包含截距的情况下进行线性回归时,或者在使用非线性函数拟合数据时。在出现负值的情况下,根据该特定标准,数据的平均值比拟合函数值更适合结果。由于确定系数的最一般定义也被称为纳什-萨特克利夫模型效率系数,因此在许多领域首选最后一种表示法,因为用平方字母表示拟合优度指标可能从-无穷大到1(即,它可能产生负值)是令人困惑的


似乎预测比水平线更糟糕。

TLDR:R2可能为负值,并且您对
train\u test\u split
结果进行了错误的干扰

我将在下文解释这两种说法

cross\u val\u score
符号翻转以查看
错误
损失
指标 从中,您可以看到,
cross\u val\u score
实际上翻转了某些指标的符号。但仅适用于
错误
损失
指标(越低越好),而不适用于
得分
指标(越高越好):

所有scorer对象都遵循这样一个惯例,即返回值越高,返回值越低。因此,度量模型和数据之间距离的度量,如metrics.mean_squared_error,可以作为neg_mean_squared_error使用,它返回度量的负值

由于
r2
是一个
score
指标,因此它不会翻转符号。在交叉验证中,您将获得
-0.33
。请注意,这是正常的。从
r2\u分数

可能的最佳分数为1.0,可能为负(因为模型可能任意更差)。如果一个常数模型总是预测y的期望值,而不考虑输入特征,则R^2得分为0.0

这就引出了第二部分:为什么使用CV和训练/测试分割会得到如此不同的结果

CV和训练/测试分割结果之间的差异 使用
train\u test\u split
获得更好结果的原因有两个

对概率而非类别进行
r2
评估(您使用的是
predict\u proba
而不是
predict
可以减少错误的危害:

print(r2_score(y_test, model.predict_proba(X_test)[:,1], multioutput='variance_weighted'))
 0.19131536389654913
而:

 print(r2_score(y_test, model.predict(X_test)))
 -0.364200082678793
10
的平均值折叠cv,但不检查方差,方差很高。如果检查方差和结果的详细信息,您将看到方差很大:

scores = cross_val_score(model, X, y, cv=10, scoring='r2')
scores
array([-0.67868339, -0.03918495,  0.04075235, -0.47783251, -0.23152709,
   -0.39573071, -0.72413793, -0.66666667,  0.        , -0.16666667])

scores.mean(), scores.std() * 2
(-0.3339677563815496, 0.5598543351649792)

希望能有帮助!

我必须做
X=X.resporate(-1,1))
来提供
X
LogisticRegression
。你也是这样吗?如果是,你能编辑代码吗?'“我忘了在帖子中添加这一点,但编辑得太晚了,但为什么你试图在分类问题上使用
r2分数
LogisticRegression
是一个分类器,你的目标似乎也是二进制类。LogisticRegression被编程为给出离散值,因此这里的R平方不适合检查这种情况下的性能。另一种情况下的线性回归是regressor@VivekKumar你会使用什么样的拟合优度测试?为什么分类需要拟合优度。分类问题涉及根据特征确定类之间的最佳边界,而不是拟合特征上的曲线。你可以尝试使用
精度
回忆
精度
auc
等。请看Wow。所以交叉值使用。默认情况下预测而不是。预测概率…有没有办法让交叉值得分使用概率?我刚刚在其他答案中发现了这一点。交叉值预测(方法='predict'u proba')我如何使用cross\u val来预测概率?我使用了
cross\u val\u predict
,但我刚刚了解到它不用于计算R2。您好,您可以使用
scoring=“neg\u log\u loss”
,它使用
predict_proba
进行计算,更适合于回归模型,正如Vivek在对问题的评论中所说。注意,它将返回负值,因为它是否定的,并且它是一个误差度量,所以绝对值越低越好。
 print(r2_score(y_test, model.predict(X_test)))
 -0.364200082678793
scores = cross_val_score(model, X, y, cv=10, scoring='r2')
scores
array([-0.67868339, -0.03918495,  0.04075235, -0.47783251, -0.23152709,
   -0.39573071, -0.72413793, -0.66666667,  0.        , -0.16666667])

scores.mean(), scores.std() * 2
(-0.3339677563815496, 0.5598543351649792)