作者:拾毅者
原文:http://blog.csdn.net/dream_angel_z/article/details/50867951
本文主要介绍几种常用的分类评估指标,同时介绍如何绘制ROC曲线以及AUC值的便捷的计算方法。最后再附上一个绘制ROC曲线和计算AUC的源码实现。
首先我们来看看下面这个混淆矩阵:
pred_label/true_label | Positive | Negative |
---|---|---|
Positive | TP | FP |
Negtive | FN | TN |
如上表所示,行表示预测的label值,列表示真实label值。TP,FP,FN,TN分别表示如下意思:
根据以上几个指标,可以分别计算出Accuracy、Precision、Recall(Sensitivity,SN),Specificity(SP)。
在实际当中,我们往往希望得到的precision和recall都比较高,比如当FN和FP等于0的时候,他们的值都等于1。但是,它们往往在某种情况下是互斥的,比如这种情况,50个正样本,50个负样本,结果全部预测为正,那么它的precision为1而recall却为0.5.所以需要一种折衷的方式,因此就有了F1-score。
F1-score表示的是precision和recall的调和平均评估指标。
此外还有MCC:
ROC(receiver operating characteristic),平面的横坐标是false positive rate(FPR)假阳率,纵坐标是true positive rate(TPR)真阳率。ROC计算过程如下:
从上往下逐个样本计算,最后会得到一条光滑的曲线 。
然而,千言万语不如下面的这幅图懂得快:
AUC(area under the curve)就是ROC曲线下方的面积,取值在0.5到1之间,因为随机猜测得到额AUC就是0.5。面积如下图所示,阴影部分即为AUC面积:
AUC的几种解释(来自【Interpreting the AUROC】):
下面来介绍下它的计算方法,AUC的计算主要有以下三种。
第一种:积分思维。这也是在早期机器学习文献中常用的AUC计算方法。从积分的思想中演化而来的。假如我们的测试样本有限,那么我们得到的AUC曲线必然是呈现阶梯形状。因此,计算的AUC也就是这些阶梯下面的面积之和(有没有想起以前学高数时的积分面积哈)。我们可以这样来计算,首先把score值进行排序,假设score越大,此样本属于正类的概率就越大。然后一边扫描一边计算就可以得到我们想要的AUC。但是,这样做会有个缺点,当多个测试样本的score值相等时,我们调整一下阈值,得到的不是往上或者往右的延展,而是斜着向上形成一个梯形。此时,就需要计算这个梯形的面积,这样是比较麻烦。 简单的用代码描述下
auc = 0.0
height = 0.0
for each training example x_i, y_i:
if y_i = 1.0:
height = height + tpr
else
auc += height * fpr
return auc
第二种:Mann–Whitney U test(MWW)。关于AUC还有一个很有趣的性质,它和Wilcoxon-Mann-Witney Test类似(可以去google搜一下),而Wilcoxon-Mann-Witney Test就是测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。有了这个定义,就可以得到了另外一中计算AUC的方法:计算出这个概率值。我们知道,在有限样本中我们常用的得到概率的办法就是通过频率来估计之。这种估计随着样本规模的扩大而逐渐逼近真实值。样本数越多,计算的AUC越准确类似,也和计算积分的时候,小区间划分的越细,计算的越准确是同样的道理。具体来说就是: 统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score。当二元组中正负样本的 score相等的时候,按照0.5计算。然后除以MN。实现这个方法的复杂度为O(n^2 )。n为样本数(即n=M+N),公式表示如下:
第三种:该方法和上述第二种方法原理一样,但复杂度降低了。首先对score从大到小排序,然后令最大score对应的sample的rank值为n,第二大score对应sample的rank值为n-1,以此类推从n到1。然后把所有的正类样本的rank相加,再减去正类样本的score为最小的那M个值的情况。得到的结果就是有多少对正类样本的score值大于负类样本的score值,最后再除以M×N即可。值得注意的是,当存在score相等的时候,对于score相等的样本,需要赋予相同的rank值(无论这个相等的score是出现在同类样本还是不同类的样本之间,都需要这样处理)。具体操作就是再把所有这些score相等的样本 的rank取平均。然后再使用上述公式。此公式描述如下:
这三种方法,第一种比较好理解,后面两种确实不太好理解,先记下,慢慢理解。
最后,附上ROC曲线绘制代码。下面使用的思想类似积分,但是求得是AUC的近似值,忽略了梯形部分,Code如下:
依赖库:
# -*- coding: utf-8 -*-
""" Created on Sat Mar 12 17:43:48 2016 @author: liudiwei """
import numpy as np
import matplotlib.pyplot as plt
def plotROC(predScore, labels):
point = (1.0, 1.0) #由于下面排序的索引是从小到大,所以这里从(1,1)开始绘制
ySum = 0.0
numPos = np.sum(np.array(labels)==1.0)
numNeg = len(labels)-numPos
yStep = 1/np.float(numPos)
xStep = 1/np.float(numNeg)
sortedIndex = predScore.argsort() #对predScore进行排序,的到排序索引值
fig = plt.figure()
fig.clf()
ax = plt.subplot(111)
for index in sortedIndex.tolist()[0]:
if labels[index] == 1.0: #如果正样本各入加1,则x不走动,y往下走动一步
delX = 0
delY = yStep;
else: #否则,x往左走动一步,y不走动
delX = xStep
delY = 0
ySum += point[1] #统计y走动的所有步数的和
ax.plot([point[0], point[0] - delX], [point[1], point[1] - delY],c='b')
point = (point[0] - delX, point[1] - delY)
ax.plot([0,1],[0,1],'b--')
plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
plt.title('ROC Curve')
ax.axis([0, 1, 0, 1])
plt.show()
#最后,所有将所有矩形的高度进行累加,最后乘以xStep得到的总面积,即为AUC值
print "the Area Under the Curve is: ", ySum * xStep
对于ROC曲线绘制中的参数,输入的第二个参数是类别标签(如,+1,-1形成的文件,每行表示一个样本的真实类别);第一个参数则是由模型训练出来的预测强度,如Adaboost对样本i预测的结果为0.67,对i+1个样本预测的结果是0.3,等等,每行一个,格式和classLabels一样。最后绘制ROC曲线的同时,也在输出ROC曲线下方的AUC面积。
[1] https://en.wikipedia.org/wiki/Receiver_operating_characteristic
[2] http://blog.csdn.net/chjjunking/article/details/5933105
[3]《Machine Learning in Action》
[4] https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test
[5] Understanding ROC curve
[6] http://stats.stackexchange.com/questions/145566/how-to-calculate-area-under-the-curve-auc-or-the-c-statistic-by-hand