ROC和AUC的原理及AUC计算方法

1.非均衡分类问题

      在大多数情况下不同类别的分类代价并不相等,即将样本分类为正例或反例的代价是不能相提并论的。例如在垃圾邮件过滤中,我们希望重要的邮件永远不要被误判为垃圾邮件,还有在癌症检测中,宁愿误判也不漏判。在这种情况下,仅仅使用分类错误率来度量是不充分的,这样的度量错误掩盖了样例如何被错分的事实。所以,在分类中,当某个类别的重要性高于其他类别时,可以使用Precison和Recall多个比分类错误率更好的新指标。

Precison(查准率):预测为正例的样本中真正正例的比例。

Recall(召回率):真正为正例的样本有多少被预测出来。

      可见,我们可以根据我们最终的目标来选择度量指标。例如,在癌症检测中,我们希望选择Recall较高的模型(有病为正例)。而在垃圾邮件过滤中,我们希望选择Precison较高的模型。但是我们很容易构造一个高查准率或高召回率的分类器,但是很难保证两者同时成立。构建一个同时使两者很大的分类器是具有挑战性的。

      ROC就是一个用于度量分类中的非均衡性的工具


2.ROC曲线

ROC(Receiver Operating Characteristic)曲线和AUC(area under the curve)常被用来评价一个二值分类器(binary classifier)的优劣。

下面简单介绍ROC和AUC的特点,以及更为深入地讨论如何作出ROC曲线图以及计算AUC。

需要提前说明的是,我们这里只讨论二值分类器。对于分类器,或者说分类算法,评价指标主要有precision,recall,F-score,以及我们今天要讨论的ROC和AUC。

ROC可以用来比较不同分类器的相关性能,下图是一个ROC曲线的示例。

 

ROC和AUC的原理及AUC计算方法

其中,ROC曲线的横坐标为false positive rate(FPR 假阳率),纵坐标为true positive rate(TPR 真阳率)。

FPR:所有负例中有多少被预测为正例; TPR:有多少真正的正例被预测出来;

ROC 描绘了两者的相对权衡:

benefits(true postives)
costs(false positives)

下图中详细说明了FPR和TPR是如何定义的。

ROC和AUC的原理及AUC计算方法

F-measure: precison和recall的调和平均值。没有一个单个的度量可以告诉所有的信息,所以建议使用多个度量。

      接下来我们考虑ROC曲线图中的四个点和一条线:

第一个点,(0,1),即FPR=0, TPR=1,这意味着FN(false negative)=0,并且FP(false positive)=0。这是一个完美的分类器,它将所有的样本都正确分类。

第二个点,(1,0),即FPR=1,TPR=0,所有正例都被预测为负例,而所有正例都没被预测出来,这是一个最糟糕的分类器,因为它成功避开了所有的正确答案。

第三个点,(0,0),即FPR=TPR=0,即FP =TP =0,可以发现该分类器预测所有的样本都为负样本。

第四个点(1,1),分类器实际上预测所有的样本都为正样本。

       经过以上的分析,我们可以断言,ROC曲线越接近左上角,该分类器的性能越好,意味着分类器在假阳率很低的同时获得了很高的真阳率。
虚线y=x:这条对角线上的点其实表示的是一个采用随机猜测策略的分类器的结果。例如(0.5,0.5),表示该分类器随机对于一半的样本猜测其为正样本,另外一半的样本为负样本。出现在右下角三角形中的任何分类器都比随机猜测更糟糕。因此,在ROC图中,此三角形通常为空。

3.如何画ROC曲线

      对于一个特定的分类器和测试数据集,显然只能得到一个分类结果,即一组FPR和TPR结果,而要得到一个曲线,我们实际上需要一系列FPR和TPR的值,这又是如何得到的呢?

我们先来看Wikipedia上面对ROC曲线的定义:

“In signal detection theory, a receiver oprating 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.”
       问题在于“as its discrimination threashold is varied”。如何理解这里的“discrimination threashold”呢?它代表的是分类器以多大的置信度将样本分类为正样本。分类器的一个重要功能”概率输出“,即表示分类器认为某个样本具有多大的概率属于正样本(或负样本)。通过更深入地了解各个分类器的内部机理,我们总能想办法得到一种概率输出。通常来说,是将一个实数范围通过某个变换映射到(0,1)区间。

      假如我们已经得到了所有样本的概率输出(属于正样本的概率),那么我们就可以通过改变”discrimination threshold“来绘制ROC曲线。

(许多分类器,例如决策树或者规则集合,被设计产生一个类别决策,即将每个样本预测为Y或N。当使用这样的离散分类器时,产生一个单个额confusion矩阵,对应于一个ROC点。而一些分类器,例如Naive Bayes,产生一个样本概率值,这样一个ranking/scoring分类器可以使用一个threshold来产生一个discrete(binary)分类器:如果分类器输出的概率大于threshold,分类器产生Y,否则产生N。每个不同的threshold值在ROC空间产生一个不同的点(对应于一个不同的confusion matrix)。)

现在的问题是如何改变“discrimination threashold”?

具体过程如下所述:

1.如图,我们根据每个测试样本属于正样本的概率值score从大到小排序。(下图是一个示例,图中共有20个测试样本,“Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本))

 

ROC和AUC的原理及AUC计算方法

2.接着,我们从高到低,依次将score作为阈值threshold,当测试样本属于正样本的概率大于或等于这个threshold时,我们认为它为正样本,否则为负样本。

例如:对于图中第4个样本,其score值为0.6,那么score值大于等于0.6的样本1,2,3,4都被认为是正样本,而其他样本则被认为是负样本。

3.每次选取不同的score作为threshold,我们就可以得到一组FPR和TPR,即曲线上的一点。总共得到了20组FPR和TPR的值,将这些(FPR,TPR)对连接起来,就可以得到完整的ROC曲线如下图。(当threshold取值越多,ROC曲线就越平滑)

ROC和AUC的原理及AUC计算方法

当我们将threshold设置为1和0时,即分别对应将所有样本划分为负样本和将所有样本划分为正样本,就可以的得到曲线上的(0,0)和(1,1)两点。

      关于score值:分类器都会提供每个样例被判为阳性或者阴性的可信程度值,大多数分类器都能够做到这一点,但是在通常情况下,这些值会在最后输出离散分类标签之前被清除。例如,朴素贝叶斯能够提供一个可能值,在Logistic回归中输入到sigmoid函数中的是一个数值。在Adaboost和SVM中,都会计算一个数值然后输入到sign()函数中,所有的这些值都可以看做score,用于衡量给定分类器的预测强度。

      所以,我们并不一定要得到每个测试样本是正样本的概率值,只要得到这个分类器对该测试样本的“评分值”即可(评分值并不一定在(0,1)区间)。评分越高,表示分类器越肯定地认为这个测试样本是正样本,而且同时使用各个评分值作为threshold。我认为将评分值转化为概率更易于理解一些。

ROC和AUC的原理及AUC计算方法

      此图中,ROC点(0.1,0.5)产生了最高的准确率。注意到分类器的最好的准确率出现在threshold=0.54时,而不是我们认为的在类别平衡分布的threshold等于0.5处。

4.AUC值的计算

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

      在了解了ROC曲线的构造过程后,编写代码实现并不是一件困难的事情。相比自己编写代码,有时候阅读其他人的代码收获更多,当然过程也更痛苦些。在此推荐scikit-learn中关于计算AUC的代码。

AUC意味着什么
      那么AUC值的含义是什么呢?根据(Fawcett, 2006),AUC的值的含义是: > The AUC value is equivalent to the probability that a randomly chosen positive example is ranked higher than a randomly chosen negative example.

      这句话有些绕,我尝试解释一下:首先AUC值是一个概率值,当你随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值。当然,AUC值越大,当前的分类算法越有可能将正样本排在负样本前面,即能够更好的分类。

为什么使用ROC曲线
      既然已经这么多评价标准,为什么还要使用ROC和AUC呢?因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。而在这种情况下,ROC曲线能够保持不变。下图是ROC曲线和Precision-Recall曲线的对比:

ROC和AUC的原理及AUC计算方法

      在上图中,(a)和(c)为ROC曲线,(b)和(d)为Precision-Recall曲线。(a)和(b)展示的是分类其在原始测试集(正负样本分布平衡)的结果,(c)和(d)是将测试集中负样本的数量增加到原来的10倍后,分类器的结果。可以明显的看出,ROC曲线基本保持原貌,而Precision-Recall曲线则变化较大。

5.ROC曲线的python代码实现

ROC和AUC的原理及AUC计算方法

代码解释:

上述程序中的函数有两个输入参数,第一个参数就代表的是score,代表的是分类器的预测强度。第二个参数是classLabels,即样本真实的类标签。首先创建一个浮点数二元组cur,将它初始化为(0.0,0.0),代表从坐标点(0.0,0.0)开始绘制ROC曲线。接着通过数组过滤的方式计算正例的数目,并将该值赋给numPosClas,该值确定了在y坐标轴上的步进数目。(因为y轴的含义是有多少正例被预测出来,所以它的长度为正例的数目),相应的,也可以得到x轴的步长。

接下来,我们将score从大到小排序得到排序索引,因为threshold是从大到小设置。所以最开始threshold为1.0,即所有样本都被预测为负例,因此是从点(0,0)开始绘制。当在循环中遍历坐标点时,每当得到一个类别为1的样本,那么就要沿着y轴增加一个步长,即增加真阳率。对于类别为0的样本,则沿着x轴增加一个步长,增加假阳率。一旦确定了是在哪个轴的方向熵进行移动的,就可以在当前点和新点之间画出一条线段,再更新坐标点cur。

(例如,对与样本点1,当前threshold为0.9,即score大于等于0.9的样本为正,小于为负,那么样本点1就被预测为正,而该样本的真实标签也为正,所以真阳率+1。同理,当遍历到样本3时,threshold设为0.7,此时样本3被预测为正例,但是该样本其实为负例,所以假阳率+1,代表又一个负样本被误判为正例。)

为了计算,我们需要对多个小矩形的面积进行累加。这些小矩形的宽度是xStep,因此我们可以对所有矩形的高度进行累加,所有高度的和随着x轴的每次移动而依次增加,然后再乘以xStep得到总面积。

运行结果:

ROC和AUC的原理及AUC计算方法

       说明,文中图都来自论文(Fawcett, 2006)截图.