分类之性能评估指标

zh
zh
zh
26
文章
0
评论
2020-04-1803:05:00 评论 1,595 4709字
摘要

本文主要介绍几种常用的用于分类的性能评估指标,同时介绍如何绘制ROC曲线以及计算AUC值的便捷方法。最后再附上一个绘制ROC曲线和计算AUC的Python源码实现。

一.Precision和Recall

首先我们来看看下面这个混淆矩阵:

pred_label/true_label

Positive

Negative

Positive

TP

FP

Negtive

FN

TN

如上表所示,行表示预测的label值,列表示真实label值。TP,FP,FN,TN分别表示如下意思:

  • TP(true positive):表示样本的真实类别为正,最后预测得到的结果也为正;
  • FP(false positive):表示样本的真实类别为负,最后预测得到的结果却为正;
  • FN(false negative):表示样本的真实类别为正,最后预测得到的结果却为负;
  • TN(true negative):表示样本的真实类别为负,最后预测得到的结果也为负.

根据以上几个指标,可以分别计算出Accuracy、Precision、Recall(Sensitivity,SN),Specificity(SP)。

分类之性能评估指标

  • Accuracy:表示预测结果的精确度,预测正确的样本数除以总样本数。
  • precision,准确率,表示预测结果中,预测为正样本的样本中,正确预测为正样本的概率;
  • recall,召回率,表示在原始样本的正样本中,最后被正确预测为正样本的概率;
  • specificity,常常称作特异性,它研究的样本集是原始样本中的负样本,表示的是在这些负样本中最后被正确预测为负样本的概率。

在实际当中,我们往往希望得到的precision和recall都比较高,比如当FN和FP等于0的时候,他们的值都等于1。但是,它们往往在某种情况下是互斥的。例如,有50个正样本,50个负样本,结果全部预测为正样本,那么TP=50,FP=50,TN=0,FN=0,按照上面的公式计算,可以得到正样本的recall却为1,precision却为0.5.所以需要一种折衷的方式,因此就有了F1-score。

分类之性能评估指标

F1-score表示的是precision和recall的调和平均评估指标。

另外还有一个指标,即MCC,该指标对于不均衡数据集的评估非常有效,公式如下:

分类之性能评估指标

二.ROC曲线

ROC(receiver operating characteristic),平面的横坐标是false positive rate(FPR)假阳率,纵坐标是true positive rate(TPR)真阳率。ROC计算过程如下:

  • 首先每个样本都需要有一个label值,并且还需要一个预测的score值(取值0到1);
  • 然后按这个score对样本由大到小进行排序,假设这些数据位于表格中的一列,从上到下依次降序;
  • 现在从上到下按照样本点的取值进行划分,位于分界点上面的我们把它归为预测为正样本,位于分界点下面的归为负样本;
  • 分别计算出此时的TPR(Recall)=TP/P和FPR(1-SP)=FP/N,然后在图中绘制(FPR, TPR)点。

从上往下逐个样本计算,最后会得到一条光滑的曲线 。

然而,千言万语都不如下面这幅图懂得快:

分类之性能评估指标

『roc曲线绘制动画—图片来自[参考文献5]http://stats.stackexchange.com/questions/105501/understanding-roc-curve/105577

三.AUC计算

AUC(area under the curve)就是ROC曲线下方的面积,取值在0.5到1之间,因为随机猜测得到额AUC就是0.5。面积如下图所示,阴影部分即为AUC面积:

分类之性能评估指标

『AUC面积图解—图片来自[参考文献5]http://stats.stackexchange.com/questions/105501/understanding-roc-curve/105577

AUC的几种解释(来自【Interpreting the AUROC】):

  • The expectation that a uniformly drawn random positive is ranked before a uniformly drawn random negative.
  • The expected proportion of positives ranked before a uniformly drawn random negative.
  • The expected true positive rate if the ranking is split just before a uniformly drawn random negative.
  • The expected proportion of negatives ranked after a uniformly drawn random positive.
  • The expected false positive rate if the ranking is split just after a uniformly drawn random positive.

下面来介绍下它的计算方法,AUC的计算主要有以下三种。

第一种:积分思维。这也是在早期机器学习文献中常用的AUC计算方法。从积分的思想中演化而来的。假如我们的测试样本有限,那么我们得到的AUC曲线必然是呈现阶梯形状。因此,计算的AUC也就是这些阶梯下面的面积之和(有没有想起以前学高数时的积分面积哈)。我们可以这样来计算,首先把score值进行排序,假设score越大,此样本属于正类的概率就越大。然后一边扫描一边计算就可以得到我们想要的AUC。但是,这样做会有个缺点,当多个测试样本的score值相等时,我们调整一下阈值,得到的不是往上或者往右的延展,而是斜着向上形成一个梯形。此时,就需要计算这个梯形的面积,这样是比较麻烦。 简单的用代码描述下

  1. auc = 0.0
  2. height = 0.0
  3. for each training example x_i, y_i:
  4. if y_i = 1.0:
  5. height = height + tpr
  6. else
  7. auc += height * fpr
  8. 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如下:

依赖库:

  • numpy
  • matplotlib
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sat Mar 12 17:43:48 2016
  4. @author: liudiwei
  5. """
  6. import numpy as np
  7. import matplotlib.pyplot as plt
  8. def plotROC(predScore, labels):
  9. point = (1.0, 1.0) #由于下面排序的索引是从小到大,所以这里从(1,1)开始绘制
  10. ySum = 0.0
  11. numPos = np.sum(np.array(labels)==1.0)
  12. numNeg = len(labels)-numPos
  13. yStep = 1/np.float(numPos)
  14. xStep = 1/np.float(numNeg)
  15. sortedIndex = predScore.argsort() #对predScore进行排序,的到排序索引值
  16. fig = plt.figure()
  17. fig.clf()
  18. ax = plt.subplot(111)
  19. for index in sortedIndex.tolist()[0]:
  20. if labels[index] == 1.0: #如果正样本各入加1,则x不走动,y往下走动一步
  21. delX = 0
  22. delY = yStep;
  23. else: #否则,x往左走动一步,y不走动
  24. delX = xStep
  25. delY = 0
  26. ySum += point[1] #统计y走动的所有步数的和
  27. ax.plot([point[0], point[0] - delX], [point[1], point[1] - delY],c="b")
  28. point = (point[0] - delX, point[1] - delY)
  29. ax.plot([0,1],[0,1],"b--")
  30. plt.xlabel("False positive rate"); plt.ylabel("True positive rate")
  31. plt.title("ROC Curve")
  32. ax.axis([0, 1, 0, 1])
  33. plt.show()
  34. #最后,所有将所有矩形的高度进行累加,最后乘以xStep得到的总面积,即为AUC值
  35. 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

End.

作者:拾毅者

来源:『刘帝伟』维护的个人技术博客

本文均已和作者授权,如转载请与作者联系。

  • 我的微信公众号
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: