第9周-机器学习ML策略(2)

进行误差分析:Carrying out error analysis

误差分析在我们实际进行机器学习项目中是非常重要的一步,它有利于提高我们的模型表现,使我们的算法逼近人类水平。

Look at dev examples to evaluate ideas

假设我们有这样的一个例子,我们要做一个猫分类的分类器,但是其准确率只有90%,也就是错误率为10%。在分析了分类错误的例子后,发现图片将一些狗狗也分类成了猫,因此,我们是需要花上数月训练出一个新的狗分类模型,还是通过其他方法呢?
image.png

误差分析流程:(尽管有些人会鄙视人工统计做法,但这种误差分析的流程可以节省时间来确定哪些是最有希望的方向,某个方向是否有价值等等)

  • Get ~100 mislabeled dev set examples.
  • Count up how many are dogs.

分析结果:如果只有5%的出错例子是狗,那么我们训练的狗分类器实际上作用不大,而只是将误差从10%下降到9.5%,但至少改善了我们算法的性能上限。再假设我们发现50%的图片是狗的照片,那么我们花时间去解决狗的图片会比较值得,因为我们的误差降到了5%。

Evaluate multiple ideas in parallel

假设我们有针对猫分类器的多种改善算法性能的想法,吴老师用的是表格来表示人工过一遍我们要评估的想法。
image.png

在这个人工统计过程中可能会遇到其他的印象因素,比如因为图片加了滤镜导致分了错误,那么也可以再添加一列进行统计。这样的统计方式能够快速地帮助你确定算法优化的方向。通过计算不同错误标记类型占总数的百分比,可以帮助我们发现哪些问题需要优先解决,或者给你构思新优化方向的灵感。

在做误差分析时,有时我们会注意到验证集当中有些样本被错误标记了,要怎么做呢?请看下一节。

清楚标注错误的数据:Cleaning up incorrectly labeled data

在观察数据时,当发现一些数据的标签是错误的,是否需要花时间对标签进行修正呢?

首先我们可以观察训练集,如果发现这些错误是随机的,那么可以不予理会(只要数据集足够大,那么实际误差也会比较小),当然修正它也完全可以:DL algoritms are quite robust to random errors in the training set. 即深度学习算法对训练集中的随机误差是十分鲁棒的。但对于系统误差而言,深度学习算法则并不鲁棒。即如果我们始终将白色的狗标记为猫,那么我们的分类器就会一直学习错误的结果。

如果我们在验证集或者测试集上发现标记错误的样例,应该怎么做呢?我们也可以做误差分析,计算错误标记的例子数量。
image.png
从表格中知道,一共有6%的错误标记例子,那么是否需要或者值得花时间对这些标记进行修正呢?吴恩达老师的建议是,如果这些例子验证影响了分类器在验证集上的表现,那么就需要对其进行修正;反正,则不应该花费宝贵的时间进行人工修正。

举一个例子进行解释:
image.png
对于左边的例子,我们的总体错误率为10%,而因为标记错误导致的错误率为0.6%,那么当务之急不是去修改标记,而是针对9.6%去进行算法的改善;对于右边的例子,总体错误率为2%,而因为标记错误导致的错误率为0.6%,此时修改错误标记的样本则变得很有必要。另外需要记住的是,设置验证集的目的是为了帮助我们在分类器A和B之间进行选择。

在对验证集/测试集进行标记的修正时,我们需要注意以下几点:

  1. Apply same process to your dev and test sets tot make sure they continue to come from the same distribution.(我们在验证集上设置目标,并且希望推广到测试集上进行目标的推广,因此两个数据集的分布需要一致。所以如果我们要对验证集进行样例修正,那么也需要对测试集这么做。)
  2. Consider examining examples your algorithm got right as well as ones it got wrong.(我们不仅需要检查算法出错的例子,也需要再次检查它做对的例子,因为这些例子也可能是标记错误的,否则是不公平的。不过这种做法通常不采用,因此可能有98%做对,而2%做错,而检查98%的例子所花的时间会很多。)
  3. Train and dev/test data may come from slightly different distributions.(如果我们只决定修正验证集和测试集中的标签,因为它们通常比训练集小,那么可能会在数据集的分布上有细微的差别。)

