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

112

我正在使用scikit-learn的linear_model.LinearRegression作为预测模型。它运行良好,非常完美。但是当我尝试使用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: Can't handle mix of binary and continuous target
9个回答

163
尽管这里有许多错误答案试图通过数值操作预测结果来规避错误,但你的错误根本原因是一个理论问题而非计算问题:你试图在回归(即数字预测)模型(LinearRegression)中使用分类指标(准确率),这是毫无意义的。与大多数性能指标一样,准确率将苹果与苹果进行比较(即0/1的真实标签与0/1的预测),因此,当你要求函数将二进制真实标签(苹果)与连续预测(橙子)进行比较时,你会得到一个预期的错误,其中消息从计算角度告诉你问题的确切所在。
Classification metrics can't handle a mix of binary and continuous target

尽管该消息并未直接告诉您正在尝试计算无效的度量标准(实际上我们不应该期望它走得那么远),但scikit-learn至少向您发出了明确的警告,告诉您正在尝试错误的操作;在其他框架中并非必然如此——例如,在非常相似的情况下,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上的流行机器学习课程中解释了为什么这是一个坏主意 - 参见他在Youtube上的Lecture 6.1 - Logistic Regression | Classification(解释从 ~3:00开始),以及Hastie、Tibshirani和同事共同编写的(强烈推荐并免费提供的)教材An Introduction to Statistical Learning的第4.2节“为什么不使用线性回归[进行分类]?”...


1
我同意,既然我们有逻辑回归,为什么要使用线性回归呢?但是,在ISL的该章节中倒数第二段(第七版中?),作者似乎暗示在二元分类情况下实际上可能并不那么糟糕:“可以证明,使用线性回归得到的$X\hat{\beta}$实际上是这种特殊情况下$Pr(\text{drug overdose}\mid X)$的估计”,“分类...将与线性判别分析(LDA)过程相同”。有任何见解吗? - Ben Reiniger
这个答案和另一个答案都是正确的,并且解释得很好。 - PKumar
1
“好的,但我想使用线性回归,然后将输出四舍五入/阈值化,有效地将预测视为'概率'...”这不就是逻辑回归吗? 一种将(可能为负)对数转换为概率的带有sigmoid / softmax函数的线性回归吗? - Super-intelligent Shade
1
@Super-intelligentShade,这绝对不是要最小化的成本函数(交叉熵)也不同。请注意,此类非编程问题的进一步细节在SO上是离题的。如果您仍有疑问,请考虑在Stats SE上发布。 - desertnaut
评论作者是正确的,使用线性回归来进行分类是不可取的。这里有一个很好的讨论,解释了为什么不应该这样做(链接)。需要注意的是,并不是因为阈值处理有什么问题。事实上,许多分类器都是通过这种方式工作的。例如,对于连续预测变量的不同截断阈值,通过观察灵敏度和特异度来绘制分类评分的ROC曲线下面积。也就是说,分类=回归+阈值! - undefined

23

accuracy_score 是一种分类度量标准,不能用于回归问题。

您可以在文档中查看可用的回归度量标准。


8
问题是真实的y是二进制(0和1),而你的预测不是。你可能生成了概率而不是预测,因此出现了这个结果 :) 请尝试生成类成员,应该会有用!

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

7

sklearn.metrics.accuracy_score(y_true, y_pred)方法中将y_pred定义为:

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

这意味着y_pred必须是一个包含1和0的数组(预测标签)。它们不应该是概率。

可以使用LinearRegression()模型的方法predict()predict_proba()生成预测标签(1和0)和/或预测概率。

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-learn的LinearRegression不包含predict_proba方法(文档),如果它确实包含这个方法,那将是非常奇怪的。你是否真的运行了你在这里展示的代码片段? - desertnaut
友情建议:仅因为某些回答获得了一些赞而保留错误和无效的答案既不是一个好主意,也不是 SO 的工作方式。我善意地建议您删除这个回答(从长远来看,这对您的声誉也更有利)。 - desertnaut

6

这对我解决了同样的问题, 使用 .round() 来进行预测。

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

这会导致极其误导性的输出结果。 - undefined

1
我遇到了相同的问题。y_test和y_pred的数据类型不同。请确保两者的数据类型相同。 y_test和y_pred的数据类型不同

-2
错误是由于y_pred和y_true的数据类型不同导致的。y_true可能是数据框(DataFrame),而y_pred是数组列表(ArrayList)。如果您将它们都转换为数组,那么问题就会得到解决。

1
请阅读@desertnaut的回答。试图这样做在理论上是错误的。 - Rama

-2

只需使用

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

1
这是完全错误的;请参考上面的答案,其中解释了为什么。 - desertnaut

-2

accuracy_score是一种分类度量标准,不能用于回归问题。

请使用以下方式:

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

2
你一开始的答案是正确的,而且你应该就此停止;按照你所建议的去操纵结果是无效的,而且实际上与你第一个(正确的)陈述相矛盾。请注意,这正是最初被接受的(但错误的)答案中提出的建议,现在已被删除。 - desertnaut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接