机器学习策略(2)

"deeplearning.ai-Class3-Week2"

Posted by Canary on April 12, 2018

GitHub项目传送门

欢迎Star

误差分析(Carrying out error analysis)

如果试图让学习算法完成通常由人类所做的任务,但它并没达到人类水平的话,就需要人工检查一下学习算法所犯的错误,这有助于了解接下来需要去做什么,这个过程被称为 误差分析

例如,你可能会发现一个猫图片识别器错误地将一些看上去像猫的狗误识别为猫。这时,立即盲目地去研究一个能够精确识别出狗的算法不一定是最好的选择,因为我们不知道这样做会对提高分类器的准确率有多大的帮助。所以一个好的误差分析的流程就相当重要。

收集错误样例:

我们可以从分类错误的样本中统计出狗的样本数量。根据狗样本所占的比重来判断这一问题的重要性。

  • 假如狗类样本所占比重仅为 5%,那么即使花费几个月的时间来提升模型对狗的识别率,改进后的模型错误率并没有显著改善;
  • 而如果错误样本中狗类所占比重为 50%,那么改进后的模型性能会有较大的提升。因此,花费更多的时间去研究能够精确识别出狗的算法是值得的。

并行分析(举例):

  • 修改那些被分类成猫的狗狗图片标签;
  • 修改那些被错误分类的大型猫科动物,如:狮子,豹子等;
  • 提升模糊图片的质量。

为了并行的分析,建立表格来进行。以单个错误分类样本为对象,分析每个样本错误分类的原因。

在表格的最左侧,列出需要分析的图像集,然后使用另外几列对应评估的想法。最后一列则通常被留下用来写评论(或者备注)。当填满整个表格后,就可以统计这些算法(错误)的百分比或者每个错误类型的百分比。例如下图所示的情况,检查的图像中 8%是狗、43%是其他的猫科动物,另外 61%是模糊的图像。

在分析过程中,有时会发现其他错误类型,比如可能发现有 Instagram 滤镜干扰了分类器。出现这种情况时,只需要在分析时在电子表格中增加这样的一列,也将其纳入误差分析中即可。

最后,统计错误类型的百分比,这个分析步骤可以给我们一个粗略的估计,让我们大致确定是否值得去处理每个不同的错误类型。

总结一下,进行误差分析首先应该找一组错误例子,这些错误例子可能在开发集或者测试集里。然后观察这些错误标记的例子,统计属于不同错误类型的错误数量。在这个过程中,有时可能会得到启发,归纳出新的误差类型,例如本小节例子所提的 lnstagram 的滤镜问题。那么,针对这一新类型可以在表格中新建一个错误类型,将其纳入误差分析中。总之,通过统计不同错误标记类型占总数的百分比将有助于发现哪些问题需要优先解决,或者能够提供构思新优化方向的灵感。

清除标注错误的数据(Cleaning up incorrectly labeled data)

我们用 mislabeled examples 来表示学习算法输出了错误的 Y 值。而在做误差分析时,有时会注意到数据集中有些样本被人为地错误标记(incorrectly labeled)了,这时该怎么做?

如果是在训练集中,由于机器学习算法对于随机误差的 稳健性(Robust) (也称作“鲁棒性”),只要这些出错的样本数量较小,且分布近似随机,就不必花费时间一一修正。

而如果出现在验证集或者测试集,则可以在进行误差分析时,通过统计人为标记错误所占的百分比,来大致分析这种情况对模型的识别准确率的影响,并比较该比例的大小和其他错误类型的比例,以此判断是否值得去将错误的标记一一进行修正,还是可以忽略。

上图例子中,假设它所占的百分比是 6%,那么是否值得修正这 6%的标记出错的例子呢?

这里有三个指标来确定是否值得去人工修正标记出错的数据。

  1. 应该关注整体的开发集误差,假设在本例中是 10%。
  2. 然后,应该查看错误标记引起的错误的数量或者百分比,在这个例子中,6%的错误来自标记出错,也就是 0.6%。
  3. 最后,应该查看其他原因导致的错误。
    • 在本例中,假设开发集上有 10%的错误,其中 0.6%是因为标记出错,其他原因所导致的错误占 9.4%。在这种情况下,其他原因所导致的 9.4%的误差需要集中精力修正,而标记出错导致的错误是总体错误的一小部分而已。
    • 如果误差降到了 2%,但是总体错误中的 0.6%还是标记出错导致的,那么此时去检查一组标记出错的开发集图片就是相对合理的。

我们知道,开发集的主要作用是在不同算法之间进行比较,选择错误率最小的算法模型。但是,如果有标记出错的数据(0.6%)的存在,当不同算法(两个分类器A 和 B 时,在开发集上一个有 2.1%的误差,另一个有 1.9%的误差)错误率比较接近的时候,我们无法仅仅根据开发集上测试的结果准确指出哪个算法模型更好,必须修正标记出错的数据。

当你决定在验证集和测试集上手动检查标签并进行修正时,有一些额外的方针和原则需要考虑:

  • 在验证集和测试集上 同时使用同样的修正手段 ,以保证验证集和测试集来自相同的分布;
  • 同时检查判断正确和判断错误的例子(通常不用这么做);
  • 在修正验证集和测试集时,鉴于训练集的分布不必和验证/测试集完全相同,可以不去修正训练集(学习算法是相当鲁棒的)。

快速搭建第一个系统并开始迭代(Build your first system quickly, then iterate)

对于如何构建一个机器学习应用模型,Andrew给出的建议是先快速构建第一个简单模型,然后再反复迭代优化。

  • 设置训练、开发、测试集和优化指标(确定方向);
  • 快速训练出一个初步的系统,用训练集来拟合参数,用验证集调参,用测试集评估;
  • 使用偏差方差分析、误差分析去确定后面步骤的优先步骤。

在不同分布上的训练集和测试集(Training and testing on different distributions)

在深度学习的时代,因为需求的数据量非常大,现在很多的团队,使用的训练数据都是和开发集和测试集来自不同的分布。

下面是一些处理训练集和测试集存在差异的最佳的做法。以前一周中的猫的分类问题为例:假设现在想识别一个手机应用中用户上传的他们用手机拍摄的照片是不是猫?

现在存在的现状是:我们可以从网上获取大量的高清晰的猫的图片200000张, 从手机获取拍摄的不清晰的图片10000张。但是我们系统的目的是应用到手机上做分类。也就是说,我们的训练集和开发集、测试集来自于不同的分布。

比较好的方法是:将从网页下载的200000张图片都设为训练集,如果需要的话,再加上5000张来自手机上传的图片。至于开发集和测试集则都是来自手机上传的图片,例如将 2500 张来自手机上传的图片作为开发集,剩下的 2500 张作为测试集。

  • 好处:开发集全部来自手机图片,瞄准目标;
  • 坏处:训练集和开发、测试集来自不同的分布。

从长期来看,这样的分布能够给我们带来更好的系统性能。

数据分布不匹配的偏差和方差分析(Bias and Variance with mismatched data distributions)

之前的学习中,我们通过比较人类水平误差、训练集错误率、验证集错误率的相对差值来判断进行偏差(人类水平误差和训练集错误率差值)/方差(人类水平误差和验证集错误率差值)分析。

  • 假设例子中训练误差是 1%,开发误差是 10%。如果开发集来自和训练集一样的分布,那么比对之下就可以发现这里存在很大的方差问题。

但在训练集和验证/测试集分布不一致的情况下,无法根据相对差值来进行偏差/方差分析。这是因为训练集错误率和验证集错误率的差值可能来自于算法本身(归为方差),也可能来自于样本分布不同。

  • 比如可能因为训练集都是高分辨率、很清晰的图片,所以很容易识别,但开发集上的图片可能由于图片分辨率不高等而难以识别。即可能算法本身没有方差问题,这只不过是反映了开发集包含更难以精确分类的图片。

那么我们如何去确定是由于分布不匹配的问题导致开发集的误差,还是由于算法中存在的方差问题所致?

