1.快速构建并迭代第一个系统
当你想要构建一个新的垃圾邮件过滤系统时,团队可能会有各式各样不同的想法:
- 收集海量的垃圾邮件作为训练集。例如,设置一个 “蜜罐(honeypot,计算机安全领域又称为诱饵)”,故意地向垃圾邮件系统发送一些虚假邮件地址,以便于能够自动收集到垃圾 邮件系统发送到这些地址的垃圾邮件内容。
- 开发用于理解邮件文本内容的功能。
- 开发用于理解邮件信封或邮件头部特征的功能,据此了解邮件经由了哪些网络服务器进行 中转。
- 更多…
虽然我在反垃圾邮件领域已经有了一定的经验,却依然难以保证每次都能顺利在上面的方向中进行抉择。如果你在此领域并不是一个专家,难度会变得更大。 如果在一开始就试图设计和构建出完美的系统会显得有些困难,不妨先花几天时间构建并训练一个最基础的系统。 或许这个最基础的系统与我们所能构建的 “最佳” 系统相去甚远,但研究其中的基础功能也是很有价值的:你能快速找到一些线索来帮助你决定在什么方向上投入时间。后面的一些章节会 向你剖析该如何解读这些线索。
2.误差分析:根据开发集样本评估想法
在使用猫咪 app 时,你注意到它将一些狗的图片误分类为猫了,因为有些狗的样子的确很像猫。团队中有人建议,加入第三方软件来帮助系统更好地处理狗的样本,但这需要一个月的时间去完成。面对团队成员高涨的热情,你会允许他们这样做吗?
在执行这项计划前,我建议你先预估一下该任务能提升多少系统精度。这样你就能够更加理性地判断是否值得花一个月的时间做这件事,还是将这段时间用于其它任务。
具体而言,你可以这样:
- 收集 100 个开发集中被误分类的样本,即造成系统误差的样本。
- 人为查看这些样本,并计算其中狗的比例。
查看误分类样本的这一过程称为误差分析(补充:或者是回归问题中预测误差的分布情况)。在上面的例子中,如果只有 5% 误分类的图像是狗,那么无论你在狗的问题上做多少的算法改进,最终都不会消除超过原有的 5% 误差 . 也即是说 5% 是该计划项目所能起到帮助的“上限”(最大可能值)。所以如果整个系统当前的精度为 90%(对应误差为 10%),那么这种改进最多能将精度提升到 90.5% (对应误差下降到9.5% , 改进了原有 10% 误差其中的 5%)。
相反,如果你发现 50% 的误分类图像是狗,那就可以自信地说这个项目将效果明显,它可以将精度从 90% 提升到 95% (相对误差减少 50%,整体误差由 10% 下降到 5%)。这种简单的误差分析计算过程可以协助你快速评估,从而了解是否需要将处理狗样本的第三方软件进行整合。它为是否值得进行这项投入给出了一个量化的基准。
误差分析也可以帮助你在不同的想法中发现哪些想法将更有前景。我见过许多工程师不愿意进行误差分析,他们更倾向于直接提出一个并实现一个想法,而不考虑该想法是否值得花时间去投入。这是一个普遍的误解:后果可能是你的团队在耗费一个月的时间后却发现收益甚少。人为检查 100 个样本并不会占用太多的时间。即使你每分钟只检查一张图片,也能够在两小时内完成,而这两个小时可能可以帮你节省一个月的工作量。
误差分析(Error Analysis) 指的是检查被算法误分类的开发集样本的过程(或者算法拟合偏差很大的开发集样本),以便帮助你找到造成这些误差的原因。这将协助你确定各个项目的优先级(就像上面的例子所提到的那样)并且获得探索新方向的灵感,我们将会在之后再讨论这些内容。接下来的几章会给出一些误差分析的最佳实践。
3.在误差分析时并行评估多个想法
对于改进猫检测器,你的团队有一些想法
- 修正算法将狗误分类为猫的问题。
- 修正算法将大型猫科动物(比如狮子、黑豹等等,下面用大猫代指)误分类为家猫的问题。
- 改善系统在模糊图像上的表现。
- …
上述的想法都可以以并行的形式进行评估。通常我会创建一个电子表格,一边查看被误分类的
100 个开发集样本一边完善表格内容,同时我也会留下一些能够帮助我记住特定样本的备注。为了说明这一过程,如下所示是一个仅含四个样本的小型开发集的电子表格: 你会发现表格中图片 3 的”大猫”与“模糊”列都被勾选了,另外由于一个样本可能与多个类别都有关联,所以表格底部的百分比加起来可能不是 100 %.虽然你可能事先规定了一些类别(狗,大猫,模糊)并进行了手动的分类,但在浏览图像时你可能会受到启发并发现一些新的类别。比如你在浏览一些图片时发现,经过 Instagram 滤镜处理过的图片在识别时对结果造成了误差,你就可以在电子表格中加入一个新的 “Instagram”列。手动查看误分类样本,并思考人类如何/是否能正确地分类这些样本,这将帮助你发现新的类别以及解决方案。
探寻方法去改进对应误差的类别是很有帮助的。举个例子,如果你能“撤销” Instagram 的滤镜效果并恢复到原始图片,那么 Instagram 分类就能发挥作用。这不代表你只能局限于那些已有的改进途径的类别;这个过程主要是为了帮助你对一些潜在的,有改进效果的方向培养一定的敏感度。
假设你已检查了 100 个开发集的误分类样本,并得到了下面的表格 现在你应该可以判断出,对于解决狗的误分类问题项目最多可以改进 8% 的误差,处理大猫和模糊类则可以改进更多。因此你将更有可能挑选后两者之一进行处理。如果你的团队有足够的人力并行处理多个方向,则可以要求一部分成员处理大猫类别,另一部分成员处理模糊类别。误差分析并不会产生一个明确的数学公式来告诉你什么任务的优先级最高。你还需要考虑在不同类别上的预期进展以及解决每个类别所需的工作量。
(补充:这部分和特征工程一样,比较灵活,没有什么固定的模式,并且对于存在大量误分类样本很难通过人工的方式来归纳总结或者要付出很大的代价,比较好的方法就是通过一些半自动化的方式来分析比如可视化等手段)
4.清洗误标注的开发集和测试集
在进行误差分析时,你可能会注意到一些开发集的样本被误标注(mislabeled )了。此处的“误标注”指的是图像在使用算法处理前,已经被负责标注的人员进行了错误的标注,也就是说,某个样本 (x,y) 的分类标签(label) y 的值并不正确。例如,一些不是猫的图片被误标注为猫,反之亦然。如果你不确定这些被误标注的图片是否起着关键作用,可以添加一个类别来跟踪记录误标注样本的比例: 那么这个时候,需要修正开发集中的标签吗?回忆一下当初设立开发集的目标——帮助你快速评估算法性能,从而判断算法 A 和 B 哪一个更好。如果开发集中误标注的部分的确影响了你的判断,那么花时间去修正这些标签就是值得的。
举个例子,假设你的分类器表现如下:
- 开发集整体精度……………… 90% (10% 整体误差)
- 误标注样本造成的误差…… 0.6% (6% 开发集误差)
- 其它原因造成的误差………. 9.4% (94% 开发集误差)
相对于你正在改进的 9.4% 误差,误标记的 0.6% 误差看起来就不那么重要了。在开发集中手动修正误标注样本不会带来不好的影响,但这样的做法并不是必要的:当你不知道整个系统的误差是 10% 还是 9.4% 时,这样处理会看起来不错。
假设你不断地改进猫分类器,并达到了以下性能:
- 开发集整体精度……………… 98.0% (2.0% 整体误差)
- 误标注样本造成的误差…… 0.6% (30% 开发集误差)
- 其它原因造成的误差………. 1.4% (70% 开发集误差)
此时 30% 的开发集误差是由误标注样本造成的,这对精度估计造成了显著的影响。此时就应该考虑改进开发集样本中的标签质量。处理这些误标注的样本将帮助你找出分类器的误差是接近 1.4% 还是 2.0% ,差异显著。在项目初始阶段容许一些误标注的开发集/测试集样本并不罕见,你可以选择在系统改进到一定程度时再来考虑被误标注的样本,因为这些误差在整体误差中的占比会逐渐增大。上一章中解释了如何通过算法改进类似于狗、大猫和模糊图片的误差类别,而在本章你学习了如何通过修正数据的标签来处理误标注的样本。
不论你使用什么方式修正开发集标签,请记住,要将同样的方式应用于你的测试集,这可以保持二者服从相同的分布。我们在第 6 章中已经讨论过了这样操作的意义,在那个问题中,团队成员花费了很多时间优化开发集,直到后来才意识到他们正在根据不同的测试集以不同的标准进行判断。
如果你决定改进标签质量,请仔细检查系统中被误分类和正确分类的样本的标签。对于某个样本,可能原始标注和算法预测的标签都是错误的。如果你仅修复系统误分类的样本标签,则有可能在评估中引入偏差。假设你有 1000 个开发集样本,同时分类准确率为 98%,那么检查20 个误分类的样本会比检查 980 个正确分类的样本要容易得多。由于在实际操作中,检查误分类样本较为容易,这就导致了开发集会衍生出一定的偏差。如果你只对开发产品和应用感兴趣,如此程度的偏差是可以接受的。但如果你计划在学术论文中引用此结果,可能就需要完全无偏地度量测试集的精度,此时这样做就会出现问题。
5.将大型开发集拆分为两个子集
假设你有一个含有 5000 个样本的大型开发集,该开发集的误差为 20% ,这意味着算法将误分类 1000 张开发集图片。人工手动检查这 1000 张图片会花费很长时间,所以我们在误差分析时没必要使用所有的图片。
在这种情况下,我会将开发集明确地分成两个子集,但只人工检查其中的一个。你将使得那些经人工查看的图片更快地过拟合,而另一部分没有被人工查看的图片可以在调参时使用。 继续上面的例子:在该例子中,算法将 5000 个开发集样本中 的1000 个样本误分类。假设我们想要对经人工检查的大约 100 个错误样本(整体的10%)进行误差分析,你应该随机选择10% 的开发集,并将其放入 Eyeball 开发集中(译者注:直译为眼球不妥,保留原文),以提醒我们自己,我们正在用眼睛看着它。(对于语音识别项目,你可能需要听一些音频的剪辑,此时则将数据集称为 Ear 开发集)。因此 Eyeball 开发集将有 500 个样本,其中,预计被算法误分类样本约 100 个。
第二个子集叫做 Blackbox 开发集(直译为黑箱,保留原文),它由剩余的 4500 个样本组成。你可以使用 Blackbox 开发集,通过测量错误率来自动评估分类器,也可以使用它来选择算法或调整超参数。但是,你应该避免将目光局限于此。我们使用术语“ Blackbox ”是因为我们只使用该子集来获得分类器的“ Blackbox ”评价。
为什么我们要把开发集明确分为 Eyeball 开发集和 Blackbox 开发集呢?因为当你在 Eyeball开发集中建立了对样本的直观认识之后,可使得Eyeball开发集更快地过拟合。如果你发现Eyeball 开发集的性能比 Blackbox 开发集提升得更快,说明已经过拟合到 Eyeball 开发集了。此时可能需要丢弃它并寻找一个新的 Eyeball 开发集,比如可以将更多 Blackbox 开发集中的样本移到 Eyeball 开发集中,也可以考虑去获取新的标注数据。将开发集明确地分为 Eyeball 和 Blackbox 开发两个子集将很有帮助,它使你了解在人为的误差分析过程中 Eyeball 开发集何时开始发生过拟合。
(补充:这里实际上就是针对上面我们说的在做误差分析的时候样本太多人工看不过来的解决办法,我们把开发集再且分为较小的eyeball和blackbox两个数据集,然后观察eyeball数据集的情况,但是个人感觉这种方法对于cv领域可能会有帮助,毕竟人们可以直观的从分类错误的图上总结出问题所在,但是如果是结构化数据,可以通过可视化的手段来总结预测错误的样本的一些规律和模式等,比如将预测精度高的样本和预测精度低的样本分为两组然后分别对各个维度特征进行可视化对比查看异同)
6. Eyeball 和 Blackbox 开发集该设置多大?
Eyeball 开发集应该大到能够让你对算法的主要错误类别有所察觉。如果你正在处理一项实际情况中人类表现良好的任务(例如识别图像中的猫),下面是一些粗略的指导方案:
? 如果分类器在 Eyeball 开发集上只出现 10 次误判,这个开发集就有点小了。若只有 10 个错误样本,很难准确估计不同错误类别的影响。但如果数据非常少且无法提供更多 Eyeball开发集样本时,聊胜于无,这将有助于确立项目的优先级。
? 如果分类器在 Eyeball 开发集样本上出现了约 20 次误判,你将可以开始大致了解主要的误差来源。
? 如果有约 50 个错误样本,你将能够比较好地了解主要的误差来源。
? 如果有约 100 个错误样本,你将会非常清楚主要的误差来源。我见过有人手动分析更多的错误样本——有时候多达500个。只要你有足够多的数据,这将是无害的。
假设你的分类器有 5% 的错误率。为了确保在 Eyeball 开发集中有约 100 个误分类的样本,样本开发集应该有约 2000 个样本(因为 0.05 * 2000 = 100)。分类器的错误率越低,为了获得足够多的错误样本进行误差分析,需要的 Eyeball 开发集就越大。
如果你正在处理一项,实际情况中人类也无法很好完成的任务,那么检查 Eyeball 开发集将不会有大的帮助,因为很难找出算法不能正确分类一个样本的原因。此时你可能也不需要建立Eyeball 开发集,我们会在后面的章节讨论诸如此类问题的指导方案。
Blackbox 开发集该有多大呢?我们先前提到,开发集有约 1000-10000 个样本是正常的 。完善一下该陈述,一个有 1000-10000 个样本的 Blackbox 开发集通常会为你提供足够的数据去调超参和选择模型,即使数据再多一些也无妨。而含有 100 个样本的 Blackbox 开发集虽然比较小,但仍然是有用的。如果开发集较小,那么你可能没有足够的数据将其分成足够大的 Eyeball 开发集和 Blackbox开发集来满足目的。相反,你的整个开发集可能需要用作 Eyeball 开发集——即,你将手动检查所有的开发集数据。在 Eyeball 和 Blackbox 开发集之间,我认为 Eyeball 开发集更加重要(假设你正在研究一个人类能够很好解决的问题,检查这些样本能使得你更有洞悉力)。如果你只有一个 Eyeball 开发集,你可以在这个开发集上进行误差分析、模型选择和超参数调整,缺点是过拟合开发集的风险更大。如果你有充足的数据,那么 Eyeball 开发集的大小将主要取决于你能够手动分析样本的时间。实际上,我很少看到有人手动分析超过 1000 个错误样本。
7.基础误差分析
当你开始一个新项目,尤其是在一个你不擅长的领域开展项目时,很难正确预判出最有前景的方向。
所以,不要在一开始就试图设计和构建一个完美的系统。相反,应尽可能快(例如在短短几天内)地构建和训练一个系统雏形。然后使用误差分析法去帮助你识别出最有前景的方向,并据此不断迭代改进你的算法。
- 通过手动检查约 100 个被算法错误分类的开发集样本来执行误差分析,并计算主要的错误类别。使用这些信息来确定优先修正哪种类型的错误。
- 考虑将开发集分为人为检查的 Eyeball 开发集和非人为检查的 Blackbox 开发集。如果在Eyeball 开发集上的性能比在Blackbox 开发集上好很多,说明你已过拟合 Eyeball 开发集,下一步应该考虑为其获取更多数据。
- Eyeball 开发集应该足够大,以便于算法有足够多的错误分类样本供你分析。对大多数应用来说,含有1000-10000个样本的Blackbox 开发集已足够。
- 如果你的开发集不够大,无法按照这种方式进行拆分,那么就使用 Eyeball 开发集来执行人工误差分析、模型选择和调超参。
|