跟着吴恩达学深度学习(三)

前言

第一门课的笔记见:跟着吴恩达学深度学习(一)

第二门课的笔记见:跟着吴恩达学深度学习(二)

本文对应了吴恩达深度学习系列课程中的第三门课程《结构化机器学习项目》,本门课程主要介绍机器学习中的一些策略和方法,能够更快更有效地让机器学习系统工作。

第三门课程授课大纲:

  • 机器学习(ML)策略(1)
  • 机器学习(ML)策略(2)

1 机器学习(ML)策略(1)

1.1  为什么是ML策略

从一个启发性的例子(motivating example)开始讲,以一个猫分类器为例,经过一段时间的调整,系统准确率达到了90%,但还不够好。可能有很多想法去改善系统,比如:

  • 收集更多的训练数据。
  • 收集更多多样化的训练集数据。可能你的训练集的多样性还不够,你应该收集更多不同姿势的猫咪图片,或者更多样化的反例集。
  • 使用梯度下降训练算法训练久一点。
  • 换一个完全不同的优化算法,比如Adam优化算法。
  • 尝试使用规模更大的神经网络,
  • 尝试更小的神经网络。
  • 尝试dropout,
  • 添加L2正则化。
  • 修改网络的架构,比如修改激活函数,改变隐藏单元的数目之类的方法。

当尝试优化一个深度学习系统时,通常可以有很多想法可以去试。如果做出了错误的选择,完全有可能白费时间,在错误的方向上尝试之后才意识到这方法根本不管用。因此,学习一些策略(strategies),一些分析机器学习问题的方法,可以指引我们朝着最有希望的方向前进。

1.2  正交化

最高效的机器学习人员,非常清楚需要调整什么来实现一个预期效果,这一过程被称为“正交化”(Orthogonalization)。 

再来通过两个例子来理解一下正交化。

比如一张老式电视,有很多旋钮可以用来调整图像的各种性质,所以对于这些旧式电视,可能有一个旋钮用来调图像垂直方向的高度,另外有一个旋钮用来调图像宽度,也许还有一个旋钮用来调梯形角度,还有一个旋钮用来调整图像左右偏移,还有一个旋钮用来调图像旋转角度之类的。电视设计师花了大量时间设计电路,那时通常都是模拟电路来确保每个旋钮都有相对明确的功能(interpretable function)。如一个旋钮来调整这个(高度),一个旋钮调整这个(宽度),一个旋钮调整这个(梯形角度),以此类推。所以在这种情况下,正交化指的是电视设计师设计这样的旋钮,使得每个旋钮都只调整一个性质,这样调整电视图像就容易得多,就可以把图像调到正中。

再比如学车的时候,一辆车有三个主要控制,第一是方向盘(steering),方向盘决定我们往左右偏多少,还有油门(acceleration)和刹车(braking)。就是这三个控制,其中一个控制方向,另外两个控制速度,这样就比较容易解读。知道不同控制的不同动作会对车子运动有什么影响。所以正交化是指可以想出一个维度,这个维度是控制转向角,还有另一个维度来控制速度,那么就需要一个旋钮尽量只控制转向角,另一个旋钮,在这个开车的例子里其实是油门和刹车控制了速度

要弄好一个监督学习系统,通常需要确保四件事情:

(1)通常必须确保至少系统在训练集(training sets)上得到的结果不错。所以训练集上的表现必须通过某种评估,达到能接受的程度,对于某些应用,这可能意味着达到人类水平的表现(human level performance),但这取决于我们的应用。

(2)训练集表现良好后,希望系统也能在开发集(dev set)上有好的表现

(3)同时也希望系统在测试集(test set)上也有好的表现

(4)在最后,希望系统在测试集上系统的成本函数在实际使用(real world)中表现令人满意

所以类似地,面对不同的情况有不同的解决办法。

(1)如果不满足四件事中第一件事,即算法在成本函数上不能很好地拟合训练集。想要一个旋钮,这样你可以用来确保你的可以调整你的算法,让它很好地拟合训练集,所以用来调试的旋钮是可以训练更大的网络或者可以切换到更好的优化算法,比如Adam优化算法,等等。我们将在本周和下周讨论一些其他选项。

(2)如果不满足第二件事,即发现算法对开发集的拟合很差,那么应该有独立的一组旋钮去调试。比如说,算法在开发集上做的不好,它在训练集上做得很好,但开发集不行,然后有一组正则化的旋钮可以调节,尝试让系统满足第二个条件。类比到电视,就是现在调好了电视的宽度,如果图像的高度不太对,就需要一个不同的旋钮来调节电视图像的高度,然后希望这个旋钮尽量不会影响到电视的宽度。增大训练集可以是另一个可用的旋钮,它可以帮助我们的学习算法更好地归纳开发集的规律,现在调好了电视图像的高度和宽度。

(3)如果它不符合第三件事情,即系统在开发集上做的很好但测试集上做得不好。那么我们需要调的旋钮,可能是更大的开发集。因为如果它在开发集上做的不错,但测试集不行这可能意味着开发集过拟合了,需要往回退一步,使用更大的开发集。

(4)最后,如果它在测试集上做得很好但无法给猫图片应用用户提供良好的体验。这意味着需要改变开发集或成本函数。因为如果根据某个成本函数,系统在测试集上做的很好,但它无法反映算法在现实世界中的表现,这意味着要么开发集分布设置不正确,要么成本函数测量的指标不对。

因此,我们要非常清楚,到底是四个问题中的哪一个,知道可以调节哪些不同的东西尝试解决那个问题。

1.3  单一数字评估指标

