gpt4 book ai didi

python - 如何计算部分曲线下面积 (AUC)

转载 作者:太空狗 更新时间:2023-10-29 21:25:39 31 4
gpt4 key购买 nike

在 scikit learn 中,您可以使用以下方法计算二元分类器的曲线下面积

roc_auc_score( Y, clf.predict_proba(X)[:,1] )

我只对误报率小于 0.1 的曲线部分感兴趣。

Given such a threshold false positive rate, how can I compute the AUC only for the part of the curve up the threshold?

这里有几个 ROC 曲线的例子,用于说明:

Illustration of ROC-curves plot for several types of a classifier.

scikit 学习文档展示了如何使用 roc_curve

>>> import numpy as np
>>> from sklearn import metrics
>>> y = np.array([1, 1, 2, 2])
>>> scores = np.array([0.1, 0.4, 0.35, 0.8])
>>> fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)
>>> fpr
array([ 0. , 0.5, 0.5, 1. ])
>>> tpr
array([ 0.5, 0.5, 1. , 1. ])
>>> thresholds
array([ 0.8 , 0.4 , 0.35, 0.1 ]

有没有一种简单的方法可以从这里转到部分 AUC?


似乎唯一的问题是如何计算 fpr = 0.1 时的 tpr 值,因为 roc_curve 不一定会给你这个值。

最佳答案

假设我们从

开始
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,都会获得完全相同的结果(fpr、tpr、阈值等) , 1,但是一些 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]);

enter image description here

通过构造,有限长度 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 一致的结果,需要使用矩形求和,而不是梯形求和。

让我们编写自己的函数来直接从 fprtpr 计算 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 相同的结果,对于梯形求和,我们得到不同的、更高的结果。

所以,现在我们只需要看看如果我们在 FPR 为 0.1 时终止,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]

这是如何运作的?它只是检查 fprthresh 的插入点在哪里。鉴于 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 保持一致,应使用第一个。

关于python - 如何计算部分曲线下面积 (AUC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39537443/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com