

机器学习笔记(十三)——重中之重的性能度量方式你要懂
source link: https://segmentfault.com/a/1190000022481468
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

性能度量
本文参考《机器学习》和《机器学习实战》
在之前讲述的所有分类介绍中,我们都是假设所有类别的分类代价是一样的,由于主要探讨的是二分类问题,所以可看作1和0的分类代价相同。
而对于分类代价相同的问题,我们通常利用正确率或错误率来评价所构建分类器性能的好坏。比如手写数字识别系统,对于测试数据集,它的准确率可以达到98%,就可以说这个模型比较不错。
但是我们现在考虑癌症检测问题,我们也通过某种算法构建了一个准确率不错的分类器,将病人相关数据输入,会得出一个预测结果——阳性或阴性。假如这个人没有患病,分类器预测结果却是阳性,这可能只是影响病人的心情,在做几次检测可以解决的问题;但是假如这个人患病了,分类器预测结果为阴性,那么病人可能不会重视,直至癌症晚期,从而失去了生命。
这个时候分类器的准确率已经不足以评判该模型的好坏,因为我们更看重的是从患癌症中的人有多少可以被成功地检测出来,所以我们需要考察一种新的分类器性能度量的方法。
查准率、查全率
现在一般都会遇见一个情况就是在淘宝刚刚搜过的物品,而当你刷抖音或者朋友圈的时候会给推荐类似的商品。它肯定不可能随意推荐,一定是根据你的喜好,而这时就需要注重两个事情,一是“推荐的物品有多少是用户感兴趣的”、二是“用户感兴趣的物品有多少被推荐”。
针对上述两种情况,就有了查准率(precision)和查全率(recall)两种更加适应此类需求的性能度量,也可以称之为正确率和召回率,在不同文献中可能有不同的名字。
在介绍这两个概念之间需要知道什么是混淆矩阵:
其中T、F、P、N分别对应四个单词True、False、Positive、Negative。如何快速记下混淆矩阵呢?先看第一个字母,如果第一个字母为T,代表预测结果与真实结果一致,F则反之。
比如FN,预测出的结果是反例(N),但它预测结果与真实结果不一致(F),所以真实结果应该为正例(P);而对于TN,预测的结果是反例(N),但它预测的结果与真实结果一致(T),所以真实结果也为反例(N)。
由上述混淆矩阵就可以得出查准率公式和查全率公式。
查准率公式如下:
查全率公式如下:
查准率给出的是预测为正例的样本中的真正正例的比例;查全率给出的是预测为正例的真实正例占所有真实正例的比例。
可以很容易构造一个高查准率或高查全率的分类器,但是很难保证两者同时成立。比如将所有样本都判定为正例,那么此时查全率是很高的,但是查准率却很低,所以两者之间是相互矛盾的关系。
P-R曲线与F1度量
像逻辑回归、AdaBoost等算法构建出的分类器,并不能直接得出分类结果是1还是0,而是通过和一个阈值比较进行判断,前者是通过Sigmoid函数判断,后者则是通过符号函数sign判断。
假如对样本进行一个简单的排序,排在最前面的是分类器认为“最可能”分类为正例的样本,排在后面的则是分类器认为“最不可能”分类为正例的样本,按照这个顺序逐个把样本当做正例预测,每次就可算出当前的查准率和查全率。
而通过查准率和查全率则可绘制出相关的曲线——PR曲线:
对于不同分类器而言,当其对应的PR曲线越向右上角凸出则代表该分类器越优,比如B分类器优于C分类器。而对于产生交叉的两条曲线,则是比较其对应的“平衡点(BEP)”值的大小,平衡点就是曲线的查准率和查全率相等的点,所以A分类器优于B分类器。
除了“平衡点”之外,更加常用的是通过F1度量来判断两个分类器之间性能的高低:
而在不同的应用情景下,我们可能更加注重查准率和查全率其中之一,$F_\beta$则可以体现出分类器对查准率或查全率的偏好:
当$\beta=1$时,$F_\beta$退化至标准的F1度量;当$\beta>1$时,查全率有更大的影响;$\beta<1$时,查准率有更大的影响。
ROC曲线
除了PR曲线之外,ROC曲线也可以用来对模型性能评估,在绘制ROC曲线之前,也需要将样本进行排序,方式与绘制PR曲线前排序一致。PR曲线是以查准率和查全率作为横纵坐标轴,而ROC曲线是以真正例率(真阳率)、假正例率(假阳率)作为横纵坐标轴绘制曲线。
而真正例率和假正例率也是基于混淆矩阵得到的。
真正例率公式如下:
假正例率公式如下:
其中真正例率是真正例所占真实为正例的比例;假正例率是假正例所占真实为反例的比例。
以假正例率作为x轴、以真正例率作为y轴可绘制ROC曲线图如下:
上图有两个ROC曲线,左侧的预测样本是无限的,所以对应的ROC曲线是平滑的,虚线给出的是随机猜测的结果曲线;而现实中数据集都是有限的,所以右侧有棱角的ROC曲线才是常见的。
在理想的情况下,最佳分类器应该尽可能处于左上角,这意味着该分类器假正例率非常低的同时又有着很高的真正例率。
比较不同的ROC曲线通常是比较曲线所覆盖的阴影面积,这个指标被称作AUC,它只是给出的分类器的平均性能值,并不能完全代表ROC曲线,一个完美的分类器对应AUC的值为1.0,而随机猜测的AUC的值为0.5。下面将会给出绘制ROC曲线的代码,并作简要介绍。
上图中Inst#代表排序、Class代表分类标签(p为正、n为负)、Score代表预测强度,即有多少可能被分类器预测为正类,在这张图的基础上绘制ROC曲线。
首先在所有排序的样本最左边画一条线,如下:$$|1·2·3...20$$ 线左边的样本被认为是正类,右边的被认为是负类,此时TP=0,FN=10,TN=10,FP=0,所以TPR=0(Y轴),FPR=0(X轴),该点位于原点(0,0)。
然后将竖线向右移动,如下: $$1|2·3·4...20$$ 同样线左边的样本被认为是正类,右边的被认为是负类,此时TP=1,FN=9,TN=10,FP=0,所以TPR=0.1(Y轴),FPR=0(X轴)。
依次类推,知道竖线移动到20的右边,通过这样的推导就可以总结出一个规律,每次碰到一个预测为正类的样本,在Y方向上加一个步长,否则就要在X方向上加一个步长,Y轴步长和X轴步长就是1除以正类样本或者负类样本的个数。
当然这个前提是预测强度的排列由大到小排列,如果排列顺序是由小至大,起点就变成了(1,1),加一个步长相应变为减一个步长。
下面给出了绘制对应ROC曲线图的代码:
# 分类器的预测强度 predStrengths = [0.9,0.8,0.7,0.6,0.55,0.54,0.53,0.52,0.51,0.505, 0.4,0.39,0.38,0.37,0.36,0.35,0.34,0.33,0.30,0.1] # 类别标签 classLabels = [1,1,0,1,1,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0] font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14) # 中文字体 cur = (0.0, 0.0) # 起始位置 ySum = 0.0 numPosClas = np.sum(np.array(classLabels) == 1.0) # 统计正类的数量 yStep = 1 / float(numPosClas) # y轴步长 xStep = 1 / float(len(classLabels) - numPosClas) # x轴步长 print("y轴步长为:",yStep) print("x轴步长为:",xStep) sortedIndicies = sorted(predStrengths,reverse=True) # 将预测强度从大到小排列 fig = plt.figure() fig.clf() ax = plt.subplot(111) # 遍历整个类别数组,如果标签为1,纵轴加上一个步长; # 如果标签为0,横轴加上一个步长。 for index in range(len(sortedIndicies)): if classLabels[index] == 1: delX = 0; delY = yStep else: delX = xStep; delY = 0 ySum += cur[1] # 纵轴上的高度累加,用于计算AUC ax.plot([cur[0], cur[0] + delX], [cur[1], cur[1] + delY], c = 'b') # 绘制ROC曲线 cur = (cur[0] + delX, cur[1] + delY) #更新绘制光标的位置 ax.plot([0,1], [0,1], 'b--') # 绘制虚线 plt.title('ROC曲线', FontProperties = font) plt.xlabel('假正例率', FontProperties = font) plt.ylabel('真正例率', FontProperties = font) ax.axis([0, 1, 0, 1]) print('AUC面积为:', ySum * xStep) # 计算AUC的值 plt.show()
ROC曲线图片如下:
计算对应的AUC面积也是非常简单的,从图中可以看到Y轴步长和X轴步长都为0.1,我们可以将这个不规则图形划分成10个宽为0.1的矩形,所以只需要算出每个矩形的高,进行累加运算,然后在乘以0.1就可以得出AUC的面积。
总结
上述知识是机器学习中相当重要的一部分,也是机器学习的基础,因为构建一个分类器往往是比较容易的,而第一次构建出的分类器并不能保证其性能最优,所以在此基础上更多操作是对分类器进行调优,我们在调优时针对不同的应用场景可能度量分类器性能的方式也会有所不同。
欢迎各位伙伴和博主交流呀
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK