准确度、精确率、召回率、F1值作为评估指标,经常用到评估模型的分类效率。准确度评估预测正确的比例,精确率评估预测正例的查准率,召回率评估真实正例的查全率,二分类问题比较好理解,面对多分类问题拆分成多个二分类问题,分别计算各个类别的每个类别的精确率和召回率,最终求均值既能作为所有样本的评估指标
一、基本概念
这里引入混淆矩阵并介绍Posion和Negative的概念,模型的优劣是借助目标样本作为评估载体来衡量的,目标样本定义为阳性(或称为Position、正),与之相对的则定义为隐性(或称为Negative、负)。而在预测过程中,则会出现以下四种情况,从而构建出基于预测值-实际值的混淆矩阵:
TP(True Positives):真阳性,又称为真正例,预测为阳性而且实际上也是阳性
TN(True Negatives):真阴性,又称为真负例,预测为阴性而且实际上也是阴性
FP(False Positives):假阳性,又称为假正例,预测为阳性然而实际上却是阴性,属于误报 (在统计学假设检验中,假阳性也称为I型错误 Type I error)
FN(false Negatives):假阴性,又称为假负例,预测为阴性然而实际上却是阳性,属于漏报 (在统计学假设检验中,假阴性也称为II型错误 Type II error)
阴性或阳性代表的是模型对样本的预测值,真假是与实际值比较是否一致的结论,一致为真相反为假。真阳性,代表模型预测值为阳性,与实际值一致,因此,遇到混淆矩阵的四种情况时,先考虑阴性阳性是预测结果值,再根据真假推断实际值,并统计出对应情况的样本数
用二分类的问题类举例,有10个不同编号的黑白小球,分别有3个黑球和7个白球:
模型预测同样编号小球的结果为黑球4个,白球6个。为了醒目将预测正确的结果用红色标出:
准确率 Accuracy
准确率:所有预测样本中预测正确所占的比例,主要关注的是对整体预测结果的正确性,即包含阴性的正确性TN也包含阳性的正确性TP,用公式表示:
以黑球为阳性P,则预测黑球正确的样本数TP=2,预测白球正确的样本数TN=5,预测黑球错误的样本数FP=2,预测白球错误的样本数FN=1,
预测结果中红色代表全部预测正确T的共7个样本数(黑色2个TP和白色5个TN),预测结果总共有10个样本(TP+TN+FP+FN),则 ACC = (2+5)/10 = 0.7
注意,若以白球为阳性P,则全部预测正确T的同样也是7个样本数,预测结果同样共有10个样本,此时同样 ACC = 0.7,由此可见,准确率代表的是模型预测正确的能力,无论以何种标签值作为阳性P都是同样的结果
数据样本不平衡
分析数据会遇到一个样本数据不平衡的情况,如数据量呈现8比2的比例,这种情况下在做机器学习就需要考虑如何合理的训练与分配数据,值得一提的是,样本不平衡的情况并不罕见
一、样本不平衡会带来什么问题
假设有10个人的数据集中有8个好人和2个坏人,如果存在一个机器学习模型,对每一个样本“人”进行判断时都贴上“好人”的标签,那么模型的预测结果将会全是“好人”
在8个好人和2个坏人的10人数据集中,经过某机器学习模型运算,8个好人被预测为好人,2个坏人也被预测为好人,则以好人作为目标样本,假设好人为阳性,并根据混淆矩阵的定义,TP=8(将阳性好人正确预测为阳性好人),TN=0,FP=2(将阴性坏人错误预测为阳性好人),FN=0
则该模型的预测准确率为:
Accuracy = (8+0)/(8+0+2+0) = 0.8
同样也可以借助坏人作为目标样本,假设坏人为阳性,则TP=0,TN=8(将阴性好人正确预测为阴性好人),FP=0(将阴性好人错误预测为阳性坏人),FN=2(将阳性坏人错误预测为阴性好人),依然可以得到模型的的预测准确率为Accuracy = (0+8)/(0+8+0+2) = 0.8
由此可见,目标样本只是用来作为计算准确率的辅助载体,无论目标样本使用哪种样本作为阳性,准确率公式分母指代的所有样本TP+TN+FP+FN数目始终是相同的,而分子指代的正确预测阳性和正确预测阴性(TP+TN)的样本数目也始终是相同的,所以都不会影响代表模型预测数据集的准确率
注意,这是一个不能分辨好坏人的模型,却依然可以有高达80%的准确率,如果轻信这样一个模型的数据集预测结果是不明智的,究其原因在于这是一个极端不平衡的数据集,很明显采用准确率对不平衡数据集进行评估方法是有不那么管用的
二、准确率作为样本不平衡数据集的模型评估指标失效的原因
准确率是非常直观的评估指标,在二分类任务中,因为结果总共只有好人(Positive)或者坏人(Negative),根据准确率公式,准确率体现的就是模型正确预测的能力,即所有正确预测(包含正确预测好人的和正确预测坏人的)的样本除以所有的样本。
准确率 = 正确预测阳性的能力(TP)+ 正确预测阴性的能力(TN)。
只预测好人的模型虽然不能够识别坏人,但是准确率是正确预测好人和正确预测坏人的总和,单方面的正确预测好人能力占总和的比重足够高也对准确率有决定性影响,如果数据集中好人坏人各占50%,那么预测全为好人(TP=50%,TN=0%)则表示模型正确预测能力就是50%,而只要数据集中好人多于坏人,那么就可以保证预测能力大于50%,如果全是好人,那么准确率就能到达100%。准确率就是这么被误导的。在数据不平衡的情况下,预测阳性能力的占比可能远大于一半,从而掩盖了预测阴性能力弱的事实。
这就是为什么在数据不平衡的情况下,准确率无法体现模型的真实水平。直接在数据不平衡下用准确率作为指标,将准确率高达90%的模型作为评估结果,这样的准确率和模型在实际预测中是毫无意义的。
三、从图形上解释混淆矩阵和准确率
在分类的逻辑回归预测函数评估中,预测结果是是一个连续性概率值,假设真值函数和预测函数的概率分布为正态分布,可将正态分布的凸起部分作为阳性的概率分布,平伏部分作为阴性的概率分布,由于预测函数不可能完全拟合真值函数,因此这两者的正态分布明显不会完全相同。
可转化为概率分布的散点图,图中黑色圆圈代表真值函数,红色圆圈代表预测函数,小圆球代表阳性,小圆环代表阴性。
由此可以很清楚地看出TN、FN、TP、FP所代表的含义以及相互间关系。而在实际的预测中,可能会没有FN或FP的情况,这取决于预测函数拟合真值函数时两者之间的位置包含关系。
四、样本不平衡数据集的模型评估指标
精确率 Precision
精确率:又称“查准率”,是以预测结果为判断依据,判断预测为阳性的样本中预测正确所占比例。关注的是阳性预测结果的正确性,决定该正确性的关键是假阳性FP,由于分母是限定范围的依据标准,即是以预测的阳性结果为衡量基准,用以衡量其中预测正确的比例,所以精确率就是阳性预测结果的准确度,而阳性预测结果分两种,要么实际是阳性的TP,要么实际是阴性的FP,用公式表示:
以黑球为阳性P,预测结果中为阳性的共有4个样本(黑色4个P),其中预测正确的有2个样本(TP),则 precision = 2/4 = 0.5
注意,若以白球为阳性P,则预测结果中为阳性的共有6个样本(白色6个P),其中预测正确的有5个样本(TP),则 precision = 5/6 = 0.83,与准确率的预测结果正确性不同,精确率是以阳性预测结果的正确性,也即阳性预测结果的准确度,是需要先确定阳性样本对象条件的
召回率 Recall
召回率:又称为“查全率”,是以实际样本为判断依据,判断实际阳性的样本中被预测正确所占的比例。关注的是实际阳性样本被预测的完整性,决定完整性的关键是假阴性FN,评估所有实际阳性样本是否被全部预测出来,召回率就是实际阳性样本的预测准确度,而实际阳性样本中,要么被预测正确TP,要么被预测错误FN,用公式表示:
以黑球为阳性P,实际样本中为阳性的共有3个(黑色3个P),其中预测正确的有2个样本(TP),则 recall = 2/3 = 0.67
同样注意,若以白球为阳性P,实际样本中为阳性的共有7个(白色7个),其中预测正确的5个样本(TP),则 recall = 5/7 = 0.71 ,与查准率相似,查全率是实际阳性样本被预测的准确度,同样需要先确定阳性样本对象条件
从图形上解释精确率和召回率
举个猫狗识别分类的例子,如下图所示,圆形区域代表识别结果,画布中线代表现实分类,小圆球代表狗的图片,小圆环代表猫的图片。现在利用模型去识别狗(阳性)的图片,结果在识别出的8张图片中有5张是狗的图片(TP),3张是猫的图片(FP误报),得到则该模型的精确率precision=5/8,召回率recall=5/12。
单独用精确率或者召回率是否能很好的评估模型好坏
1、什么情况下精确率很高但是召回率很低?
精确率高代表预测阳性结果中的TP命中数高,召回率低代表实际样本被预测的TP命中数低,那么,两者同时满足对相同的命中数TP而言阳性的预测结果样本会低于阳性的实际样本,即预测模型只预测正确了较少的实际阳性样本就可能造成这种情况,比如黑球为阳性实际样本有3个,分别是1、2、3号球,如果只预测出1号球是黑色,此时本该阳性的样本都被漏报了,精确率p=1,但是召回率r=1/3
2、什么情况下召回率很高但是精确率很低?
同样,精确率低代表预测阳性结果中的TP命中数低,召回率高代表实际样本被预测的TP命中数高,同时满足则阳性预测结果样本高于阳性的实际样本,即预测模型预测出了比实际阳性样本更多的样本就可能造成这种情况,比如黑球为阳性实际样本只有3个,分别是1、2、3号球,如果10个球都被预测为黑球,此时本该阴性的样本都被虚报了,召回率r=1,精确率p=3/10
对于不平衡的数据集,在现实中,往往都在追求捕捉占少数的样本,如判断潜在犯罪者和普通人的例子,潜在犯罪者相比普通人毕竟是极少数,一方面单纯地追求捕捉全少数样本而波及普通人,就会令甄别成本上升,另一方面过于放开对少数样本的捕捉力度导致漏掉潜在犯罪者,又会无法达成模型的目标。所以在现实中,往往在寻找捕全少数样本的能力(查全率)和将多数样本错判后需要付出的成本(查准率)之间的平衡。由此可见,准确率和召回率是互相影响的,理想情况下肯定是做到两者都高,但一般情况下召回率和精确率是此消彼长的,两者之间的平衡代表了尽可能捕全少数样本的需求和尽量不要误伤多数样本的需求的博弈。究竟要偏向于哪一方,取决于对业务的需求: 究竟是误伤多数类的成本更高,还是无法捕捉少数类的代价更高,如果是做搜索,那就是保证召回率的情况下提升准确率;如果做疾病监测、反垃圾,则是保证准确率的条件下提升召回率。
F1值
为了同时兼顾精确率和召回率,创造了两者的调和平均数作为考量两者平衡的综合性指标,称之为F-measure。F-Measure是Precision和Recall加权调和平均数
当参数α=1时,就是最常见的F1,即Precision和Recall的调和平均数,两个数之间的调和平均倾向于靠近两个数中比较小的那一个数,因此追求尽量高的F1, 能够保证精确率和召回率都比较高。F1在[0,1]之间分布,越接近1越好,因为F1综合了P和R的结果,当F1较高时则能说明试验方法比较有效
当在样本不平衡数据集中,如实际有10个黑球0个白球,以黑球为阳性进行模型预测也全被正确预测为阳性,此时P和R同时为1,F1=1。当有一个很大,另一个很小的时候,比如P=1,R~0,此时F1~0。分子2PR的2完全是为了使F1的最终取值在0-1之间,进行区间放大,无实际意义
sklearn 的评估函数
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
y_true = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
y_pred = [1, 1, 0, 1, 1, 0, 0, 0, 0, 0]
print("acc:", accuracy_score(y_true, y_pred))
print("p:", precision_score(y_true, y_pred))
print("r:", recall_score(y_true, y_pred))
print("f1:", f1_score(y_true, y_pred))
输出结果为
acc: 0.7
p: 0.5
r: 0.6666666666666666
f1: 0.5714285714285715
pyspark 的评估函数
from pyspark.mllib.evaluation import MulticlassMetrics
from pyspark import SparkConf, SparkContext
conf = SparkConf() \
.setMaster("local") \
.setAppName("Metrics-test")
sc = SparkContext(conf=conf)
predictionAndLabels = sc.parallelize([ #(预测值,真实值)
(1.0, 1.0),
(1.0, 1.0),
(0.0, 1.0),
(1.0, 0.0),
(1.0, 0.0),
(0.0, 0.0),
(0.0, 0.0),
(0.0, 0.0),
(0.0, 0.0),
(0.0, 0.0)])
metrics = MulticlassMetrics(predictionAndLabels)
print("acc:", metrics.accuracy)
print("p:", metrics.precision(1.0)) # 必须传入label值,否则统计的是类别0和类别1的均值
print("r:", metrics.recall(1.0))
print("f1", metrics.fMeasure(1.0))
tensorflow 的评估函数
import tensorflow as tf
train_graph = tf.Graph()
with train_graph.as_default():
labels = tf.constant([1, 1, 1, 0, 0, 0, 0, 0, 0, 0])
predicts = tf.constant([1, 1, 0, 1, 1, 0, 0, 0, 0, 0])
# 返回的是一个二元组tuple
accuracy = tf.metrics.accuracy(labels, predicts)
precision = tf.metrics.precision(labels, predicts)
recall = tf.metrics.recall(labels, predicts)
f1 = tf.metrics.mean((2 * precision[1] * recall[1]) / (precision[1] + recall[1]), name='f1_score')
with tf.Session(graph=train_graph) as sess:
sess.run(tf.local_variables_initializer())
result = sess.run([accuracy, precision, recall, f1])
print(result)
输出结果为
[(0.0, 0.7), (1.0, 0.5), (1.0, 0.6666667), (0.0, 0.57142854)]
多分类下的评估
多分类问题的评估是可以转换成多个二分类的评估方式的,最后求均值就是多分类的评估指标
二分类也可以看成是特殊的多分类,比如黑球和白球的预测问题。前面都是拿预测黑球当作阳性,完全忽视了白球的预测情况,这样的评估也是不够完全的。如果也要考虑白球的预测情况,该如何修改评估指标?先算出黑球为阳性时的评估指标,精确率、召回率、F1值,然后可以把白球当作阳性,再算一次白球的精确率、召回率、F1值。最后算精确率的时候可以把黑球的准确率和白球的准确率进行求均值,就可以作为最后的评估指标
之前的例子中,黑球为阳性时,p = 2/4;同理可计算白球为阳性时,p = 5/6;如果不考虑样本分布,无加权求均值,p = (2/4+5/6)/2 。用sklearn的代码实现这个逻辑
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
y_true = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
y_pred = [1, 1, 0, 1, 1, 0, 0, 0, 0, 0]
print("p:", precision_score(y_true, y_pred, average='macro'))
输出结果为:
p: 0.6666666666666667
sklearn还支持其他求均值方式,也可以设置权重值
类别更多的情况下,加入球色有黑、白、蓝三种颜色的球,真实颜色和预测颜色如下表格
对预测结果统计成混淆矩阵
计算准确率:
(2+3+1)/(2+1+1+1+3+1+0+0+1) = 0.6
按颜色计算精确率:
黑色为阳性时的P = 2/(2+1+1) = 0.5
白色为阳性时的P = 3/(3+1+1) = 0.6
蓝色为阳性时的P = 1/(1+0+0) = 1
求得均值为 (0.5+0.6+1)/3 = 0.7
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
y_true = [1, 1, 1, 0, 2, 0, 2, 2, 0, 0]
y_pred = [1, 1, 0, 1, 1, 0, 2, 0, 0, 0]
print("acc:", accuracy_score(y_true, y_pred))
print("p:", precision_score(y_true, y_pred, average='macro'))
输出结果为:
acc: 0.6
p: 0.7000000000000001
同理,对召回率、F1值同样计算
准确率分解
再回到准确率,把准确率细化为两个指标,分别是:指标1. 正确预测好人的能力;指标2. 正确预测坏人的能力
其实,正确预测好人的能力实际上就是敏感度,而正确预测坏人的能力就是特异度,都是机器学习上非常常用的度量指标
敏感度 sensitivity
样本实际值为好人,而模型预测为好人的正确率。公式: Sensitivity = True positives / (True positives + False negatives) = TP/(TP+FN),也就是对于阳性的查全率/召回率
特异度 specificity
样本实际值为坏人,而模型预测为坏人的正确率。公式:Specificity = True negatives / (True negatives + False positives) = TN/(TN+FP),也就是对于阴性的查全率/召回率
特异度是与敏感度/查全率/召回率同样针对实际样本为判断依据
如果敏感度高,特异度低,模型只会看好人,不会看坏人,即模型判定阳性的可能性远高于阴性
如果敏感度低,特异度高,模型只会看坏人,不会看好人,即模型识别阴性能力比识别阳性更强
只有敏感度和特异度都比较高,模型既可以分辨好人,也可以分辨坏人,才是一个有用的模型
还是以10个人中8个好人和2个坏人的不平衡数据集被全部识别为好人为例,以好人为阳性应用敏感度和特异度,得到 sensitivity = TP/(TP+FN) = 8/(8+0) =1,specifictiy = TN/(TN+FP) = 0/(0+2) = 0,虽然敏感度特别高,但是特异度为0,说明这个模型不具备识别坏人的能力,从评估指标上验证了这个模型是没有用的
五、模型评估指标的作用
在数据科学中,查看精确率和召回率来评估构建的模型是很常见的。而在医学领域,通常要观察特异度和敏感度来评估医学测试。这些概念非常相似,但又有所不同。当这两个世界相遇时,即当一个医学测试是一个机器学习模型时,这种差异可能会在医学界和从事数据科学研究的人员之间造成许多误解
再从医学应用角度重温一遍定义
召回率 —— 在所有阳性样本中,有多少是预测为阳性的?
特异度 —— 在所有没有患病的人当中,有多少人得到阴性结果?
敏感度 —— 在所有患病的人中,有多少人得到阳性结果?
如果把一个阳性的样本定义为患者,可以看到召回率和敏感度是一样的,但精确率和特异性是不同的。精确率也被称为PPV(阳性预测值)
精确率、召回率、敏感度的每一个组合都是可能的吗? 都代表什么情况?
为了更好地理解,创建了 8 个不同的分类问题和分类器。每个分类器尝试将 10 个样本以最大化或最小化每个度量的方式分类到阳性和阴性篮子中