如何在 sklearn 中获取用于二进制分类的 roc auc
Posted
技术标签:
【中文标题】如何在 sklearn 中获取用于二进制分类的 roc auc【英文标题】:How to get roc auc for binary classification in sklearn 【发布时间】:2020-07-06 00:45:27 【问题描述】:我有二进制分类问题,我想计算结果的 roc_auc。为此,我使用 sklearn 以两种不同的方式完成了它。我的代码如下。
代码 1:
from sklearn.metrics import make_scorer
from sklearn.metrics import roc_auc_score
myscore = make_scorer(roc_auc_score, needs_proba=True)
from sklearn.model_selection import cross_validate
my_value = cross_validate(clf, X, y, cv=10, scoring = myscore)
print(np.mean(my_value['test_score'].tolist()))
我得到的输出是0.60
。
代码 2:
y_score = cross_val_predict(clf, X, y, cv=k_fold, method="predict_proba")
from sklearn.metrics import roc_curve, auc
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(2):
fpr[i], tpr[i], _ = roc_curve(y, y_score[:,i])
roc_auc[i] = auc(fpr[i], tpr[i])
print(roc_auc)
我得到的输出是0: 0.41, 1: 0.59
。
我很困惑,因为我在两个代码中得到了两个不同的分数。请让我知道为什么会发生这种差异以及正确的做法是什么。
如果需要,我很乐意提供更多详细信息。
【问题讨论】:
k_fold 的值是多少?并请解释您在代码 2 中究竟要做什么。为什么auc(roc_curve(y, y_score[:,i]))
应该给出一个有效的 AUC 值?
@desertnaut 谢谢你的评论。我明白了, k_fold 值是不同的。但是,即使使用相同的 k_fold,我也会得到一些不同的值。代码 1:0.5864040216803137
和代码 2:0: 0.41393184645202347, 1: 0.5860681535479765
:)
请查看我更新的评论,并确保您实际上是在比较苹果和苹果
@desertnaut 我的第二个代码的来源来自这些 SO 问题:***.com/questions/43043271/…、***.com/questions/45641409/… 请让我知道您的想法。谢谢你:)
发布一些数据和完整的代码。在您使用的情况 1 中,cv=10,在情况 2 中使用一些 KFolds。以获得相同的结果。使用相同的数据,相同的数据预处理和相同的 sklearn 版本。
【参考方案1】:
您似乎使用了另一个答案中的部分代码,所以我想也回答这个问题。
对于二元分类情况,您有 2 个类,一个是正类。
例如查看here。 pos_label
是正类的标签。当pos_label=None
时,如果y_true
在-1, 1
或0, 1
中,则pos_label
设置为1
,否则会报错..
import matplotlib.pyplot as plt
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.multiclass import OneVsRestClassifier
from sklearn.model_selection import cross_val_predict
from sklearn.linear_model import LogisticRegression
import numpy as np
iris = datasets.load_iris()
X = iris.data
y = iris.target
mask = (y!=2)
y = y[mask]
X = X[mask,:]
print(y)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
positive_class = 1
clf = OneVsRestClassifier(LogisticRegression())
y_score = cross_val_predict(clf, X, y, cv=10 , method='predict_proba')
fpr = dict()
tpr = dict()
roc_auc = dict()
fpr[positive_class], tpr[positive_class], _ = roc_curve(y, y_score[:, positive_class])
roc_auc[positive_class] = auc(fpr[positive_class], tpr[positive_class])
print(roc_auc)
1: 1.0
和
from sklearn.metrics import make_scorer
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_validate
myscore = make_scorer(roc_auc_score, needs_proba=True)
clf = OneVsRestClassifier(LogisticRegression())
my_value = cross_validate(clf, X, y, cv=10, scoring = myscore)
print(np.mean(my_value['test_score'].tolist()))
1.0
【讨论】:
我怀疑OP的2nd block中的不同结果是由于positive class的定义不同,但无法轻易证明 奈。可能是这样。 @makis 非常感谢您的回答。我发现它非常有用。我还有一个关于交叉验证的问题,我认为您可能有一些好主意来解决它。问题是:***.com/questions/60851341/… 请让我知道您对此的想法。谢谢你:) @makis 当我设置positive_class = 1
时,您的第一个代码中出现错误。我的y_bin
如下所示。 [[1], [0], [0], ..., [1]]
。我得到的错误是IndexError: index 1 is out of bounds for axis 1 with size 1
。只是想知道是否有办法解决这个问题。我期待着您的回音。谢谢你:)
我在块 1 中的代码中有一个类型。现在它已修复。以上是关于如何在 sklearn 中获取用于二进制分类的 roc auc的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Sklearn 的随机森林分类器中将训练模型用于另一个数据集?