ROC介绍及AUC计算方法

来源:互联网 发布:网络教育统考课程作弊 编辑:程序博客网 时间:2024/05/29 21:34

近段时间看了下有关ROC和AUC的相关知识,在这里总结一下,有任何不对的地方,欢迎大家指正。

基础知识

针对一个二分类问题,每个测试样本都会有一个真实分类和预测分类,因此可以得到四种结果:

  • 真阳性(true positive):真实值为正,预测值也为正;
  • 假阳性(false positive):真实值为正,预测值为负;
  • 真阴性(true negative):真实值为负,预测值为正;
  • 假阴性(false negative):真实值为负,预测值也为负。

其关系如下图所示:

真阳性率TPR = TP / (TP+FN)
假阳性率FPR = FP / (FP+TN)
真阳性率和假阳性率是ROC最主要的两个基础指标。

ROC介绍

ROC的全名叫做Receiver Operating Characteristic,其主要分析工具是一个画在二维平面上的曲线——ROC curve。

平面的横坐标是false positive rate(FPR),纵坐标是true positive rate(TPR)。将一系列(FPR, TPR)点连接起来,即构成了ROC曲线。那么问题来了,怎么得到这一系列(FPR, TPR)点呢?
在这里引用下Wikipedia上对ROC的定义:

In signal detection theory, a receiver operating characteristic (ROC), or simply ROC curve, is a graphical plot which illustrates the performance of a binary classifier system as its discrimination threshold is varied.

针对特定的分类器和测试数据集,如何对测试样本进行分类呢?首先分类器会为测试样本打一个score,表示该样本预测为正类的概率,当score大于指定的threshold时,预测为正类,否则预测为负类。这样每个样本都会有一个真实的分类和预测的分类,统计计算得到TP,FP,TN,FN,由此就可以计算得到一个(FPR, TPR)点。
结合Wikipedia上上对ROC的定义和分类器预测过程,我们可以通过改变不同的threshold,就可以得到一系列的(FPR, TPR)点。在实际操作过程中,将测试样本按照预测分值从大到小排序,以每一个预测分值为threshold,大于等于threshold的都预测为正,否则预测为负,这样就能得到该score的(FPR, TPR)。
下面举个栗子,如下表所示,一共有五个测试样本,预测分值为0.9,0.8,0.7,0.5,0.3,对应的真实分类为1,1,-1,-1,1。当0.7为threshold时,对应的预测分类为1,1,1,-1,-1。
此时,TP=2,FP=1,TN=1,FN=1,TPR = TP / (TP+FN) = 2/3,FPR = FP / (FP+TN) = 1/2。

序号 分值 真实分类 5 0.9 1 4 0.8 1 3 0.7 -1 2 0.5 -1 1 0.3 1

AUC引用

虽然,用ROC curve来表示分类器的performance很直观好用。可是,人们总是希望能有一个数值来标志分类器的好坏。于是Area Under roc Curve(AUC)就出现了。顾名思义,AUC的值就是处于ROC曲线下方的那部分面积的大小。通常,AUC的值介于0.5到1.0之间,较大的AUC代表了较好的performance。下面主要总结下AUC的计算方法。

方法一

最直观的,根据AUC这个名称,我们知道,计算出ROC曲线下面的面积,就是AUC的值。计算ROC曲线上任意两个相邻点的连线与x轴构成的梯形面积,将这些梯形面积累加,就得到最终的AUC。计算公式如下:

AUC=i=0n1(xi+1xi)(yi+1+yi)2

方法二

一个关于AUC的很有趣的性质是,它和Wilcoxon-Mann-Witney Test是等价的,而Wilcoxon-Mann-Witney Test就是测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。有了这个定义,我们就得到了另外一中计算AUC的办法。具体来说就是统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score。当二元组中正负样本的 score相等的时候,按照0.5计算。然后除以MN。实现这个方法的复杂度为O(n^2)。n为样本数(即n=M+N)。

方法三

第三种方法实际上和上述第二种方法是一样的,但是复杂度减小了。它也是首先对score从大到小排序,然后令最大score对应的rank为n,第二大score对应的rank为n-1,以此类推。然后把所有的正类样本的rank相加,再减去正正样本组合在一起的个数。得到的就是所有样本中正类样本的score大于负类样本的score的样本对个数。然后再除以M×N。这种方法理解起来稍微有点难度,假设样本排序后第一个正样本的rank为ranki,排在它前面的都预测为正样本,不能够用来组成正负样本对了,因此只能和它后续的样本进行组合,组合方式一共有ranki种(包含与自身的组合),其中与正样本组合的方式一共有M种,因此第一个正样本能够组成的正负样本的个数为(ranki-M),以此类推,第二个正样本组成的个数为(rankj-(M-1)),… …。总和为(ranki-M)+ (rankj-(M-1)) + … + (rankk-1) = iϵpositiverankiM(M+1)2

AUC=iϵpositiverankiM(M+1)2MN

以上表为例,AUC=(5+4+1)34/232=0.67
另外,特别需要注意的是,再存在score相等的情况时,对相等score的样本,需要 赋予相同的rank(无论这个相等的score是出现在同类样本还是不同类的样本之间,都需要这样处理)。具体操作就是再把所有这些score相等的样本 的rank取平均。然后再使用上述公式。我简单实现了下方法三,对应的scala代码实现如下:

def areaUnderROC(data:Array[((Double, Double), Int)]): Double = {    var positive_num = 0    var negative_num = 0    var cur_positive_num = 0    var cur_count = 0    var cur_rank_num = 0.0    var sum_rank = 0.0    var last_score = -1.0    val count = data.length    var i = 0    while(i < count) {        if(data(i)._1._2 > 0) positive_num += 1 else negative_num += 1        val cur_score = data(i)._1._1        if(last_score != cur_score && last_score != -1.0) {            sum_rank += cur_rank_num / cur_count * cur_positive_num            cur_rank_num = 0.0            cur_count = 0            cur_positive_num = 0        }        cur_rank_num += data(i)._2        cur_count += 1        if(data(i)._1._2 > 0) cur_positive_num += 1        last_score = data(i)._1._1        i += 1    }    if(last_score != -1.0) {    sum_rank += cur_rank_num / cur_count * cur_positive_num    }    var auc = 0.0    if(positive_num == 0) {        auc = 0.0    } else if(negative_num == 0) {        auc = 1.0    } else {        auc = (sum_rank - positive_num * (positive_num + 1) / 2) / (positive_num * negative_num)    }    auc}

AUC计算的分布式实现

最后简单介绍下MLLib中的AUC计算实现过程,只介绍下大致流程,详细地可以参考Spark Evaluation Metrics,其实就是对第一种计算方式的实现。

  • 首先预测分聚合计算每个预测分的正负样本个数;
  • 按照预测分降序排列;
  • 在每个partition内部累加正负样本数;
  • 在partition间累加正负样本数,并得到总的正负样本数;
  • 根据每个预测分,首先累计上一个partition的正负样本数,再在本partition内部累加排序在该预测分之前的预测分的正负样本数;
  • 计算每个预测分的TPR和FPR;
  • 最后根据AUC=n1i=0(xi+1xi)(yi+1+yi)2得到最终的AUC。