ele*_*ora 7 python statistics machine-learning scikit-learn
在scikit中,您可以计算二进制分类器的曲线下面积
roc_auc_score( Y, clf.predict_proba(X)[:,1] )
Run Code Online (Sandbox Code Playgroud)
我只对假阳性率小于0.1的曲线部分感兴趣.
给定这样的阈值误报率,如何计算仅在曲线上升到阈值的部分的AUC?
以下是几个ROC曲线的示例,用于说明:
scikit learn docs展示了如何使用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 ]
Run Code Online (Sandbox Code Playgroud)
有没有一种简单的方法可以从这个到AUC?
似乎唯一的问题是如何计算fpr = 0.1时的tpr值,因为roc_curve并不一定能给你这个.
假设我们开始
import numpy as np
from sklearn import metrics
Run Code Online (Sandbox Code Playgroud)
现在我们设定真实y和预测scores:
y = np.array([0, 0, 1, 1])
scores = np.array([0.1, 0.4, 0.35, 0.8])
Run Code Online (Sandbox Code Playgroud)
(注意,y你的问题已经向下移动了1.这是无关紧要的:无论是预测1,2还是0,1都可以获得完全相同的结果(fpr,tpr,阈值等),但是sklearn.metrics如果没有,则会产生一些阻力.使用0,1.)
我们在这里看看AUC:
>>> metrics.roc_auc_score(y, scores)
0.75
Run Code Online (Sandbox Code Playgroud)
如在你的例子中:
fpr, tpr, thresholds = metrics.roc_curve(y, scores)
>>> fpr, tpr
(array([ 0. , 0.5, 0.5, 1. ]), array([ 0.5, 0.5, 1. , 1. ]))
Run Code Online (Sandbox Code Playgroud)
这给出了以下图:
plot([0, 0.5], [0.5, 0.5], [0.5, 0.5], [0.5, 1], [0.5, 1], [1, 1]);
Run Code Online (Sandbox Code Playgroud)
通过构造,有限长度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计算的实际点数.然后,在这种情况下,线性插值是两者之间可能存在的点的近似值.在某些情况下,人们也跟着猜想,如果当时ÿ已经足够大,之间的点将被线性插值.sklearn.metrics不使用这个猜想,并且为了得到与之一致的结果sklearn.metrics,有必要使用矩形,而不是梯形,求和.
让我们编写自己的函数来直接计算AUC fpr和tpr:
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
Run Code Online (Sandbox Code Playgroud)
该函数采用FPR和TPR,以及一个可选参数,说明是否使用梯形求和.运行它,我们得到:
>>> auc_from_fpr_tpr(fpr, tpr), auc_from_fpr_tpr(fpr, tpr, True)
(0.75, 0.875)
Run Code Online (Sandbox Code Playgroud)
我们得到与sklearn.metrics矩形求和相同的结果,以及梯形求和的不同的更高的结果.
所以,现在我们只需看看如果我们以0.1的FPR终止,FPR/TPR点会发生什么.我们可以用模块做到这一点bisect
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]
Run Code Online (Sandbox Code Playgroud)
这是如何运作的?它只是简单地检查,其中将插入点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]))
Run Code Online (Sandbox Code Playgroud)
最后,我们只需要从更新版本中计算AUC:
>>> auc_from_fpr_tpr(fpr, tpr), auc_from_fpr_tpr(fpr, tpr, True)
0.050000000000000003, 0.050000000000000003)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,矩形和梯形求和都给出相同的结果.请注意,一般情况下,他们不会.为了与之保持一致sklearn.metrics,应该使用第一个.
Python sklearnroc_auc_score()现在允许您设置max_fpr. 在您的情况下,您可以设置max_fpr=0.1,该函数将为您计算 AUC。https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html
仅在 [0.0, 0.1] 范围内计算 fpr 和 tpr 值。
然后,您可以使用numpy.trapz来评估部分 AUC (pAUC),如下所示:
pAUC = numpy.trapz(tpr_array, fpr_array)
Run Code Online (Sandbox Code Playgroud)
此函数使用复合梯形规则来计算曲线下的面积。
| 归档时间: |
|
| 查看次数: |
10734 次 |
| 最近记录: |