Java教程

训练神经网络的秘诀

本文主要是介绍训练神经网络的秘诀,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

训练技巧

  • 关注数据
  • Baselines
  • 过拟合
  • 正则化

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

关注数据

训练神经网络之前,不要碰任何模型,而是应该尽力检查数据。经常需要数小时的查看数据,了解数据分布,找到数据模式,我们大脑非常适合干这个,有一次,我发现数据集中有一些重复的数据,另一次,我发现了损坏的图片/标签,寻找一些数据不平衡。我通常还会注意我自己对数据进行分类的过程,能够给我们最终的架构实现一些线索。例如,

  • 这些都是局部特征还是全局相关?
  • 有多少种变化以及这种变化采取了什么形式?
  • 哪些是伪变化,可以通过数据预处理剔除?
  • 细节有多重要,可以承受多大的下采样?
  • 标签有多脏?

神经网络是数据集的压缩和编译,你能从predict中理解输出是怎么来的,一旦你发现输出和数据不匹配,一定是哪里错了

找到这个感觉之后,你可以code 一些你想到的 搜索/过滤/排序(标签类型,图片尺寸,标注数量等)算法,并可视化分布数来,通过一些异常值,能查看到数据集的bugs

Baselines

这个阶段最好选择一些简单的模型,例如 - 线性分类器或非常小的ConvNet。训练并可视化损失和其他指标(例如,acc),模型预测,并在此途中执行一系列test

  • 固定随机种子。始终使用固定的随机种子,以保证当您运行代码两次时,您将获得相同的结果。这消除了变异因素,并有助于保持理智。
  • 简化。禁用任何不必要的操作。例如,关闭任何数据增强。数据增强是我们以后可能会采用的常规策略,但就目前而言,只会增加引入一些愚蠢错误的机会。
  • 重视eval。在绘制eval损失时,在整个(大)测试集上运行评估。不要只是在batch上绘制测试损失,然后在 Tensorboard 中平滑。
  • 验证loss@ init。验证loss从正确的loss值开始。例如。如果正确初始化最后一层,则应在初始化时在 softmax 上计算 -log(1/n_classes)。可以为 L2 回归、Huber 损失等计算出相同的默认值。(这儿没弄明白什么意思)
  • 初始化。正确初始化最终层权重。例如。如果您正在回归一些mean为 50 的数据,则将最终 bias初始化为 50。如果您有一个正负样本比为 1:10 的不平衡数据集,请在logits层 上设置bias,以便您的网络 在初始化时以0.1的概率预测。正确设置这些将加速收敛并消除“曲棍球”loss曲线(loss先低后高),在最初的几次迭代中,网络基本上只是学习bias。logits的理解参考这儿
  • baseline。监控除损失之外的我们可解释和可检查的指标(例如accuracy)。尽可能评估自己的accuracy并与之进行比较。或者,对测试数据的预测和真实相比较。
  • 与输入无关的 baseline。训练与输入无关的 baseline(例如,最简单的方法是将所有输入设置为0)。应该比有实际输入数据(不为0)的性能更差。确定模型是否从输入中提取到信息。
  • batch上过拟合。只包含几个样本(至少2个)的单个batch上过拟合。我们可以增加模型的容量(例如添加layersfiltersfilter有两种理解:在有的文档中,一个filter等同于一个卷积核:只是指定了卷积核的长宽深; 而有的情况(例如tensorflow等框架中,filter参数通常指定了卷积核的长、宽、深、个数四个参数),filter包含了卷积核形状和卷积核数量的概念:即filter既指定了卷积核的长宽深,也指定了卷积核的数量。并验证我们可以达到最低的loss(例如0)。把标签和预测可视化在同一个图中,并确保一旦我们达到最小损失,它们就会完美对齐。如果不是这样,那就有bug,我们无法继续进行下一阶段。
  • 验证减少的训练loss。在这个阶段,你可能会欠拟合你的数据集,因为你正在使用一个玩具模型。尝试稍微增加其容量。您的训练loss是否按预期减少了?
  • 在网络之前可视化。将数据可视化要放在正确的位置, y_hat = model(x)之前(或 tf 中的 sess.run)之前。也就是说 - 要准确地可视化什么数据送入了网络,将数据和标签的原始张量解码为可视化。这是唯一的“真相来源”。我无法统计这有多少次拯救了我并揭示了数据预处理和增强方面的问题。
  • 动态可视化prediction 。我喜欢在训练过程中对固定测试批次的模型预测进行可视化。这些prediction 如何“动态”变化将为告诉我们关于训练如何进行的非常好。很多时候,如果网络以某种方式抖动,不稳定,会感觉到网络“努力”取拟合你的数据。非常低或非常高的学习率很容器引起抖动。
  • 使用反向传播来绘制依赖关系。深度学习代码通常包含复杂的、矢量化的和广播的操作。我遇到过几次的一个相对常见的错误是我们自己犯的错(例如,使用viewview而不是transpose/permute)并且不经意间在batch维度上混合了信息。令人沮丧的是,网络通常仍能正常训练,因为它会忽略来自其他样本的数据。debug 这个的一种方法是将损失设置为微不足道的东西,例如样本i 的所有输出的总和,运行backward一直到输入 ,并确保您得到一个非零梯度在第 i 个输入上。相同的策略可用于例如确保您在时间 t 的Autoregressive model仅取决于 1…t-1。更一般地说,梯度决定了网络中什么的信息,这对调试很有用。
  • 一个通用的编码技巧,但我经常看到人们在不加思考的搬代码会产生bug。我喜欢为我现在正在做的事情写一个完整的循环的代码,然后调试。

过拟合

这个阶段需要更好的理解数据集,并完全训练和评估整个代码,对于任何一个模型,我们可以计算出metric,也掌握了与输入无关的baseline 的性能表现,尽管是糟糕的baseline,我们对性能有了个直观的感觉,这个阶段,我们回迭代让模型更好

找到训练出好模型的方法有两步,第一,先获得一个能过拟合的足够大的模型(关注训练损失),然后适当的正则化(关注验证损失)。我喜欢这两步的原因是如果不能达到低的错误率,那就说明有bugs

  • 挑选模型。
    为了达到良好的训练损失,需要为数据选择适当的架构。在选择这个时,我的#1建议是:不要成为英雄。我已经看到了很多人渴望疯狂和创造性的像在玩乐高一样堆叠积神经网络工具。在项目的早期阶段强烈抵制这种诱惑。我总是建议人们只发现多的paper,并复制他们最简单的架构,实现了良好的性能。例如。如果正在图像分类,请不要成为英雄,第一次运行只需复制粘贴reset-50
  • adam 是安全的。
    在设baseline线的早期阶段,我喜欢使用adam3e-4lr。在我的体验中,adam是非常宽容的超参数,即使是糟糕的lr。对于Convnets,一个调整好的SGD几乎总是略高于adam,但最佳lr区域更狭窄,具体问题。 (注意:如果使用的RNN和相关序列模型使用adam更常见。在项目的初始阶段,再次,不要成为英雄,并遵循相关的论文。)
  • 一次只改变一个。
    如果您有多个signals 插入您的分类器,我会建议您逐一插入它们,每次确保获得您预期的性能提升。还有其他建立复杂性的方法 - 例如可以先尝试插入较小的图像,并使其更大,以后更大。
  • 不要信使用默认的 learning rate decay
    如果您从其他域中重新启动代码,请始终非常小心,有 learning rate decay。不同的模型使用不同的decay schedules,在默认的epoch数下使用默认的schedule会更糟,schedule应根据数据集的大小变化。例如。 Imagenet将在epoch 30上设置decay10,如果不是训练Imagenet,那么你肯定不需要decay。如果不小心,代码可以偷偷的更早的将lr调整变到零,而导致模型不收敛。在我自己的工作中,我总是禁用 learning rate decay(我使用常数LR)并在最后一直调整这一切。

正则化

拟合了训练数据之后,我们选在需要在验证集上提升精度,同时会降低训练集的精度,一些tips

  • 获取更多数据。首先,在任何实际中规范模型的最佳和优选方式是添加更多训练数据。当你可以收集更多数据时花费很多时间压榨小型数据集是一个非常常见的错误。据我所知,添加更多数据是几乎无限期地单调整理神经网络性能的唯一方式。
  • 数据增强。最好的真实数据是一份半假的数据 - 尝试更具先进性的数据增强。
  • 创造性的增强。如, domain randomization,simulation,,hybrids,如在场景中插入数据,甚至是GAN。
  • 预训练。即使你有足够多的数据,尽可能使用预训练模型。
  • 坚持监督学习。不要对非监督学习过度兴奋,据我所知,在CV领域没有哪个版本的非监督学习模型能够表现出非常好的结果(虽然NLP似乎在BERT的带动下不错)。
  • 较小的输入维度。删除可能包含脏数据。如果您的数据集很小,则任何添加的虚假输入都会过度带入脏数据。同样,如果低级细节并不重要,尝试输入较小的图像。
  • 较小的模型尺寸。在许多情况下,您可以在网络上使用域知识约束来减少其大小。例如,曾经是在backbone顶部使用全连接的层在ImageNet上,但这些已经用简单的平均池化代替,消除了该过程中的一大堆参数。
  • drop。添加dropout。使用Dropout2d(空间丢失)
  • weight decay。增加weight decay的惩罚系数。
  • early stopping。根据您的test,val损失停止训练,以保存模型,防止过拟合。
  • 尝试更大的模型。更大的模型的性能通常比较小型模型更好。
这篇关于训练神经网络的秘诀的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!