无论是调整超参数,尝试不同的学习算法,还是在搭建机器学习系统时尝试不同手段,可以发现,如果有一个单实数评估指标(single real number evaluation metric),进展会快得多,它可以快速告诉我们“新尝试的手段比之前的手段好还是差”。

通过之前课程的学习,我们知道机器学习是一个非常经验性的过程。举个例子,现在训练得到分类器A,重新训练之后得到分类器B。评估分类器的一个合理方式是观察它的查准率(precision)查全率(recall)

ClassifierPrecisionRecallF1 Score
A95%90%92.4%
B98%85%91.0%

查准率的定义是在的分类器标记为猫的例子中,有多少真的是猫

所以如果分类器A有95%的查准率,这意味着你的分类器说这图有猫的时候,有95%的机会真的是猫。

查全率定义就是,对于所有真猫的图片,分类器A正确识别出了多少百分比。实际为猫的图片中,有多少被系统识别出来。如果分类器A查全率是90%,这意味着对于所有的图像,比如说开发集都是真的猫图,分类器准确地分辨出了其中的90%。

事实证明,查准率和查全率之间往往需要折中,两个指标都要顾及到。在机器学习的文献中,结合查准率和查全率的标准方法是F1分数P和R的调和平均数),公式为:

F1=\frac{2}{\frac{1}{P}+\frac{1}{R}}

在这个例子中,如上方表格,我们快速选出分类器A,淘汰B。

除了F1 分数之外,还可以使用平均值(average)作为单值评价指标来对模型进行评估。如下图所示,A, B, C, D, E, F六个模型对不同国家样本的错误率,可以计算其平均性能,然后选择平均错误率最小的那个算法(C算法)。

AlgorithmUSChinaIndiaOtherAverage
A3%7%5%9%6%
B5%6%5%10%6.5%
C2%3%4%5%3.5%
D5%8%7%2%5.35%
E4%5%2%4%3.75%
F7%11%8%12%9.5%

1.4  满足和优化指标

在一些情况中把所有事情组合成单实数评估指标有时并不容易,在那些情况里,有时候设立满足(satisficing)优化指标(optimizing metrics)是很重要的。

ClassifierAccuracyRunning time
A90%80ms
B92%95ms
C95%1500ms

如上表,这里有A、B、C三个分类器,如果只看中分类准确度,可以使用F1分数或者其他衡量准确度的指标。但是如果除了准确度,还需要考虑运行时间,会发现这两个指标的线性加权求和可能太刻意,Accuracy和Running time这两个指标不太合适综合成单值评价指标。因此,我们可以说准确度是一个优化指标(optimizing metric),因为想要准确度最大化(maximize accuracy),你想做的尽可能准确,但是运行时间就是我们所说的满足指标(satisficing metric),意思是它必须足够好,它只需要小于100毫秒,达到之后,我们不在乎这指标有多好。所以这是一个相当合理的权衡方式,或者说将准确度和运行时间结合起来的方式。实际情况可能是,只要运行时间少于100毫秒,就不会在乎运行时间是100毫秒还是50毫秒,甚至更快。所以,在这种情况下,分类器B最好。

更一般地说,如果你要考虑N个指标,有时候选择其中一个指标做为优化指标是合理的。尽量优化那个指标,然后剩下N-1个指标都是满足指标,只要满足设定的阈值就好。

1.5  训练/开发/测试集划分

设立训练集,开发集和测试集的方式大大影响在建立机器学习应用方面取得进展的速度。

开发集(dev set),有时称为保留交叉验证集(hold out cross validation set)。机器学习中的工作流程是尝试很多思路,用训练集训练不同的模型,然后使用开发集来评估不同的思路,然后选择一个,然后不断迭代去改善开发集的性能,直至最后可以得到一个令你满意的成本,然后再用测试集去评估。

举个例子,要开发一个猫分类器(cat classfier),然后你在这些区域(regions)里运营,美国(US)、英国(UK)、其他欧洲国家(Other Europe),南美洲(South America)、印度(India)、中国(China),其他亚洲国家(Other Asia)和澳大利亚(Australia),那么应该如何设立开发集和测试集呢?

其中一种做法是,选择其中4个区域(可以使用前四个,但也可以是随机选的区域),然后将来自这四个区域的数据构成开发集。而其他四个区域(用后四个,也可以随机选择4个),这些数据构成测试集。事实证明,这个想法非常糟糕,因为这个例子中,开发集和测试集来自不同的分布。相反,应该保证开发集和测试集来自同一分布。如果来自不同分布,针对开发集优化时瞄准一个靶心,而在测试时效果却不佳,因为靶心移到不同的位置了。为了避免这种情况,可以将所有数据随机洗牌(shuffled),放入开发集和测试集,所以开发集和测试集都有来自八个地区的数据,并且开发集和测试集都来自同一分布,这分布就是把所有数据混在一起服从的分布。

在设立开发集和测试集时,要选择能够反映未来会得到的数据或认为很重要的数据作为开发集和测试集。特别是,这里的开发集和测试集应该来自同一个分布。所以不管未来会得到什么样的数据,一旦算法效果不错,要尝试收集类似的数据,而且,不管那些数据是什么,都要随机分配到开发集和测试集上。因为这样,才能瞄准想要的目标,让团队高效迭代来逼近同一个目标,希望最好是同一个目标。如果能遵循这个方针,甚至可以省下几个月的工作。

1.6  开发集合测试集的大小

在深度学习时代,设立开发集和测试集的方针也在变化。在机器学习早期,这样70%:30%或者60%:20%:20%的经验法则是相当合理的。如果有几千个样本或者有一万个样本,这些做法也还是合理的。但在现代机器学习中,我们更习惯操作规模大得多的数据集,比如说一百万个训练样本,这样分可能更合理,98%作为训练集,1%开发集,1%测试集。

