转载 微信公众号 “顶级程序员”

 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 计算能力提升。仅仅在几年前,我们才能够训练足够大的神经网络,以利用我们现在拥有的庞大数据量。

具体来讲,即使你收集了足够多的数据,如果还使用传统算法(逻辑回归)来处理数据,依然会出现“停滞”现象。这就意为着即使你给算法在多的数据,算法的学习曲线也会变平,算法效果不会在有所提升。

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

传统算法似乎不知道如何处理我们现在拥有的所有数据。

如果你在同一个监督学习任务训练一个小的神经网络(NN),有可能获得稍微好一点的效果:

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

这里所说的“小型神经网络”是指一个神经网络拥有少数的隐藏单元/层/参数。最后,如果你训练一个大型神经网络,你能够获得更好的性能表现。

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

因此,如果你想得到最好的性能表现,(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个数字用于评估你的分类器性能。多数字评估指标使得我们很难去比较算法的优势。假设你的算法性能指标如下:

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

在这种情况下,我们无法看出那一个分类器性能更好,因此多数字评估指标无法直观指导你使用那一个更好的分类器。

在算法开发期间,你的团队会在算法结构、模型参数调优和特征选择等方面进行多种方法的尝试。单一数字评估指标(比如精度)允许你根据算法的准确率将你的模型进行排序,以便于快速决定那一个算法的性能更好。

如果你比较关注查准率和查全率这2个指标,建议你使用一种标准方法将这2个指标组合为单一数字指标。例如,你可以使用查准率和查全率的平均值作为单一数字指标。你也可以计算算法的“F1度量”,它是一种计算二者平均值的改进方法,比简单计算平均值方法效果要好。

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

当你正在选择一个适合的分类算法时,单一数字评价指标可以快速帮助你做出选择。它给出了一个清晰的算法优先级排序,同时给出了明确的前进方向。

作为最后一个例子,假设你获得了四个主要市场((i) 美国, (ii)中国, (iii)印度,和(iv) 其他地区)的猫分类器的准确率,会得到四个指标值。通过将这四个指标值求平均值或加权平均值,最后会得到一个单一数字指标。将多指标值合并为单一指标值最常用的方法之一是求多指标值的平均值或加权平均值。

9. 优化指标和满意指标

这是将多指标值合并为单一数字指标的另一种方法。

假设你比较关注一个学习算法的准确率和运行时间。现在你需要在下面的三个分类器中做出选择:

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

如果通过下面的计算公式将准确率和运行时间合并为单一指标,在此看起来有些不自然:

准确率-0.5*运行时间

你可以这样做:首先,定义一个“可接受”的运行时间范围。假设我们说算法在100ms内的运行时间是可接受的。则分类器在满足可接受运行时间内,取最大准确率的算法。在此,运行时间是一个“满意指标”—你的分类算法只需要在这个指标上做的“足够好”即可,也就是算法的运行时间满足最多100ms。准确率是“优化指标”。

如果你正在权衡N个不同的指标,比如模型的二进制文件大小(因为用户不想下载在大的APP文件)、运行时间和准确率,你可以考虑将其中N-1个值作为“满足度指标”,也就是说你只需要考虑他们满足一个特定的值即可。定义最后一个值作为“优化指标”。例如,设置一个阈值作为二进制文件和运行时间的接受范围,并且在这些限制下去优化算法的准确率。

作为最后一个例子,假设你正在构建一个硬件系统,该系统使用一个麦克风监听用户说的特别“唤醒词”,从而唤醒系统工作。比如Amazon Echo监听“Alexa”;苹果Siri监听“Hey Siri”;安卓监听“Okay Google”;百度APP监听“Hello Baidu”。你同时关注假正例的比例—指当没有人说唤醒词时,系统被唤醒的频率和假反例的比例—指当用户说了唤醒词时,系统没有被唤醒的频率。使这个系统性能达到的一个合理目标是减少负反值的比例(优化指标),在24时工作中没有出现一个负正例(满意度指标)。

一旦你的团队开始对评估指标进行优化,他们将能够获得较快的进展。

10. 有一个开发集和度量指标来加速算法的迭代

人们很难事先知道什么方法能够很好的解决新问题。即使是经验丰富的机器学习研究者在给出满意答案之前也需要进行多种方法的尝试。在构建机器学习系统时,我通常会做以下的思考:

1. 首先想一些构造这个系统的想法。

2. 用代码实现这些想法。

3. 通过实验来验证我的想法如何(通常我前面的一些想法都没有很好的表现)。

基于以上的学习,在回过头来产生更多的想法,在进行验证。以此类推进行不断的迭代。

【转】吴恩达新书《Machine Learning Yearning》翻译连载_1-LMLPHP

这是一个不断迭代的过程。你迭代的过程越快,你进步的就会越快。这就是为什么拥有开发集/测试集和一个度量指标是如此的重要:每次当你在开发集上验证你的想法时,评价指标可以快速使你判断自己是否在朝正确的方向前进。

假设你没有一个具体的开发集和度量指标。因此你的团队每次开发新的猫分类器时,你必将新的分类器移值进你的APP中,并亲身体验几个小时从直观上判断新的分类器性能是否有所提升。这样的开发效率极其低下!同时,如果你的团队将分类器的准确率从95.0%提高到了95.1%,在你亲身体验过程中有可能无法感受到这0.1%的提升。然而,系统整体的准确率是由许多个0.1%构成的。有一个开发集和度量指标可以快速使你验证那些成功的想法给你的系统带来了小(或大)的提升,因此你可快速决定哪些想法还要继续改进,那些想法可以抛弃。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

10-03 15:41