《机器学习要领》 基本误差分析(中文翻译版)

Machine Learning Yearning Chapter3 Basic Error Analysis(Chinese ver)

Posted by Canary on April 26, 2018

前言

本篇博客是 Andrew NG 《Machine Learning Yearning》 的「第三章:基本误差分析」翻译。本章内容将通过描述手动分析误差的流程,来为项目优化选择合适的方向。 👉官网传送门
👉GitHub 项目传送门,欢迎 Star

13. 快速搭建第一个系统并开始迭代

你想要构建一个新的反垃圾邮件系统,你的团队有几个想法:

  • 收集一个大的垃圾邮件训练集,例如,设置诱饵系统(Honeypot):故意将一个假的电子邮件地址分发给已知的垃圾邮件发送方,以便自动收集他们发送的垃圾邮件;
  • 开发用于识别电子邮件文本内容的功能;
  • 开发用于识别电子邮件标题特征的功能,以分析出邮件消息都经过了哪些服务器;
  • 等等……

即使我在反垃圾邮件系统上有着丰富的经验,也很难选择其中的一个方向。如果你不是该领域专家的话,那会更难。

所以,不要试图去设计和构建一个完美的系统。相反,应该快速地构建和训练出一个初始系统来——这或许只需要几天时间1,即使这个基础系统和你要建立的最佳系统隔个十万八千里。但对这个基础系统进行研究仍然是值得的:你将快速找到一些线索来帮助你指出你该投入时间的最有希望的方向。接下来的几个章节将指导你如何理解这些线索。

14. 误差分析:查看开发集样本来评估想法

当你在使用你的猫咪分类 App 的时候,你注意到有几张狗的照片被错误分类成了猫。这些狗看起来也确实像猫。

一个团队成员建议加入第三方软件,这样可以让系统更好的处理狗的图片。这个变动预计将耗费一个月的时间,同时团队的其他成员也很热衷于这个方案。你应该让他们继续下去吗?

在投入这一个月的时间来完成这项任务之前,我建议你应该首先评估下这个改变到底能提升多少系统准确率。然后,你才可以更加理性地决定是否值得为此花费一个月的开发时间,或者说不如用这一个月时间去完成一些其他的任务。

具体来说,你可以做以下事情:

  1. 收集你系统误分类(Misclassified)的 100 个开发集样例,即系统发生错误的那些样本;
  2. 人工检查这些样例,并记录它们中的狗图像的占比。

检查误分类样例的过程被称为:误差分析(Error Analysis)。在这个例子中,如果你发现在误分类的样本中狗的图片占比只有 5%,那么无论你如何改进对狗的识别算法,都不可能降低 5% 以上的错误,换句话说,5% 是预定的改进计划(加入第三方库)所能提升的「上限(Ceiling)」。因此,如果你的系统目前的准确率是 90%(10%的误差),那么这个改进最多能将准确率提升到 90.5%2

相反的,如果你发现在误分类的样本中有 50% 被误分类为狗,那么你可以坚信这个提议(引入第三方软件)会对系统准确率的提升有很大帮助。它可以把准确率从 90% 提升到 95%3

这种简单的误差分析计算过程为你提供了一种方法来评估为「修正误分类为狗」这个问题而加入第三方软件的潜在价值。它为决定是否将时间投入到这项工作提供了量化基础。

误差分析经常能帮助你弄清楚不同方向所隐藏的价值。我曾经常看到许多工程师都不愿意进行误差分析。相比于质疑某个想法是否值得花时间投入,直接扎入一个想法并行动更加让人感到刺激。这是一个常见的错误:这种习惯可能会导致你的团队花费了一个月的时间才发现它并不能为系统带来什么好处。

手动检查这 100 个误分类样例并不需要花费很长的时间。即使你每幅图片都花费 1 分钟,总的算下来也就是不到 2 小时的事情。而这短短的两个小时却能节省你一个月的精力。

「误差分析」是指在开发集中检查被算法错误分类的那些样本以便理解错误根本原因的过程。它能够帮助你确定项目的优先顺序(如本例所示),并启发我们接下来将要考虑的新的方向。接下来的几节内容还将接着介绍一些误差分析的最佳实践。

15. 在误差分析中并行评估多个想法

你的团队有几个改进猫检测器的想法。

  • 修正算法中将狗识别为猫的问题;
  • 修正算法中将大型猫科动物(Great Cat)(狮子,豹)识别为家猫的问题;
  • 提升系统在模糊图像(Blurry Images)上的性能表现。
  • ……