测试集的目的是完成系统开发之后帮助评估投产系统的性能。方针就是,令测试集足够大,能够以高置信度评估系统整体性能。所以除非需要对最终投产系统有一个很精确的指标,一般来说测试集不需要上百万个例子,甚至不单独分出一个测试集(test set)也是可以的。但是,不建议在搭建系统时省略测试集,因为有个单独的测试集比较安心。因为可以使用这组不带偏差的数据来测量系统的性能。

1.7  什么时候该改变开发/测试集和指标

假设我们在构建一个猫分类器,试图找到很多猫的照片向爱猫人士用户展示,决定使用的指标是分类错误率。所以算法A和B分别有3%错误率和5%错误率,所以算法A似乎做得更好。但是算法A由于某些原因,把很多色情图片分类成猫了。从用户接受的角度来看,算法B实际上是一个更好的算法,因为它不让任何色情图像通过。

这时应该改变评估指标了,或者要改变开发集或测试集。在这种情况下,用的分类错误率指标可以写成这样:

Error=\frac{1}{m_{dev}}\sum_{i=1}^{m_{dev}}I[y_{pred}^{(i)}\ne y^{(i)}]

y_{pred}表示预测值,取值 0 或 1。I[]表示一个函数,用来统计括号里式子为真的样例数量。

上个评估指标的问题在于,它对色情图片和非色情图片一视同仁,但其实真的希望分类器不会错误标记色情图像。这样可以考虑加一个权重项:

Error=\frac{1}{m_{dev}}\sum_{i=1}^{m_{dev}}w^{(i)}I[y_{pred}^{(i)}\ne y^{(i)}]

如果w=10,则把色情图片分类成猫这一错误的惩罚权重加大10倍。

如果你希望归一化常数,使错误率仍然在0-1之间,公式如下:

Error=\frac{1}{\sum w^{(i)}}\sum_{i=1}^{m_{dev}}w^{(i)}I[y_{pred}^{(i)}\ne y^{(i)}]

目前为止,我们只讨论了如何定义一个指标去评估分类器,也就是说,我们定义了一个评估指标帮助我们更好的把分类器排序,能够区分出它们在识别色情图片的不同水平,这实际上是一个正交化的例子。

在处理机器学习问题时,应该把它切分成独立的步骤。

(1)设定目标:弄清楚如何定义一个指标来衡量你想做的事情的表现

(2)通过训练,射中目标:可以分开考虑如何改善系统在这个指标上的表现。

再举个例子,现有两个分类器A和B,在开发集上分别有3%和5%的错误率,但在实际部署算法产品时,算法B表现更好。即使它在开发集上表现不错,我们发现我们一直在用从网上下载的高质量图片训练,但当我们部署到手机应用时,算法作用到用户上传的图片时,那些图片取景不专业,没有把猫完整拍下来,或者猫的表情很古怪,也许图像很模糊。这是另一个问题,开发集/测试集和实际应用的图片不同分布。所以方针就是修改指标或者开发测试集。因为应用处理的是低质量图像,那么就应该改变开发测试集,让数据更能反映你实际需要处理好的数据。

1.8  为什么是人的表现

🙋在过去的几年里为什么更多的机器学习团队一直在讨论如何比较机器学习系统和人类的表现?

原因大致有两个,首先是因为深度学习系统的进步,机器学习算法突然变得更好了。在许多机器学习的应用领域已经开始见到算法已经可以威胁到人类的表现了。其次,在某些领域用机器学习系统解决问题的效率比用人工解决问题的效率要高,在这种情况下,人们自然要比较人类和机器孰优孰劣。

如上图所示,x轴是时间,在很多机器学习任务中,在一个任务上付出的可能是很多个月甚至很多年,在前一阶段进展是很快的,当这个算法表现比人类更好时,那么进展和精确度的提升就变得更慢了。也许它还会越来越好,但是在超越人类水平之后,它还可以变得更好,但性能增速,准确度上升的速度这个斜率,会变得越来越平缓,我们都希望能达到理论最佳性能水平。随着时间的推移,当你继续训练算法时,发现性能无法超过某个理论上限(theoretical limit),这就是所谓的贝叶斯最优错误率(Bayes optimal error)。所以贝叶斯最优错误率一般认为是理论上可能达到的最优错误率。

事实证明,机器学习的进展往往相当快,直至超越人类的表现之前一直很快,当超越人类的表现时,有时进展会变慢。那么是什么原因导致机器学习在超越人类时进度会变慢呢?

(1)一个原因是人类水平在很多任务中离贝叶斯最优错误率已经不远了,人们非常擅长看图像,分辨里面有没有猫或者听写音频。所以,当机器超越人类的表现之后也许没有太多的空间继续改善了。

(2)但第二个原因是,只要机器的表现比人类的表现更差,那么实际上可以使用某些工具来提高性能。一旦超越了人类的表现,这些工具就没那么好用了。

对于人类擅长的任务(包括但不限于看图识别事物,听写音频,阅读语言),只要机器学习算法比人类差,有三种策略可以应对:

  • 让人帮助标记数据,这样就有更多的数据可以喂给学习算法。
  • 但只要人类的表现比任何其他算法都要好,就可以让人类看看你算法处理的例子,分析错误出在哪里,并尝试了解为什么人能做对,算法做错,这样做有助于提高算法的性能。
  • 同样也可以更好地分析偏差和方差。但是只要算法仍然比人类糟糕,就有这些重要策略可以改善算法。

而一旦算法做得比人类好,这三种策略就很难利用了。所以这可能是另一个和人类表现比较的好处,特别是在人类做得很好的任务上。

