ROC曲线的理解

ROC曲线的理解和python绘制ROC曲线

ROC曲线的理解

考虑一个二分问题,即将实例分成正类(positive)或负类(negative)。对一个二分问题来说,会出现四种情况。如果一个实例是正类并且也被 预测成正类,即为真正类(True positive),如果实例是负类被预测成正类,称之为假正类(False positive)。相应地,如果实例是负类被预测成负类,称之为真负类(True negative),正类被预测成负类则为假负类(false negative)。


表格表示
1. 尽量把相关的识别出来,TPR越大越好
2. 把不相关的识别为相关,FPR越小越好


从列联表引入两个新名词。其一是真正类率(true positive rate ,TPR), 计算公式为TPR=TP/ (TP+ FN),刻画的是分类器所识别出的 正实例占所有正实例的比例。另外一个是假正类率(false positive rate, FPR),计算公式为FPR= FP / (FP + TN),计算的是分类器错认为正类的负实例占所有负实例的比例。还有一个真负类率(True Negative Rate,TNR),也称为specificity,计算公式为TNR=TN/ (FP+ TN) = 1 - FPR。

FPR = FP/(FP + TN) 负样本中的错判率(假警报率)
TPR = TP/(TP + TN) 判对样本中的正样本率(命中率)
ACC = (TP + TN) / P+N 判对准确率

如何绘制ROC曲线

  • 对于一个特定的分类器和测试数据集,显然只能得到一个分类结果,即一组FPR和TPR结果。但是分类器的一个重要功能“概率输出”,即表示分类器认为某个样本具有多大的概率属于正样本(或负样本)。如果不是在(0,1)之间,可以通过sigmod函数映射到(0,1)之间。我们可以通过改变阈值(discrimination threashold)来判断测试集的样本是正例,还是负例。
    图解
    对应的图形
  • 例如:我们通过一个分类器得出了所有样本的属于正例的输出概率,并根据测试集中的概率值从大到小的排列。图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本),“Score”表示每个测试样本属于正样本的概率。
    样例
  • 对于图中的第4个样本,其“discrimination threashold”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。每次选取一个不同的threshold,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。当选取不同的discrimination threashold就可以得到不同的 FPR和TPR值。

AUC值

AUC(Area Under Curve)被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。

- 如上,是三条ROC曲线,在0.23处取一条直线。那么,在同样的低FPR=0.23的情况下,红色分类器得到更高的PTR。也就表明,ROC越往上,分类器效果越好。我们用一个标量值AUC来量化他。

AUC的物理意义

  • 假设分类器的输出是样本属于正类的socre(置信度),则AUC的物理意义为,任取一对(正、负)样本,正样本的score大于负样本的score的概率。

ROC曲线的优势

ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。
- AUC = 1,是完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
- AUC = 0.5,跟随机猜测一样(例:丢铜板),模型没有预测价值。
- AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测。
样例
- 在上图中,(a)和(c)为ROC曲线,(b)和(d)为Precision-Recall曲线。(a)和(b)展示的是分类其在原始测试集(正负样本分布平衡)的结果,(c)和(d)是将测试集中负样本的数量增加到原来的10倍后,分类器的结果。可以明显的看出,ROC曲线基本保持原貌,而Precision-Recall曲线则变化较大。

计算AUC

  • 第一种方法:AUC为ROC曲线下的面积,那我们直接计算面积可得。面积为一个个小的梯形面积之和。计算的精度与阈值的精度有关。
  • 第二种方法:根据AUC的物理意义,我们计算正样本score大于负样本的score的概率。取N*M(N为正样本数,M为负样本数)个二元组,比较score,最后得到AUC。时间复杂度为O(N*M)。
  • 第三种方法:与第二种方法相似,直接计算正样本score大于负样本的概率。我们首先把所有样本按照score排序,依次用rank表示他们,如最大score的样本,rank=n(n=N+M),其次为n-1。那么对于正样本中rank最大的样本,rank_max,有M-1个其他正样本比他score小,那么就有(rank_max-1)-(M-1)个负样本比他score小。其次为(rank_second-1)-(M-2)。最后我们得到正样本大于负样本的概率为:

    时间复杂度为O(N+M)。

