【深度学习基础】第二十七课:机器学习策略(下)

错误分析,数据集的划分,数据不匹配问题,迁移学习,多任务学习,端到端的深度学习

Posted by x-jeff on June 20, 2020

【深度学习基础】系列博客为学习Coursera上吴恩达深度学习课程所做的课程笔记。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。

1.错误分析

对模型输出结果中的错误案例进行分析,以帮助我们更高效的寻找优化模型的方向。

以一个猫图片分类器为例,假设该分类器的错误率为10%。我们可以挑选出100个该分类器识别错误的图片。统计这100张图片错误的原因。比如可能有8%的图片是因为把狗的照片误分为猫的照片,30%是因为把狮子识别成了猫,40%是因为图片过于模糊从而导致识别错误,剩余22%则是因为图片加了各种各样的滤镜。据此,我们便可把精力放在优化模型对模糊图像的识别以及对狮子图片的识别上。如果我们把过多的精力集中在优化模型对狗图片的识别上,即使我们纠正了所有对狗照片的识别,也只能使模型的错误率下降0.8%(10% $\times$ 8% = 0.8%)而已,到达9.2%的错误率,是一个性价比很低的选择。

同样的,对于数据集中错误标记的数据也应该被纳入到错误分析的统计之中,通过其占错误数据的百分比来决定修正错误标记任务的优先级。

对于训练集中随机出现的错误标记,深度学习往往可以自行克服这个问题。因为训练集通常很大,而错误标记占比很小。 但是对于验证集和测试集中的错误标记则通常需要人为修正。

2.数据集的划分

假设我们需要开发一个手机APP,该APP会识别用户上传的图片是否是猫的图片。

现在我们有两个数据集的来源:一个是我们真正关心的数据分布,即用户上传的图片,如下图右侧,拍摄手法很不专业。另一个数据来源是爬取网络上高清的猫的图片,如下图左侧,有着专业的拍摄手法:

假设我们收集到的用户上传的图片为10k张,而从网络上爬取下来的图片有200k。如果本着数据分布一致性的原则,只选择用户上传的10k张图片来训练和测试模型,对于深度学习来说,数据量未免太小了些。

解决上述问题的一个办法就是将用户上传的图片和网络图片混合在一起,然后随机划分到训练集、验证集和测试集。假设验证集和测试集各分配了2500张图片,这2500张图片中大约只有119($2500 \times \frac{10k}{210k} \approx 119 $)张是用户上传的图片。这样训练出来的模型在用户上传的图片中的表现并不好。

另一种更好的解决办法是将200k的网络图片和5000张用户图片作为训练集,剩余的5000张用户图片分别划分进验证集(2500张)和测试集(2500张)。这样训练得到的模型在用户图片中的表现更好,更符合我们的真实需求。

但是这种方法存在一个问题就是验证集/测试集和训练集的数据分布不一致。接下来我们讨论如何处理这个问题。

3.数据不匹配问题

在第2部分中第二种数据集划分方法下,假设人类的错误率接近0%(我们将其视为贝叶斯最优错误率),模型在训练集上的错误率为1%,验证集上的错误率为10%。此时我们无法判断验证集增加的9%错误率是由方差还是数据分布不一致引起的。因此我们新设立一个训练-验证集来帮助我们分析这个问题。随机从训练集中抽取一部分数据作为训练-验证集,剩余的数据留在训练集用于训练模型:

其中,训练集和训练-验证集的数据服从同一分布,验证集和测试集的数据服从同一分布。此时假设在训练-验证集上得到的错误率是9%,那么模型优化的主要方向应该是减少方差;反之如果训练-验证集的错误率只有1.5%,那么模型优化的主要方向就应该是消除数据分布不一致带来的影响,即解决数据不匹配问题

综上所述,在分析模型优化方向的时候,我们通常要考虑以下四个错误率:

  1. 贝叶斯最优错误率(或用人的表现近似)。
  2. 训练集的错误率。
  3. 训练-验证集的错误率。
  4. 验证集的错误率。

通过比较这4个错误率的相对大小,决定是解决模型的偏差问题还是方差问题,又或者是数据不匹配问题。我们在之前的博客中已经介绍了解决偏差或者方差问题的方法,那么我们怎么解决数据不匹配的问题呢?

首先我们可以收集尽可能多的类似于验证集数据分布的数据纳入进训练集。其次也可以使用人工合成数据来接近验证集的数据分布,例如验证集中的数据大多都有噪声,我们就可以将类似的噪声合成到训练集中。人工合成数据通常都很有效,但是要记住我们有可能从所有可能性的空间只选了很小一部分去模拟数据,例如我们人工添加的噪声可能只是所有噪声类型中的一小部分。

4.迁移学习

神经网络可以从一个任务中习得知识,并将这些知识应用到另一个独立的任务中,这就是所谓的迁移学习(transfer learning)