因此,亲自检查数据也是很有用的,能够帮助我们确定要优秀尝试哪些方法或者想法。

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

在这一节中,吴恩达老师讲解了快速搭建系统并且迭代这一步的重要性。他举了语音识别的例子,比如我们需要搭建一个语音识别例子,但是我们不清楚应该在哪个方向进行改进。可能的方向如下:
image.png

因此,吴恩达老师建议我们,先不要想着在什么方向上下手,而是迅速开始搭建系统进行训练和迭代,再根据实际的算法表现来选定方向。整个步骤流程如下:

  1. Set up dev/test set and metric.
  2. Build initial system quickly.
  3. Use Bias/Variance analysis & Error analysis to prioritize next steps.通过这一步找出最有希望的方向。

如果我们在某个应用领域上很有经验,那么上述建议的适用程度则低一些。当在这个应用领域上有很多学术文献,这些文献处理的问题和我们要解决的几乎完全相同时,比如人脸识别有很多学术文献,那么我们完全可以从现有文献出发,一开始就搭建复杂的系统。

很多时候,大多数团队要么搭建了过于复杂的系统,要么搭建了过于简单的系统。因此,如果我们希望将机器学习算法应用到新的应用程序里,我们的目标是弄出能用的系统,而不是发明全新的机器学习算法,那么我们可以快速搭建你的第一个系统,并进行迭代,用他们的算法表现来做误差分析之类的,根据分析结果确定下一步优先要做的方向。

在不同的分布上进行训练和测试

深度学习算法对训练数据有着很大的需求,当我们收集到足够多带标签的数据构成训练集时,算法效果最好。这也导致很多团队用尽一切办法去收集大量数据放置到训练集中,即便这些数据与验证集、测试集来自不同的分布。在深度学习时代,越来越多的团队使用来自和验证集、测试集分布不同的数据来训练。这里有一些做法可以用来处理训练集和测试集存在差异的情况。

再次取猫分类的例子:
image.png
然而,来自手机app的图片只有10,000张,来自网页的图片有200,000张。而我们又不愿意直接用10,000张图片来训练,因为这样训练集的规模就太小了。而网页的图片很多,但是它又不是我们原本的分布。我们有以下两个选择:

  1. 将所有图片随机打乱后,再划分训练集、验证集和测试集。比如设置训练集为205,000张图片,验证集为2,500张图片,测试集为2,500张图片。然而,由于我们的目的是设置验证集用来不断逼近我们的目标,但是实际上,验证集中有2381张来自网页的图片,而只有119张来自手机。也就是说,如果这样设计,那么我们会花大量时间用来优化来自网页下载的图片(不符合我们的目的)。

  2. 选择二是训练集一共有200,000张来自网页的图和5,000张来自手机的图片,而验证集和测试集都是2,500张来自手机的图片。这样划分数据的好处是我们现在瞄准的目标就是想要处理的目标,即我们的验证集包含的图片都来自手机,这就是我们真正关心的图片分布。因此我们试着搭建一个学习系统,让系统在处理手机上传图片分布时效果良好。当然,这样做的缺点是训练集和验证集/测试集的分布不同,但事实证明,这样的划分方法能够长期给你带来更好的系统性能。
    image.png

接下来看一下语音识别的例子。我们应该如何收集数据来训练产品语言识别模块呢?最后的数据集划分方法类似上面的方法2。
image.png

Bias and Variance with mismatched data distributions

估计学习算法的偏差和方差可以帮助我们确定接下来应该优化做的方向,但是,当你的训练集和验证集、测试集的分布不同时,分析偏差和方差的方式可能不同。

