Deep Learning Note: 3-2 设置目标
1. 使用单一评价标准
机器学习涉及很多可以选择的算法和需要调优的超参数,往往难以在一开始就找到最佳选择。因此,应用机器学习是一个反复迭代的过程,通过不断地调整和尝试各种选择并评估其结果,逐步找到更好的算法和参数,使得模型的性能逐步提高。在这一过程中,使用一个单一的评价指标来对模型性能进行评估,可以立即知道所进行的调整是否有效,有利于提高迭代的效率。
例如使用不同的超参数得到了两个分类器 A 和 B,为了判断二者谁更好,比较它们的准确率(Precision)和召回率(Recall)如表 1:
表 1
分类器 | 准确率 | 召回率 |
---|---|---|
A | 95% | 90% |
B | 98% | 85% |
从上表可见,A 的召回率更高,B 的准确率更高,难以决定二者谁更好。实际上,准确率和召回率之间存在取舍关系。当使用两个指标来评估模型时,往往难以快速地找出性能最好的模型。此时,需要找到一个新的评价指标,这个指标能够综合准确率和召回率,唯一地评价一个模型的性能。
结合准确率和召回率的常见方法是使用 $F_1$ 分数($F_1$ Score),即准确率 $P$ 和召回率 $R$ 的调和平均数:
\begin{equation}
F_1 = \frac{2}{\frac{1}{P} + \frac{1}{R}} \tag{1}
\end{equation}
由式 (1) 计算得到分类器 A 和分类器 B 的 $F_1$ Score 如下表:
表 2
分类器 | 准确率 | 召回率 | $F_1$ 分数 |
---|---|---|---|
A | 95% | 90% | 92.4% |
B | 98% | 85% | 91.0% |
由上表,通过 $F_1$ 分数可以很快地找出分类器 A 具有更好的性能。
选择合适的开发集以获取准确的评估数值(如准确率、召回率),并选择唯一的一个(实数)评估指标,可以快速地判断模型的性能,加快调优迭代的速度。
再举一例,假设你正在开发一个识别图片中的猫的应用,备选的两个算法在不同地区有不同的错误率,如表 3 所示:
表 3
算法 | 美国 | 中国 | 印度 | 其他 |
---|---|---|---|---|
A | 3% | 7% | 5% | 9% |
B | 5% | 6% | 5% | 10% |
通过表 3 中四个地区的数值,可以看到两个算法互有胜负,难以决定哪个算法的效果更加。需要找到一个唯一的指标来对两个算法进行评估,比如算法的平均错误率(假设各个地区的市场同样重要),如表 4:
表 4
算法 | 美国 | 中国 | 印度 | 其他 | 平均 |
---|---|---|---|---|---|
A | 3% | 7% | 5% | 9% | 6% |
B | 5% | 6% | 5% | 10% | 6.5% |
通过平均错误率,可以很直接地看出算法 A 的效果更好,可以选择算法 A 并在其基础上进行后续的调优和迭代。
2. 满足指标和优化指标
有时难以将所有的评价标准整合到唯一的一个指标中,这时需要分清主次,设定满足指标(Satisficing Metric)和优化指标(Optimizing Metric)。
例如,对于某个特定问题,我们关心分类器的准确率和执行预测所需的运行时间,此时有三个分类器的性能如表 5 所示:
表 5
分类器 | 准确率 | 运行时间 |
---|---|---|
A | 90% | 80ms |
B | 92% | 95ms |
C | 95% | 1500ms |
我们可以制定一个新的指标,比如二者的加权平均数,来综合准确率和运行时间这两个指标。但准确率和运行时间二者并没有什么必然的关系,强行将二者组合在一起显得十分生硬,没有说服力。
更合理的做法是,选择准确率作为优化指标,即希望准确率最大化;同时选择运行时间作为满足指标,即分类器的运行时间要满足某个条件,例如不能超过某个上限,满足条件后就不再关心具体数值。此时的评价指标相当于在限制运行时间的前提下,准确率更大的分类器更好。例如限制运行时间不能大于 100 ms,此时分类器 C 被排除;在剩下的 A 和 B 中,不再关心运行时间,只选择准确率最大的分类器,即 B。
更一般地,对于 N 个评价指标,选择其中一个指标作为优化指标,选择剩下的 N-1 个指标作为满足指标。
再举一例,语音控制系统通常可以被特定的词语所唤醒(例如用户可以通过对 iPhone 说 Hey Siri 唤醒 Siri),对于唤醒词的检测,选择准确率和虚警率来评估其性能,此时可以选择最大化准确率,同时保证虚警率不要太高(例如限定每运行 24 小时最多出现 1 次虚警),即选择准确率作为优化指标,虚警率作为满足指标。
3. 开发集和测试集的分布
训练集、开发集、测试集的选择会极大地影响到模型迭代的效率。
还是以从图片中识别猫的分类器为例,假设这个应用主要针对以下地区:
- 美国
- 英国
- 其他欧洲地区
- 南美
- 印度
- 中国
- 其他亚洲地区
- 澳大利亚
要从这些地区的数据中选择开发集和测试集。一种错误的选择方式是,使用地区 1 ~ 4 的数据作为开发集,使用地区 5 ~ 8 的数据作为测试集。这种选择方式会导致开发集和测试集具有不同的分布。设定测试集和唯一的评价指标,相当于确定所要瞄准的靶子;通过在测试集上使用评价指标对训练得到的模型进行评估,找出最好的模型,相当于向靶子射箭,并找出最接近靶眼的一支箭。如果开发集和测试集具有不同的分布,通过开发集选出的最佳模型,很可能无法在测试集上取得同样的性能,就像射错了靶子,最后只能是白费功夫。所以,一种合理的选择方式是,先将所有 8 个地区的数据混合起来,然后再从中分出开发集和测试集,使得开发集和测试集具有同样的分布。
另一个真实的反面例子是,某个团队尝试训练一个预测贷款审批的模型,即使用贷款申请作为输入,预测申请者是否能够偿还贷款,作为是否批准贷款的依据。在优化过程中,使用的是中等收入地区的邮编号码作为开发集。而在测试时,使用的却是低收入地区的邮编号码,此时开发集和测试集来自不同的分布,花了大量时间在中等收入地区数据上训练的模型不能很好地适用于低收入地区的测试集。这个团队浪费了 3 个月时间,不得不回过头重新开始。这就相当于花了三个月时间瞄准了一个靶子,然后发现真正想要射的靶子却在别处。
总而言之,开发集和测试集要能够反映未来实际应用中真正重要的数据,且具有相同的分布。
3. 开发集和测试集的大小
在机器学习的早期阶段,通常使用按照 70% / 30% 的比例将所有数据划分为训练集或测试集,或按照 60% / 20% / 20% 的比例将数据划分为训练集、开发集和测试集。当时能够使用的数据十分有限,比如只有 100、1000 或 10000 个样本,按照这样的比例进行划分是合理的。
但在现代机器学习领域,使用的数据量有了巨大的提升,开发集和测试集通常会占用更小的比例。比如有 100 万个样本,此时则应该使用如 98% / 1% / 1% 的比例划分训练集、开发集和测试集。虽然开发集和测试集只占了很小的比例,但由于样本基数很大,二者也都有 10000 个样本,足够用于测试。而深度学习的算法往往需要大量的数据,因此要把更多的数据留给训练集。
测试集用来得到对最终系统性能的无偏估计,其大小只要能给出对系统整体性能的高置信的评估即可,一般不需要特别大的测试集。除非要获得非常精确的系统性能,才需要使用更大的测试集。如果不需要对最终系统性能进行评估,则也可以不使用测试集,只划分训练集和开发集。
4. 修改开发/测试集和评价指标
前面提到,设定测试集和唯一的评价指标,相当于确定所要瞄准的靶子。但有时项目进行到一半,发现靶子放错地方了,这是就需要重新调整靶子的位置,即修改开发/测试集和评价指标。
例如对于前面从图片中识别猫的分类器,使用分类错误率作为评价标准,算法 A 有 3% 的错误率,算法 B 有 5% 的错误率,这样来看算法 A 具有更好的性能。但之后通过更细致的检查,发现算法 A 会误将一些色情图片也识别为猫。如果使用算法 A 来自动检测猫的图片,并将图片推荐给用户,因为 A 的错误率更低,用户可以看到更多的猫,但一些色情图片也会被 A 误判为猫并推荐给用户,这是不能容忍的。而对于算法 B,虽然它的错误率较高,但不会将色情图片误判为猫,此时无论从公司还是从用户的角度,都会选择算法 B。虽然通过开发集和评估和指标(错误率),可以判定 A 更好,但实际上却选择了 B。
上面例子使用错误率作为评估指标,即:
\begin{equation}
\frac{1}{m_{dev}} \sum_{i=1}^{m_{dev}}I\{y_{pred}^{(i)} \neq y^{(i)}\}
\end{equation}
上式中,$m_{dev}$ 为开发集样本数,$y_{pred}^{(i)}$ 和 $y^{(i)}$ 分别为第 $i$ 个样本的预测和真实标签,$I$ 为恒等函数,$I\{y_{pred}^{(i)} \neq y^{(i)}\}$ 在 $y_{pred}^{(i)} \neq y^{(i)}$ 时为 1,反之为 0。
在上面例子中使用错误率作为评价指标的问题是,错误率对于色情图片和非色情图片一视同仁:无论是将一张豹子的图片分类为猫,还是将一张色情图片分类为猫,都只是计为 1 次错误。而实际中我们不希望出现色情图片,需要增大将色情图片分类为猫的惩罚力度,例如添加一个权重 $w^{(i)}$,通过 $w^{(i)}$ 增大将色情图片分类为猫的错误的权重:
\begin{equation}
\frac{1}{\sum_{i=1}^{m_{dev}}w^{(i)}} \sum_{i=1}^{m_{dev}} w^{(i)} I\{y_{pred}^{(i)} \neq y^{(i)}\}
\end{equation}
\begin{equation}
w^{(i)} =\begin{cases}1 & 当x^{(i)}不是色情图片\\
10 & 当x^{(i)}是色情图片\end{cases}
\end{equation}
当评价指标不再能正确地反映模型的真实性能,不再能给出模型性能的正确排序时,就需对整评估指标进行调整,有时还需要调整开发集。
解决上面例子中问题的思路也体现了正交化的思想,即首先定义一个评估指标,然后再考虑如何让模型在这个指标上获得更好的性能,这两个步骤是独立的、互不影响的。仍使用靶子的比喻来讲,就是首先确定要把靶子放在哪里,然后再考虑如何准确地射中靶子。
再举一个例子,还是对于从图片中识别猫的分类器,使用分类错误率作为评价标准,使用的开发集和测试集是从网上搜集的高质量的高清图片。在开发集上,算法 A 有 3% 的错误率,算法 B 有 5% 的错误率。但实际部署之后,用户实际上传的图片往往质量较低,画质模糊,此时发现算法 B 的错误率反而更低。这里的问题是,开发集和测试集的分布与实际场景中数据的分布不一致。使用高质量的高清图片作为开发集和测试集时,可以得到算法 A 具有较低的错误率,但实际用户期望的是应用对于他们上传的低质量图片也有很高的准确率。此时需要调整开发集和测试集,保证它们与实际场景中的数据具有同样的分布,即使用与用户上传图片的质量类似的(低质量)图片。
当使用开发集和测试集在评价指标上达到很好的效果,并不能保证在实际关心的应用场景也具有很好的效果时,此时也需要修改评价指标和开发/测试集。