1.9  可避免偏差

Human error1%7.5%
Training error8%8%
Dev error10%10%

如上表,如果人类水平的错误为1%,训练错误率为8%,开发集错误率为10%。在这种情况下,观察到8-1=7,10-8=2。我们会把重点放在减少偏差上,比如说训练更大的神经网络,或者跑久一点梯度下降。

假设人类水平错误实际为7.5%,可能数据集中的图像非常模糊,分辨率很低,这个时候8-7.5=0.5,10-8=2。此时,减少学习算法的方差(例如正则化),可能更合理。

对于猫分类器这个例子来说,用人类水平的错误率估计或代替贝叶斯误差或贝叶斯最优误差,对于计算机视觉任务而言,这样替代相当合理,因为人类实际上是非常擅长计算机视觉任务的,所以人类能做到的水平和贝叶斯误差相差不远。根据定义,人类水平错误率比贝叶斯误差高一点,因为贝叶斯误差是理论上限,但人类水平错误率离贝叶斯误差不会太远。所以这里比较意外的是取决于人类水平错误率有多少,或者这真的就很接近贝叶斯误差,这取决于我们认为什么样的水平是可以实现的。

这里有一个专业术语,贝叶斯误差或者对贝叶斯误差的估计和训练错误率之间的差值称为可避免偏差(avoidable bias)。当我们可能希望一直提高训练集表现,直到接近贝叶斯误差,但实际上你也不希望做到比贝叶斯误差更好,这理论上是不可能超过贝叶斯误差的,除非过拟合。而训练错误率和开发错误率之间的差值,就大概说明算法在方差问题上还有多少改善空间。

总的来说,如果能够理解人类水平错误率,就能对贝叶斯误差进行估计,也就可以在不同的场景中专注于不同的策略,使用避免偏差策略(bias avoidance tactics)还是避免方差策略(variance avoidance tactics)

1.10  理解人的表现

1.9小节中,我们用过“人类水平错误率”用来估计贝叶斯误差,那就是理论最低的错误率,下面看看医学图像分类例子。

观察这样的放射科图像,然后作出分类诊断,假设一个普通的人类,未经训练的人类,在此任务上达到3%的错误率。普通的医生,也许是普通的放射科医生,能达到1%的错误率。经验丰富的医生做得更好,错误率为0.7%。还有一队经验丰富的医生,让他们都看看这个图像,然后讨论并辩论,他们达成共识的意见达到0.5%的错误率。

🙋应该如何界定人类水平错误率?人类水平错误率3%,1%, 0.7%还是0.5%?

思考人类水平错误率最有用的方式之一是,把它作为贝叶斯误差的替代或估计。

因为有些系统,这些医生团队可以达到0.5%的错误率。所以根据定义,最优错误率必须在0.5%以下。那么在这个背景下,可以用0.5%估计贝叶斯误差,所以可以将人类水平定义为0.5%。

当然,我们可以使用1%,只要超越了一个普通医生的表现,如果能达到这种水平,那系统已经达到实用了。也许超过一名放射科医生,一名医生的表现,意味着系统在一些情况下可以有部署价值了。因此在定义人类水平错误率时,要清楚你的目标所在。如果目标是展示超过一个普通人的水平,那么可以使用1%。但是如果目标是代表贝叶斯误差,那么就需要选择0.3%。

如果想理解偏差和方差,那么在人类可以做得很好的任务中,可以估计人类水平的错误率,使用人类水平错误率来估计贝叶斯误差。计算训练错误率到贝叶斯误差估计值的差距,体现可避免偏差问题有多大,可避免偏差问题有多严重,而训练错误率和开发错误率之间的差值体现方差上的问题有多大,算法是否能够从训练集泛化推广到开发集。本小节的和之前小节中重大的区别是,以前比较的是训练错误率和0%,直接用这个值估计偏差。

1.11  超过人的表现

情形一情形二
Teams of humans error0.5%0.5%
One human error1%1%
Training error0.6%0.3%
Dev error0.8%0.4%

如上表,假设有一个问题,由人类团队通过深入讨论和辩论,可以达到0.5%的错误率,单个人类专家错误率是1%,然后算法有0.6%的训练错误率,0.8%的开发错误率。据此可以得出,可避免偏差是0.1%,方差是0.2%,因此减少方差的空间可能更大。再看情形二,0.3%训练错误率和0.4%开发错误率,而此时的可避免偏差无法回答,也不知道是否过拟合,这时依靠人类直觉去判断算法往什么方向优化就很难了。

现如今机器学习已经在很多问题上大大超越人类水平了。如以下场景:

(1)网络广告(online advertising),估计某个用户点击广告的可能性。

(2)提出产品建议(product recommendations),推荐电影或书籍之类的任务。

(3)物流预测(logistics prediction),从A到B开车需要多久,或者预测快递车从开到需要多少时间。

(4)预测某人会不会偿还贷款(repay a loan),这样你就能判断是否批准这人的贷款。

1.12  改善你的模型的表现

想要让一个监督学习算法达到实用,基本上希望或者假设你可以完成两件事情。

(1)首先,你的算法对训练集的拟合很好,这可以看成是你能做到可避免偏差很低。

(2)其次,在训练集中做得很好,然后推广到开发集和测试集也很好,这就是说方差不是太大。

如果想要提升机器学习系统的性能,可以关注训练错误率和贝叶斯误差的距离(可避免偏差)以及开发错误率和训练错误率的距离(方差),然后针对不同的问题采用不同策略。

2 机器学习(ML)策略(2)

2.1  进行误差分析

