《机器学习要领》 不同分布下的训练和测试(中文翻译版)

Machine Learning Yearning Chapter7 Training and testing on different distributions(Chinese ver)

Posted by Canary on June 6, 2018

前言

本篇博客是 Andrew NG 《Machine Learning Yearning》 的「第七章:不同分布下的训练和测试」翻译。本章内容将探讨当训练集的数据分布和开发/测试集的分布不一致的时候可能出现的情况。有时候不得不将与测试集不同分布的训练集用在构建模型上,那什么时候这种做法合适呢?如何确保你的算法表现总能在目标分布中表现良好呢?此外,本章同时将教会你如何诊断出数据不匹配,你也将学习如何解决数据不匹配的技术。开启本章内容,出发!
👉官网传送门
👉GitHub 项目传送门,欢迎 Star

36. 当你不得不在不同分布中进行训练和测试

你将你的猫咪图片应用程序的用户上传的 1 万张图片,手动分类为 「猫」 和 「非猫」 两种。同时你也通过互联网下载了额外的 20 万张图片。这种情况下,你应该如何去定义训练/开发/测试集呢?

因为 1 万张来自于用户的猫咪图像密切反映了你的算法想要去拟合的数据概率分布,因此,你可以将这部分数据用于开发集和测试集。如果你正在训练对数据有大规模需求的算法(Data-Hungry Algorithm),你可以将取自互联网的那 20 万张猫咪图片用于训练你的算法。这样的话,你的训练集和开发/测试集的数据就不服从同一分布了。这会对你的算法性能产生什么影响呢?

与其将数据单纯的划分为训练/开发/测试集,不如将 21 万张图片混合然后随机分配到训练/开发/测试集中。这种情况下,所有的数据均来自相同的分布了。但是我不推荐使用这种方法,因为 20.5万/21万 ≈ 97.6% 的开发/测试集数据会来自互联网图片,这比例并不能很好的反映出你数据的真实分布。切记,我们对选择开发/测试集的忠告:

  • 选择能够映射出你在未来将要获得的数据,且表现出良好效果的开发集和测试集。

关于机器学习的大多数学术文献都认为训练集、开发集和测试集来自同一分布1。在机器学习的早期,数据很稀缺,我们通常只能从某个概率分布中获取一个数据集,所以我们会随机的将这些数据分割为训练/开发/测试集,并假设所有的数据来自于同一分布,上述做法效果不错。

但在大数据时代,我们有能力获取到大量数据,例如猫的互联网图片。即使训练集的数据和开发/测试集的数据来源于不同分布,我们仍然希望用这些数据来用于算法学习,因为它可以为算法提供大量信息。

对于猫咪检测器的例子,与其将所有的用户上传的猫图分配给开发/测试集,不如将 5000 张(一半)分配给开发/测试集,然后将剩下的那 5000 张图片给训练集。这样,你的 205000 张训练集图片既包含了 5000 张来自用户上传的图片,也包含了那来自互联网的 20 万张图片,我们将在后续章节讨论为什么这种方法是有效的。

让我们来看第二个例子,假设你正在构建一个语音识别系统用来为语音控制的移动地图/导航应用程序转录街道地址。你有 2 万个用户口述街道名称的样本,同时你还有 50 万个用户讨论其他主题的音频样本。你可能将 10000 个街道相关的样本置入开发/测试集,并将剩下的 10000 个样本连同那 50 万个其他主题的样本用来进行算法的训练。

我们继续假设你的开发集数据和测试集数据来自同一分布。但是重要的是要明白不同的训练集和开发/测试集概率分布会带来一些额外的挑战。

37. 如何决定是否使用所有数据

假设你的猫咪检测器的训练集包含了 1 万张用户上传的图像。这些数据都是来自于和独立的开发/测试集相同的分布,同时代表的是你的算法想要表现良好的那种分布。你还有额外的 2 万张取自互联网的猫咪图片。你是否应该将 2万 + 1万 = 3万 这所有的图片作为你的训练集的数据?或者是放弃那 2 万张图片以防止你的学习算法出现偏差?

当使用早期的学习算法(比如手工设计计算机视觉特征,然后使用一个简单的线性分类器)时,合并这两种类型的数据导致性能更差的风险是存在的。因此,一些工程师会警告你不要把这来自网络的 2 万张图片包括进来。

但在当今这个强大、灵活的学习算法时代——比如大型神经网络——这种风险已经大大降低。如果你能负担得起用足够多的隐藏单元/层来构建一个神经网络,你就可以安全地将 2 万张图片添加到你的训练集中。

