深度学习实战技巧
转载声明:本文为「顶级程序员」编译团队原创文章,转载请联系后台。
1. 为什么要学习机器学习策略?
机器学习众多重要应用的基础,包括搜索引擎、垃圾邮件过滤、语音识别、商品推荐等。假设你或者你的团队正在做机器学习应用项目,同时你想获得快速进步。你可以从这本书中找到满意的答案。
示例:建立一个识别含有猫图像的新兴公司
你正在建立一个新兴公司,该公司将给猫的爱好者提供大量的猫图片。你计划使用神经网络来建立一个计算机视觉系统用于识别图片中的猫。
但不幸的是,你的学习算法识别准确率不是足够的好。所以你面临具大的压力来提高算法的识别准确率。你应该做些什么呢?
你的团队有许多好的方法,比如:
l 获得更多的数据:收集更多猫的图上。
l 收集大量多样化的训练集。例如,猫在不同位置的图片;不同毛色的猫;多种相机设置拍摄的图片等。
l 通过加大梯度下降的迭代次数,来增加算法的训练时间。
l 尝试更大的神经网络,拥有更多的层、隐藏单元和参数。
l 尝试更小的神经网络。
l 尝试增加正则化(比如L2正则)。
l 改变神经网络的架构(激活函数、隐藏层的数量等)。
如果你能够从以上方法中选择一个好的方案,你将打造一个领先的猫图片识别平台以及带领你的公司走向成功。如果你选择了一个差的方案,你有可能要浪费数月时间。
我们应该怎么选择呢?
这本书将告诉你如何选择。多数的机器学习问题会留下一些线索,而这些线索会告诉你哪些是有用的尝试,哪些是无用的尝试。学会使用这些线索将会节约你数月或数年的开发时间。
2. 怎么使用这本书帮助你的团队
学习完本书后,你将对如何制定机器学习项目技术方向有一个深刻理解。
你的团队成员有可能不明白为什么你会建议某一个具体的方向。或者你想你的团队能够定义一个单一数量评估指标,但他们并不信服。你应该如何去说服他们?
这就是设置短章节的原因:这样你能够将这些章节打印出来并且提供给你的团队成员你想要团队成员知道的1-2内容。
在优先次序上做一些调整,对于你团队的生产率可能会产生巨大的影响。通过帮助你的团队做出这样的变化,我希望你能成为你们团队的超级英雄。
3. 预备知识和符号约定
如果你已经学习了机器学习课程(比如在Coursera上我的机器学习慕课课程)或你有应用监督学习的经验,你将能够很容易明白下面的内容。
假设你熟悉监督学习算法:使用标识的训练样例(x,y),学习一个从x到y的映射函数。监督学习算法包含线性回归、逻辑回归和神经网络。机器学习的形式有多种,但是机器学习的主要实际应用都是监督学习。
我将会频繁提及神经网络(同样称为“深度学习”)。你只需要对他们有一个基本了解即可。
如果你对在此提到的概念不熟悉,请到Coursera上观看机器学习课程的前三周视频。网址:http://ml-class.org
4. 规模推动机器学习的发展
深度学习(神经网络)的许多观点已经存在了十几年。为什么这些观点现在才得到重视?
有2个最为重要的因素推动了深度学习的发展:
l 大量可用数据。现在人们花费更多的时间使用数字设备(笔记本电脑、移动设备)。因此我可以将他们使用数字设备产生的大量数据用于学习算法训练。
l 计算能力提升。仅仅在几年前,我们才能够训练足够大的神经网络,以利用我们现在拥有的庞大数据量。
具体来讲,即使你收集了足够多的数据,如果还使用传统算法(逻辑回归)来处理数据,依然会出现“停滞”现象。这就意为着即使你给算法在多的数据,算法的学习曲线也会变平,算法效果不会在有所提升。
传统算法似乎不知道如何处理我们现在拥有的所有数据。
如果你在同一个监督学习任务训练一个小的神经网络(NN),有可能获得稍微好一点的效果:
这里所说的“小型神经网络”是指一个神经网络拥有少数的隐藏单元/层/参数。最后,如果你训练一个大型神经网络,你能够获得更好的性能表现。
因此,如果你想得到最好的性能表现,(i)你可以训练一个非常大的神经网络,它性能表现将位于绿色曲线的上方;(ii)拥有更多的数据。
还有许多其它的细节(比如神经网络的结构)也是非常重要的,这些方面也有很多的创新。现阶段提升算法的性能最可靠的方法仍然是(i)训练更大的网络和(ii)获得更多的数据。
怎样实现(i)和(ii)是非常复杂的。这本书将会详细讨论这些细节。我们将从对传统学习算法和神经网络都有用的一般策略开始,并建立对构建深度学习系统的最先进策略。
5. 你的开发集和测试集
让我们回顾一下前面讲过的猫图像例子:你开发了一款移动APP,用户可以将多种类型的图片上传到APP。你希望APP能够自动筛选猫的图片。
你的团队拥有一个庞大的训练集,而这个训练集是通过下载不同网站上含有猫的图片(正样本)和不含有猫的图片(负样本)组成。他们将该训练集按照70%作为训练集、30%作为测试集进行分割。使用这个数据,他们构建了一个在训练集和测试集都表现很好的猫识别算法。
但是当你将这个识别算法部署到移动APP时,你会发现识别算法表现非常差。
为什么会这样?
你发现用户上传的图片与你从网站上下载的作为训练集的图片有些不同:用户使用手机拍摄的图片分辨率低、模糊和光线较差。由于你们训练集/测试集数据都来自于网站,而你的算法对于手机拍摄的图片缺乏较好的泛化能力。
在大数据时代之前,人们通常将数据集按照70%:30%随机进行分割作为机器学习算法的训练集和测试集。但是在越来越多的应用中这不是一个好的方法,因为训练集的分布(上面例子中指网站图像)是不同于最终实际应用场景图像的分布(手机图像)。
通常我们的定义:
l 训练集—用于你的学习算法中。
l 开发集—用于调整学习算法的参数、特征选择以及做出其他的选择。有时候将开发集称为保留交叉验证集。
l 测试集—用于评估算法的性能,但是不要使用该数据集对学习算法和参数做出任何决定。
当你定义了一个开发集和测试集,你的团队将会尝试多种方法(比如选择不同的学习算法参数)观察哪种方法最好。开发集和测试集可以让你的团队看到你的算法工作的如何。
换句话说,开发集和测试集目的是指导你的团队对机器学习系统做出最重要的改变。
因此,你应该做到:
选择开发集和测试集,反映未来你期望获得的数据并在上面做的更好。
当你的实际数据(智能手机图像)和测试集(网站图像)在性质上不一样时,你的测试集不应该只有可用数据的30%那么简单。
如果你还没有发你的APP,也就意味着没有任何用户,你将不能获得使你未来做的更好的数据。但你仍然可以尝试去接近这一点。例如,请你的朋友们用手机拍摄一些猫的图像发给你。当你的APP发布后,你可以使用实际用户数据更新程序的开发集/测试集。
如果你实在是没有办法去获得你想要的数据,也许网站图像也是一个不错的开始。但是,你应该关注这个系统缺乏好的泛化能力的风险。
有时候我们需要去决定投资多少去获获取发好的开发集和测试集。但是不要假设训练集与测试集具有相同的分布。尝试去挑选能够反映平台实际应用场景的测试样本,而不是你使用过的数据。
6. 你的开发集和测试集应该具有相同分布
根据你的市场,你将你的猫APP图像数据分为四个区域:(i)美国、 (ii)中国、(iii) 印度和(iv)其他。构造一个开发集和一个测试集,我们可以将美国和印度看作开发集;中国和其他看作测试集。换句话说,我们可以随机的分配2个区域作为开发集,而另外2个区域作为测试集。
一旦你定义了开发集和测试集,你的团队将专注于提高开发集的表现性能。因此,开发集应该反映你最想提升性能的任务:在四个地区做的最好,而不是二个。
开发集和测试集具有不同的分布导致的第二个问题:你的团队有可能在测试集上表现很好,而在测试集上表现很差。我曾经在很多的挫折和白费努力中看到过这个结果。应该避免这样的事情发生在你的身上。
例如,你的开发团队开发一个系统在开发集上表现很好,而在测试集上表现很差。而你的开发集和测试集都来自同一分布,则你应该明确知道:你的算法在开发集上过拟合了。通过获得更多的开发集数据可以避免过拟合的产生。
如果开发集和测试集具有不同的分布,则你的选择就不太清楚了。可能会有以下几个错误:
1. 你的算法已经在开发集上过拟合了
2. 测试集比开发集更难识别。你的算法性能表现达到了你预期的期望,因此没有可能做出进一步显著性的改进了。
3. 测试集不一定比开发集难,只是他们来自不同分布。因此在开发集上表现很好的算法在测试集上并不能表现很好。在这种情况下,把大量工作用于提高算法在开发集上的表现性能是无意义的。
机器学习应该方面的工作已经很困难了。开发集和测试集的不匹配增加了额外的不确定性,关于是否改进开发集的分布性能或提高测试集的表现性能。这使得很难找出什么是起作用的和什么不起作用的,因此很难去优先处理谁。
如果你面对的是第三方基准测试问题,他们的开发者有可能提供来自于不同分布的开发集和测试集。在这种情形下,运气的好坏将会很大程度上影响你算法的表现性能。当然,开发能够在一个分布上训练并推广到另一个分布上仍然表现很好的学习算法是一个重要的研究方向。如果你的目标是做特定机器学习应用而不是学术研究,我建议选择具有相同分布的开发集和测试集。这会使你的团队更有效率。
7. 需要多大开发集/测试集?
开发集应该足够大,大到足以检测你正在尝试不同算法之间的差异。例如,如果分类器有90.0%的准确率而分类器B有90.1%的准确率,则有100个样本的开发集将不能区分0.1%的区别。与我看到的其他机器学习问题相比,一个100个样本的开发集太小。开发集通常样本数量应该在1000到10,000之间。在10000个样本下,你将有可能检测到0.1%的性能提升。
对于一些成熟和重要的应用(例如,广告、搜索引擎和商品推荐),我已经看到一些团队为了提升0.01%的性能而不懈努力,因为这直接影响到公司的利益。在这种情况下,开发集有可能远远超过了10000个样本,为了能够找到更小的改进空间。
测试集的数量多少合适哪?应该足够大,大到能够对于你的系统性能全面评估,拥有足够高的可靠性。一种流行的启发式算法使用数据集的30%用作测试集。当你拥有一个适中的数据量(100到10000之间)时,这个测试集将能很好的工作。在大数据时代,现在我们面对的机器学习问题有时候会超过10亿样本量,分配给开发集/测试集的比例一直在减少,虽然开发集/测试集样本绝对数量在增长。在分配开发集和测试集数据时,开发集和测试集的数量没必要超过其评估算法性能所需的数据量。
8. 给你的团队进行算法优化建立单一数值评估指标
分类准确率是单一数字评估指标的示例:当你的算法对开发集(或测试集)进行分类时,会得到一个样本分类准确性的数字比例。根据这个指标,如果分类器A准确率为97%,分类器B准确率为90%,则分类器A的分类效果更好。
相比之下,查准率和查全率不属于单一数字评估指标体系:它给出2个数字用于评估你的分类器性能。多数字评估指标使得我们很难去比较算法的优势。假设你的算法性能指标如下:
在这种情况下,我们无法看出那一个分类器性能更好,因此多数字评估指标无法直观指导你使用那一个更好的分类器。
在算法开发期间,你的团队会在算法结构、模型参数调优和特征选择等方面进行多种方法的尝试。单一数字评估指标(比如精度)允许你根据算法的准确率将你的模型进行排序,以便于快速决定那一个算法的性能更好。
如果你比较关注查准率和查全率这2个指标,建议你使用一种标准方法将这2个指标组合为单一数字指标。例如,你可以使用查准率和查全率的平均值作为单一数字指标。你也可以计算算法的“F1度量”,它是一种计算二者平均值的改进方法,比简单计算平均值方法效果要好。
当你正在选择一个适合的分类算法时,单一数字评价指标可以快速帮助你做出选择。它给出了一个清晰的算法优先级排序,同时给出了明确的前进方向。
作为最后一个例子,假设你获得了四个主要市场((i) 美国, (ii)中国, (iii)印度,和(iv) 其他地区)的猫分类器的准确率,会得到四个指标值。通过将这四个指标值求平均值或加权平均值,最后会得到一个单一数字指标。将多指标值合并为单一指标值最常用的方法之一是求多指标值的平均值或加权平均值。
9. 优化指标和满意指标
这是将多指标值合并为单一数字指标的另一种方法。
假设你比较关注一个学习算法的准确率和运行时间。现在你需要在下面的三个分类器中做出选择:
如果通过下面的计算公式将准确率和运行时间合并为单一指标,在此看起来有些不自然:
准确率-0.5*运行时间
你可以这样做:首先,定义一个“可接受”的运行时间范围。假设我们说算法在100ms内的运行时间是可接受的。则分类器在满足可接受运行时间内,取最大准确率的算法。在此,运行时间是一个“满意指标”—你的分类算法只需要在这个指标上做的“足够好”即可,也就是算法的运行时间满足最多100ms。准确率是“优化指标”。
如果你正在权衡N个不同的指标,比如模型的二进制文件大小(因为用户不想下载在大的APP文件)、运行时间和准确率,你可以考虑将其中N-1个值作为“满足度指标”,也就是说你只需要考虑他们满足一个特定的值即可。定义最后一个值作为“优化指标”。例如,设置一个阈值作为二进制文件和运行时间的接受范围,并且在这些限制下去优化算法的准确率。
作为最后一个例子,假设你正在构建一个硬件系统,该系统使用一个麦克风监听用户说的特别“唤醒词”,从而唤醒系统工作。比如Amazon Echo监听“Alexa”;苹果Siri监听“Hey Siri”;安卓监听“Okay Google”;百度APP监听“Hello Baidu”。你同时关注假正例的比例—指当没有人说唤醒词时,系统被唤醒的频率和假反例的比例—指当用户说了唤醒词时,系统没有被唤醒的频率。使这个系统性能达到的一个合理目标是减少负反值的比例(优化指标),在24时工作中没有出现一个负正例(满意度指标)。
一旦你的团队开始对评估指标进行优化,他们将能够获得较快的进展。
10. 有一个开发集和度量指标来加速算法的迭代
人们很难事先知道什么方法能够很好的解决新问题。即使是经验丰富的机器学习研究者在给出满意答案之前也需要进行多种方法的尝试。在构建机器学习系统时,我通常会做以下的思考:
1. 首先想一些构造这个系统的想法。
2. 用代码实现这些想法。
3. 通过实验来验证我的想法如何(通常我前面的一些想法都没有很好的表现)。
基于以上的学习,在回过头来产生更多的想法,在进行验证。以此类推进行不断的迭代。
这是一个不断迭代的过程。你迭代的过程越快,你进步的就会越快。这就是为什么拥有开发集/测试集和一个度量指标是如此的重要:每次当你在开发集上验证你的想法时,评价指标可以快速使你判断自己是否在朝正确的方向前进。
假设你没有一个具体的开发集和度量指标。因此你的团队每次开发新的猫分类器时,你必将新的分类器移值进你的APP中,并亲身体验几个小时从直观上判断新的分类器性能是否有所提升。这样的开发效率极其低下!同时,如果你的团队将分类器的准确率从95.0%提高到了95.1%,在你亲身体验过程中有可能无法感受到这0.1%的提升。然而,系统整体的准确率是由许多个0.1%构成的。有一个开发集和度量指标可以快速使你验证那些成功的想法给你的系统带来了小(或大)的提升,因此你可快速决定哪些想法还要继续改进,那些想法可以抛弃。
11.何时更改开发/测试集和评估指标
当开始一个新项目时,我会试图迅速选好开发/测试集 ,因为这可以给团队制定一个明确的目标。
我通常会要求我的团队在不到一周之内(极少多于一周时间)想出一个初始的开发/测试集和评估指标,提出一个不太完美的方案并迅速行动起来往往比过分考虑这些会更好。但是“一周”这个时间表并不适用于成熟的应用。例如,反垃圾邮件就是一个成熟的深度学习应用。我曾经见过一些开发已经成熟的系统的团队花费数月时间来获得更好的开发/测试集。
如果你后来发现你初始的开发/测试集或评估指标与你的目标并不完全一致,那么马上利用一切办法进行更改。例如,如果在你的开发集和评估指标上分类器A比分离器B表现好,但你的团队认为在实际应用中分类器B更适合你的产品,那么这就很有可能是一个你需要更改开发/测试集或评估指标的迹象。
有三个主要原因可能会造成开发集/评估指标不正确地把分类器A排得更高:
1. 你需要做得好的实际数据分布和开发/测试集是不同的。
假设你的初始开发/测试集主要是一些成年猫的照片,但是在你实际查看猫app后,发现用户上传的小猫的照片比预期多得多。所以,开发/测试集的数据分布并不能代表你需要做得好的实际的数据分布。这种情况下,你需要更新开发/测试集,使其更具代表性。
2. 你已经过拟合了开发集。
在开发集上重复评估不同方法的过程可能导致你的算法逐渐对开发集“过拟合”。当你做完开发后,你会在测试集上评估你的算法。如果你发现算法在开发集上的表现远好于在测试集上的表现,这可能是你已经过拟合开发集的迹象。这种情况下,你需要更新你的开发集了。
如果你需要跟踪团队的进度,你也可以每周或每月用测试集定期评估你的系统。但不要用测试集来做出任何关于改进算法的决定,包括是否回退到上一周的系统。如果这样做了,你将开始过度拟合测试集,并且不可能再依靠它来给出一个你的系统性能的完全无偏估计(你可能会在发表论文或做出重要商业决策用到这)。
3. 评估指标正在衡量的并不是项目所需要优化的东西。
假设对于你的猫app,你的评估指标是分类准确率。该指标现在把分类器A排在分类器B前面。但是假如你尝试了这两种算法,发现分类器A会偶尔允许色情图片通过。那么即使分类器A准确率更高,偶发的色情图片所带来的坏影响也意味着这个分类器的表现是不被接受的。你需要做什么呢?
这里,评估指标不能辨别出对产品而言算法B比算法A更好这一事实。所以,你不能再相信这个评估指标能挑选出最佳算法。现在是改变评估指标的时候了。例如,你可以改变评估指标,加重对色情图片通过的惩罚。我强烈建议你选择一个新的评估指标,用这个新的评估指标来为你的团队明确定义一个新的目标,而不是在没有可信任的评估指标下一直进行,然后在分类器中手动选择。
在项目中改变开发/测试集或评估指标是很常见的。拥有一个初始的开发/测试集和评估指标能帮助你快速迭代。如果你发现开发/测试集和评估指标使你的团队远离了正确方向,这不是什么大问题!只需要改变它们,并确保你的团队知道新的方向就可以。
12.结语:建立开发集和测试集
· 你希望在未来获得什么样的数据、并且想在上面做得好?从能反映出这个的数据分布中选择开发集和测试集。这可能不同于你的训练数据分布。
· 如果可能的话,选择来自同一分布的开发集和测试集。
· 为你的团队选择单一数字评估指标进行优化。如果你关心多个目标,考虑把它们合并到一个公式中(例如平均多个错误度量),或设定满足指标和优化指标。
· 机器学习是一个高度迭代的过程:在你发现满意的方法之前,你可能需要尝试很多的想法。
· 具有开发/测试集和单一数字评估指标可以帮助你快速评估算法,然后更快速的迭代。
· 当开始一个全新的应用时,尝试快速建立开发/测试集和评估指标,最好在一周之内。当然,在成熟的应用程序上花费更长的时间也是可以的。
· 按照70%:30%的旧比例划分训练/测试集不适用于你拥有大量数据的情况;开发集和测试集可以占有远小于30%的数据量。
· 你的开发集应足够大,大到能检测出你的算法准确性上的有意义的改变,但没必要更大。你的测试集也应足够大,大到能给你系统的最后性能一个有把握的评估。
· 如果你的开发集和评估指标使你的团队远离了正确方向,快速改变它:(i)如果你过拟合了开发集,那么就去获得更多的开发集数据。(ii)如果你所关心的实际分布和开发/测试集的分布不同,那么就去获得新的开发/测试集数据。(iii)如果你的评估指标不再能衡量对你来说最重要的东西,那么就改变评估指标。
13.快速构建第一个系统,然后迭代
你想建立一个新的反垃圾邮件系统。你的团队有以下几个想法:
· 收集一个含有大量垃圾邮件的训练集。例如,设置一个“蜜罐”:给已知垃圾邮件发送者故意发送虚假的电子邮件地址,这样就可以自动收集他们发送到这些地址的垃圾邮件。
· 开发理解电子邮件文本内容的功能。
· 开发理解电子邮件信封/标题特性的功能,以显示消息经过的网络服务器集。
· 其他。
尽管我在反垃圾邮件上做过大量工作,但我仍然很难选定其中的一个方向。如果你不是该应用领域的专家,那将更难。
所以,开始的时候不要试图设计和构建完美的系统。相反,应该快速构建和训练出一个基本系统——也许是在短短的几天内5。即使这个基本系统与你所能构建的“最佳”系统相去甚远,研究该基本系统的功能仍然很有价值:你将很快找到最值得你投入时间的方向的线索。接下来的几章将告诉您如何去解读这些线索。
5(此建议旨在帮助希望构建AI应用程序的读者,而不是那些以发表学术论文为目标的读者。稍后我将会回到学术主题。)
14.偏误分析:查看开发集样本来评估想法
当你使用猫app时,你注意到一些狗的图片被错误识别成了猫。一些狗长的像猫!
一个团队成员建议和第三方软件合作,使系统可以更好地处理狗样本。这些改变需要花费一个月的时间,并且团队成员热衷于这一方案。你应该要求他们这样做吗?
在投资这个任务一个之前,我建议你首先评估一下它实际上会提高多少系统的准确率。然后你才能更加理性地决定这是否值得花费这一个月的开发时间,还是使用这段时间做些别的事情更好。
具体来说,你可以做以下事情:
· 获取100个系统错误分类的样例。比如,系统出错的例子。
· 手动查看这些样本,计算其中有多少比例是狗的图像。
查看错误分类样本的这一过程被称为偏误分析(error analysis)。在该案例中,如果你发现被错误分类的图像中只有5%是狗,那么无论你在狗的图像上如何改进你的算法,你都不会消除超过5%的错误。换句话说,5%是上述建议能够达到的“天花板”(也就是最大可能的改进上限)。因此,如果整个系统当前的准确率为90%(10%的错误率),这一改进最多可能得到90.5%的准确率(或者9.5%的错误率,比原来10%的错误率少5%)。
相反,如果你发现50%的错误图像都是狗,那么你应该更相信第三方软件的介入能获得很大的效果。它能将准确率从90%提升到95%(错误率相对减少50%,从10%降到5%)。
这种偏误分析的简单计算过程能够给你一个快速的方法,来决定与第三方机构合作解决“狗”问题是否值得。它为决定是否应该做出这笔投资提供了一个定量的基准。
偏误分析通常会帮你选出不同的方向中哪些更有前景。我看到许多工程师不愿意进行偏误分析。相比于考量一个想法是否值得花时间投入,直接进行并实现通常会更让人感到更刺激。这是一个常见的错误:这可能导致你的团队花费一个月时间只获得很少的收益。
手动检查100个样本不会花费太长时间。即使你每分钟只看一张图片,两小时内就可以完成。这两个小时比你白白浪费一个月时间划算多了。
偏误分析(Error Analysis)是指检查开发集中被算法错误分类的样本的过程,以便了解错误产生的深层原因。它不仅可以帮助你重点发展项目,正如该例子所述,而且还能启发一些新的方向,下面我们就会讨论该内容。接下来的几个章节还将介绍一些偏误分析的最佳实践案例。
15.在偏误分析过程中并行评估多个想法
你的团队有以下几个想法来改进猫检测器:
· 修复算法将狗错认为是猫的问题。
· 修复算法将大型猫科类动物(狮子、豹等)被错认为是家猫(宠物)的问题。
· 提高系统在模糊图像上的表现。
· ……
你可以并行且有效地评估所有这些想法。我通常会创建一个电子表格,查看100个分类错误的开发集样本并填写在表格上,同时记下可以帮助我记住具体样本的注释。为了演示这个过程,让我们来看一下你可能生成的一个由4个示例组成的小开发集的电子表格:
表格中图片3在大型猫科动物和模糊图片两列都被勾选了。此外,由于一个例子可能与多个类别相关联,底部的百分比不一定达得到100%。
尽管你可能将这个过程首先描述为类别分类(狗、大型猫科动物和模糊图片),然后查看样例并对它们进行分类。实践中,当你在查看样例时,可能受到启发而提出一些新的错误类别。例如,也许查看过十几张图像后,你发现许多错误的图片都经过Instagram 过滤器的预处理。你可以返回并在电子表格中添加“Instagram”列。手动查看算法出错的样例,并思考人是如何/是否能正确地分类这些样例,这通常会启发你想出新的类别和解决办法。
最有用的错误类别是你有改进想法的错误类别。例如,如果你有办法“撤销” Instagram 过滤器从而恢复原始图像,那么添加Instagram类别是最有用的。但是你不必只局限于你已经有想法去改进的错误类别;这个过程的目标是建立你对最有希望关注的领域的直觉。
偏误分析是一个迭代的过程。如果开始的时候你在脑海里没有任何分类,不要担心!查看一些图片之后,你就可能会提出一些关于错误类别的想法。手动分类一些图片之后,你就可能会想出一些新的错误类别,然后根据新的类别再返回重新检查这些图片。以此类推。
假如你完成了对100个错误分类的开发集样本的偏误分析,并得到以下结果:
现在你知道了,解决狗分类错误的项目可以减少最多8%的错误。致力于大型猫科动物和模糊的图片对降低错误率帮助更大。所以,你可能会挑选后两者中的一个来进行处理。如果你的团队有足够多的人可以同时展开多个方向,你也可以让一些工程师处理大型猫科动物图片,另外一些解决模糊图像。
偏误分析并不会有一个明确的数学公式来告诉你什么才是最高优先级的任务。你还必须考虑你希望在不同错误类别上取得多少进展,以及处理每个错误类别所需要的工作量。
16.清理贴错标签的开发和测试集样本
在偏误分析中,你可能会注意到开发集中的一些样本被错误标记了。这里所说的“错误标记”,是指即使在算法遇到它之前,图片已经被打标人员贴上了错误的标签。即:样本 (x,y) 中的类别标签y的值不正确。例如,也许一些不是猫的图片被错贴标签为包含猫,反之亦然。如果你怀疑错误标记的图像占比很大,添加一个类别来记录有错误标记的样本的占比:
你应该纠正开发集中的这些标签吗?记住,开发集的目的是为了帮你快速评估算法,以便你可以判断算法A或B哪个更好。如果被错误标注的开发集的一小部分妨碍你做出这些判断,那么花时间去修正错误标注的开发集标签是值得的。
例如,假设你的分类器表现如下:
· 开发集的整体准确率……90%(10%整体错误率)
· 样本贴错标签导致的错误……0.6%(开发集错误率中的6%)
· 其他原因导致的错误……9.4%(开发集错误率中的94%)
在这里,由于错误标注导致的0.6%的不准确性,相对于你可以改进的9.4%的错误而言,可能没有那么重要。手动修复开发集中错误标注的图像并没有什么坏处,但这样做并不重要:不知道系统是否有10%还是9.4%的整体错误率可能没什么问题。
假设你不断改进猫分类器并达到以下性能:
· 开发集的整体准确率……98.0%(2.0%整体错误率)
· 样本贴错标签导致的错误……0.6%(开发集错误率中的30%)
· 其他原因导致的错误……1.4%(开发集错误率中的70%)
30%的错误是由于错误标注的开发集图像造成的,这将会为您的准确率估计增加显著的错误。现在去提高开发集中标签的质量是有价值的。处理错误标注的样本将帮助您算出分类器的错误是接近1.4%还是2%——这是一个相对显著的差异。
开始容忍一些错误标记的开发集样本并不罕见,只是在系统改进之后才改变主意,这样错误标记的样本相对于错误集的比例就会增加。
最后一章解释了如何通过算法的提升来改进错误类别,例如狗、大型猫科动物和模糊图片。在本章中你会了解到,你也可以通过改善数据标签在错误标记的类别上工作。
无论你采用什么方法来修正开发集标签,记得也将其用于测试集标签,以便开发集和测试集继续服从统一分布。将开发集和测试集固定在一起可以避免我们在第六章中讨论的问题,即你的团队优化了开发集的性能,只是到后来才意识到他们在根据不同的测试集进行不同的标准判断。
如果你决定提升标签的质量,那么请考虑仔细检查系统错误分类的样本的标签,以及正确分类样本的标签。在一个样本中,原始标签和学习算法有可能都是错的。如果只是修正系统已经错误分类的样本的标签,可能会在评估中引入误差。如果你有1000个开发集样本,并且分类器准确率为98%,那么检查错误分类的20个样本比检查正确分类的所有980个样本要容易的多。因为在实践中只检查错误分类的样本比较容易,所以偏差会蔓延到一些开发集中。如果你只对开发产品和应用感兴趣,那么这种偏差是可以接受的,但如果你计划在学术研究论文中使用该结果,或者需要对测试集的准确性进行完全无偏见的测量,这将会是一个问题。
17.如果你有一个大的开发集,将其分成两个子集,只着眼于其中的一个
假设你有一个含有5000个样本的大开发集,其中有20%的错误率。这样,算法将对约1000个开发图片进行错误分类。手动检查1000张图片会花费很长时间,所以我们可能会决定在偏误分析中不使用所有图片。
在这种情况下,我会明确地将开发集分成两个子集,只看其中一个,另一个不看。你将会很快的过拟合你手动查看的那部分。你可以使用未手动查看的部分来调参。
继续上面的例子,在该例子中算法将5000个开发集样本中的1000个进行了错误分类。假设我们想手动检查约100个错误样本(错误样本的10%)进行偏误分析。你应该随机选择10%的开发集,并将其放入我们口中的眼球开发集(Eyeball dev set)中,以提醒我们自己,我们正在用眼睛看它。(对于语音识别项目,你可以在其中听音频剪辑,或许可以将这个数据集称为耳朵开发集)。因此,眼球开发集有500个样本,其中我们预计算法会错误分类约100个。
开发集的第二个子集叫做黑盒开发集(Blackbox dev set),它将拥有剩余的4500个样本。你可以使用黑盒开发集,通过测量它们的错误率来自动评估分类器。也可以使用它来选择算法或调超参。但是,你应该避免用眼睛去看它。我们使用术语“黑盒”是因为我们只使用数据集的子集来获得分类器的“黑盒”评估。
为什么我们将开发集明确分为眼球开发集和黑盒开发集呢?因为你会获得眼球开发集中样本的直观认识,你就会开始更快的过拟合眼球开发集。如果你发现眼球开发集比黑盒开发集性能提升的更快,你已经过拟合眼球开发集了。这种情况下,你可能需要丢弃它并找一个新的眼球开发集,可以通过将更多黑盒开发集中的样本移到眼球开发集中,也可以通过获取新的标注数据来获得。
将开发集明确地分为眼球和黑盒可以让你知道手动偏误分析过程中什么时候会开始导致数据的眼球部分过拟合。
18.眼球和黑盒开发集应该多大?
你的眼球开发集应该足够大,大到可以让你了解到算法的主要错误类别。如果你正在从事一项人类表现很好的任务(如识别图像中的猫),以下是一些粗略的指导方针:
· 一个使你的分类器犯错10次的眼球开发集将被认为是非常小的。只有10个错误,很难准确估计不同错误类别的影响。但如果您的数据非常少,并且无法将更多的数据放入眼球开发集,那么有总比没有好,这将有助于项目的优先顺序。
· 如果分类器在眼球开发集上样本上犯了约20个错误,你将会开始大致了解主要的错误来源。
· 如果有约50个错误,你将会比较好的了解主要的错误来源。
· 如果有约100个错误,你将会很清楚主要的错误来源。我见过有人手动分析更多的错误——有时候多达500个。只要你有足够多的数据,这是没有坏处的。
假设你的分类器有5%的错误率。为了确保在眼球开发集中有约100个错误标记的样本,眼球开发集应该有约2000个样本(因为0.05 * 2000 = 100)。分类器的错误率越低,为了获得足够多的错误来分析,眼球开发集就需要越大。
如果你正在做一个连人都做不好的任务,那么检查眼球开发集将不会有什么帮助,因为很难找出算法不能正确分类一个样本的原因。这种情景下,你可能会忽略眼球开发集。我们将在后续章节中讨论这些问题的指导方针。
黑盒开发集该如何?我们之前说过,开发集有约1000-10000个样本是正常的。为了完善这个表述,尽管更多的数据几乎没什么坏处,一个有1000-10000个样本的黑盒开发集通常会为你提供足够的数据去调超参和选择模型。一个含有100个样本的黑盒开发集比较小,但仍然有用。
如果你有一个小的开发集,那么你可能没有足够的数据将其分成足够大的眼球和黑盒开发集来达到目的。相反,你的整个开发集可能不得不用作眼球开发集——也就是说,你将手动检查所有的开发集数据。
在眼球和黑盒开发集之间,我认为眼球开发集更重要(假设你正在研究一个人类能够很好解决的问题,检查这些样本能帮你获得洞察力)。如果你只有一个眼球开发集,你可以在这个开发集上进行偏误分析、模型选择和调超参。只有一个眼球开发集的缺点是过拟合开发集的风险更大。
如果你有数据的充足访问权限,那么眼球开发集的大小将主要取决于你有时间去手动分析的样本的数量。例如,我很少看到有人手动分析超过1000个错误。
19.结语:基本偏误分析
· 当你开始一个新项目时,尤其是在一个你不是专家的领域,很难正确猜测出最有前景的方向。
· 所以,不要在开始试图设计和构建一个完美的系统。相反,应尽可能快(可能在短短几天内)的构建和训练一个基本系统。然后使用偏误分析去帮助你识别最有前景的方向,并通过迭代改进你的算法。
· 通过手动检查约100个算法错误分类的开发集样本来执行偏误分析,并计算主要的错误类别。用这些信息来确定优先修复哪种类型的错误。
· 考虑将开发集分为手动检查的眼球开发集和不手动检查的黑盒开发集。如果在眼球开发集上的性能比在黑盒开发集上好很多,那么你已经过拟合眼球开发集了,并且应该考虑为其添加更多的数据。
· 眼球开发集应该足够大,以便于算法有足够多的错误分类样本供你分析。对很多应用来说,含有1000-10000个样本的黑盒开发集已经足够了。
· 如果你的开发集没有大到可以按照这种方式进行拆分的程度,那么就使用眼球开发集来用于手动偏误分析、模型选择和调超参。
20. 偏差和方差:错误的两大来源
假设你的训练集、开发集和测试集都来自相同的分布。那么你应该试图去获取更多的训练数据,因为这样能只提高性能,对吗?
尽管有更多的数据是没有坏处的,但是也不总是如我们期望的那样有帮助。获取更多的数据可能是浪费时间。所以,你需要决定何时该加数据,何时不用这么麻烦。
机器学习中有两个主要错误来源:偏差和方差。理解它们将有助于你决定添加数据以及其他提高性能的策略是否是对时间的良好利用。
假设你希望构建一个5%错误率的猫识别器。目前,你的训练集错误率为15%,并且你的开发集错误率为16%。在这种情况下,添加训练数据可能不会有太多帮助。你应该着眼于其他改变。实际上,在你的训练集上添加更多的样本只会让你的算法难以在训练集上做的更好。(我们会在后面的章节中说明原因。)
如果你在训练集上的错误率是15%(85%的准确率),但是你的目标是5%错误率(95%准确率),那么第一个要解决的问题是提高算法在训练集上的性能。你的开发/测试集上的性能通常比在训练集上要差。所以,如果算法在见过的样本上得到85%的准确率,那么是不可能在没见过的样本上得到95%的准确率的。
假设如上所述你的算法在开发集上有16%的错误率(84%的准确率)。我们将这16%的错误分为两部分:
· 第一,算法在训练集上的错误率。在该例中,它是15%。我们非正式地将此认为是算法的偏差(bias)。
· 第二,算法在开发(或测试)集上比训练集上差多少。在该例中,开发集比训练集差1%。我们非正式地将此认为是算法的方差(variance)6。
对学习算法的一些修改能解决错误的第1个组成部分——偏差,并且提高算法在训练集上的性能;一些修改能解决错误的第2个组成部分——方差,并帮助算法从训练集到开发/测试集上更好的泛化7。为了选择最有希望的改变,了解这两组错误中哪个更亟待解决是很有用的。
开发关于偏差和方差的良好直觉将帮助你为算法选择有效的改变。
备注:
6(统计领域对偏差和方差有更正式的定义,我们不用担心这些。粗略地说,偏差是当你有一个非常大的训练集时,你的算法在训练集上的错误率。方差是与此设置中的训练集相比,你在测试集上差多少。当你的误差衡量是均方差(mean squared error)时,你可以写下指定这两个量的公式,并证明总误差 = 偏差 + 方差(Total Error = Bias + Variance)。但是你的目的是如何在机器学习问题上取得进展,这里给出的偏差和方差的更非正式的定义就足够了。)
7(这里还有一些通过对系统架构做出大的改变的方法,能够同时减少偏差和方差。但是这些方法往往难以识别和实施。)
21 关于偏差和方差的例子
以我们的猫咪分类任务为例。一个理想的分类器(比如人)可能会用几乎完美的表现来完成这个任务。
假设你的算法可以达到以下标准:
训练集误差 = 1%
开发集错误 = 11%
这会带来什么问题呢?根据之前的章节中我们给出的定义,我们可以估计出偏差为1%,方差为10%(=11%-1%)。因此,这带来了高方差。该分类器有着很低的训练误差,但是它并不能一般化为开发集。我们称之为过度拟合。
现在再来看看这个:
训练集误差 = 15%
开发集错误 = 16%
我们可以估计出偏差为15%然后方差为1%。这个分类器对训练集的拟合很差,误差为15%,但它在开发集上的误差和训练误差相差无几。 因此,该分类器具有高偏差低方差。 我们说这个算法是欠拟合的。
我们再来看一个例子:
训练集误差 = 15%
开发集错误 = 30%
我们可以估计出偏差和方差均为15%。该分类器具有高偏差和高方差:它在训练集上表现不佳,因此具有高偏差,并且其在开发集上的性能更差,因此它也具有高方差。 过度拟合/欠拟合术语很难应用于此,因为该分类器同时过度拟合和欠拟合。
我们最后再来看一个例子:
训练集误差 = 0.5%
开发集错误 = 1%
这个分类器做得很不错,不仅低偏差而且低方差。祝贺你以极佳的表现完成了这个任务。
22 与最佳错误率做比较
在我们的猫咪识别的例子中,“理想的”错误率——由“最佳”分类器所实现的——将近0%。一个人在看照片的时候几乎总是可以分辨出来里面是不是有一只猫的;因此我们希望机器也可以做到这个地步。
其他的问题则有点儿难度。举个例子,假设你正在构建一个语音识别系统,发现14%的音频片段具有极多的背景噪音或者是非常的难以理解,即使是人类也无法识别所说的内容。在这种情况下,即便是“最佳”语音识别系统也会有14%左右的错误。
假设在刚才那个语音识别问题上你的算法可以达到以下标准:
训练集误差 = 15%
开发集错误 = 30%
训练集的性能已经接近14%的最佳错误率。因此,在偏差或训练集性能方面没有太大的改进空间。但是,该算法并没有很好地推广到开发集; 因此,由于变化导致的误差存在很大的改进空间。
这个例子类似于前一章的第三个例子,它的训练集误差为15%,开发集误差为30%。 如果最佳错误率为~0%,那么15%的训练误差留下了很大的改进空间。 这表明减少偏差的变化可能是富有成效的。 但如果最佳错误率为14%,则相同的训练集性能告诉我们,分类器的偏差几乎没有改进的余地。
对于最佳错误率和0相差非常多的问题,这里是算法错误的更详细分类。 继续上面的语音识别例子,30%的总开发集错误可以分解如下(类似的分析可以应用于测试集错误):
最佳错误率(“不可避免的偏差”):14%。假设我们决定,即使世界上最好的语音系统,我们仍然会有14%的错误。我们可以将此视为机器学习算法偏差的“不可避免”部分。
可避免的偏差:1%。这是以训练集误差和最佳误差率之间的差值得来的。【注8】
方差:15%。训练集误差和开发集误差的差值。
为了将其与我们之前的定义联系起来,偏差和可避免偏差的关系如下【注9】:
偏差 = 最佳错误率(不可避免偏差)+可避免偏差
“可避免的偏差”反映了算法在训练集上的表现比“最佳分类器”差多少。
方差的概念与以前一样。从理论上讲,我们总是可以通过训练大量训练集将方差减少到接近零。因此,对于足够大的数据集,所有方差都是“可避免的”,因此不存在“不可避免的方差”。
我们再来考虑一个例子,还是最佳错误率为14%,然后我们满足:
训练集误差 = 15%
开发集错误 = 16%
在前一章中我们将其称为高偏差分类器,现在我们可以说它的可避免偏差为1%,方差约为1%。因此,该算法已经做得很好,几乎没有改进的余地。它只比最佳错误率差2%。
我们从这些例子中看到,了解最佳错误率有助于指导我们的后续步骤。在统计中,最佳错误率也称为贝叶斯错误率或贝叶斯率。
那我们该怎么才能知道最佳错误率是多少呢?对于人类相当擅长的任务,例如识别图片或抄录音频片段,你可以要求人类提供标签,然后测量人工标记相对于训练集的准确性。这将给出最佳错误率的估计。如果你正在解决甚至人类都难以解决的问题(例如,预测该推荐什么电影或向用户展示什么样的广告),则很难估计最佳错误率。
在“与人类绩效比较(第33至35章)”一节中,我将更详细地讨论将机器学习算法的性能与人类绩效进行比较的过程。
在最后几章中,你学习了如何通过查看训练和开发设置错误率来估计可避免/不可避免的偏差和方差。下一章将讨论如何使用此类分析中的见解来优先考虑减少偏差的技术还是减少方差的技术。根据项目当前的问题是高(可避免)偏差还是高方差,你应该应用不同的技术。让我们继续!
【注8】如果此数字为负数,则你在训练集上的表现优于最佳错误率。这意味着你在训练集上过度拟合,并且该算法已经过度记忆训练集。你应该关注让方差减少的方法,而不是进一步减少偏差。
【注9】选择这些定义是为了传达有关如何改进学习算法的见解。这些定义与统计学家定义偏差和方差的方式不同。从技术上讲,我在这里定义的“偏差”应该被称为“我们归因于偏差的错误”; 并且“可避免的偏差”应该是“我们归因于学习算法偏差超过了最佳错误率的错误”。
23 解决偏差和方差
解决偏差和方差问题最简单的准则如下:
如果你具有较高的可避免偏差,请增加模型的大小(例如,通过添加网络层数/神经元来增加神经网络的大小)。
如果你的方差很大,请为训练集增加数据。
如果你能够无限制地增加神经网络大小并增加训练数据,那很多机器学习的问题都迎刃而解了。
但是实际上,增加模型的大小最终会导致计算问题,因为训练非常大的模型很慢。你也可能无法获得更多的训练数据。(即使在互联网上,也只有有限张的猫片!)
不同的模型体系结构——例如,不同的神经网络体系结构——会针对你的问题具有不同的偏差/方差。最近的许多深度学习研究已经开发出很多创新的模型架构。因此,如果你使用神经网络,学术文献可以成为灵感的重要来源。github上还有很多很棒的开源实现。但是,尝试新架构的结果比我们都简单准则(增加模型大小和添加数据)更难以预测。
增加模型大小通常会减少偏差,但也可能会增加方差和过度拟合的风险。但是,这种过度拟合问题通常仅在你不使用正则化时出现。如果你有着精心设计的正则化方法,那么通常可以安全地增加模型的大小而不会增加过度拟合。
假设你正在应用具有L2正则化或遗弃的深度学习,其中正则化参数在开发集上表现最佳。如果你增加模型大小,通常你的性能将保持不变或改善;它不太可能显着恶化。避免使用更大模型的唯一原因是计算成本增加。
24 偏差与方差的权衡
你可能听说过“偏差与方差权衡”。我们对大多数学习算法做出的改变,有一些可以减少偏差,但代价是增加方差,反之亦然。这在偏差和方差之间产生了“权衡”。
举个例子,在神经网络中增加模型添加神经元/层的大小,或这增加输入的特征——通常会减少偏差,但可能会增加方差。对应的,添加正则化通常会增加偏差但会减少方差。
在现代,我们经常可以访问大量数据,并且可以使用非常大的神经网络(深度学习)。因此,我们做权衡的机会比较少,而且现在有更多的选择来减少偏差而不会损害方差,反之亦然。
举个例子,你通常可以增加神经网络大小并调整正则化方法以减少偏差而不会显着增加方差。通过添加训练数据,你通常还可以在不影响偏差的情况下减少方差。
如果选择适合你任务的模型体系结构,则还可以同时减少偏差和方差。但是选择这样的架构可能很困难。
在接下来的几章中,我们将讨论用于解决偏差和方差的其他特定技术。
25 降低可避免偏差的技术
如果你的学习算法可避免的偏差非常高,那么可以尝试以下技术:
增加模型大小(例如神经元/层数):这种技术可以减少偏差,因为它可以让你更好地适应训练集。如果你发现这会增加方差,那么就使用正则化,这通常会消除方差的增加。
根据错误分析修改输入特征:假设你的错误分析激发你创建其他特征,帮助算法消除特定类别的错误。 (我们将在下一章进一步讨论这个问题。)这些新特征可能有助于偏见和差异。理论上,添加更多特征可能会增加差异;但如果你发现这种情况,那就使用正则化,这通常会消除方差的增加。
减少或消除正则化(L2正则化,L1正则化,丢失):这将减少可避免的偏差,但会增加方差。
修改模型体系结构(例如神经网络体系结构),使其更适合你的问题:此技术可以影响偏差和方差。
一种无用的方法:
添加更多训练数据:此技术有助于解决方差问题,但通常对偏差没有显着影响。
26 训练集的误差分析
你的算法必须在训练集上运行良好,才能期望它在开发/测试集上表现良好。
除了前面描述的用于解决高偏差的技术之外,我有时还会根据类似于Eyeball开发套件的错误分析的协议对训练数据进行误差分析。 如果你的算法具有高偏差,即如果它不能很好地拟合训练集,则这可能很有用。
举个例子,假设你正在为应用程序构建语音识别系统,并从志愿者那里收集了一组音频剪辑。 如果你的系统在训练集上表现不佳,你可能会考虑了解一组约100个例子,它们会告诉你这些算法很难理解训练集错误的主要类别。 与开发集误差分析类似,你可以统计不同类别的错误:
在此示例中,你可能会发现你的算法在使用具有大量背景噪音的训练示例时会遇到特别的困难。因此,你可以专注于能够更好地适应具有背景噪声的训练示例的技术。
在给定与学习算法相同的输入音频的情况下,你还可以仔细检查一个人是否可以转录这些音频片段。如果有太多的背景噪音,任何人都无法弄清楚所说的内容,那么期望任何算法正确识别这些话语可能是不合理的。我们将在后面的部分讨论将算法与人类级别性能进行比较的好处。
27 降低方差的技术
如果你的学习算法存在高方差,你可以尝试以下技术:
添加更多训练数据:这是解决方差的最简单、最可靠的方法,只要你可以访问更多的数据以及足够的计算能力来处理数据。
添加正则化(L2正则化,L1正则化,丢失):此技术可减少方差但增加偏差。
添加早期停止(即基于开发设置误差,提前停止梯度下降):此技术可减少方差但增加偏差。早期停止的行为与正则化方法非常相似,有些作者称之为正则化技术。
减少输入要素数量/类型的特征选择:此技术可能有助于解决方差问题,但也可能会增加偏差。稍微减少特征的数量(比如从1000个特征到900个)不太可能对偏差产生巨大影响。只要你没有排除太多有用的特征,减少它(例如从1000个特征减少到100个,减少10倍)就更有可能产生重大影响。在现代深度学习中,当数据充足时,关注重点就已经不在特征选择了,现在我们更有可能给所有特征都赋予算法,并让算法基于数据选择使用哪些特征。但是当你的训练集很小时,特征选择可能非常有用。
减小模型大小(例如神经元/层的数量):谨慎使用。这种技术可以减少方差,同时可能增加偏差。但我不推荐这种技术来解决方差。添加正则化通常会提供更好的分类性能。减小模型尺寸的优势在于降低了计算成本,从而加快了训练模型的速度。如果加速模型训练很有用,那么一定要考虑减小模型大小。但是,如果你的目标是减少方差,并且你不关心计算成本,请考虑添加正则化。
以下是关于解决偏差的前一章重复的另外两种策略:
根据错误分析修改输入特征:假设你的错误分析激发你创建其他特征,帮助算法消除特定类别的错误。这些新特征可能有助于解决偏差和方差的问题。在理论上,增加更多特征可以增加方差;但如果你发现这种情况,那就使用正则化,这通常会消除方差的增加。
修改模型体系结构(例如神经网络体系结构),使其更适合你的问题:此技术可以影响偏差和方差。
28 诊断偏差和方差:学习曲线
我们已经看到一些方法来估计那些可归因于可避免偏差与方差的错误的数量,我们可以通过估计最佳错误率并计算算法的训练集和开发集错误来实现这一目的。现在让我们讨论一种更具信息性的技术:绘制学习曲线。
学习曲线将你的开发集错误与训练示例的数量进行对比。要绘制它,你需要使用不同的训练集大小运行算法。举个例子,如果你有1,000个示例,则可以在100,200,300,...,1000示例上训练算法的单独副本。 然后你可以绘制开发集误差如何随训练集大小而变化。给大家展示一个例子:
随着训练集数据的增多,开发集误差应当下降。
我们经常会有一些“期望的错误率”,我们希望我们的学习算法最终能够实现这个错误率。例如:
如果我们希望人类的表现,那么人为错误率可能是“期望错误率”。
如果我们的学习算法服务于某些产品(例如提供猫片),我们可能会基于直觉地知道需要什么级别的性能来为用户提供良好的体验。
如果你长期从事一项重要的应用,那么你可能会基于直觉地知道下一季度/年度可以合理地取得多少进展。
为你的学习曲线加上期望值之后图像会变成这样:
你可以通过视觉外推延伸红色“dev error”曲线来猜测通过添加更多数据后能够有多接近期望值。在上面的示例中,将训练集大小加倍可能会使你达到所需的性能。
但是,如果开发错误曲线已经“平稳”(即变平),那么你可以立即告诉自己,添加再多的数据也无法实现你的目标了:
因此,考虑学习曲线可能会帮助你避免花费数月时间收集两倍的无用训练数据的情况。
这个过程的一个缺点是,如果你只看开发误差曲线,哪怕你有更多的数据,也很难推断和预测红色曲线的确切位置。 还有一个附加图可以帮你估计添加数据的影响:训练误差。
29 绘制训练错误图像
随着训练集大小的增加,你的开发集(和测试集)误差应该会减少。但是,随着训练集大小的增加,训练集误差通常会增加。
让我们用一个例子说明这种效果。假设你的训练集只有两个示例:一个猫图像和一个非猫图像。然后,学习算法很容易“记住”训练集中的两个示例,并获得0%的训练集错误。即使其中一个或两个训练样例都被错误标记,算法仍然很容易记住两个标签。
现在假设你的训练集有100个例子。可能一些例子甚至被贴错了标签,或者含糊不清——有些图像非常模糊,所以即使是人类也无法判断是否有猫。可能学习算法仍然可以“记住”大部分或全部训练集,但现在更难以获得100%的准确度。通过将训练集从2个增加到100个,你会发现训练集的准确度会略有下降。
最后,假设你的训练集有10,000个示例。在这种情况下,算法更难以完全适合所有10,000个示例,特别是如果有些模糊不清或标注错误。因此,你的学习算法在此训练集上会更糟糕。
让我们在之前的数据中添加一个训练误差图:
你可以看到蓝色“训练误差”曲线随着训练集的大小而增加。此外,你的算法通常在训练集上比在开发集上做得更好; 因此,红色偏差误差曲线通常严格地位于蓝色训练误差曲线之上。
我们接下来讨论如何解释这些图。
30 解释学习曲线:高偏差
假设你的开发错误曲线如下图所示:
我们之前曾说过,如果你的开发误差曲线稳定,你不可能仅通过添加数据来达到预期的性能。
但我们其实很难确切地知道红色开发误差曲线的外推是什么样的。 如果开发集很小,你会更加不确定,因为曲线可能会受很多因素的影响。
假设我们将训练误差曲线添加到该图中并获得以下图像:
现在,你可以绝对确定添加更多数据绝对不是一个好办法了。 为什么呢? 记住我们的两个观察结果:
随着我们添加更多训练数据,训练误差只会变得更糟。因此,蓝色训练误差曲线只能保持相同或更高,因此它只能远离所需性能的(绿线)水平。
红色偏差误差曲线通常高于蓝色训练误差。因此,即使训练误差高于期望的性能水平,添加更多数据也几乎无法使红色偏差误差曲线下降到所需的性能水平。
在相同的图上检查开发误差曲线和训练误差曲线使我们能够更自信地推断开发误差曲线。
为了便于讨论,假设期望的性能是我们对最佳错误率的估计。上图是具有高可避免偏差的学习曲线的标准“教科书”示例:在训练集最大的时候——可能与我们所有的训练数据相对应——训练误差与期望值之间存在较大差距,表明可避免的偏差很大。此外,训练曲线和开发曲线之间的差距很小,表明方差很小。
以前,我们仅在该图的最右侧点测量训练集和开发集误差,这对应于使用所有可用的训练数据。绘制完整的学习曲线,可以更全面地了解算法在不同训练集大小上的表现。