python 绘制ROC曲线代码

  • 分类器的分类的结果:predStrengths:
  • [[-0.646419 0.53886223 0.91726555 0.21712009 -0.69768794 1.22181293
    1.22748297 0.58145314 -0.40165729 0.03508613 0.27123572 0.59407783
    1.53203035 0.64819347 1.04739323 -0.40165729 -1.02662219 0.5606821
    0.34364609 -0.40784481 -0.02469954 1.53203035 1.1676973 1.0995114
    0.73717581 0.23749438 0.52166747 0.85052522 0.5606821 1.69342306
    -1.02662219 -0.03331166 0.95841088 0.6538635 -0.40165729 -1.58160132
    -0.32315478 -0.69921001 1.22748297 0.23749438 -1.58160132 0.23749438
    -0.03331166 -0.49069632 -0.81111385 -1.58160132 -1.27705394 1.22748297
    -0.10329743 -1.33116957 0.91726555 0.59407783 0.91726555 0.5606821
    0.20691998 0.27123572 0.5606821 -0.02469954 -0.70343447 -1.58160132
    1.1676973 0.95841088 -0.37284836 -0.19233647 0.21712009 0.68306018
    0.18462128 1.53203035 0.20077111 1.22748297 0.18537621 1.53203035
    -0.01293737 -0.32647673 0.5606821 -0.03331166 1.31646531 1.69342306
    -0.07846957 0.02322857 -0.70620467 1.2613064 0.21712009 -1.40405878
    0.59407783 1.47224468 -0.40165729 0.5606821 0.89862521 1.22748297
    0.40165729 0.20691998 1.1550726 -0.07279954 0.79073955 1.41702908
    0.62790127 -0.40784481 1.1676973 -0.40784481 1.31646531 -0.95663642
    0.4544483 0.90429525 0.29848817 0.89862521 0.50089643 1.1676973
    -0.86522948 0.21712009 -0.35372918 0.85052522 1.22748297 -0.01293737
    0.38747052 1.56689706 1.99797044 0.54030781 0.44691059 0.80958618
    1.1676973 -1.22493577 1.22748297 -0.27513129 0.84485519 1.40550435
    -0.38301695 0.48217959 0.07292214 0.86522948 0.5606821 0.5273375
    1.22748297 -1.27705394 -0.40165729 -0.07846957 1.53203035 0.80958618
    0.90429525 0.85052522 -0.12406847 -1.58160132 1.53203035 0.36264266
    0.98760756 1.38320565 0.91726555 -0.24749538 1.42269911 1.31646531
    -1.00798185 0.11221091 1.1550726 1.93818477 0.84485519 1.22748297
    1.11413356 1.10095697 1.22181293 -0.36264266 0.5606821 0.58145314
    -0.57967867 0.64819347 0.16432908 1.22748297 1.53203035 0.27366031
    -0.63171474 0.91726555 -0.65827656 0.05809528 -0.65827656 -0.77909388
    0.5606821 1.36456531 -1.24647954 -0.24026458 -0.65208904 -0.40165729
    0.5606821 -1.40405878 1.11413356 1.36456531 -0.40784481 0.90429525
    0.83188488 0.6538635 0.58145314 0.64654161 -0.01902951 1.69342306
    -1.33116957 0.34364609 1.31646531 0.02322857 -0.0976274 1.1198036
    0.21712009 1.22181293 -0.27513129 0.81111385 1.53203035 -0.07846957
    -0.65208904 0.44124055 0.5606821 0.36264266 1.1550726 0.07292214
    -0.03331166 0.89862521 0.84485519 1.20884263 1.53203035 0.5606821
    -0.63790227 1.1676973 0.84485519 -0.39598725 0.9932776 -0.35372918
    0.64819347 1.22748297 1.53203035 -0.65827656 0.5606821 -1.02662219
    0.93811868 -0.39598725 -1.58160132 0.5606821 0.52166747 0.79073955
    -0.32647673 1.22748297 1.1676973 0.27123572 -0.07424511 -1.33116957
    0.91726555 0.54891992 0.6538635 0.59407783 -1.58160132 -0.40165729
    -0.65208904 -0.02469954 1.53203035 -0.40784481 0.54030781 0.21712009
    -0.95663642 -0.49069632 -0.01902951 1.1198036 -0.65827656 1.53203035
    0.20691998 0.49937436 1.13595343 -0.01293737 -0.29542349 0.84485519
    0.83188488 0.34364609 0.54030781 0.95675902 0.90429525 0.83188488
    -0.65208904 -0.40165729 -1.58160132 0.38313956 -0.32924692 0.69768794
    1.47224468 1.22748297 0.83188488 1.42269911 -0.65827656 -0.35372918
    -0.01293737 1.53203035 0.95841088 -1.04249592 0.23749438 0.5606821
    1.20719077 0.91726555 -0.10329743 -0.57967867 0.27123572 1.69342306
    0.05809528 -0.65208904 -1.02662219 0.27123572 0.5606821 ]]
  • 实际的标签:classLabels
  • [-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0]

ROC曲线展示

def plotROC(predStrengths, classLabels):
    import matplotlib.pyplot as plt
    cur = (1.0,1.0) #cursor
    ySum = 0.0 #variable to calculate AUC
    numPosClas = sum(array(classLabels)==1.0)
    yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas)
    sortedIndicies = predStrengths.argsort()#get sorted index, it's reverse
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    #loop through all the values, drawing a line segment at each point
    for index in sortedIndicies.tolist()[0]:
        if classLabels[index] == 1.0:
            delX = 0; delY = yStep;
        else:
            delX = xStep; delY = 0;
            ySum += cur[1]
        #draw line from cur to (cur[0]-delX,cur[1]-delY)
        ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b')
        cur = (cur[0]-delX,cur[1]-delY)
    ax.plot([0,1],[0,1],'b--')
    plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
    plt.title('ROC curve for AdaBoost horse colic detection system')
    ax.axis([0,1,0,1])
    plt.show()
    print "the Area Under the Curve is: ",ySum*xStep
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值