这种观察依赖于这样一个事实:存在 $x \rightarrow y$ 的映射,对于来自不同分布的两种类型的数据都适用。换句话说,存在这样的一个系统,无论是输入来自互联网的图片还是输入用户上传的图片,它都能准确的预测出正确的标签来,即使不知道图像的来源。

添加额外的 2 万张图像会产生以下效果:

  1. 它能为你的神经网络提供更多的例子说明猫是什么样子的。这很有帮助,因为互联网图片和用户上传的移动应用图片确实有一些相似之处。你的神经网络可以将从互联网图像中获得的一些知识应用到处理移动应用程序图像中来;
  2. 它迫使神经网络分出一部分能力来学习特定于互联网图像的属性(例如分辨率较高,图像帧的不同分布等)。如果这些属性和移动应用程序中的图像差别很大的话,它将「消耗」掉一部分神经网络的性能。因此,从移动应用程序图像的分布中识别数据的能力就会降低——这是你真正关心的。理论上,这可能会影响算法的性能。

为了使用不同的术语来描述第二种效应,我们求助于虚拟人物夏洛克·福尔摩斯,他说你的大脑就像一个阁楼:它只有有限的空间。「每增加一点知识,你就会忘记一些你以前知道的东西。」因此,最重要的是,不要让无用的事实把有用的事实挤掉2

幸运的是,如果你有足够的计算能力来构建一个足够大的神经网络——即足够大的阁楼——那么这不是一个严重的问题。你有足够的能力同时从互联网和移动应用图片中学习,而不需要担心两种类型的数据争夺你的阁楼容量。你的算法的「大脑」足够大,就不必担心阁楼空间用完。

但是如果你没有足够大的神经网络(或者其他高度灵活的学习算法),那么你应该更加注意你的训练集和你的开发/测试集的分布问题。

如果你认为你所拥有的数据对提升算法表现没有任何好处,那么,你应该出于计算原因而忽略这些数据。例如,假设你的开发/测试集主要包含了人物、地点、地标和动物的随机图片,可能你还有大量扫描的历史文档。

这些图片不包含任何类似于猫的元素。它们看起来完全不同于你的开发/测试集。没有必要将这些图片归类到反例中,因为这些样本对于算法来说并不能体现出前边提到的第一个效果——几乎没有哪一个神经网络能够从这些样本中学习出用于你的开发/测试集分布的知识。同时它们还会浪费神经网络的计算资源和表示能力。

38. 如何决定是否包含不一致的数据

假设你想学习预测纽约市的房价。考虑到房子的大小(输入特征 x), 您需要预测价格(目标标签 y)。

纽约市的房价非常高。假设你有关于密歇根州底特律的房价的第二个数据集,那里的房价要低得多。你应该在你的训练集中包含这些数据吗?

如果给定相同的 x (房子大小一样),y 房子的价格则根据其是在纽约市还是在底特律(地点不同)而不同。如果你只关心预测纽约市的房价,那么把这两个数据集放在一起就会影响你的算法表现。在这种情况下,最好忽略不一致的底特律房价数据3

这个纽约市和底特律的例子与移动应用程序和网络猫图片的例子有什么不同?

猫图像的例子是不同的,因为在给定输入图像 x 的情况下,即使不知道图像是互联网图像还是移动应用上传的图像,也可以可靠地预测标签 y 表明是否有猫。也就是说,有一个函数 $f(x)$ 可以可靠的从输入 x 映射到目标输出 y,即使不知道 x 的来源。因此,互联网图像识别任务与移动应用图像识别任务「一致」。这意味着除了计算成本之外,包含所有的样本几乎没有什么负面影响,或许还有一些潜在的显著优势。相比之下,纽约市和密歇根州底特律的数据并不一致,给定相同的 x(房子的大小),根据房子的位置,价格是非常不同的。

39. 数据加权

假设你有 20 万张来自互联网的图片和 5000 张来自移动应用用户的图片。这些数据集的大小之间的比率为 40:1。理论上,只要你建立一个巨大的神经网络,并对所有 205000 张图像进行足够长时间的训练,那么尝试让算法同时在网络图像和移动图像上都表现出色的做法并没有什么坏处。

但在实践中,与仅对 5000 幅图像进行训练相比,使用比移动应用程序图像多 40 倍的互联网图像来训练算法,可能意味着你需要花费 40 倍甚至更多的计算资源来对两者进行建模。

