机器学习入门系列(2)–如何构建一个完整的机器学习项目,第十篇!
该系列的前 9 篇文章:
- 机器学习入门系列(2)–如何构建一个完整的机器学习项目(一)
- 机器学习数据集的获取和测试集的构建方法
- 特征工程之数据预处理(上)
- 特征工程之数据预处理(下)
- 特征工程之特征缩放&特征编码
- 特征工程(完)
- 常用机器学习算法汇总比较(上)
- 常用机器学习算法汇总比较(中)
- 常用机器学习算法汇总比较(完)
这个系列的文章也是要开始进入尾声了,最后就主要是模型评估部分的内容了。
在机器学习领域中,对模型的评估非常重要,只有选择和问题相匹配的评估方法,才能快速发现算法模型或者训练过程的问题,迭代地对模型进行优化。
模型评估主要分为离线评估和在线评估两个阶段。并且针对分类、回归、排序、序列预测等不同类型的机器学习问题,评估指标的选择也有所不同。
模型评估这部分会介绍以下几方面的内容:
- 性能度量
- 模型评估方法
- 泛化能力
- 过拟合、欠拟合
- 超参数调优
本文会首先介绍性能度量方面的内容,主要是分类问题和回归问题的性能指标,包括以下几个方法的介绍:
- 准确率和错误率
- 精确率、召回率以及 F1
- ROC 曲线 和 AUC
- 代价矩阵
- 回归问题的性能度量
- 其他评价指标,如计算速度、鲁棒性等
1. 性能度量
性能度量就是指对模型泛化能力衡量的评价标准。
1.1 准确率和错误率
分类问题中最常用的两个性能度量标准–准确率和错误率。
准确率:指的是分类正确的样本数量占样本总数的比例,定义如下:
A c c u r a c y = n c o r r e c t N Accuracy = \frac{n_{correct}}{N} Accuracy=Nncorrect
错误率:指分类错误的样本占样本总数的比例,定义如下:
E r r o r = n e r r o r N Error = \frac{n_{error}}{N} Error=Nnerror
错误率也是损失函数为 0-1 损失时的误差。
这两种评价标准是分类问题中最简单也是最直观的评价指标。但它们都存在一个问题,在类别不平衡的情况下,它们都无法有效评价模型的泛化能力。即如果此时有 99% 的负样本,那么模型预测所有样本都是负样本的时候,可以得到 99% 的准确率。
这种情况就是在类别不平衡的时候,占比大的类别往往成为影响准确率的最主要因素!
这种时候,其中一种解决方法就是更换评价指标,比如采用更为有效的平均准确率(每个类别的样本准确率的算术平均),即:
A m e a n = a 1 + a 2 + ⋯ + a m m A_{mean}=\frac{a_1+a_2+\dots+a_m}{m} Amean=ma1+a2+⋯+am
其中 m 是类别的数量。
对于准确率和错误率,用 Python 代码实现如下图所示:
def accuracy(y_true, y_pred):
return sum(y == y_p for y, y_p in zip(y_true, y_pred)) / len(y_true)
def error(y_true, y_pred):
return sum(y != y_p for y, y_p in zip(y_true, y_pred)) / len(y_true)
一个简单的二分类测试样例:
y_true = [1, 0, 1, 0, 1]
y_pred = [0, 0, 1, 1, 0]
acc = accuracy(y_true, y_pred)
err = error(y_true, y_pred)
print('accuracy=', acc)
print('error=', err)
输出结果如下:
accuracy= 0.4
error= 0.6
1.2 精确率、召回率、P-R 曲线和 F1
1.2.1 精确率和召回率
精确率,也被称作查准率,是指所有预测为正类的结果中,真正的正类的比例。公式如下:
P = T P T P + F P P = \frac{TP}{TP+FP} P=TP+FPTP
召回率,也被称作查全率,是指所有正类中,被分类器找出来的比例。公式如下:
R = T P T P + F N R = \frac{TP}{TP+FN} R=TP+FNTP
对于上述两个公式的符号定义,是在二分类问题中,我们将关注的类别作为正类,其他类别作为负类别,因此,定义:
TP(True Positive)
:真正正类的数量,即分类为正类,实际也是正类的样本数量;FP
(False Positive):假正类的数量,即分类为正类,但实际是负类的样本数量;FN(False Negative)
:假负类的数量,即分类为负类,但实际是正类的样本数量;TN(True Negative)
:真负类的数量,即分类是负类,实际也负类的样本数量。
更形象的说明,可以参考下表,也是混淆矩阵的定义:
预测:正类 | 预测:负类 | |
---|---|---|
实际:正类 | TP | FN |
实际:负类 | FP | TN |
精确率和召回率是一对矛盾的度量,通常精确率高时,召回率往往会比较低;而召回率高时,精确率则会比较低,原因如下:
- 精确率越高,代表预测为正类的比例更高,而要做到这点,通常就是只选择有把握的样本。最简单的就是只挑选最有把握的一个样本,此时
FP=0
,P=1
,但FN
必然非常大(没把握的都判定为负类),召回率就非常低了; - 召回率要高,就是需要找到所有正类出来,要做到这点,最简单的就是所有类别都判定为正类,那么
FN=0
,但FP
也很大,所有精确率就很低了。
而且不同的问题,侧重的评价指标也不同,比如:
- 对于推荐系统,侧重的是精确率。也就是希望推荐的结果都是用户感兴趣的结果,即用户感兴趣的信息比例要高,因为通常给用户展示的窗口有限,一般只能展示 5 个,或者 10 个,所以更要求推荐给用户真正感兴趣的信息;
- 对于医学诊断系统,侧重的是召回率。即希望不漏检任何疾病患者,如果漏检了,就可能耽搁患者治疗,导致病情恶化。
精确率和召回率的代码简单实现如下,这是基于二分类的情况
def precision(y_true, y_pred):
true_positive = sum(y and y_p for y, y_p in zip(y_true, y_pred))
predicted_positive = sum(y_pred)
return true_positive / predicted_positive
def recall(y_true, y_pred):
true_positive = sum(y and y_p for y, y_p in zip(y_true, y_pred))
real_positive = sum(y_true)
return true_positive / real_positive
简单的测试样例以及输出如下
y_true = [1, 0, 1, 0, 1]
y_pred = [0, 0, 1, 1, 0]
precisions = precision(y_true, y_pred)
recalls = recall(y_true, y_pred)
print('precisions=', precisions) # 输出为0.5
print('recalls=', recalls) # 输出为 0.3333
1.2.2 P-R 曲线和 F1
很多时候,我们都可以根据分类器的预测结果对样本进行排序,越靠前的是分类器越有把握是正类的样本,而最后面的自然就是分类器觉得最不可能是正类的样本了。
一般来说,这个预测结果其实就是分类器对样本判断为某个类别的置信度,我们可以选择不同的阈值来调整分类器对某个样本的输出结果,比如设置阈值是 0.9,那么只有置信度是大于等于 0.9 的样本才会最终判定为正类,其余的都是负类。
我们设置不同的阈值,自然就会得到不同的正类数量和负类数量,依次计算不同情况的精确率和召回率,然后我们可以以精确率为纵轴,召回率为横轴,绘制一条“P-R曲线”,如下图所示:
当然,以上这个曲线是比较理想情况下的,未来绘图方便和美观,实际情况如下图所示:
对于 P-R 曲线,有:
1.曲线从左上角 (0,1)
到右下角 (1,0)
的走势,正好反映了精确率和召回率是一对矛盾的度量,一个高另一个低的特点:
- 开始是精确率高,因为设置阈值很高,只有第一个样本(分类器最有把握是正类)被预测为正类,其他都是负类,所以精确率高,几乎是 1,而召回率几乎是 0,仅仅找到 1 个正类。
- 右下角时候就是召回率很高,精确率很低,此时设置阈值就是 0,所以类别都被预测为正类,所有正类都被找到了,召回率很高,而精确率非常低,因为大量负类被预测为正类。
2.P-R
曲线可以非常直观显示出分类器在样本总体上的精确率和召回率。所以可以对比两个分类器在同个测试集上的 P-R
曲线来比较它们的分类能力:
- 如果分类器
B
的P-R
曲线被分类器A
的曲线完全包住,如下左图所示,则可以说,A
的性能优于B
; - 如果是下面的右图,两者的曲线有交叉,则很难直接判断两个分类器的优劣,只能根据具体的精确率和召回率进行比较:
- 一个合理的依据是比较
P-R
曲线下方的面积大小,它在一定程度上表征了分类器在精确率和召回率上取得“双高”的比例,但这个数值不容易计算; - 另一个比较就是平衡点(Break-Event Point, BEP),它是精确率等于召回率时的取值,如下右图所示,而且可以判定,平衡点较远的曲线更好。
- 一个合理的依据是比较
当然了,平衡点还是过于简化,于是有了 F1 值这个新的评价标准,它是精确率和召回率的调和平均值,定义为:
F 1 = 2 × P × R P + R = 2 × T P 样 本 总 数 + T P − T N F1 = \frac{2 \times P \times R}{P+R}=\frac{2\times TP}{样本总数+TP-TN} F1=P+R2×P×R=样本总数+TP−TN2×TP
F1 还有一个更一般的形式: F β F_{\beta} Fβ,能让我们表达出对精确率和召回率的不同偏好,定义如下:
F β = ( 1 + β 2 ) × P × R ( β 2 × P ) + R F_{\beta}=\frac{(1+\beta^2)\times P\times R}{(\beta^2 \times P)+R} F