当学习算法还没有达到人类的表现,那么人工检查一下算法犯的错误也许可以了解接下来应该做什么,这个过程称为错误分析(error analysis)。

以调试猫分类器为例,假如我们已经取得了90%准确率(易知10%错误),这离希望的目标还有很远的距离。注意到算法将一些狗分类成猫,可能有人建议针对狗的图片进行优化,例如收集更多的狗图,问题在于,我们是不是应该去开始做一个项目专门处理狗?花费几个月的时间值得吗?

这时有个错误分析流程,可以让我们很快知道这个方向是否值得努力。首先,人工收集一下开发集有多少错误标记的样本是狗,假设100个错误样本中只有5个是狗,如果在狗的问题上花了很多时间,那么最多能将错误率从10%下降到9.5%。在机器学习中,称这种能够改善算法性能的上限为性能上限(the ceiling on performance),就意味着,最好能到哪里,完全解决狗的问题可以对我们有多少帮助。现在,假设发生了另一件事,实际上50%都是狗的照片,现在花时间去解决狗的问题可能效果更好,错误率可能从10%下降到5%,值得一试。

在机器学习中,有时候我们很鄙视手工操作,或者使用了太多人为数值。但如果要搭建应用系统,那这个简单的人工统计步骤,错误分析,可以节省大量时间,可以迅速决定什么是最重要的,或者最有希望的方向。

接下来看如何使用错误分析来评估某个想法,比如上述狗的问题是否值得解决。

有时你在做错误分析时,也可以同时并行评估几个想法,以改善猫检测器为例:

(1)也许可以改善针对狗图的性能,

(2)有时候要注意,那些猫科动物,如狮子,豹,猎豹等等,它们经常被分类成小猫或者家猫,所以可以想办法解决这个错误。

(3)提高模糊图像表现。

如果用错误分析来评估以上三种思路,可以建立一个表格或者普通文本文件,人工地一张一张检查每张图片,每一列是可能的问题,最后一列可以备注,最后统计这些算法(错误)的百分比。在这个例子中8%是狗,43%是大猫,61%属于模糊,12%是Instagram滤镜。这样的分析结果没有给一个严格的数学公式,但是可以知道哪些问题有改进的潜力。在这里,改善大猫和模糊图片的识别对性能提高的上限空间会大得多。

进行错误分析,应该找一组错误样本,可能在开发集里或者测试集里,观察错误标记的样本,并按假阳性和假阴性来看,统计属于不同错误类型的错误数量。在这个过程中,我们可能会得到启发,归纳出新的错误类型。如果过了一遍错误样本,然后发现还有这么多Instagram滤镜或Snapchat滤镜,这些滤镜干扰了分类器,就可以在途中新建一个错误类型。

总之,通过统计不同错误标记类型占总数的百分比,可以帮我们发现哪些问题需要优先解决,或者给你构思新优化方向的灵感

2.2  清楚标注错误的数据

在监督学习中,数据由输入x和输出标签y构成,如果发现一些y标注错误,是否值得花时间去修正这些标签呢?

如上图,在猫分类问题中,发现倒数第二张图片其实不是猫,但却被标记成1了,所以这是标记错误的样本(incorrectly labeled data)。事实证明,深度学习算法对于训练集中的随机错误是相当健壮的。如果错误足够随机,那么放着这些错误不管可能也没问题,只要总数据集总足够大,实际错误率可能不会太高。深度学习算法对随机误差很健壮,随机错误或近似随机错误对大多数深度学习算法来说不成问题,但对系统性的错误就没那么健壮了

🙋那么如果在开发集和测试集中有错误标记的样本呢?

如果担心错误标记的数据对开发集和错误集有影响,一个比较推荐的做法就是在错误分析的过程中,增加一列(见下图Incorrectly labeled)统计y标签错误的样本数。如果这些标记错误严重影响了在开发集上评估算法的能力,那么就应该去花时间修正错误的标签。但是如果使用开发集去评估模型,没有太大影响,那么时间最好不要花在这上面。

举个例子,来决定值得花时间去减少错误标记的数量。

样本A样本B
Overall dev set error10%2%
Errors due incorrect labels0.6%0.6%
Errors due to other cause9.4%1.4%

先来看样本A,关注整体的开发集错误率,系统90%准确率,有10%错误率,同时6%的错误来着标记,那么关注错误标记引起的错误的数量或者百分比,在这里6%*10%=0.6%,意味着开发集的错误中0.6%是标记出错,剩下9.4%是其他原因导致的,所以在这种情况下,应该集中精力修正9.4%的错误

再看另一个样本B,假设在学习问题上取得了很大进展,所以现在错误率不再是10%了,假设你把错误率降到了2%,但总体错误中的0.6%还是标记出错导致的。则0.6%/2%=30%,占比较高,所以现在其他原因导致的错误是1.4%。当测得的那么大一部分的错误都是开发集标记出错导致的,那似乎修正开发集里的错误标签似乎更有价值。因此,现在就有很好的理由去修正开发集里的错误标签,因为在样本B中,标记出错对算法错误的整体评估标准有严重的影响。而样本A中,标记出错对算法影响的百分比还是相对较小的。

还有一些额外的情况要考虑:

(1)开发集和测试集必须来自相同的分布。如果打算修正开发集上的部分数据,那么最好也对测试集做同样的修正以确保它们继续来自相同的分布。

(2)同时检验算法判断正确和判断错误的样本,因为算法有可能因为运气好把某个东西判断对了。

(3)修正训练集中的标签其实相对没那么重要,可能决定只修正开发集和测试集中的标签,因为它们通常比训练集小得多,可能不想把所有额外的精力投入到修正大得多的训练集中的标签,所以这样其实是可以的。

