马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
据称,开始训练神经网络非常简朴。许多库和框架都以展示 30 行神奇的代码片段来办理题目而自大,给人一种这些东西是即插即用的(错误)印象。常见的环境如下:
- >>> your_data = # plug your awesome dataset here
- >>> model = SuperCrossValidator(SuperDuper.fit, your_data, ResNet50, SGDOptimizer)
复制代码 #conquer world here
这些库和示例激活了我们大脑中认识尺度软件的部分 - 通常可以获得干净的 API 和抽象。哀求库演示:
- >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
- >>> r.status_code
- 200
复制代码 不幸的是,神经网络并非如此。当您稍微偏离训练 ImageNet 分类器时,它们就不是“现成的”技术。
当您粉碎或错误设置代码时,通常会遇到某种非常。您插入了一个整数,而某个函数需要字符串。该函数只需要 3 个参数。此导入失败。该键不存在。两个列表中的元素数目不相等。此外,通常可以为某个功能创建单元测试。
这只是训练神经网络的开始。从语法上来说,统统都大概是正确的,但整个过程并没有得到正确的安排,而且很难分辨。“大概的错误面”很大,符合逻辑(而不是语法),而且很难进行单元测试。比方,也许你在数据增强期间左右翻转图像时忘记翻转标签。你的网络仍然可以(令人震惊地)很好地工作,因为你的网络可以内部学习检测翻转的图像,然后左右翻转它的猜测。大概,也许你的自回归模子由于一次错误而意外地将它试图猜测的东西作为输入。大概你试图削减你的梯度,但却削减了丧失,导致训练期间非常示例被忽略。大概你从预训练检查点初始化了你的权重,但没有使用原始均匀值。大概你只是搞砸了正则化强度、学习率、衰减率、模子大小等的设置。因此,只有在幸运的环境下,设置错误的神经网络才会抛出非常;大多数时间它会进行训练,但默默地工作得更糟。
因此,“快速而激烈”的神经网络训练方法行不通,只会导致痛苦。现在,痛苦是让神经网络良好运作的一个非常天然的部分,但可以通过彻底、防御、偏执和痴迷于可视化险些所有大概的事情来减轻痛苦。与深度学习成功最密切相关的品质是耐心和对细节的关注。
应对方案
从简朴到复杂,对每一步中将会发生什么做出具体的假设,然后通过实行验证它们或进行调查,直到发现一些题目。要尽力避免的是一次性引入大量“未履历证”的复杂性,这一定会引入错误/错误设置,而这些错误/设置将需要很长时间才能找到(如果永远找不到的话)。如果编写神经网络代码就像训练代码一样,你会希望使用非常小的学习率,并在每次迭代后猜测然后评估完整的测试集。
1. 与数据融为一体
训练神经网络的第一步是完全不打仗任何神经网络代码,而是从彻底检查数据开始。这一步至关重要。扫描数据,了解它们的分布并探求模式。是否包罗重复的示例,是否有破坏的图像/标签。探求数据不平衡和偏差。
一旦你有了定性分析,编写一些简朴的代码来搜索/过滤/排序,无论你想到什么(比方标签类型、注释大小、注释数目等),并可视化它们的分布和沿任何轴的非常值。尤其是非常值险些总是能展现数据质量或预处理中的一些错误。
2. 创建端到端的训练/评估框架
现在了解了数据,下一步是创建一个完整的训练 + 评估框架,并通过一系列实行获得对其正确性的信任。在这个阶段,最好选择一些简朴的模子,训练它,可视化丧失/任何其他指标(比方准确性)、模子猜测,并在此过程中使用明确的假设执行一系列实行。
此阶段的提示和技巧:
- 固定随机种子。始终使用固定随机种子来包管当您运行代码两次时,您将获得相同的结果。这消除了变革因素并有助于让您保持理智。
- 简化。确保禁用任何不须要的花哨功能。比方,在此阶段一定要关闭任何数据增强。数据增强是一种正则化计谋,我们大概会在以后纳入,但现在它只是引入一些愚蠢错误的另一个时机。
- 在您的 eval 中添加有效数字。绘制测试丧失时,对整个(大型)测试集进行评估。不要只绘制批次上的测试丧失,然后依靠 Tensorboard 对其进行平滑处理。我们追求正确性,非常愿意放弃时间来保持理智。
- 验证丧失 @ init。验证您的丧失是否从正确的丧失值开始。比方,如果您正确初始化最后一层,则应-log(1/n_classes)在初始化时测量 softmax。可以为 L2 回归、Huber 丧失等得出相同的默认值。
- 初始化好。正确初始化终极层的权重。比方,如果您要回归一些均匀值为 50 的值,则将终极偏差初始化为 50。如果您有一个不平衡的数据集,其正数:负数的比例为 1:10,则在 logits 上设置偏差,以便您的网络在初始化时猜测概率为 0.1。正确设置这些将加快收敛速度并消除“曲棍球棒”丧失曲线,在前几次迭代中,您的网络根本上只是在学习偏差。
- 人类基线。监控除丧失之外的可人类解释和检查的指标(比方准确性)。尽大概评估您本身的(人类)准确性并与之进行比较。大概,对测试数据进行两次注释,对于每个示例,将一个注释视为猜测,将第二个注释视为根本究竟。
- 独立于输入的基线。训练独立于输入的基线(比方,最简朴的方法是将所有输入设置为零)。这应该比您现实插入数据而不将其清零时的表现更差。是吗?即您的模子是否学会从输入中提取任何信息?
- 过拟合一个批次。过拟合一个只有几个示例的批次(比方少至两个)。为此,我们增加了模子的容量(比方添加层或过滤器)并验证我们是否可以达到最低的可实现丧失(比方零)。我还喜欢在同一个图中可视化标签和猜测,并确保一旦达到最小丧失,它们终极会完善对齐。如果它们不对齐,则阐明某处有错误,我们无法继承下一阶段。
- 验证训练丧失是否淘汰。在此阶段,由于您正在使用玩具模子,因此您的数据集大概会出现拟合不足的环境。实行稍微增加其容量。您的训练丧失是否按预期下降?
- 在网络之进步行可视化。可视化数据的正确位置绝对就在网络之前y_hat = model(x)(或sess.run在 tf 中)。也就是说,您希望准确地可视化进入网络的内容,将原始数据张量和标签解码为可视化内容。这是唯一的“原形来源”。我数不清有多少次这拯救了我,并展现了数据预处理和增强中的题目。
- 可视化猜测动态。我喜欢在训练过程中可视化固定测试批次上的模子猜测。这些猜测如何移动的“动态”将为您提供有关训练进展的非常好的直觉。很多时间,如果网络以某种方式摆动过多,就会感觉到网络“难以”顺应您的数据,从而袒露出不稳定性。非常低或非常高的学习率也很容易在抖动量中被注意到。
- 使用反向传播来绘制依赖关系图。您的深度学习代码通常包罗复杂、矢量化和广播操作。我遇到过几次的一个相对常见的错误是人们会弄错这一点(比方他们使用view而不是transpose/permute某处)并偶然中混合了批次维度上的信息。令人沮丧的究竟是,您的网络通常仍会训练正常,因为它会学会忽略来自其他示例的数据。调试此题目(和其他相关题目)的一种方法是将丧失设置为一些微不足道的东西,比方示例i的所有输出的总和,不停向后传递到输入,并确保仅在第i 个输入上获得非零梯度。相同的计谋可用于比方确保您的自回归模子在时间 t 仅依赖于 1…t-1。更一样平常地说,梯度为您提供了有关网络中什么依赖于什么的信息,这对于调试很有效。
- 概括特殊环境。这更像是一个通用的编码技巧,但我常常看到人们在从头开始编写相对通用的功能时,会犯错误。我喜欢为我现在正在做的事情编写一个非常具体的函数,让它工作,然后稍后将其概括,确保得到相同的结果。这通常实用于矢量化代码,我险些总是先写出完全循环的版本,然后一次一个循环地将其转换为矢量化代码。
3. 过分拟合
现在,阶段已经准备好迭代一个好的模子。可以采用两个阶段来探求好的模子:起首获得一个充足大的模子,使其可以大概过拟合(即专注于训练丧失),然后对其进行适当的正则化(放弃一些训练丧失以改善验证丧失)。
此阶段的一些提示和技巧:
- 选择模子。为了达到良好的训练丧失,需要为数据选择合适的架构。将神经网络工具箱的乐高积木堆叠成各种的奇特架构,在项目标早期阶段要坚决抵抗这种勾引,而是应该找到最相关的,最简朴的、能实现良好性能的架构。比方,如果你正在对图像进行分类,只需在第一次运行时复制粘贴 ResNet-50。然后可以做一些更自定义的事情并击败它。
- adam 是安全的。在设定基线的早期阶段,发起使用学习率为3e-4的 Adam 。Adam 对超参数的容忍度更高,包罗糟糕的学习率。对于 ConvNets,颠末良好调解的 SGD 险些总是会略胜 Adam,但最佳学习率区域要窄得多,而且针对具体题目。(注意:如果您使用的是 RNN 和相关序列模子,则更常使用 Adam。在项目标初始阶段,再次强调,不要妄自尊大,而要遵照最相关的论文。)
- 每次只复杂化一个。如果有多个信号要插入分类器,发起逐个插入它们,并确保每次都能获得预期的性能提升。不要一开始就将整个模子都扔到水槽里。另有其他方法可以增加复杂性 - 比方,您可以实行先插入较小的图像,然后再将它们放大,等等。
- 不要相信学习率衰减默认值。如果你正在重新使用来自其他领域的代码,请始终非常小心学习率衰减。 在典型的实现中,筹划将基于当前的时期数,这大概会根据数据集的大小而有很大差异。比方,ImageNet 在第 30 个时期会衰减 10。如果不小心,你的代码大概会偷偷地将你的学习率过早地降至零,从而不允许你的模子收敛。
4. 正则化
抱负环境下,我们现在拥有了一个至少适合训练集的大型模子。现在是时间对其进行正则化并通过放弃一些训练精度来获得一些验证精度。一些提示和技巧:
- 获取更多数据。起首,在任何现实环境中,迄今为止最好的和首选的正则化模子的方法是添加更多真实训练数据。花费大量工程周期试图从小数据会合榨代替价是一个非常常见的错误,添加更多数据险些是无限期地单调进步设置良好的神经网络性能的唯一包管方法。另一种方法是集成(如果你能负担得起的话),但在约莫 5 个模子之后就达到顶峰了。
- 数据增强。除了真实数据之外,最好的选择就是半假数据 - 实行更积极的数据增强。
- 创造性增强。如果半假数据不起作用,假数据也大概起作用。人们正在探求扩展数据集的创造性方法;比方,域随机化、使用模拟、奇妙的混合(比方将(潜在模拟的)数据插入场景)乃至 GAN。
- 预训练。如果可以的话,使用预训练网络险些不会有什么坏处,即使你- 有充足的数据。
- 坚持监视学习。不要对无监视预训练过分兴奋。
- 较小的输入维度。删除大概包罗杂散信号的特征。如果数据集较小,任何添加的杂散输入都只是过分拟合的另一个时机。同样,如果低级细节并不重要,请实行输入较小的图像。
- 更小的模子尺寸。在许多环境下,您可以使用网络领域的知识约束来减小其尺寸。比方,已往在 ImageNet 的主干顶部使用全连接层是一种流行做法,但这些层后来被简朴的均匀池化所代替,从而消除了大量的参数。
- 减小批量大小。由于批量规范中的规范化,较小的批量大小在某种程度上对应于更强的正则化。这是因为批量履历均匀值/尺度差是完整均匀值/尺度差的更近似版本,因此比例和偏移会使您的批量“摆动”更多。
- drop。添加 dropout。对 ConvNets 使用 dropout2d(空间 dropout)。请谨慎/小心地使用它,因为 dropout好像与批量尺度化不太兼容。
- 权重衰减。增加权重衰减处罚。
- 提前停止。根据测量到的验证丧失停止训练,以便在模子即将过分拟合时抓住它。
- 实行更大的模子。我最后提到这一点,也是在提前停止之后,但我已往曾发现过几次,较大的模子终极固然会过分拟合,但它们的“提前停止”性能通常比较小的模子好得多。
最后,为了进一步确信得到的网络是一个公道的分类器,可以将网络的第一层权重可视化,并确保得到公道的边沿。如果的第一层过滤器看起来像噪音,那么大概有些不对劲。同样,网络内的激活有时会表现奇怪的伪影并暗示存在题目。
5. 调参
现在,应该已经“掌握”了数据集,并探索了广泛的模子空间,以找到可实现低验证丧失的架构。此步骤的一些提示和技巧:
- 随机搜索优于网格搜索。对于同时调解多个超参数,使用网格搜索来确保覆盖所有设置听起来很诱人,但请记着,最好使用随机搜索。直观地说,这是因为神经网络通常对某些参数比其他参数更敏感。在极限环境下,如果参数a很重要,但改变b没有效果,那么您宁愿更彻底地对a进行采样,而不是在几个固定点多次采样。
- 超参数优化。目前有大量的贝叶斯超参数优化工具箱,我的一些朋友也报告说他们使用它们取得了成功,但我的个人履历是,探索良好而广泛的模子和超参数空间的最先进的方法是使用实习生
|