我们继续用猫分类器为例。我们可能会遇上这样的情况:
image.png
一般情况下,我们会认为这个算法的方差过大,而采取减小方差的方法。但是,如果训练集和验证集的分布不同,即算法因为没有看过验证集相似的数据而表现不佳,那么这可能就不是单纯的减小方差的问题。问了判断到底是否应该减小方差,我们可以设置一个training-dev set: Same distribution as training set, but not used for training.

一个针对training-dev set的解释。如图,数据分为了4个部分,其中training-dev set不参与训练。
image.png

情景一:

  • Training error:1%
  • Training-dev error: 9%
  • Dev error: 10%
    这种情况下,发现尽管训练集和Training-dev集的分布相同,但是算法表现并不好,可以判断存在方差问题。

情景二:

  • Training error: 1%
  • Training-dev error: 1.5%
  • Dev error: 10%
    这种情况下,我们的方差问题其实很小,因此这实际上是数据不匹配问题,因为我们的算法没有直接在Training-dev集和Dev集上训练,而且两个数据集分布不同,但是算法在前者表现好,而后者表现差,说明是数据不匹配即分布不同导致的问题。

情景三:

  • Training error: 10%
  • Training-dev error: 11%
  • Dev error: 12%
    注意我们的人类水平即贝叶斯误差估计是0%,而这个情景很明显存在偏差问题,存在可避免偏差问题。

情景四:

  • Training error: 10%
  • Training-dev error: 11%
  • Dev error: 20%
    这个情景存在着两个问题:第一,可避免偏差相当高,因为我们在训练集上也没有做好;第二,数据不匹配问题,可以看到Training-dev集数据集和dev数据集的表现相差很大。

Bias/variance on mismatched training and dev/test sets

image.png

对图上内容做详细解释:通过training set error和human level error,我们可以得知avoidable bias;通过training set error和training-dev set error,我们可以得知方差variance;通过training-dev set error和dev error,我们可以知道数据不匹配情况;通过dev error和test error,我们可以知道算法过拟合的程度。

我们观察到,上述误差是一个递增的过程,但也可能出现向下图右侧的情况:
image.png
这主要是有时候,我们的验证集/测试集分布比我们应用实际处理的数据要容易得多,那么误差真的可能如上图那样下降。

More general formulation

image.png

通常情况下,我们可以完成上述的一个表格,其中左边为训练数据,而右边为测试/验证数据,可以发现他们的分布不同。通过计算红框中不同的差值,我们可以判断算法的偏差、方差和数据不匹配的问题。当然,我们也可以将表格填满,从而发现人类表现在左边比在右边要更好,可以发现更多的数据特性。

我们在之前就讲过如何降低偏差、降低方差的方法,那么,如何处理数据不匹配的问题呢?

定位数据不匹配:Addressing data mismatch

如果我们的训练集来自和验证集/测试集不同的分布,而误差分析显示我们存在数据不匹配的问题,我们应该怎么做呢?

一般我们会这么做,而这种方法通常可以解决很多问题。

  • Carry out manual error analysis to try to understand difference between traning and dev/test sets. 通常我们需要观察一下验证集的样本,弄清楚训练集和验证集的不同。就汽车语音识别系统而言,我们可能发现验证集的数据存在很多汽车噪音,这就是验证集和训练集的差异之一。当我们了解了验证集误差的性质时,我们就知道验证集和训练集不同,因此就会尝试做下一步。
  • Make training data more similar; or collect more data similar to dev/test sets. 比如,当我们发现车辆背景噪声是主要的误差来源,那么我们可以模拟车辆噪声数据;或者发现很难识别街道数据时,则下意识地添加数字的语音信息。(人工合成数据)

Artificial data synthesis

给出一个简单的音频合成例子:
image.png

通过人工合成数据,我们可以很方便地得到更多的数据,而不需要自己收集数据。所以,当我们的误差分析显示我们应该让自己的数据听起来像在车里录的,那么我们可以人工合成这样的音频,再给机器学习算法进行训练。