2.3  快速搭建你的第一个系统,并进行迭代

在语音识别领域,如果正在考虑建立一个新的语音识别系统,其实可以走很多方向,可以优先考虑很多事情。例如,善于处理嘈杂的背景,处理带口音时更加健壮等。一般来说,对于几乎所有的机器学习程序可能会有50个不同的方向可以前进,并且每个方向都是相对合理的可以改善你的系统。但挑战在于,如何选择一个方向集中精力处理

快速设立开发集和测试集还有指标,这样就决定了目标所在,如果目标定错了,之后改也是可以的。但一定要设立某个目标,然后马上搭好一个机器学习系统原型,然后找到训练集,训练一下,看看效果,开始理解算法表现如何,在开发集测试集,评估指标上表现如何。当建立第一个系统后,就可以马上用到之前说的偏差方差分析,还有之前最后几个视频讨论的错误分析。建立这个初始系统的所有意义在于,它可以是一个快速和粗糙的实现

如果将机器学习算法应用到新的应用程序里,主要目标是弄出能用的系统而不是发明全新的机器学习算法,这是完全不同的目标,那时目标应该是想出某种效果非常好的算法。所以搭建快速而粗糙的实现,然后做偏差/方差分析,做错误分析,最后用分析结果确定下一步优先要做的方向。

2.4  在不同的划分上进行训练并测试

深度学习对训练数据的需求量很大,当我们收集到足够多的带标签的数据构成训练集时,算法效果最好,这导致很多算法团队想尽一切办法去收集数据,即使有些数据,甚至是大部分数据都来自和开发集、测试集不同的分布。本小节将介绍一些最佳做法来处理训练集和测试集存在差异的情况。

假设我们在开发一个识别猫的手机应用,有两个数据来源:

(1)一个是你真正关心的数据分布,来自应用上传的数据,一般更业余,有些甚至很模糊,有1万张;

(2)另一个数据来源是爬取网页,可以下载很多取景专业、高分辨率、拍摄专业的猫图片,有20万张。

而我们真正关心的算法表现是最终系统处理来自应用程序的这个图片分布时效果好不好,因为最后用户会上传第一组图片,分类器必须在这个任务中表现良好。那么现在的困境在于,第二组这20万张图片并不完全来自你想要的分布,那么我们可以怎么做呢?

有两种方案以供选择,第一种方案是将两组数据合并在一起,这样就有21万张照片,把这21万张照片随机分配到训练、开发和测试集中。假设已经确定开发集和测试集各包含2500个样本,所以训练集有205000个样本。现在这么设立数据集有一些好处,也有坏处。好处在于,训练集、开发集和测试集都来自同一分布,这样更好管理。但坏处在于,开发集中2500个样本其中很多图片(2500*200/210=2381)都来自网页下载的图片,平均而言,只有119张图来自手机上传,那并不是我们真正关心的数据分布,真正要处理的是来自手机的图片。要记住,设立开发集的目的是告诉团队去瞄准的目标,而第一种样本处理方式中你目标的方式和大部分精力都用在优化来自网页下载的图片,这其实不是我们想要的。所以不建议使用第一个选项。

还有第二种方案,设置开发集和测试集都是手机图。而训练集包含了来自网页的20万张图片,还有5000张来自应用的图片,开发集就是2500张来自应用的图片,测试集也是2500张来自应用的图片。现在瞄准的目标就是想要处理的目标。缺点在于训练集和开发集、测试集的分布不一样。但事实证明,这样把数据分成训练、开发和测试集,在长期能给你带来更好的系统性能

2.5  不匹配数据划分的偏差和方差

估计学习算法的偏差和方差可以帮忙确定接下来的优化方向,但是当训练集和开发集、测试集不同分布时,分析偏差和方差的方式可能不一样。

继续以猫分类器为例,人类在这个问题上做到几乎完美,所以认为贝叶斯误差几乎是0%,所以要进行错误率分析,通常需要看训练误差(training error),也要看看开发集的误差(dev error)。比如,训练集误差是1%,开发集误差是10%,如果开发集和训练集分布一样,显然模型存在很大的方差问题(variance),模型处理训练集很好,但是泛化能力却很弱。但如果训练数据和开发数据来自不同的分布,就不能再下这个结论了。所以也许算法没有方差问题,这只不过反映了开发集包含更难准确分类的图片。

因此,这个分析的问题在于,当我们看训练误差,再看开发误差,有两件事变了。第一件事,算法只见过训练集数据,没见过开发集数据。第二件事,开发集数据来自不同的分布。而且因为同时改变了两件事情,很难确认这增加的9%误差率有多少是因为算法没看到开发集中的数据导致的,这是问题方差的部分,有多少是因为开发集数据就是不一样。

为了分辨清楚两个因素的影响,定义一组新的数据是有意义的,我们称之为训练-开发集(training-dev set),这是一个新的数据子集。从训练集的分布里挖出来,但不会用来训练网络。现在进行误差分析时,需要关注训练集误差、训练-开发集误差和开发集误差

样本A样本B样本C样本D
训练集误差1%1%10%10%
训练-开发集误差9%1.5%11%11%
开发集误差10%10%12%20%

如上表,根据样本A中的数据,可以得出结论:算法存在方差问题,因为训练-开发集的错误率是在和训练集来自同一分布的数据中测得的

从样本B中的数据,可以看出现在算法的方差问题就很小了,因为从训练数据转到训练-开发集数据,错误率只上升了一点点(1.5%-1%=0.5%)。但开发集的错误率就大大上升了,这是数据不匹配(dis-matched data)的问题。

再来看样本C中的数据,这样的情况存在可避免偏差问题,因为算法做的比人类水平差很多。

最后看样本D中的数据,这其实有两个问题。第一,可避免偏差相当高(10%-0%=10%)。这里方差似乎很小(11%-10%=1%),但数据不匹配问题(20%-11%=9%)很大,所以对于这个样本,算法有很大的偏差或者可避免偏差问题,还有数据不匹配问题

📜总结

  • 训练集误差(training error)和人类水平误差(human-level error)反映可避免偏差(avoidable error)
  • 训练-开发集误差(training-dev error)和训练集误差(training error)反映方差(variance)
  • 开发集误差(dev error)和训练-开发集误差(training-dev error)反映数据不匹配问题(data mismatch problem)
  • 测试集误差(test error)和开发集误差(dev error)反映开发集过拟合的程度(degree of overfitting to dev set)

2.6  处理数据不匹配

假如正在开发一个语音激活的后视镜应用,如果发现车辆背景噪音是主要的错误来源,那么可以模拟车辆噪声数据,加入到训练集中。我们的目的是让训练数据更接近开发集,那么我们应该怎么做呢?

其中一种技术是人工合成数据(artificial data synthesis)。实际上没有那么多在汽车噪音下录制的音频,训练样本很可能没有背景噪声,可以人工添加背景噪声,通过人工数据合成,处理后的数据再喂给机器学习算法,这样会让模型训练的效果更准确。值得注意的是,人工合成有一个潜在问题,如果只录了一个小时车辆背景噪音,然后反复播放,给每段语音都增加同一段背景噪声,这样可能对这个汽车噪音过拟合。

总而言之,如果存在数据不匹配问题,应该做错误分析或者看看训练集、开发集,试图找出这两个数据分布到底有什么不同,然后看看是否有办法收集更多看起来像开发集的数据作训练。有一种办法是人工数据合成,但是一定要谨慎,要记住有可能从所有可能性的空间只选了很小一部分去模拟数据

2.7  迁移学习

深度学习中,最强大的理念之一就是,有时候神经网络可以从一个任务中学习知识,并将这些知识应用到另一个独立的任务中。例如,也许我们已经训练好一个神经网络,能够识别像猫这样的对象,然后使用那些知识,或者部分知识去帮助更好地阅读x射线扫描图,这就是所谓的迁移学习(transfer learning)

假设已经训练好一个图像识别神经网络,并在(x,y)对上训练,其中x是图像(图像是猫、狗、鸟或其他东西),y是某些对象。如果把这个神经网络拿来迁移学习,在不同任务中学到的知识,比如放射科诊断,就是说阅读x射线扫描图。可以把神经网络最后的输出层删除,还有进入到最后一层的权重删掉,然后为最后一层重新赋予随机权重,然后让它在放射诊断数据上训练。

现在,我们在新的放射科数据集上重新训练网络,有几种做法:

(1)如果你的放射科数据集很小,你可能只需要重新训练最后一层的权重,就是W^[L]和b^[L],并保持其他参数不变。

(2)如果你有足够多的数据,你可以重新训练神经网络中剩下的所有层。

经验规则是,如果你有一个小数据集,就只训练输出层前的最后一层,或者也许是最后一两层。但是如果你有很多数据,那么也许你可以重新训练网络中的所有参数。如果你重新训练神经网络中的所有参数,那么这个在图像识别数据的初期训练阶段,有时称为预训练(pre-training),因为你在用图像识别数据去预先初始化,或者预训练神经网络的权重。然后,如果以后更新所有权重,然后在放射科数据上训练,有时这个过程叫微调(fine tuning)

🙋什么时候迁移学习是有意义的?

(1)如果想从任务A学习并迁移一些知识到任务B,那么当任务A和任务B都有同样的输入时,迁移学习是有意义的。

(2)当任务A的数据比任务B多得多时,迁移学习意义更大。所有这些假设的前提都是,我们希望提高任务B的性能,因为任务B每个数据更有价值,对任务B来说通常任务A的数据量必须大得多,才有帮助,因为任务A里单个样本的价值没有比任务B单个样本价值大。

(3)如果觉得任务A的低层次特征,可以帮助任务B的学习,那迁移学习更有意义一些。

迁移学习最有用的场合是,如果尝试优化任务B的性能,通常这个任务数据相对较少。

2.8  多任务学习

在迁移学习中,步骤是串行(sequential process)的,从任务A里学习然后将其迁移到任务B。在多任务学习(multi-task learning)中,是同时开始学习的,试图让单个神经网络同时做几件事情,然后希望这里每个任务都能帮到其他所有任务。

假设在研发无人驾驶车辆,那么你的无人驾驶车可能需要同时检测不同的物体,比如检测行人(pedestrians)、车辆(cars)、停车标志(stop signs),还有交通灯(traffic lights)各种其他东西。输入图像x,输出y,现在不是一个标签,而是4个标签。

现在可以做的是训练一个神经网络,来预测这些y值,就得到这样的神经网络,输入x,现在输出是一个四维向量y。这里输出有四个节点,所以第一个节点就是我们想预测图中有没有行人,然后第二个输出节点预测的是有没有车,这里第三个输出节点预测有没有停车标志,这里第四个输出节点预测有没有交通灯,所以这里是y帽四维的。

对于整个训练集的平均损失定义为:

\frac{1}{m}\sum_{i=1}^{m}\sum_{j=1}^{4}L(\hat{y}^{(i)},y_j^{(i)})

此时,需要注意整个训练集的平均损失和之前分类猫的例子主要区别在于,现在你要对j=1到4求和,这与softmax回归的主要区别在于,与softmax回归不同,softmax将单个标签分配给单个样本

