假设我们开始
import numpy as np
from sklearn import metrics
现在我们设置真实的y 和预测的scores:
y = np.array([0, 0, 1, 1])
scores = np.array([0.1, 0.4, 0.35, 0.8])
(请注意,y 已从您的问题中向下移动了 1。这无关紧要:无论预测 1、2 还是 0、1,都会获得完全相同的结果(fpr、tpr、阈值等),但有些sklearn.metrics 函数如果不使用 0、1 则很麻烦。)
让我们看看这里的 AUC:
>>> metrics.roc_auc_score(y, scores)
0.75
如您的示例:
fpr, tpr, thresholds = metrics.roc_curve(y, scores)
>>> fpr, tpr
(array([ 0. , 0.5, 0.5, 1. ]), array([ 0.5, 0.5, 1. , 1. ]))
这给出了以下情节:
plot([0, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 1], [0.5, 1], [1, 1]);
通过构造,有限长度 y 的 ROC 将由矩形组成:
因此,对于有限的 y,ROC 将始终由从 (0, 0) 到 的一系列连接的水平和垂直线来表征(1, 1)。
AUC 是这些矩形的总和。在这里,如上所示,AUC 为 0.75,因为矩形的面积为 0.5 * 0.5 + 0.5 * 1 = 0.75。
在某些情况下,人们选择通过线性插值来计算 AUC。假设 y 的长度远大于为 FPR 和 TPR 计算的实际点数。然后,在这种情况下,线性插值是 可能之间的点的近似值。在某些情况下,人们还遵循 猜想,即如果 y 足够大,则两者之间的点将被线性插值。 sklearn.metrics没有使用这个猜想,要得到与sklearn.metrics一致的结果,需要用矩形求和,而不是梯形求和。
让我们编写自己的函数来直接从fpr 和tpr 计算AUC:
import itertools
import operator
def auc_from_fpr_tpr(fpr, tpr, trapezoid=False):
inds = [i for (i, (s, e)) in enumerate(zip(fpr[: -1], fpr[1: ])) if s != e] + [len(fpr) - 1]
fpr, tpr = fpr[inds], tpr[inds]
area = 0
ft = zip(fpr, tpr)
for p0, p1 in zip(ft[: -1], ft[1: ]):
area += (p1[0] - p0[0]) * ((p1[1] + p0[1]) / 2 if trapezoid else p0[1])
return area
此函数接受 FPR 和 TPR,以及一个可选参数,说明是否使用梯形求和。运行它,我们得到:
>>> auc_from_fpr_tpr(fpr, tpr), auc_from_fpr_tpr(fpr, tpr, True)
(0.75, 0.875)
对于矩形求和,我们得到与 sklearn.metrics 相同的结果,而对于梯形求和,我们得到不同的更高结果。
所以,现在我们只需要看看如果我们以 0.1 的 FPR 终止,FPR/TPR 点会发生什么。我们可以使用bisect module
import bisect
def get_fpr_tpr_for_thresh(fpr, tpr, thresh):
p = bisect.bisect_left(fpr, thresh)
fpr = fpr.copy()
fpr[p] = thresh
return fpr[: p + 1], tpr[: p + 1]
这是如何工作的?它只是检查thresh 在fpr 中的插入点在哪里。鉴于 FPR 的属性(它必须从 0 开始),插入点必须在水平线上。因此,该矩形之前的所有矩形都应该不受影响,该矩形之后的所有矩形都应该被删除,并且这个矩形应该可能被缩短。
让我们应用它:
fpr_thresh, tpr_thresh = get_fpr_tpr_for_thresh(fpr, tpr, 0.1)
>>> fpr_thresh, tpr_thresh
(array([ 0. , 0.1]), array([ 0.5, 0.5]))
最后,我们只需要根据更新版本计算 AUC:
>>> auc_from_fpr_tpr(fpr, tpr), auc_from_fpr_tpr(fpr, tpr, True)
0.050000000000000003, 0.050000000000000003)
在这种情况下,矩形和梯形求和给出相同的结果。请注意,一般情况下,它们不会。为了与sklearn.metrics 保持一致,应该使用第一个。