如果你没有庞大的计算资源,你可以给互联网图像一个低得多的权重作为妥协。

例如,假设你的优化目标是平方误差(Squared Error)(这对于分类任务来说不是一个好的选择,但它会简化我们的解释)。因此,我们的学习算法试图优化:

上边公式第一项计算的是对 5000 张移动应用程序图像的平方误差求和,第二项计算的是对 20 万张移动互联网图像的平方误差求和,你可以对第二项设置超参数 $\beta$ 来优化公式:

如果设定 $\beta = 1/40$ ,算法相当于给予了 5000 个移动图像和 20 万个互联网图像相同的重视程度。当然,你也可以通过结合验证集等方式,把参数 $β$ 设置为其他值。

通过降低附加的互联网图片的权重,你就不必构建一个庞大的神经网络来保障算法在这两种类型的任务上都有效运作。只有当您觉得附加的数据(互联网图片)与开发/测试集的分布差异较大,或者是附加的数据比来自与开发/测试集(移动应用程序图像)相同分布的数据大得多的时候,才需要这种类型的重新加权。

40. 从训练集到开发集的泛化

假设你正准备在训练集和开发/测试集分布不同的情况下中应用机器学习,比方说:训练集包含互联网图像 + 手机 App 图像,而开发/测试集却只包含手机 App 图像。不过,该算法运行起来效果不佳,以下是一些可能出些了问题的地方:

  1. 机器学习算法在训练集表现不佳。这是在训练集分布上出现了高(可避免)偏差的问题;
  2. 算法对训练集表现良好,但没法推广运用于之前没有见过的数据中(这些数据与训练集分布相同)。这是高偏差问题。
  3. 算法能很好地泛化到从与训练集相同的分布中抽取的新数据中,而不是从开发/测试集分布中抽取的数据。我们将此问题称之为:数据不匹配(Data Mismatch)——训练集数据和开发/测试集数据不匹配。

例如,假设人类在猫识别任务上达到接近完美的表现。 你的算法实现了这一点:

  • 在训练集上的误差有 1%;
  • 算法在和训练集相同分布中提取的新数据上的误差为 1.5%;
  • 开发集上的误差有 10%。

在这种情况下,显然存在数据不匹配的问题。要解决这个问题,您可以尝试使训练集数据去接近开发/测试集的数据,我们将在后续内容里讨论这类技术。

为了计算出算法受到上述各个问题(1、2、3)的影响程度,额外提供一个数据集是很有帮助的。具体来说,不是将所有的训练集数据都喂给算法,我们将训练集分为两部分:一部分是用于算法训练的实际训练集,另一部分我们则将它称为「训练-开发」集,该部分数据不参与算法训练。

因此,现在你有四个数据子集:

  • 训练集:这是拿来训练算法的数据集(例如:互联网图片+移动应用程序图片)。当然这不要求一定要和我们的真实数据分布(开发/测试集数据分布)一样。
  • 训练-开发集:这部分数据集来自与训练集相同分布(例如:互联网图片+移动应用程序图片),这通常比训练集要小。他只需要足够用来评估和跟踪我们学习算法的进度就行了;
  • 开发集:这与测试集的数据分布相同。,它反映了我们最终关注的数据的分布情况(例如:移动应用程序图片);
  • 测试集:这是和开发集相同分布的数据集(例如:移动应用程序图片)。

有了这四个独立的数据集,您现在可以评估:

  • 训练误差,通过训练集进行评估;
  • 通过训练-开发集来评估算法泛化到与训练集相同分布的新数据的能力;
  • 使用开发/测试集来评估算法应用在你关心的数据分布上的能力。

在之前的 5-7 节中的提到的指导原则同样适用于训练-开发集。

41. 辨别偏差、方差和数据不匹配导致的误差

假设人类在猫检测任务中表现是几乎完美的(≈0% 的误差),因此最优错误率约为 0%。 假设你有:

  • 训练集误差 1% ;
  • 训练-开发集误差 5%;
  • 开发集误差 5%。

上述数据告诉了你什么?这里,你发现你的算法存在高方差问题。之前讨论的解决高偏差的那些技术能够帮助你取得积极的进展。

现在,假设你有:

  • 训练集误差 10% ;
  • 训练-开发集误差 11%;
  • 开发集误差 12%。

这就告诉了你:你的算法在训练集上存在高可避免偏差问题,即,算法在训练集上表现很差,之前讨论的解决高可避免偏差的那些技术能够帮助你取得积极的进展。