你可以同时有效地评估所有的这些想法。我通常会列一张表,并在开发集上检查错误分类的 100 张图像的时候填写它。我同时也会写下可能帮助我分析具体例子的备注。为了说明这个过程。我们来看下面的一张表,它是一个由四个样本组成的小开发集:

图片(Image) 狗(Dog) 大型猫科动物(Great Cat) 模糊图像(Blurry) 备注(Comments)
1     不寻常颜色的斗牛犬
2      
3   狮子;照片是在雨天的动物园拍摄
4     豹子在树后面
占总数百分比 25% 50% 50%  

在上表中,图片3 在「Great Cat」和「Blurry」两列都被勾选了。一个示例可能与多个类别关联,所以底部的百分比总值并不一定等于 100%。

尽管你可能会制定一些类别(狗,大型猫科动物,模糊图像等等),然后将开发集的误分类图像进行归类,但在实践中,一旦你开始浏览这些样本,你可能会受到启发,发现其他的错误类别。比如在浏览了一些样例之后,你发现许多图片分类错误是因为 Instagram 的滤镜造成的,你可以回到表格中,添加「Instagram」列。手动查看算法错误分类的示例,并思考「如果是人的话,能否/如何正确标记图片」,通常这能激发你提出新的错误类别和解决方案。

你有办法去改进的错误类别才是最有帮助的错误类别。例如,如果你有「撤销 Instagram 滤镜并将其恢复为原始图像」的好办法的话,那么添加 Instagram 类别则是最有用的。不过,你不必局限在那些你知道如何去改进的错误类别上。这个过程的目的是建立你最希望关注的领域的直觉。

误差分析是一个迭代的过程。如果你开始没有想到任何的错误类别也不用担心。看过几组图片之后,你可能就能想出一些错误类别了。在对一些图片进行手动分类之后,你可能考虑到一些新的类别,此时就要根据新的类别对图片重新检查。

假设你完成了对开发集上那 100 张误分类图片的分类,并得到下列的结果:

图片(Image) 狗(Dog) 大型猫科动物(Great Cat) 模糊图像(Blurry) 备注(Comments)
1     不寻常颜色的斗牛犬
2      
3   狮子;照片是在雨天的动物园拍摄
4     豹子在树后面
…… …… …… …… ……
占总数百分比 8% 43% 61%  

从上表你发现,处理分类为狗的这个问题最多只能消除8%的错误。而处理「Great Cat」和「Blurry」的问题却可以消除更多错误。因此,你可以挑选后两个之一来继续努力。当然,如果你的团队人手足够,也可以并行地同时开展多个方向的工作,你可以分派一些工程师负责「Great Cat」方向,分派另一些在「Blurry」方向。

「误差分析」不会产生一个严格的数学公式来告诉你最优先的任务是什么。你还必须考虑你想在不同的错误类别上取得多少的进展,以及处理每个类别所需要的工作量。

16. 清除标注错误的开发/测试集数据

在误差分析的过程中,你可能注意到开发集中有些样本被人为的错误标记(Mislabeled)了。当我在这里提到「Mislabeled」的时候,我的意思是这些图片在被输入到算法之前就已经被人为的贴错了标签。比如,样本 $(x,y)$ 中的标签 $y$ 是错的,有一些不是猫的图片被贴上了猫的标签。如果你怀疑被错误标记的数据很重要,请添加一个错误类别来跟踪被贴错标签的样本。

图片(Image) 狗(Dog) 大型猫科动物(Great Cat) 模糊图像(Blurry) 贴错标签(Mislabeled) 备注(Comments)
…… …… …… …… ……  
98       不寻常颜色的斗牛犬
99        
100       狮子;照片
占总数百分比 8% 43% 61% 6%  

那么是否值得修正开发集中这 6% 的标记出错的例子呢?请记住,开发集的目的是为了帮助你快速评估你的算法,以便判断是算法 A 还是算法 B 更好。如果被贴错标签的开发集数据妨碍了你做出这些判断。那么花时间去纠正这些人为标签错误是值得的。

例如:假设你的分类器新性能如下:

  • 开发集的整体准确率—– 90%(10%的误差);
  • 由于贴错标签导致的错误—– 0.6%(占开发集错误的6%);
  • 由于其他原因导致的错误—– 9.4%(占开发集错误的94%)。

这里,相对于 9.4% 的错误,由于错误标记导致的 0.6% 变得并不那么重要例如。在开发集中手动修复标记错误的图像没有什么坏处,但是这样做并不是必须的。因为标记出错导致的错误是总体错误的一小部分而已(0.6% 对于 10% 来说,可以忽略了)。