为了解决这个问题,我们可以再定义一个训练-验证集(Training-dev Set)。训练-验证集和训练集的分布相同(或者是训练集分割出的子集),但是不参与训练过程。可理解为模型本身的开发集由于和测试集不同分布,所以人为从测试集抽出一部分集合作为开发集

  • 计算训练集、训练-开发集和开发集上的误差。
    1. 假设模型得到的误差如下结果:
      • Training error: 1%
      • Training-dev error: 9%
      • Dev error: 10%
      • 贝叶斯最优误差大概是 0%

    可以发现当算法运行在训练-开发集上时,误差上升了很多,这就说明了算法存在方差问题,因为训练-开发集是和训练集来自同一分布。

    1. 但如果模型得到的误差分别为:
      • Training error: 1%
      • Training-dev error: 1.5%
      • Dev error: 10%
      • 贝叶斯最优误差大概是 0%

    那么在这样的情况下,我们可以看到,来自同分布的数据,模型的泛化能力强,而开发集的误差主要是来自于分布不匹配导致的。

    1. 但如果模型得到的误差分别为:
      • Training error: 10%
      • Training-dev error: 11%
      • Dev error: 12%
      • 贝叶斯最优误差大概是 0%

    那么在这样的情况下,那么就真的存在偏差问题,因为算法做得比人类水平要差很多。

    1. 但如果模型得到的误差分别为:
      • Training error: 10%
      • Training-dev error: 11%
      • Dev error: 20%
      • 贝叶斯最优误差大概是 0%

    那么在这样的情况下,同时有两个问题:一是可避免偏差相当高,另一个是数据不匹配问题。

有了“训练集错误率”、“训练-验证集错误率”,以及“验证集错误率”。

  • “训练集错误率”和“人类水平误差(贝叶斯最优误差)”的差值反映了 可避免偏差(Avoidable bias)
  • 其中,“训练集错误率”和“训练-验证集错误率”的差值反映了 方差(variance)
  • 而“训练-验证集错误率”和“验证集错误率”的差值反映了 样本分布不一致的问题 ,从而说明模型擅长处理的数据和我们关心的数据来自不同的分布,我们称之为 数据不匹配(Data Mismatch) 问题;
  • “开发集错误率”和“测试集错误率”的差值反映了开发集的 过拟合 水平。

一般情况下,人类水平误差、训练集错误率、训练-验证集错误率、验证集错误率以及测试集错误率的数值是递增的,但是也会出现验证集错误率和测试集错误率下降的情况。这主要可能是因为训练样本比验证/测试样本更加复杂,难以训练。

处理数据不匹配的问题(Addressing data mismatch)

这里有两条关于如何解决数据不匹配问题的建议:

  • 做错误分析,尝试了解训练集和验证/测试集的具体差异(主要是人工查看训练集和验证集的样本);
  • 尝试将训练数据调整得更像验证集,或者收集更多类似于验证/测试集的数据。

如果你打算将训练数据调整得更像验证集,可以使用的一种技术是人工合成数据。我们以语音识别问题为例,实际应用场合(验证/测试集)是包含背景噪声的,而作为训练样本的音频很可能是清晰而没有背景噪声的。为了让训练集与验证/测试集分布一致,我们可以给训练集人工添加背景噪声,合成类似实际场景的声音。

人工合成数据能够使数据集匹配,从而提升模型的效果。但需要注意的是,不能给每段语音都增加同一段背景噪声,因为这样模型会对这段背景噪音出现过拟合现象,使得效果不佳。

迁移学习(Transfer learning)

迁移学习(Tranfer Learning) 是通过将已训练好的神经网络模型的一部分网络结构应用到另一模型,将一个神经网络从某个任务中学到的知识和经验运用到另一个任务中,以显著提高学习任务的性能。

例如,我们将为猫识别器构建的神经网络迁移应用到放射科诊断中。因为猫识别器的神经网络已经学习到了有关图像的结构和性质等方面的知识,利用之前的神经网络模型,只改变神经网络中原有的输出层,加入新的输出层并随机初始化权重系数($W^{[L]}$、$b^{[L]}$),而其它层所有的权重系数$W^{[l]}$、$b^{[l]}$)不变,随后用新的训练集进行训练,就完成了以上的迁移学习。

如果新的数据集很小,可能只需要重新训练输出层前的最后一层的权重,即$W^{[L]}$、$b^{[L]}$,并保持其他参数不变;而如果有足够多的数据,可以只保留网络结构,重新训练神经网络中所有层的系数。这时初始权重由之前的模型训练得到,这个过程称为 预训练(Pre-Training) ,之后的权重更新过程称为 微调(Fine-Tuning)