在上述的两个例子中,算法只是分别遇到了高方差和高可避免偏差的问题,而算法可能会遇到导致同时出现高可避免偏差、高方差和数据不匹配的子集,比如:

  • 训练集误差 10% ;
  • 训练-开发集误差11%;
  • 开发集误差 20%。

通过将它们用表格的方式列出来,可能更容易理解不同类型的误差是如何互相关联的:

· 分布 A:互联网图片+移动应用程序图片 分布 B:移动应用程序图片
人类水平 人类表现水平误差(0%) ·
算法对训练集的数据上表现 训练误差(10%) ·
算法对与训练集相同分布的新数据的表现 训练-开发集误差(11%) 开发-测试集误差(20%)
  • 11%-20% 之间体现的是数据不匹配问题;
  • 0%-10% 之间体现了可避免的偏差问题;
  • 10%-11% 之间体现了方差问题。

继续以猫图像检测器为例,您可以看到 x 轴上有两种不同的数据分布。 在 y 轴上,我们有三种类型的错误:人类水平误差、算法对训练集的数据上表现、算法对与训练集相同分布的新数据的表现。我们将之间的关系和上一节的内容做一个对应——数据百分值之间体现了不同的问题。

愿意的话,你也可以填写该表中剩下的两个单元格。填写右上角的单元格时,可以找人来给你的移动应用程序图片进行人工识别并标注标签,然后根据计算的准确率来填写(该单元格体现了移动应用程序图片上的人类表现水平);填写另一个单元格时,可以选取移动应用程序图片(分布 B)的一小部分(子集)放入训练集中,再经过神经网络的学习后,计算出对该子集的训练误差来填写此单元格。通过填写这两个额外的单元格,有时可以得到关于该算法在两种不同分布(分布 A 和分布 B )上所做操作的更深入更详细的信息。

通过了解算法遭受的错误类型,您将更好地决定是关注于减少偏差、减少方差还是减少数据不匹配的问题。

42. 解决数据不匹配的问题

假设你开发出一套语音识别系统,该系统在训练集和训练-开发集上都表现得好,但是,它在你的开发集上表现不好——意味着你的系统存在数据不匹配的问题。你怎么办?

我的建议是:

  • 尝试去了解训练集和开发集的数据分布之间的哪些属性不一样;
  • 尝试去找到更多与你的算法遇到麻烦的开发集样本相匹配的训练集数据3

例如,假设您对语音识别开发集进行了误差分析:你手动检查了 100 个样本,并尝试分析出算法到底哪里出了问题。你发现你的算法性能不好,是因为在开发集数据样本中大部分的音频剪辑片段都是在汽车里录制的,而大部分的训练集数据样本都是在安静的环境下录制的,意味着,发动机和道路噪声极大的恶化了你的语音系统的性能。在这种情况下,你应该尝试去获取更多在汽车里录制的那些附带噪声的音频样本作为训练集数据。误差分析的目的是了解训练集和开发集分布之间的显著差异——这是导致数据不匹配的原因。

如果你的训练集和训练-开发集含有在车内录制的音频样本,你就应该再检测一下算法系统对其中部分数据的处理性能。如果算法对训练集中的车内录制音频样本表现良好,而对训练-开发集中的车内录制音频样本表现不佳,那么就进一步证实了获取更多车内录制数据会有用的假设。这就解释了在之前的章节中,我们为什么要讨论为你的训练集添加从相同分布的开发/测试集中选取的数据的可能性。这样你就能比较出算法分别对训练集中的音频样本和开发/测试集中的音频样本(两者均录制于车内)的性能差异了。

不幸的是,在这个过程中无法做出保证。 例如,如果你无法获得更多与开发集数据更匹配的训练集数据,则可能没有一个明确的途径来改进性能。

43. 人工合成数据

你的语音系统需要更多的数据,这些数据需要听起来需要像是录制自汽车里的。与其在开车时来收集数据,还不如通过人工合成的方法来更高效地获得数据。

假设你从一些网站下载得到了大量的纯粹的汽车/道路噪音音频剪辑数据。同时,你还有大量的关于人在安静的房间里讲话的训练集数据。方法是这样的:你将一个人在安静的房间里说话的训练集音频剪辑数据添加到汽车/道路噪音音频剪辑数据中,这样你就合成了一条新的音频数据,该数据听起来就像是有一个人在很吵的汽车里或者道路边上讲话一样。通过这种方法,我们就可以合成大量的数据,使得这些数据就好像是在车内录制的一样。

