神经网络训练的一些方法

前言

许多神经网络不WORK的原因在于逻辑与语法的错误,我们可以分单元逐个测试排除错误。但这只是训练神经网络的一个开始。一切都可能在语法上正确,但整个事情没有妥善安排,而且很难说清楚。“可能的错误表面”是大的,逻辑的(与语法相反),并且对单元测试非常棘手。例如,在数据增强期间左右翻转图像时,您可能忘记翻转标签。您的网络仍然可以(令人震惊地)工作得非常好,因为您的网络可以在内部学习检测翻转的图像,然后左右翻转其预测。或许你的自回归模型会因为一个错误的错误而意外地将它想要预测的东西作为输入。或者你试图剪切你的渐变但是修剪了损失,导致在训练期间忽略异常值的例子。或者您从预训练检查点初始化了您的权重,但没有使用原始均值。或者你只是搞砸了正则化强度,学习率,衰减率,模型大小等设置。因此,错误配置的神经网络只有在你运气好的时候才会抛出异常; 大部分时间它会训练,但默默地工作有点糟糕。
结果,(并且这在过去很难过分强调),训练神经网络的“快速和激烈”方法不起作用,只会导致痛苦。现在,痛苦是让神经网络运作良好的一个非常自然的部分,但它可以通过彻底,防御,偏执和痴迷基本上所有可能的事物的可视化来减轻。在我的经验中,与深度学习成功最相关的品质是耐心和对细节的关注。

一些建议

鉴于上述两个事实,我已经为自己开发了一个特定的过程,我将神经网络应用于新问题,我将尝试描述。你会发现它非常重视上述两个原则。特别是,它从简单到复杂构建,并且在每一步我们对将要发生的事情做出具体假设,然后通过实验验证它们或进行调查直到我们发现某些问题。我们试图非常努力地防止的是同时引入了许多“未经验证的”复杂性,这必然会引入需要永远查找的错误/错误配置(如果有的话)。如果编写您的神经网络代码就像训练一样,您需要使用非常小的学习速率并猜测,然后在每次迭代后评估完整的测试集。

  • 与数据成为一体
    训练神经网络的第一步是根本不接触任何神经网络代码,而是从彻底检查数据开始。这一步至关重要。我喜欢花费大量时间(以小时为单位)扫描数千个示例,了解它们的分布并寻找模式。幸运的是,你的大脑非常擅长这一点。有一次我发现数据包含重复的例子。另一次我发现损坏的图像/标签。我寻找数据不平衡和偏见。我通常也会关注我自己的数据分类过程,这些过程暗示了我们最终会探索的各种架构。作为一个例子 - 是非常本地的功能还是我们需要全球背景?有多少变化,它采取什么形式?什么变化是假的,可以预处理?空间位置是否重要,或者我们是否想要将其平均化?细节有多重要,我们可以在多大程度上对图像进行缩减采样?标签有多吵?
    此外,由于神经网络实际上是数据集的压缩/编译版本,因此您将能够查看网络(错误)预测并了解它们的来源。如果你的网络给你的预测看起来与你在数据中看到的内容不一致,那么就会有所收获。
    一旦获得定性意义,编写一些简单的代码来搜索/过滤/排序也是一个好主意,无论你能想到什么(例如标签的类型,注释的大小,注释的数量等),并可视化它们的分布。和沿任何轴的异常值。异常值尤其几乎总能揭示数据质量或预处理中的一些错误。

  • 设置end-to-end的培训/评估框架+获得baselines
    既然我们了解了我们的数据,我们可以找到我们超级精彩的多尺度ASPP FPN ResNet并开始培训真棒模型吗?肯定没有。这是痛苦的道路。我们的下一步是建立一个完整的培训+评估框架,并通过一系列实验获得对其正确性的信任。在这个阶段,最好选择一些你不可能以某种方式搞砸的简单模型 - 例如线性分类器或非常小的ConvNet。我们希望对其进行训练,可视化损失,任何其他指标(例如准确度),模型预测,并在此过程中使用明确的假设执行一系列消融实验。
    这个阶段的提示和技巧:

    • 修复随机种子。始终使用固定的随机种子来保证当您运行代码两次时,您将获得相同的结果。这消除了变异因素,并将帮助您保持理智。
    • 简化。确保禁用任何不必要的幻想。例如,在这个阶段肯定会关闭任何数据扩充。数据扩充是一种我们可能在以后合并的正规化策略,但是现在它只是引入一些愚蠢错误的另一个机会。
    • 在您的评估中添加有效数字。在绘制测试损失时,对整个(大)测试集进行评估。不要只是在批量上绘制测试损失,然后依靠在Tensorboard中对它们进行平滑处理。我们追求正确,并且非常愿意放弃保持理智的时间。
    • 验证loss。验证您的损失是否以正确的损失值开始。例如,如果正确初始化最后一层,则应-log(1/n_classes)在初始化时测量softmax。可以为L2回归,Huber损失等导出相同的默认值。
    • 好的权重初始化。正确初始化图层权重。例如,如果您回归一些平均值为50的值,则将最终偏差初始化为50.如果您有一个比例为1:10的不平衡数据集:正数:负数,请设置对数的偏差,以便您的网络预测概率在初始化时为0.1。正确设置这些将加速收敛并消除“曲棍球棒”损失曲线,在最初的几次迭代中,您的网络基本上只是学习偏差。
    • 比较人类。监控人为可解释和可检查的损失以外的指标(例如准确性)。尽可能评估您自己(人类)的准确性并与之进行比较。或者,对测试数据进行两次注释,并且对于每个示例,将一个注释视为预测,将第二个注释视为基础事实。
    • 验证减少训练损失。在这个阶段,你发现你的数据集不合适,因为你正在使用基本模型。尝试稍微增加网络容量。您的训练损失是否应该下降?
    • 人为过拟合。只需几个例子(例如少至两个)训练网络就可以完成过拟合。为此,我们增加了模型的容量(例如添加层或过滤器)并验证我们可以达到可实现的最低损失(例如零)。我还想在同一个图中同时显示标签和预测,并确保一旦达到最小损失,它们就会完美对齐。如果他们不这样做,那么某个地方就会出现一个错误,我们无法继续下一个阶段。
    • 训练前可视化数据。在您model.fit(x)(或sess.run)之前,明确正确地显示您的数据的位置。也就是说 - 您希望可视化确切地了解网络中的内容,将原始张量的数据和标签解码为可视化。这是唯一的“事实来源”。我无法计算这个节省了我的次数,并揭示了数据预处理和扩充中的问题。
    • 可视化预测动态。我喜欢在培训过程中对固定测试批次上的模型预测进行可视化。这些预测如何发生的“动态”将为您提供令人难以置信的良好直觉,使其了解培训的进展情况。很多时候,如果网络以某种方式摆动太多,显示出不稳定性,就有可能感觉网络“难以”适合您的数据。学习率非常低或非常高,抖动量也很明显。
  • 过拟合
    在这个阶段,我们应该对数据集有一个很好的理解,我们有完整的培训+评估管道工作。对于任何给定的模型,我们可以(可重复地)计算我们信任的度量。我们还有一个独立于输入基线的表现,一些哑基线的表现(我们更好地击败了这些基线),我们粗略地了解人类的表现(我们希望达到这一点)。舞台现在设置为迭代一个好的模型。
    我喜欢寻找一个好模型的方法有两个阶段:首先得到一个足够大的模型,它可以过度拟合(即专注于训练损失),然后适当地调整它(放弃一些训练损失以改善验证损失)。我喜欢这两个阶段的原因是,如果我们根本无法使用任何模型达到低错误率,这可能再次表明一些问题,错误或错误配置。
    这个阶段的一些提示和技巧

  • 挑选模型。为了获得良好的培训损失,您需要为数据选择合适的架构。当谈到选择这个我的#1建议是:不要成为英雄。我见过很多人都渴望疯狂和创造性地将神经网络工具箱的乐高积木堆叠在各种对他们有意义的异域架构中。在项目的早期阶段强烈抵制这种诱惑。我总是建议人们简单地找到最相关的纸张并复制粘贴他们最简单的架构,以获得良好的性能。例如,如果您要分类图像不是英雄,只需复制粘贴ResNet-50为您的第一次运行。你可以稍后做一些更自定义的事情并击败它。

  • adam是合适的。在设定基线的早期阶段,我喜欢使用学习率为3e-4的 Adam 。根据我的经验,adam对超参数更加宽容,包括不良的学习率。对于ConvNets来说,一个经过良好调整的SGD几乎总会略微优于Adam,但最佳学习率区域更加狭窄且针对特定问题。(注意:如果您使用的是RNN和相关的序列模型,那么使用Adam更为常见。在项目的初始阶段,再次,不要成为英雄并遵循最相关的论文所做的事情。

  • 一次只复杂化一个。如果您有多个增强数据插入网络,我会建议您逐个插入它们,每次都确保您获得预期的性能提升。一开始不要把所有的复杂化手段扔到你的模型上。还有其他方法可以增加复杂性 - 例如,您可以尝试先插入较小的图像,然后再将它们放大,等等。

  • 不相信学习率衰减默认值。如果你重新使用来自其他领域的代码,那么学习速度衰减时一定要非常小心。您不仅希望针对不同的问题使用不同的衰减计划,而且 - 更糟糕的是 - 在典型的实施中,计划将基于当前的纪元数,其可以根据数据集的大小而广泛变化。例如,ImageNet将在30轮训练内衰减10点。如果你没有训练ImageNet那么你几乎肯定不会想要这个。如果你不小心,你的代码可能会过早地将你的学习率提高到零,不允许你的模型收敛。在我自己的工作中,我总是完全禁用学习率衰减(我使用常数LR)并在最后调整这一点。

规范
理想情况下,我们现在拥有一个大型模型,至少适合训练集。现在是时候通过放弃一些训练准确性来规范它并获得一些验证准确性。
一些提示和技巧:

  • 获得更多数据。首先,在任何实际环境中规范模型的最佳和首选方法是添加更多真实的训练数据。如果您可以收集更多数据,那么花费大量工程周期尝试从小型数据集中挤出汁液是一个非常常见的错误。据我所知,添加更多数据几乎是唯一无限期单调改善配置良好的神经网络性能的唯一保证方式。另一个是合奏(如果你能负担得起的话),但是在5个模型之后最高。
  • 数据增加。实际数据的下一个最好的事情是半假数据 - 尝试更积极的数据增强。
  • 创造性的增强。如果半假数据不能做到这一点,假数据也可能会有所作为。人们正在寻找扩展数据集的创新方法;例如,域随机化,模拟的使用,巧妙的混合,例如将(可能模拟的)数据插入场景,甚至是GAN。
  • 预训练。即使您有足够的数据,如果可以,也很少使用预训练网络。坚持有监督的学习。对于无人监督的预训练,不要过度兴奋。不像2008年的博客文章告诉你的那样,据我所知,没有任何一个版本在现代计算机视觉中报告了强有力的结果(虽然现在NLP似乎与BERT和朋友做得很好,很可能是因为更多故意性质的文本,以及更高的信噪比)。
  • 较小的输入维度。删除可能包含虚假信号的功能。如果您的数据集很小,任何添加的虚假输入都是过度拟合的另一个机会。同样,如果低级细节无关紧要,请尝试输入较小的图像。
  • 较小的模型。在许多情况下,您可以在网络上使用域知识约束来减小其大小。例如,过去使用ImageNet骨干网顶部的完全连接层是时髦的,但这些已经被简单的平均池替换,从而消除了过程中的大量参数。
  • 减少批量大小。由于批次规范内的归一化,较小的批量大小有点对应于较强的正则化。这是因为批次经验均值/标准是完整均值/标准的更近似版本,因此标度和偏移量“摆动”更多。
  • drop。添加dropout。对ConvNets使用dropout2d(空间丢失)。谨慎/谨慎地使用这个,因为丢失似乎不适合批量标准化。
  • 权重衰减。增加减重惩罚。
  • early stopping。根据您测量的验证损失停止培训,以便抓住您的模型在过度拟合之前。
  • 尝试更大的模型。我最后提到这一点,并且只是在早停之后,但我在过去曾经发现过几次大型模型当然会最终过度装配,但是它们的“early stopping止”性能往往比小型号的性能要好得多。

最后,为了让您更加确信您的网络是一个合理的分类器,我喜欢可视化网络的第一层权重,并确保您获得有意义的优质边缘。如果您的第一层滤镜看起来像噪音,那么可能会有一些关闭。类似地,网内的激活有时可以显示奇怪的伪像并暗示问题。

调整
您现在应该“在循环中”使用您的数据集探索宽泛的模型空间,以获得实现低验证损失的体系结构。
这一步的一些提示和技巧:

  • 随机网格搜索。为了同时调整多个超参数,使用网格搜索确保覆盖所有设置听起来很诱人,但请记住,最好使用随机搜索。直观地说,这是因为神经网络通常对某些参数比其他参数更敏感。在极限情况下,如果一个参数一个问题,但改变b没有效果,那么你宁愿品尝一个不是在几个固定点多次更throughly。
  • 超参数优化。有很多花哨的贝叶斯超参数优化工具箱,我的一些朋友也报告了它们的成功,但我个人的经验是,最先进的方法是探索一个漂亮而宽广的模型和超参数空间是使用实习生?。扎心。。。

最后一些建议
一旦找到最佳类型的体系结构和超参数,您仍然可以使用一些技巧将最后一些果汁挤出系统:

  • ensembles。模型集合是一种非常有保证的方法,可以在任何事情上获得2%的准确率。
  • 保持训练。我经常看到人们试图在验证损失似乎趋于平稳时停止模型训练。根据我的经验,网络会长时间不间断地进行培训。有一次我在冬假期间不小心离开了,当我1月份回来时,它是SOTA(“最先进的”)。

译自:http://karpathy.github.io/2019/04/25/recipe/

你可能感兴趣的:(tensorflow,keras)