但是,这种人工合成数据有一个潜在问题。比如,我们在安静的背景里录得10000个小时音频数据,而只录了一个小时车辆背景噪音,我们可以尝试将车辆噪声重复10000次叠加到音频里,但是我们的学习算法会对这1小时汽车噪声过拟合。并且,如果我们只录了1个小时的车辆背景噪声,那么实际上我们可能只模拟了全部数据空间的一小部分,从汽车噪音的很小的子集中合成数据。对于我们人耳来说,这可能听起来和其他任意一小时车辆噪声是一样的,但是神经网络则会对这一小时汽车噪声造成过拟合。

image.png

因此,为了学习算法有更好的性能,可能有10000个小时的汽车背景噪声数据是更好的,但是可能对于人耳而言,我们可能会觉得自己得到的数据其实都是类似的。

再举一个汽车识别的例子。我们的学习算法可能对人工合成出的车集合产生过拟合的情况,因为它们只是所有可能出现的集合中很小的一个集合。
image.png

总结

总而言之,如果认为存在数据不匹配问题,那么我们可以进行误差分析,或者看看训练集和验证集,试图了解和找出这两个数据分布的不同之处。之后再看看是否有办法手机更多类似验证集的数据进行训练。我们提高了人工合成数据的方法,这个方法确实有效。在语音识别中,吴老师说已经看到了人工数据合成显著提升了已经很好的语音识别系统的表现,因此这是可行的。但是在使用人工数据合成时,一定要谨慎,记住我们有可能从整个的可能空间中只选了很小的一部分去模拟数据。

上述就是如何处理数据不匹配的问题。

迁移学习:Transfer learning

深度学习最强大的理念之一是,有时候我们可以从一个任务中习得知识,再将这些知识应用到另一个独立的任务中。这叫做迁移学习。比如我们的神经网络已经学会分类猫,那么学得的经验知识也可以帮助我们识别x射线扫描图。

image.png

举一个例子。假设我们用图上的神经网络进行了图像识别,识别如猫狗之类的动物,然后想用这个神经网络迁移学习其他任务的知识,如放射线诊断。那么我们可以把神经网络最后一层拿掉,然后随机初始化最后一层的权重,将目标更换为我们的放射线诊断,然后再重新训练。根据经验,如果我们的新数据集很小,那么我们可以只更新最后一层和倒数第二层的权重,而前面的权重保持不变;如果我们的数据集足够,那么也可以对所有层的权重进行更新。

因此,在图像识别数据的初期训练阶段,我们称为预训练(pre-training),因为我们在用图像数据来预训练神经网络的权重;之后,如果我们想重新更新权重,然后在放射科数据上训练,这个过程称为微调(fine tuning)。(预训练就是指预先训练的一个模型或者指预先训练模型的过程;微调就是指将预训练过的模型作用于自己的数据集,并使参数适应自己数据集的过程。)

更通俗的解释:

  • 你需要搭建一个网络模型来完成一个特定的图像分类的任务。首先,你需要随机初始化参数,然后开始训练网络,不断调整直到网络的损失越来越小。在训练的过程中,一开始初始化的参数会不断变化。当你觉得结果很满意的时候,你就可以将训练模型的参数保存下来,以便训练好的模型可以在下次执行类似任务时获得较好的结果。这个过程就是pre-training
  • 之后,你又接收到一个类似的图像分类的任务。这时候,你可以直接使用之前保存下来的模型的参数来作为这一任务的初始化参数(已经学习了很多低层次特征),然后在训练的过程中,依据结果不断进行一些修改。此时我们使用的是一个pre-trained模型,而训练过程称为fine tuning。

为什么这样做有效果呢?对于低层次特征,比如边缘检测、曲线检测、阳性物体检测,从非常大的图像识别数据库中学得这些知识,可能有助于让我们的学习算法在放射科诊断中做得更好,因为算法学到了很多结构信息的知识,如线条、点、曲线等,从而更好的进行学习。

