在机器学习中的分类算法模型的准确率当然越高越好,但往往实际工作中几乎不会出现完全正确的模型,这就需要一个指标来衡量一个算法模型的质量,或者说算法模型要达到什么指标才是合格的呢?
混淆矩阵
混淆矩阵主要用来比较分类结果和实例的真实信息。矩阵中的每一行代表实例的预测类别,每一列代表实例的真实类别。
先给大家解释一下这个表格吧
真正例(True Positive , TP):被模型预测为正的正样本。
假正例(False Positive , FP):被模型预测为正的负样本。
假负例(False Negative , FN):被模型预测为负的正样本。
真负例(True Negative , TN):被模型预测为负的负样本。
真正率(True Positive Rate,TPR):TPR=TP/(TP+FN),即被预测为正的正样本数 /正样本实际数。
假正率(False Positive Rate,FPR) :FPR=FP/(FP+TN),即被预测为正的负样本数 /负样本实际数。
假负率(False Negative Rate,FNR) :FNR=FN/(TP+FN),即被预测为负的正样本数 /正样本实际数。
真负率(True Negative Rate,TNR):TNR=TN/(TN+FP),即被预测为负的负样本数 /负样本实际数/2
那我们怎么从这个混淆矩阵的信息来做模型的评估呢,我们以新闻分类为例
准确率(Accuracy)
准确率是最常用的分类性能指标,可以最直观有效的,从名字上也不难理解,就是预测正确的数量占总的数量的百分比,即:
则上面新闻分类模型的准确率为:
我们这里再思考一下,假如数据分布不平衡,本来军事新闻假如说有90篇,那么单单看准确率是不是就不能够确定分类器的性能好坏呢?为了更好的评估分类不平衡的数据集问题,又引入精确率(Precision)和召回率(Recall)
精确率(Precision)
也许有小伙伴看到精确率会觉得和准确率不是一样吗,这里精确率是指在被模型预测的正类样本中,实际是正样本的比例,即:
则上面军事新闻的精确率就是
精确率只是针对预测正确的正样本而不是所有预测正确的样本。表现为预测出是正的里面有多少真正是正的。可理解为查准率
召回率(Recall)
召回率可以体现出在实际正样本中,分类器能预测出多少,可理解为查全率,当没有假负例出现时,召回率就是1.0,召回率的公式可以定义为:
那么上面军事类新闻的召回率就是
有了精确率和召回率这两个指标在优化算法时候就有一个初步的思路了,但是在实际问题中,这两个指标通常是此消彼长的,我们想要全面评估模型的有效性,就必须同时检查精确率和召回率,因此就又有了一个综合评价指标F1-Score
F1-Score
何为F1-Score呢,其实是从F-Measure的公式中转化过来的
F-Measure是一种统计量,又称F-Score,也是精确率(Presicion)和召回率(Recall)的加权调和平均,常用于评价分类模型的好坏,经常在信息检索和自然语言处理中使用
我们先看一下F-Measure的数学公式
这里的P是精准率(Precision),R是召回率(Recall),α是参数
当α=1时,就是我们常见的F1-Score了:即:
可能我们最常见的公式是这样写的
其实就是由α=1时的F-Measure公式得来的
当α=0时,公式就是F=P,退化为精准率
当0<α<1时,精准率的影响较大,当α无限接近于0时,就可以认为只有精准率有效
当α>1时,召回率的影响较大,当α无穷大时,就可以认为只有召回率有效
在不同的情况下,对精准率和召回率的偏重是不一样的
在推荐系统中,为了尽可能少打扰用户,更希望推荐的内容是用户喜欢的,这时,精准率比较重要,这时候我们优化就可以在优先保证精准率的前提下提高召回率
在搜索系统中,更希望尽可能全面的所有相关的内容,此时召回率比较重要,这时候我们优化就可以在优先保证召回率的前提下提高精准率
当然除了这几个评估方式还有曲线图的评估方式,可以更直观看出模型的性能
ROC曲线
在之前的文章中我提到的的逻辑回归二分类,对于正负例的判定需要设置一个阈值,大于阈值的为正例,小于阈值为负例。也许有小伙伴可能会说那我们把阈值设置的小一点,不就能提高正例的识别率了吗?但是同时也会有更多的反例被识别成正例,为了直观的表达出这个现象,就引入了ROC曲线,根据分类结果计算得到ROC空间中相应的点,连接这些点就形成ROC curve,横坐标为False Positive Rate(FPR假正率),纵坐标为True Positive Rate(TPR真正率)。一般情况下,这个曲线都应该处于(0,0)和(1,1)连线的上方,如图:
一般来说,只要ROC曲线越接近左上角,并且曲线是光滑的,那么基本上就可以确定这个模型没有很大的问题
AUC
在上面的ROC曲线图中我们可以看到有个ROC curve(auc=0.86),那这个0.86是怎么来的呢,auc又是什么呢?
AUC(Area Under Curve)被定义为ROC曲线下的面积,我们也可以说是ROC的积分(这里是指微积分里的积分哈),通常大于0.5小于1。随机挑选一个正样本以及一个负样本,分类器判定正样本的值高于负样本的概率就是 AUC 值。这样说可能理解不太容易,我们从另个角度来看AUC。
如果我们把预测结果按照预测的分数进行升序排列,那么正常来说排在前面的应该都是负样本,因此我们就可以把问题转化为负样本排在正样本前面的概率
这里我举个例子,假如我们有下面已经排好序的预测结果的数据,正样本标签为1,负样本标签为-1
label,score
-1,-0.2
1,-0.1
1,0
-1,0.1
1,0.2
-1,0.3
-1,0.4
-1,0.5
1,0.6
1,0.7
1,0.8
1,0.9
1,0.91
1,0.92
1,0.93
1,0.94
1,0.95
1,0.96
1,0.97
1,0.98
python计算代码
x = 0 #负样本个数
y = 0 #正样本个数
a = 0 #错误正负样本pair对的个数
datalist = []
with open("data.txt", 'r') as fd:
for line in fd:
fs = line.strip().split(',')
label = int(fs[0])
score = float(fs[1])
datalist.append((label,score))
print(datalist)
for one in datalist:
if one[0]==-1:
x+=1
a+=y
if one[0] == 1:
y+=1
print(1.0-a/(x*y))
如果所有的负样本都排在正样本前面,那么这个a就是0,我们看一下结果
xy代表了可以产生的正负样本的组合的总数
a/(xy) 就是错误率,最后再用1减去这个错误率就是正确的概率
#output
0.8533333333333333
接下来我们用sklearn库里的auc函数来验证一下我们的结果
from sklearn.metrics import roc_curve, auc
label_list = []
score_list = []
for one in datalist:
label_list.append(one[0])
score_list.append(one[1])
fpr, tpr, _ = roc_curve(label_list, score_list)
auc = auc(fpr, tpr)
print(auc)
#output
0.853333333333
PR曲线
PR曲线的纵坐标是精确率P,横坐标是召回率R。评价标准和ROC一样,先看平滑不平滑,如下图:
从图中可以看到这个模型效果不太理想,曲线不够光滑,另外,根据逐个样本作为阈值划分点的方法,可以推敲出,recall值是递增的(但并非严格递增),随着划分点左移,正例被判别为正例的越来越多,不会减少。而精确率precision并非递减,二是有可能振荡的,虽然正例被判为正例的变多,但负例被判为正例的也变多了,因此precision会振荡,但整体趋势是下降
另外,PR曲线肯定会经过(0,0)点,当阈值点设置过于高,将所有的样本全部判为负例,则TP=0,那么P=R=0,因此会经过(0,0)点,但随着阈值点降低,精确率初始很接近1,召回率很接近0,因此有可能从(0,0)上升的线和坐标重合,不易区分。如果最前面几个点都是负例,那么曲线会从(0,0)点开始逐渐上升。
曲线最终不会到(1,0)点。很多P-R曲线的终点看着都是(1,0)点,这可能是因为负例远远多于正例。
因此,较合理的P-R曲线应该是(曲线一开始被从(0,0)拉升到(0,1),并且前面的都预测对了,全是正例,因此precision一直是1,)