准确性得分ValueError:无法处理二进制目标和连续目标的混合


73

我正在使用linear_model.LinearRegressionscikit-learn作为预测模型。它有效且完美。我在使用accuracy_score度量标准评估预测结果时遇到问题。

这是我的真实数据:

array([1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0])

我的预测数据:

array([ 0.07094605,  0.1994941 ,  0.19270157,  0.13379635,  0.04654469,
    0.09212494,  0.19952108,  0.12884365,  0.15685076, -0.01274453,
    0.32167554,  0.32167554, -0.10023553,  0.09819648, -0.06755516,
    0.25390082,  0.17248324])

我的代码:

accuracy_score(y_true, y_pred, normalize=False)

错误信息:

ValueError:无法处理二进制目标和连续目标的混合

救命 ?谢谢。


2
dtype是什么?你能投y_truenumpy.int8吗?也许您正在寻找逻辑回归来预测分类变量?
本杰明·

1
它正在检查type_of_target(y_true)type_of_target(y_pred)(在中utils.multiclass.py)。如果数组只有2个唯一值,则将其分类为binary
hpaulj

1
请告知您您接受的答案是错误的;错误的根本原因是您试图在线性回归(即数值预测)设置中应用准确性指标,这毫无意义。有关详细信息,请参见下面的答案……
desertnaut,

1
简短地说:我认为问题在于您有二进制目标,并且已经构造了一个回归器,而应该在其中使用分类器。使用LogisticRegression代替。
Kareem Jeiroudi

Answers:


45

编辑(注释后):下面将解决编码问题,但强烈建议不要不要使用此方法,因为线性回归模型的分类器非常差,很可能无法正确分离类。

阅读@desertnaut在下面写得很好的答案,解释为什么此错误暗示着机器学习方法中的某些错误,而不是您必须“修复”的某些错误。

accuracy_score(y_true, y_pred.round(), normalize=False)

32
对于落在这里的人:这个答案是完全错误的;错误的原因是尝试在回归设置中使用准确性作为度量标准(注意OP的模型为LinearRegression不是 LogisticRegression),这毫无意义……
desertnaut

79

尽管这里有很多错误的答案试图通过数值操纵预测来规避错误,但是错误的根本原因是理论上的而不是计算上的问题:您正在尝试在回归中使用分类指标(准确性)(即数值)预测)模型(LinearRegression),这毫无意义

就像大多数性能指标一样,准确性将一个苹果与另一个苹果进行比较(即,真实标签为0/1,而预测值再次为0/1);因此,当您要求函数将二进制真标签(苹果)与连续预测(橙色)进行比较时,您会得到预期的错误,该错误消息从计算的角度确切地告诉您问题出在哪里:

Classification metrics can't handle a mix of binary and continuous target

尽管该消息并没有直接告诉您您正在尝试计算对您的问题无效的指标(并且我们实际上不应期望它走得那么远),但是scikit-learning当然是一件好事至少会给您直接和明确的警告,表示您尝试做错事;在其他框架上并不一定是这种情况-例如,请参阅Keras在非常相似的情况下行为,您根本不会收到任何警告,而最终只是抱怨在回归设置中“准确性”低下...

我对这里的所有其他答案(包括公认的且被高度推崇的答案)感到非常惊讶,这有效地建议您操纵预测以简单地摆脱错误。的确,一旦我们得到一组数字,我们当然可以开始以各种方式(舍入,阈值等)将它们混合在一起,以使我们的代码行事,但这当然并不意味着我们的数字操作是在我们要解决的ML问题的特定上下文中有意义

因此,总结一下:问题在于您正在应用适合模型(LinearRegression)的度量(准确性):如果处于分类设置中,则应更改模型(例如,LogisticRegression改为使用);如果您处于回归(即数值预测)设置中,则应更改指标。查看scikit-learn中可用的指标列表,您可以在其中确认准确性仅用于分类。

将情况与最近的SO问题进行比较,OP尝试在其中获取模型列表的准确性:

models = []
models.append(('SVM', svm.SVC()))
models.append(('LR', LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
#models.append(('SGDRegressor', linear_model.SGDRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('BayesianRidge', linear_model.BayesianRidge())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('LassoLars', linear_model.LassoLars())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('ARDRegression', linear_model.ARDRegression())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('PassiveAggressiveRegressor', linear_model.PassiveAggressiveRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('TheilSenRegressor', linear_model.TheilSenRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets
#models.append(('LinearRegression', linear_model.LinearRegression())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets

前6个模型工作正常,而其余所有(注释掉)的模型给出相同的错误。现在,您应该能够使自己确信所有注释掉的模型都是回归模型(而不是分类模型),因此是有道理的错误。

最后一个重要说明:有人宣称:

好的,但是我想使用线性回归,然后仅对输出进行四舍五入,将预测有效地视为“概率”,从而将模型转换为分类器

实际上,这已经在其他一些答案中得到了暗示,无论是否隐含。再次,这是一种无效的方法(而且您的负面预测这一事实应该已经提醒您不能将它们解释为概率)。吴安德(Andrew Ng)在Coursera受欢迎的机器学习课程中解释了为什么这是一个坏主意-请参阅他的讲座6.1-Logistic回归| 在YouTube上进行分类(解释从〜3:00开始),以及第4.2为何不进行线性回归[用于分类]?Hastie,Tibshirani和他的同事(强烈推荐和免费获得)教科书《统计学习入门》中...


我同意; 我们有逻辑时为什么要使用线性回归?但是,在ISL中该部分的倒数第二段中(在第七印刷中?),作者似乎暗示,在二进制分类的情况下,它实际上可能并不那么糟糕:“可以证明$ X在这种特殊情况下,使用线性回归获得的\ hat {\ beta} $实际上是$ Pr(\ text {drug overdose} \ mid X)$的估计值”,“分类...与...相同线性判别分析(LDA)程序”。有什么见识吗?
Ben Reiniger,

这个答案和另一个答案是正确的,解释得很好。
PKumar '20年


5

sklearn.metrics.accuracy_score(y_true, y_pred)方法定义y_pred as

y_pred:类似1d数组,或标签指示符数组/稀疏矩阵。 预测标签,由分类器返回。

这意味着y_pred必须是1或0(谓词标签)的数组。他们不应该是概率。

的预测标签(1和0)和/或预测probabilites可以使用来产生LinearRegression()模型的方法predict()predict_proba()分别。

1.生成预测标签:

LR = linear_model.LinearRegression()
y_preds=LR.predict(X_test)
print(y_preds)

输出:

[1 1 0 1]

y_preds现在可以用于该accuracy_score()方法:accuracy_score(y_true, y_pred)

2.生成标签的概率:

诸如“ precision_recall_curve(y_true,probas_pred)”之类的某些指标需要概率,可以按如下方式生成:

LR = linear_model.LinearRegression()
y_preds=LR.predict_proba(X_test)
print(y_preds)

输出:

[0.87812372 0.77490434 0.30319547 0.84999743]

1
LinearRegression返回数值预测,当然返回概率;后者由逻辑回归模型返回。
desertnaut

2
scikit学习的LinearRegression确实包括predict_proba方法(文档),这确实是奇怪的,如果它没有。您实际上运行了此处显示的代码段吗?
desertnaut

友善的建议:仅仅因为错误和无效的答案碰巧得到了赞成就在那里,这既不是一个好主意,也不是SO的工作原理。我建议您删除此选项(从长远来看,这也将对您的声誉有所帮助)。
沙漠之城

3

问题在于,真正的y是二进制(零和一),而您的预测却不是。您可能生成的是概率而不是预测,因此是结果:)尝试生成类成员身份,它应该可以工作!


LinearRegression产生数字预测,而不是概率;问题是由于尝试在回归设置中使用准确性,这是没有意义的,因此会出现错误……
desertnaut


0

您可以使用numpy更改此设置

import numpy as np
y_pred = np.where(y_pred > 0.5 ,1,0)

-1

只需使用

y_pred = (y_pred > 0.5)
accuracy_score(y_true, y_pred, normalize=False)

1
这是完全错误的。请参考上面的答案,解释原因。
desertnaut

-2

该错误是因为y_pred和y_true的数据类型不同。y_true可能是数据帧,而y_pred是arraylist。如果将它们都转换为数组,则问题将得到解决。


1
请阅读@desertnaut答案。尝试这样做在理论上是错误的。
拉玛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.