更一般地说,在一些情况下,人工数据合成允许您创建一个与开发集合理匹配的大型数据集。作为数据合成的第二个例子,我们回到我们的猫咪检测器案例中来,你注意到了在开发集中有相当一部分数据存在运动模糊的问题,因为它们都是来着用户手机上传的图片,手机拍摄加上用户的习惯导致了这些图片在拍摄的一瞬间发生了抖动。你该如何使用互联网上的那些高清图片去合成上述效果的图片呢?简单!为高清图片添加运动模糊滤镜,从而人为地使这些高清图片变的和开发集上的模糊图片差不多。

请记住,人工数据合成有一定的挑战性:有时合成出让人感觉真实的数据比合成出让计算机感觉真实的数据更容易。例如,假设您有 1000 小时的语音训练数据,但只有 1 小时的汽车噪音数据。如果你重复地利用这 1 个小时的汽车噪声数据去和这 1000 个小时语音训练数据的不同部分来合成数据,你最终会得到一个同一段噪音重复出现的合成数据集。当我们找一个人来听这段合成数据集中的音频时,他可能没法察觉出什么不同(其实所有的汽车噪声对于我们大多数人来说都是一样的),但是学习算法可能就会「过拟合」这 1 个小时的汽车噪声。这样的话,一旦新的音频片段里的汽车噪声和这 1 小时的汽车噪声不一样的话,泛化性能就会变得很差。

或者,假设你有 1000 小时的汽车噪音,但所有的这些噪音都来自 10 辆不同的汽车。在这种情况下,算法有可能「过拟合」这 10 辆车的噪声,导致如果我们对来自其他不同汽车的音频进行测试的时候算法表现就会变得很差。不幸的是,这些问题很难被发现。

再举一个例子,你正在构建一个识别汽车的计算机视觉系统,假设你与一家视频游戏公司合作,该公司拥有多辆汽车的计算机图形模型。为了训练您的算法,您可以使用这些模型生成汽车的合成图像,即使合成图像看起来非常逼真,但最终你会发现这种方法实际使用效果不好。这款游戏在整个视频游戏中可能有大约 20 辆汽车的模型——制作一辆汽车的 3D 模型的成本是非常大的。如果你在玩这个游戏,你可能不会注意到在游戏里你看到的汽车其实都是同一个模型(20 个当中的某一个),也许只是模型表面的喷漆不一样而已。换句话说,就是这些数据在你看来是很真实的。但与现实道路上的所有汽车的集合相比较,你就能发现这些来自于 20 个汽车模型生成的汽车数据对于整个世界的汽车分布来说只是其中极小的一部分。也就是说,如果你的如果您的 10 万个训练样本都基于这 20 辆汽车模型合成的话,那么很明显你的算法将「过拟合」这 20 个特定汽车模型,也就是意味着你的算法将无法泛化到有其他车型组成的开发/测试集中。

当综合数据时,考虑一下你是否真的合成了一组有代表性的样本。尽量避免在给出合成数据属性的情况下,使学习算法能够区分合成和非合成样本——然而如果所有合成数据都来自 20 辆汽车模型中的某一辆,或者所有合成音频都利用了这 1 小时的汽车噪音的话,这个建议将很难被遵循。

在进行数据合成时,我的团队有时会花上数周的时间,才能合成出一些与实际分布非常接近数据,从而更好的发挥出合成数据的效果来。但是一旦如果你能把细节弄清楚,你就能得到一个比以前大得多的训练集了。


  1. 有一些专门研究在不同分布下算法训练和测试的学术文献。例子包括:域适配 (Domain Adaptation)、迁移学习(Transfer Learning)和多任务学习(Multitask Learning)等。但因为理论和实践之间仍存在巨大的差异,如果你的算法在数据集 A 上训练然后用一些不同类型的数据集 B 去测试,你的算法效果好坏可能会与你的运气密切相关(在这里,「运气」包括了研究人员为特定任务手工设计的特征,以及一些我们还不了解的因素),这使得对不同分布下算法训练和测试的学术研究难以系统的进行。 

  2. 阿瑟·柯南·道尔的《血字的研究》 

  3. 还有一些关于「域适应」的研究——如何在一个分布上训练算法,并将其泛化到其他分布中,这些方法通常只适用于一些特殊类型的问题,而且比本章节所描述的思想应用范围要小得多。  2

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