假设你不断改进猫分类器并达到了以下性能表现:

  • 开发集的整体准确率—– 98.0%(2.0%的误差);
  • 由于贴错标签导致的错误—– 0.6%(占开发集错误的30%);
  • 由于其他原因导致的错误—– 1.4%(占开发集错误的70%)。

上述中,30% 的错误是由于错误标记开发集的样本导致的,当测得的那么大一部分的错误都是来自开发集标记出错。这种情况下,就值得去提高开发集中标签的质量了。(0.6% 对于 2% 来说,已然不能被忽略)。

开始时容忍一些错误标记的开发集/测试集样本并不罕见,随着系统的不断优化,错误标记示例的比例随着总的误差降低而增长,当这个比例对于总的误差来说不能被忽略的时候,就不能再继续容忍这些标记错误的样本了。

最后一章解释了如何通过算法改进来改善错误类别,例如狗、大型猫科动物、模糊图像等。在本章,你还可以学到通过改进数据标签来处理「Mislabeled」类别。

无论你使用什么方式来修复开发集标签,请记住同时将这个方法用在测试集上,以便让开发集和测试集继续服从同一分布。将开发集和测试集一起处理可以避免我们在第二章的第六节提到的问题,这个问题就是:当你的团队优化了开发集的性能之后才意识到是根据不同的测试集来判断不同的标准。(两者不同分布)

如果你决定了要提高标签的质量,请考虑仔细检查系统错误分类的示例标签以及正确分类的示例标签。在一个例子中,原始标签和学习算法都可能是错误的。如果你只修复被系统错误分类样例的标签,则会在评估中引入偏差(Bias),如果你有 1000 个样本大小的开发集,同时你的分类器有 98% 的准确率,那么检查该算法错误分类的 20 个样本比检查正确分类的 980 个样本要容易的多。因为在实践中只检查那些被错误分类的样本要更简单,正因为如此,偏差会蔓延到开发集中去。如果你只对开发产品或者应用程序感兴趣,这点偏差是可以接受的,但是如果你计划在学术论文上使用该结果,或者在需要完全无偏估计测量测试集准确率的时候,就会出现问题。

17. 如果你有一个很大的开发集,拆分为两半,并只关注其中一个

假设你有一个 5000 个样本大小的开发集,其中误差是 20%,也就是说,你的算法大约误分类了 1000 个样本。手动检查这 1000 个样本需要花费很长时间,因此我们决定在误差分析中只使用一部分误分类样本。

在这种情况下,我会明确地将开发集分为两个子集,并全力关注其中一个,通常对于您手动查看的那部分样本会很快的出现过拟合现象。你可以使用另一个子集来对参数进行调优。

让我们继续上边的例子,在这里,算法对 5000 个开发集样本分类,结果是大约有 1000 个样本被误分类了,同时假设我们将要手动检查 100 个误分类样本(占总错误的 10%)。

你应当随机选择 10% 的开发集样本,将其放入一个我们称之为「眼球开发集(​Eyeball dev set)」的集合中,以提醒自己正在使用我们自己的眼睛来观察(人工检查)。(对于语音识别项目,我们是用耳朵来听音频片段,可能将这部分样本集合称作「耳朵开发集」更贴切一点)。因此,这个「眼球开发集」有 500 个样本组成,我们希望我们的算法在此数据机上的误分类样本个数大概有 100 个(误差是 20%)。

对于开发集的另一个子集,称为「黑盒开发集(Blackbox dev set)」,将会拥有 4500 个样本。你可以用这个「黑盒开发集」通过测量误差率来自动评估分类器,你也可以使用这部分样本来选择算法或者调整超参数。然而你应该避免对它进行人工检查,我们之所以使用「黑盒」这个词,就是要强调我们使用的这部分数据只是为了用来获取黑盒对分类器的评估。

为什么我们要明确地将开发集分为「眼球开发集」和「黑盒开发集」呢?因为既然你能够直接对眼球开发集中的样本进行人工检查,意味着这部分数据会很快出现过拟合现象。如果你发现算法在眼球开发集的性能表现比黑盒开发集中的提升的更快,那么意味着你已经过拟合了眼球开发集了。在这种情况下,你可能需要放弃这部分数据,并通过将更多的黑盒开发集的数据转移到眼球开发集中,或者通过获取新的标记数据来找到新的眼球开发集。

将你的开发集数据明确的拆分为「眼球开发集」和「黑盒开发集」,可以让你及时知道在手动误差分析的过程中何时过拟合了眼球开发集。