再假设我们已经训练出一个语音识别系统,输入为音频片段,输出为听写文本。然后接下来我们想要完成触发词的检测,即之前所提到过的可以启动智能家居的一些出发词,那么我们可能需要去掉神经网络的最后一层,然后加入新的输出结点,当然有时候我们甚至往神经网络中加入几个新的层,然后把唤醒词检测问题的标签Y放入进行训练。
image.png

那么,迁移学习什么时候起作用呢?迁移学习起作用的场合时,对于迁移来源问题你有着很多数据,但迁移目标问题的数据则没有多少。(反过来则不适用)例如,图像识别任务中我们有10,000,000个样本,在神经网络的前面几层可以学习到很多知识,但对于放射任务,我们只有100个样本,因此我们可以迁移从图像识别训练中学到的知识,帮我们加强放射科识别任务的性能;再例如,我们已经通过10,000个小时的数据中学到了很多人类声音的特征,但对于触发词检测,我们只有1个小时的数据,因此在这种情况下,预先学到很多人类声音的特征、人类语言的组成部分等等,能够帮助我们开发出一个很好的触发词检测系统,尽管我们的数据集相对较小。

When transfer learning makes sense

  • Task A and B have the same input x.
  • You have a lot more data for Task A than Task B.
  • Low level features from A coule be helpful for learning B.

多任务学习:Multi-task learning

在迁移学习中,我们的学习步骤是串行的,我们从任务A中学习然后再迁移到任务B。在多任务学习中,我们同时开始学习,试图让神经网络同时做多个事情,然后希望这里的每个任务能够帮到其他所有任务。

举一个例子。假设我们在研发无人驾驶车辆,那么我们的无人驾驶车可能需要同时检测不同的物体,比如检测行人、车辆、停车标志、交通灯等。如下图图像。
image.png

假设图像是输入,那么我们就要输出一个向量,检测的物体越多,向量的维数越大。简单假设为检测4个物品,如下:
image.png

如果从整体来看训练集,那么整个训练集的输出则为(4,m)的矩阵。
image.png

因此接下来我们要做的就是训练一个神经网络来预测y值,从下图的神经网络输出层可以看到,4个结点分别对应了4个被检测的对象。当然,我们也需要设置cost function。可以看到,我们这里不仅要对所有的样本求和,还需要对4个维度的各自的loss求和,这是因为我们执行的是多任务学习,每个维度都有可能存在;与Softmax回归相比,Softmax回归只支持单标签,而多任务学习中一张图片可能有多个标签。
image.png
另外,尽管有的时候一些图片所给出的标签不明确,如可能输出中含?
image.png
多任务学习仍然可以进行,这个时候我们在计算loss function的时候只要考虑输出为0或1的值即可。

When multi-task learning makes sense

  • Training on a set of tasks that could be benefit from having shared lower-level features.(共用低层次特征)
  • Usually: Amount of data you have for each task is quite similar.(数据量)
  • Can train a big enough neural network to do well on all the tasks.

多任务学习的替代方法是为每个任务训练一个单独的神经网络。另外,多任务学习会降低性能的唯一情况,和训练单个神经网络相比性能更低的情况,就是我们的神经网络还不够大。如果可以训练一个足够大的神经网络,那么多任务学习肯定不会或者很少会降低性能,并且我们都希望它可以提升性能,至少比单独训练神经网络来单独完成各个任务的性能要好。

在实践中,多任务学习的使用频率要低于迁移学习。大多数迁移学习的应用都是因为我们需要解决的问题所拥有的训练数据很少,因此我们会找到一个数据很多的相关问题来预先学习,再将知识迁移到这个新问题上。但是多任务学习则比较少见,可能计算机视觉是一个例外。在物体检测(最显著的例外情况)中,我们看到更多使用多任务学习的应用,即用一个神经网络来尝试检测很多物体,比分别训练不同的神经网络来检测物体更好。总的来说,目前迁移学习的使用频率更高,但两者都可以成为我们的强力工具。