你也可以不止加入一个新的输出层,而是多向神经网络加几个新层。

迁移学习起作用的场合是迁移来源有很多某个问题的数据,但迁移目标问题却没有那么多数据。假如图像识别任务中有 1 百万个样本,这就有足够的数据帮助神经网络学习低层次特征。如果放射科任务只有一百个样本,那么就意味着放射科诊断问题的数据很少,这时,将从图像识别训练中学习到的很多知识迁移到放射科诊断问题就是合理的。

迁移学习之所以能这么做的原因是,神经网络浅层部分能够检测出许多图片固有特征,例如图像边缘、曲线等。使用之前训练好的神经网络部分结果有助于我们更快更准确地提取X光片特征。二者处理的都是图片,而图片处理是有相同的地方,第一个训练好的神经网络已经帮我们实现如何提取图片有用特征了。 因此,即便是即将训练的第二个神经网络样本数目少,仍然可以根据第一个神经网络结构和权重系数得到健壮性好的模型。

在下述场合进行迁移学习是有意义的:

  1. 两个任务有同样的输入(比如都是图像或者都是音频);
  2. 拥有更多数据的任务迁移到数据较少的任务
  3. 某一任务的低层次特征(底层神经网络的某些功能)对另一个任务的学习有帮助。

多任务学习(Multi-task learning)

迁移学习中的步骤是串行的;而 多任务学习(Multi-Task Learning) 使用单个神经网络模型来同时实现多个任务,学习是同时开始的,并且任务之间可以相互促进。

以汽车自动驾驶为例,需要实现的多任务是:不只是要判断图片是否为行人图片、车辆版、交通标志和信号灯图片,而是要知道每张照片是否有行人、汽车、停车标记或者交通灯。如果在输入的图像中检测出车辆和交通标志,则输出的 y 为:

多任务学习模型的成本函数为:

其中,j 代表任务下标,总有 c 个任务。对应的损失函数为:

多任务学习是使用单个神经网络模型来实现多个任务。实际上,也可以分别构建多个神经网络来实现。多任务学习中可能存在训练样本 Y 某些标签空白的情况,这不会影响多任务学习模型的训练。

多任务学习和 Softmax 回归看上去有些类似,容易混淆。它们的区别是,Softmax 回归的输出向量 y 中只有一个元素为 1;而多任务学习的输出向量 y 中可以有多个元素为 1。

在下述场合进行多任务学习是有意义的:

  1. 训练的一组任务可以共用低层次特征;
  2. 通常 ,每个任务的数据量接近(任务 A_1,…,A_n) ,每个任务均有1000个数据,合起来就有1000n个数据,共同帮助任务的训练,所以如果想要使用多任务学习来大幅地提升性能,那么其他任务加起来必须要有比单个任务大得多的数据量);
  3. 能够训练一个足够大的神经网络,以同时做好所有的工作。多任务学习会降低性能的唯一情况(即和为每个任务训练单个神经网络相比性能更低的情况)是神经网络还不够大。

在实践中,多任务学习的使用频率要远低于迁移学习。计算机视觉领域中的物体识别是一个多任务学习的例子。

何为端到端的深度学习(What is end-to-end deep learning?)

端到端(end-to-end)深度学习就是将所有不同阶段的数据处理系统或学习系统模块组合在一起,用一个单一的神经网络模型来实现所有的功能。它将所有模块混合在一起,只关心输入和输出。

语音识别例子:

优点与缺点(Whether to use end-to-end deep learning)

应用端到端学习的优点:

  • 只要有足够多的数据,剩下的全部交给一个足够大的神经网络。比起传统的机器学习分块模型,可能更能捕获数据中的任何统计信息,而不需要用人类固有的认知(或者说,成见)来进行分析;
  • 所需手工设计的组件更少,简化设计工作流程;

缺点:

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

根据以上分析,决定一个问题是否应用端到端学习的关键点是:是否有足够的数据,支持能够直接学习从 x 映射到 y 并且足够复杂的函数?

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