👉例子一:

假设我们已经训练好一个图像识别神经网络(比如识别图片中的猫),然后我们想要将这个网络迁移到放射科诊断任务中。我们可以将网络的输出层及其权重删去,并添加新的输出层且重新随机初始化最后一层的权重:

然后让这个新的网络在放射诊断数据上训练。如果放射诊断数据集很小,我们可以只重新训练最后一层(或者最后几层)的权重;如果数据量很大,我们可以重新训练网络中的所有层,即在之前预训练(pre-training)的基础上对权重进行更新,这个过程叫做微调(fine tuning)

为什么这样做是有效的呢?原因是因为在预训练的时候,网络已经学到了很多图像的低层次特征,比如边缘检测、曲线检测等等。这些知识有可能帮助到我们的放射诊断网络。

👉例子二:

假设我们已经训练出一个语音识别系统,输入为语音,输出为对应的文本。我们现在想要构建一个“唤醒词”检测系统,例如“hey,siri”。要做到这些,我们可以去掉网络的最后一层,并添加若干新层:

然后对得到的新的网络重新训练,方法同例子一。

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

假设我们要将任务A迁移到任务B。1)任务A和B要有同样的输入。在例子一中,输入均为图像;在例子二中,输入均为语音。2)任务A的数据量远大于任务B。比如通常情况下,我们很难获取大量的放射诊断数据。3)任务A的低层次特征可以帮助到任务B。

5.多任务学习

在迁移学习中,任务是串行的。而在多任务学习中,任务是并行的,即让一个神经网络同时执行多个任务,并且希望这里的每个任务都能帮到其他所有任务。

举个例子,假设我们正在研发无人驾驶汽车,我们需要同时检测出图片中的行人,车辆,停车标识和交通信号灯。如果训练集中共有m个样本,那么标签Y的维度就是$4 \times m$。我们可以构建如下网络:

输出层共有四个神经元,分别为行人、车辆、停车标识和交通信号灯。

cost function可按如下形式构建:

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

其中$L$可使用交叉熵损失函数

\[L(\hat{y}_j^{(i)},y_j^{(i)})=-y_j^{(i)} \log \hat{y}_j^{(i)} - (1-y_j^{(i)}) \log (1-\hat{y}_j^{(i)})\]

以上,便是一个多任务学习的例子,因为我们仅用了一个网络同时识别了多个目标。相比使用多个网络分别预测单一目标,多任务学习中神经网络的一些早期特征在识别不同目标时都会用到,这种方式通常会有更好的表现。

什么时候多任务学习是有意义的呢?通常满足以下三个条件时,多任务学习就是有意义的:

  1. 参与训练的多个任务可以共用低层次特征。
  2. 每个任务的数据量很接近(这个条件有可能不是必要的)。
  3. 一个足够大的神经网络。通常一个足够大的神经网络能够确保多任务学习的性能肯定是优于多个解决单一任务的网络。

6.端到端的深度学习

6.1.什么是端到端的深度学习

通过几个例子来解释端到端的深度学习。

👉例子一:

在语音识别任务中,输入为一段语音,输出为该语音对应的文本。

在传统方法中,语音识别需要多个阶段的处理:输入(语音)➡️提取人工设计的低层次特征➡️找到音素(音素是区分单词的最小语音单位)➡️将音素组成单词➡️输出(文本)。

而在端到端的深度学习中,我们只需将输入丢给神经网络,便可直接得到输出。

👉例子二:

在人脸识别门禁系统中,如果利用端到端的深度学习的思想,直接从门禁相机拍下的图像(输入)得到访客的身份(输出)通常不是一个很好的方法。因为访客可能以各种角度和距离被门禁相机捕获到,这给神经网络的学习带来了很大的困难,并且最关键的问题是这种情况下,数据量也没有很大,不利于神经网络的学习。目前最好的做法是先从输入中识别出访客的人脸,然后将人脸作为新的输入丢进神经网络,得到最后的输出。这样将任务拆分之后,在各个子问题上都可以获取到足够多的数据来训练模型。

相比复杂问题一步到位,将复杂问题分解为两个简单步骤有时会得到更好的表现。

6.2.是否需要使用端到端的深度学习

端到端的深度学习方法的优点:

  1. 只让数据说话,不会引入人的成见。比如在语音识别领域的传统方法中,我们会引入“音素”这一人为设定的概念;而在端到端的深度学习中,我们只是将输入丢进网络,并不会引入“音素”这一人为概念来影响网络的学习。
  2. 需要手工设计的组件会很少,简化了设计工作流程。即省去了中间步骤,可以直接从输入得到输出。

端到端的深度学习方法的缺点:

  1. 需要大量的数据。
  2. 有可能会排除掉有用的手工组件。

是否使用端到端的深度学习主要取决于是否有大量的数据。此外还要谨慎选择网络的输入和输出。