机器学习模型的评价
我们可以使用不同的指标,来评价模型的好坏
1. 混淆矩阵
混淆矩阵,又叫误差矩阵,是表示精度的一种标准格式,用n行n列的矩阵形式表示
其中,n为数据集中样本类别的数量
混淆矩阵的通用化描述如下:
预测情况 | 预测情况 | |
---|---|---|
真实情况 | 正例 | 反例 |
正例 | TP | FP |
反例 | FN | TN |
混淆矩阵的行和列分别对应类别:
每一行代表了数据的真实归属类别,其中,行和表示该类别的数据实例的数目
每一列代表了数据的预测类别,其中,列和表示预测为该类别的数据实例的数目
2. 准确率
准确率:正确分类的点数之和与数据集中数据总数的比值
准确率指标并不是衡量模型性能的最佳评判标准
举个例子
银行交易里面每10000笔交易里面就有1笔属于欺诈型交易,那么,我们此时使用准确率来衡量该模型时有:
那么,你一定会觉得这个模型非常好,因为准确率是如此的高,对吧?
实际上并非这样,该模型的意义就是发现欺诈交易,而实际上该模型没有发现任何不好的数据
因此,对于这样偏斜的数据集,模型很可能会完全忽略一些不好的样本点,所以某些场景下仅仅使用准确率来评价模型性能并不是最佳的评判标标准。
精度和召回率
对于医疗模型和邮件模型来说,忽略正确的情形并仅侧重于错误的情形,你会觉得哪种错误带来的损失更糟糕呢?
1.对于医疗模型来说,
假阳性是指有病的人被误诊为健康
假阴性指指健康的人被误诊了患有疾病
一般我们更希望将所有的病人都找到,所以假阳性比假阴性更为糟糕,因此我们希望假阳性的惩罚比假阴性更重。
2.对于邮件模型来说,
假阳性是指正常邮件被预测为了垃圾邮件
假阴性是指垃圾邮件进入了收件箱
一般我们认为并不在意找到了所有的垃圾邮件,如果说某封邮件被预测为垃圾邮件,则UI好是垃圾邮件,所以假阳性比假阴性更为糟糕,此时我们希望假阳性的惩罚比假阴性更重。
综合扎两种模型来看,其在本质上是完全不同的
医疗模型更需要的是高召回率模型
邮件模型更需要的是高精度模型
3. 召回率
对应于混淆矩阵,可定义为:
对应于医疗模型,可理解为:在所有的患病的真阳性样本数目中,被预测为生病的样本数目所占的比例
4. 精度
对应于混淆矩阵,可定义为:
对应于医疗模型,可理解为:被预测为生病的样本数目中,真阳性的样本所占的比例
5. F1-Score
由于召回率和精度都能够从不同的方面来衡量模型的性能,那么,我们是否能够同时兼顾到这两部分,对这两部分进行合并,将其合并成一个优化目标呢?
我们使用召回率和精度的调和平均数
a)调和平均数一般比算术平均数要略低
b)调和平均数一般更接近较小的那个操作数
即F1得分更接近于精度和召回率较小的值
6. F -Score
一般而言,F1的值介于召回率和精度之间,且二者的重要性是一致的
F
的定义如下:
F-β 得分的界限
对 的得分公式进行分析
β=0的情况
如果设为
,则有
因此, 当
的最低值为 0,这时候就得出精度。
β= 的情况
如果beta无限大,则有
随着β变成无穷大,则有
因此,如果取极限值,则有
故总结如下:
β的范围介于0和
之间
如果β=0,则
为精度
如果β=
,则
为召回率
一般认为,
值越小(β<1),则越靠近精度,
值越大(β>1),则越靠近召回率
7. ROC曲线(PR曲线)
ROC曲线,英文全名:the Receiver Operator Chrqacteristic,中文全名:受试者工作特性曲线
ROC曲线,又叫PR曲线,其中P指的是准确率,R指的是召回率,即以准确率为横坐标,以召回率为纵坐标的曲线,因此ROC曲线上能够直观的显示出模型在数据集上的准确率和召回率。
在进行比较时,若一个模型的ROC曲线可完全包住另一个模型的ROC曲线,就表明当前模型性能更好。
附录:
如下程序是模拟
的变化过程
!/opt/anaconda/bin/python
# coding=utf-8
"""
测试beta值对F的影响
"""
def F_beta_Score(recall, precision, beta):
F_beta = (1+beta**2) * recall * precision / (beta**2 * recall + precision)
return F_beta
def F_beta_Score_test():
import matplotlib.pyplot as plt
recall = 0.1
precision = 1
betaList = [0.1 * i for i in range(1, 9)] + [j for j in range(1, 10)]
print(betaList)
F_res = []
for beta in betaList:
res = F_beta_Score(recall, precision, beta)
F_res.append(res)
print(F_res)
plt.plot(F_res)
plt.show()
if __name__ == '__main__':
F_beta_Score_test()