在这个场合,一张图可以有多个标签。如果你训练了一个神经网络,试图最小化这个成本函数,这就是多任务学习。因为你现在做的是建立单个神经网络,观察每张图,然后解决四个问题,系统试图告诉你,每张图里面有没有这四个物体。另外你也可以训练四个不同的神经网络,而不是训练一个网络做四件事情。但神经网络一些早期特征,在识别不同物体时都会用到,然后你发现,训练一个神经网络做四件事情会比训练四个完全独立的神经网络分别做四件事性能要更好,这就是多任务学习的力量。

注意到有一些样本标记了问号,在j从1到4求和时,只对带0和1标签的j值求和,忽略有问号的选项,这样处理的话你可以使用带问号的数据集。

那么多任务学习什么时候是有意义的呢?

当下面三件事为真时,就是有意义的。

(1)第一,如果训练的一组任务,可以共用低层次特征(share low-level features)。对于无人驾驶的例子,同时识别交通灯、汽车和行人是有道理的,这些物体有相似的特征,也许能帮你识别停车标志,因为这些都是道路上的特征。

(2)第二,这个准则没有那么绝对,所以不一定是对的。但从很多成功的多任务学习案例中看到,如果每个任务的数据量很接近,表现良好

(3)最后多任务学习往往在以下场合更有意义,当可以训练一个足够大的神经网络,同时做好所有的工作,所以多任务学习的替代方法是为每个任务训练一个单独的神经网络。

实践中,多任务学习的使用频率要低于迁移学习。但多任务学习比较少见,就是需要同时处理很多任务,都要做好,可以同时训练所有这些任务,也许计算机视觉是一个例子。在物体检测中,我们看到更多使用多任务学习的应用,其中一个神经网络尝试检测一大堆物体,比分别训练不同的神经网络检测物体更好。但平均来说,目前迁移学习使用频率更高,比多任务学习频率要高,但两者都可以成为你的强力工具

2.9  什么是端到端的深度学习

深度学习中最令人振奋的最新动态之一就是端到端深度学习的兴起,那么端到端学习到底是什么呢?以前有一些数据处理系统或者学习系统,它们需要多个阶段的处理。那么端到端深度学习(end-to-end deep learning)就是忽略所有这些不同的阶段,用单个神经网络代替它。

以语音识别为例,目标是输入x,比如说一段音频,然后把它映射到一个输出y,就是这段音频的听写文本。所以传统上,语音识别需要很多阶段的处理。首先你会提取一些特征,一些手工设计的音频特征,在提取出一些低层次特征之后,可以应用机器学习算法在音频片段中找到音位,所以音位是声音的基本单位,然后将音位串在一起构成独立的词,最后将词串起来构成音频片段的听写文本。

和这种有很多阶段的流水线相比,端到端深度学习做的是,训练一个巨大的神经网络,输入就是一段音频,输出直接是听写文本。端到端深度学习就只需要把训练集拿过来,直接学到了x和y之间的函数映射,直接绕过了其中很多步骤。但对一些学科的人来说,这有点难以接受。

事实证明,端到端深度学习的挑战之一是,可能需要大量数据才能让系统表现良好,所以当你的数据集较小的时候,传统流水线方法其实效果也不错,通常做得更好。如果数据量适中,那么也可以用中间件方法,你可能输入还是音频,然后绕过特征提取,直接尝试从神经网络输出音位。

最后一个例子,儿科医生通过一个孩子手部的X光照片来判断一个孩子的发育是否正常。处理这个例子的一个非端到端方法,就是照一张图,然后分割出每一块骨头,所以就是分辨出那段骨头应该在哪里,那段骨头在哪里,那段骨头在哪里,等等。然后,知道不同骨骼的长度,你可以去查表,查到儿童手中骨头的平均长度,然后用它来估计孩子的年龄,所以这种方法实际上很好。相比之下如果直接从图像去判断孩子的年龄,那么需要大量的数据去直接训练。而这种做法今天还是不行的。

总之,端到端深度学习系统是可行的,它表现可以很好,也可以简化系统架构,让我们不需要搭建那么多手工设计的单独组件,但它也不是灵丹妙药,并不是每次都能成功

2.10 是否要使用端到端的深度学习

假设我们正在搭建一个机器学习系统,要决定是否使用端对端方法,我们来看看端到端深度学习的一些优缺点,这样你就可以根据一些准则,判断应用程序是否有希望使用端到端方法。

下面给出应用端到端学习的一些好处

  • 端到端学习真的只是让数据说话。如果有足够多的数据,直接输入去训练神经网络,更能捕获数据中的信息,而不是引入人类的成见。如果你让你的学习算法学习它想学习的任意表示方式,而不是强迫你的学习算法使用音位作为表示方式,那么其整体表现可能会更好。
  • 所需手工设计的组件更少,所以这也许能够简化你的设计工作流程,你不需要花太多时间去手工设计功能。

这里还有一些缺点

  • 可能需要大量的数据。
  • 排除了可能有用的手工设计组件

如果没有很多的数据,把人类知识直接注入算法的途径,这总不是一件坏事。学习算法有两个主要的知识来源,一个是数据,另一个是手工设计的任何东西,可能是组件,功能,或者其他东西。所以当我们有大量数据时,手工设计的东西就不太重要了,但是当我们没有太多的数据时,构造一个精心设计的系统,实际上可以将人类对这个问题的很多认识直接注入到问题里,进入算法里应该挺有帮助的。所以端到端深度学习的弊端之一是它把可能有用的人工设计的组件排除在外了,精心设计的人工组件可能非常有用,但它们也有可能真的伤害到你的算法表现。这是一把双刃剑,手工设计的组件往往在训练集更小的时候帮助更大。

  • 36
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值