18. 眼球开发集和黑盒开发集应该多大?

你的眼球开发集应该足够大,大到能够让你分析出算法的主要错误类别。如果你正在负责一项人类表现良好的任务(如识别图像中的猫),以下是一些粗略的指导方针:

  • 如果你的分类器在眼球开发集中犯错 10 次——这是非常小的误差,将很难估计不同错误类别的影响,即使你的数据集很小,无法继续扩大开发集规模,但是有总比没有好,这将依然有助于项目的优先级制定;
  • 如果分类器在眼球开发集中犯错 20 次,你将开始大概地了解错误的来源;
  • 如果有约 50 个错误,你会比较好的了解错误的主要来源;
  • 如果大约 100 个错误,你将能够深刻的理解错误的主要来源,我曾看到有人手动分析过多达 500 个的错误。只要你足够的数据,就不会有什么坏处。

假设你的分类器有 5% 的误差,为了确保在眼球开发集中会出现约 100 个错误标记的样例,眼球开发集必须有大约 2000 个样本(0.05*2000 = 100)。随着分类器的误差变低,为了获得足够多的错误来分析,眼球开发集的样本量则要越大。

如果你正在负责一项连人类也没办法做的很好的任务,那么检查眼球开发集的这项操作作用不大,因为很难找出算法不能正确分类一个样本的原因。这种情况下,忽略眼球开发集吧,我们将在后续章节讨论此类问题的解决方案。

那黑盒开发集又有哪些要点呢?我们之前提到过,开发集的样本量从 1000-10000 都是很常见的。现在完善以下这一表述:一个有着 1000-10000 个样本的黑盒开发集基本上能够为你提供足够的数据量来进行参数调优和模型选择。一个含有 100 个样本的黑盒开发集虽然小,但依然是有用处的。

如果你只有一个小的开发集,那么你可能没办法将其分割成足够大的眼球开发集和黑盒开发集。取而代之的操作是你不得不将整个开发集都当作是眼球开发集——你将手动检查整个开发集。

在眼球开发集和黑盒开发集之间,我认为眼球开发集更加重要(假设你正在研究一个人类表现水平很高的问题,检查这些样本能帮你获得对系统性能表现的深刻理解)。如果你只有一个眼球开发集,你可以在这个开发集中进行误差分析、参数调优和模型选择。只有一个眼球开发集的缺点只是出现过拟合的风险更大而已。

如果你有大量的数据,那么眼球开发集的大小将主要取决于你想要分配多少时间去手动分析它们。但是,我基本上没看到过有人会去手动分析超过 1000 个错误。

19. 小结:基本误差分析

  • 当你开始一个新项目,特别是当你并不是该领域的专家时,很难正确猜测最有希望的方向;
  • 不要一开始就计划着构建一个完美的系统,尝试在短短的几天时间内快速建立并训练出一个初始系统来,然后使用误差分析手段来识别出最有前途的优化方向并从这个方向出发对算法进行迭代;
  • 通过手动检查的方式分析 100 个算法误分类的开发集样例,并算出主要的错误类别的比例。利用这个信息来确定优先级顺序;
  • 考虑将开发集分割成眼球开发集(手动检查)和黑盒开发集(不手动检查)。如果算法在眼球开发集的表现比黑盒开发集的表现好的多,那么说明你已经过拟合了眼球开发集,此时应考虑为眼球开发集获取更多的数据。
  • 眼球开发集应该足够大以便你的算法能提供足够的误分类样本供你分析。对于很多应用程序来说,1000-10000 个样本大小的黑盒开发集足够了;
  • 如果你的开发集不够大,将无法按照这种方式拆分,此时只需将整个开发集当作眼球开发集进行手动错误分析、模型选择和参数调优。

  1. 这个建议是针对那些想要构建人工智能应用程序的读者,而不是那些想要发表学术论文的人。稍后我会回到做研究的话题上来。 

  2. 译者注:上一段,说到的 10% 的误差应该指的是开发集误差。因为取出的 100 个误分类样例都来自 10% 的开发集误差样本里边,也就是如果你将这 5% 的错误全部消除,对于整个开发集来说,提升的性能也就只有 0.5%(10% 的 5% = 0.5%),即从 90%->90.5%。 

  3. 译者注:10% 的开发集误差,里边有 50% 是被误分类为狗,假设完全修复这个 Bug 可以提升 5%(10% 的 50% = 5%),也就是从 90%->95%。 

知识共享许可协议本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。欢迎转载,并请注明来自:黄钢的博客 ,同时保持文章内容的完整和以上声明信息!