什么是端到端的深度学习:end-to-end deep learning

深度学习中最令人振奋的动态之一就是端到端深度学习的兴起。简而言之,以前有一些数据处理系统或者学习系统,它们需要多个阶段的处理,而端到端深度学习就是忽略所有这些不同的阶段,用单个神经网络来代替它。

举一个语音识别的例子:
image.png
可以看到,传统的流水线方法包含多个阶段,包括人工提取特征、学习音位、构成单词等,而端到端深度学习只需要将数据集输入后,通过深层神经网络就可以得到我们的听写文本(transcripts),因此优势很明显。然而,端到端深度学习的一个缺点是,训练的时候需要大量的数据,因此在具有大数据集的前提下,采用端到端的效果会很好;而当数据集较小时,传统流水线方法的效果也很好;当数据量适中时,可以采用中间件方法,即我们可能输入的是音频,跳过特征提取步骤,尝试从神经网络输出音位(phoneme),这也算是向端到端学习迈出的一小步。

再举一个人脸识别的例子,是一个人脸门禁系统。这个系统的输入应该是相机的照片,迄今为止最好的方法应该是多步的:首先要运行一个软件来检测人脸,放大图像的部分,并通过裁剪使人脸居中,再将图片作为神经网络的输入,来学习出该人的身份。(研究人员发现,比起一步到位,把这个问题分解成两个更简单的步骤表现得更好)
image.png
这里注意,训练第二步时,我们输入两张图片,然后神经网络所做的是将输入的两张图进行比较,判断是否是同一个人。即假设我们有10,000个员工,那么就将每个员工图片与进入者的图片进行比对即可。

为什么这里两步法更好呢?

  1. 我们要解决的两个问题,每个问题实际上很简单
  2. 两个子任务的训练数据都很多。具体来说,有很多数据可以用于人脸识别训练,任务就是观察一张图,找出人脸所在的位置并框出来。对于任务二,业务领先的公司也拥有着数亿图像用于训练,通过观察两张图片,判断照片中认得身份来确定是否为同一个人。相比之下,如果我们想一步到位,即端到端学习,但是我们实际的数据对(x,y)的量要少得多,其中x是门禁系统拍摄的图像,y是人的身份,因为我们没有足够多的数据去解决这个端到端学习问题。

再来看几个例子。以机器翻译为例,传统的机器翻译也有着一个复杂的流水线过程,而端到端深度学习在机器翻译的表现很好:
image.png

从一个手的骨骼判断儿童的年龄:
image.png
由于没有足够的数据来用端到端方式来训练词任务,因此相比之下,多步方法的效果更好。

总结:端到端深度学习系统是可行的,它的表现可以很好,可以简化系统架构,让我们不需要搭建那么多手工设计的单独组件,但这一方法并不是每次都能成功。

是否使用端到端学习

Pros and cons of end-to-end deep learning

Pros:

  • Let the data speak. (Enough data)
  • Less hand-designing of components needed.

Cons:

  • May need large amount of data.
  • Excludes potentially useful hand-designed components.(数据来源:original data, hand-designed data在小数据集上很有用)

Applying end-to-end deep learning

Key question: Do you have sufficient data to learn a function of the complexity needed to map x to y?

举一个更复杂的例子:
image.png
可以看到,这不是一个端到端学习的例子,相反,它做到了以下两点:

  1. Use DL to learn individual components.
  2. Carefully choose X->Y depending on what tasks you can get data for.

相反的,要通过观察图像直接判断方向盘转向,即端到端学习,我认为在自动驾驶领域里基本是不太可能的一件事。

本周作业

下面粘贴做错的题:
1、答案是C,而我选了AB。
image.png
2、答案是AD,而我选了A。
image.png