前言

深度学习调参手册

这不是一个官方支持的谷歌产品。

Varun Godbole, George E. Dahl, Justin Gilmer, Christopher J. Shallue, Zachary Nado

† Google Research, Brain Team

‡ Harvard University

Table of Contents

这份文件为谁准备?

这份文件是为深度学习模型性能极为感兴趣的工程师和研究人员(包括个人和团队)准备的。我们假设其有一定机器学习和深度学习概念及基本知识。

我们的重点是超参数调整过程。同时也触及了深度学习训练的其他方面,如管道实现和优化,但对这些方面的讲述并不完整。

我们假设机器学习问题是一个监督学习问题或看起来很像一个问题的东西(如自监督)。也就是说,本文中的一些建议可能适用于其他类型的问题。

为什么需要调参手册?

目前,要想让深度神经网络在实践中运行良好,需要付出惊人的努力和猜想。更糟糕的是,人们很少记录获得良好结果的设置。论文掩盖了导致其最终结果的过程,以呈现一个更干净的故事,而从事商业问题的机器学习工程师很少有时间概括他们的调参过程。教科书倾向于回避实践指导,优先考虑基本原则,即使其作者有必要应用工作经验来提供有效的建议。在准备创建这份文件时,我们找不到任何全面的说明来实际解释如何用深度学习获得好的结果。相反,我们在博客文章和社交媒体上发现了一些建议的片段,从研究论文的附录中窥见了一些技巧,偶尔有关于某个特定项目或管道的案例研究,还有很多困惑。 深度学习专家和不太熟练的从业者使用表面上类似的方法,但取得的结果间存在着巨大的差距。同时,这些专家也欣然承认他们所做的一些事情可能没有充分的理由。随着深度学习的成熟并对世界产生更大影响,社区需要更多资源,涵盖有用的设置,包括所有的实际细节,这对获得良好的结果至关重要。

我们是由5名研究人员和工程师组成的团队,他们已经在深度学习领域工作了很多年,其中一些人早在2006年就开始工作了。我们已经将深度学习应用于语音识别、天文学等各种问题,并在这一过程中学到了很多。这份文件是从我们自己训练神经网络、教导新的机器学习工程师以及为我们的同事提供深度学习实践建议的经验中发展出来的。 尽管看到深度学习从少数学术实验室实践的机器学习方法变成了为数十亿人使用的产品提供动力已经令人欣慰,但作为一门工程学科,深度学习仍然处于起步阶段,我们希望这份文件能鼓励其他人帮助该领域实现实验协议系统化。

这份文件是我们试图清理我们自己的深度学习方法时产生的,因此它代表了作者在写作时的观点,而不是任何形式的客观真理。我们自己在超参数调整方面的挣扎使其成为我们指导的一个重点,但我们也涵盖了在工作中遇到的其他重要问题(或看到的错误)。我们的意图是让这项工作成为一份活的文件,随着我们信仰的改变而不断成长和发展。例如,关于调试和减轻训练失败的材料,我们两年前是不能写的,因为它是基于最近的结果和正在进行的调查。不可避免地,我们的一些建议将需要更新,以考虑到新的结果和改进的工作流程。我们不知道最佳的深度学习配方,但在社区开始写下和辩论不同的过程之前,我们无法找到它。 为此,我们鼓励发现我们的建议有问题的读者提出代替意见,并提供令人信服的证据,以便我们能够更新手册。我们也希望看大可能有不同建议的指南和手册,以便我们能够作为一个社区努力实现最佳过程。 最后,任何标有🤖 的部分都是我们想做更多研究的地方。只有在尝试写完这本手册后,才完全明白在深度学习从业者的工作流程中可以找到多少有趣的和被忽视的研究问题

新项目指南

我们在调参过程中做出的许多决定可以在项目开始时做一次,只有在情况发生变化时才会偶尔重新审核。

我们的指导意见做出以下假设:

选择模型架构

概述: 当开始一个新项目时,尽量重用一个已经工作的模型。

选择优化器

概述: 从当前问题中最流行的优化器开始

选择batch size

概述: batch size控制着训练速度,不应该被用来直接调整验证集的性能。通常情况下,理想的batch size是可用硬件所支持的最大batch size

确定可行的batch size并估计训练工作量

[Click to expand]

选择batch size尽可能减少训练时间

[Click to expand]

训练时间 = (每steps时间) x (总steps)

选择batch size以尽量减少资源消耗

[Click to expand]

资源消耗 = (setp资源消耗) x (总steps)

改变batch size需要重新调整大多数超参数

[Click to expand]

batch norm如何与batch size相互作用

[Click to expand]

选择初始配置

提高模型性能的科学方法

就本文而言,机器学习开发的最终目标是最大化所部署模型的效用。即使开发过程的许多方面在不同的应用中有所不同(如时间长度、可用的计算资源、模型的类型),我们通常可以在任何问题上使用相同的基本步骤和原则。

我们下面的指导意见做出了以下假设:

渐进式调整策略

概述: 从简单的配置开始,逐步进行改进,同时建立对问题的洞察力。确保任何改进都是基于强有力的证据,以避免增加不必要的复杂性。

在高层次上,我们的增量调整策略包括重复以下四个步骤:

  1. 为下一轮的实验确定一个适当范围的目标。
  2. 设计并运行一套实验,使之在这一目标上取得进展。
  3. 从结果中学习
  4. 考虑是否推出新的最佳配置。

本节的其余部分将更详细地探讨这一策略。

探索与开发

概述: 大多数时候,我们的首要目标是深入了解问题。

为下一轮实验选择目标

概述: 每一轮的实验都应该有一个明确的目标,而且范围要足够窄,以便实验能够真正朝着目标取得进展。

设计下一轮实验

概述: 确定指标超参数、需要调整超参数和固定超参数,以实现实验目标。建立一个研究序列来比较指标超参数的不同值,同时对调整超参数进行优化。选择调整超参数的搜索空间,以平衡资源成本和科学价值。

识别指标、调整和固定超参数

[Click to expand]

创建一套研究报告

[Click to expand]

在内容丰富的实验和负担得起的实验之间取得平衡

[Click to expand]

从实验结果中提取灵感

概述: 除了努力实现每组实验的原始科学目标外,还要通过附加问题的检查表,如果发现问题,要修改实验并重新运行。

识别不良的搜索空间边界

[Click to expand]

图 1:不良搜索空间边界和良好搜索空间边界例子

在搜索空间中未对足够的点进行采样

[Click to expand]

检查训练曲线

[Click to expand]

概述: 检查训练曲线是识别常见故障的一个简单方法,可以帮助我们确定下一步要采取行动的优先次序。

用隔离图检测参数变化是否有用

[Click to expand]

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 2: ImageNet上训练的ResNet-50最佳权重衰减值隔离图

自动生成常用检查图谱

[Click to expand]

确定是否采用训练管道变化或超参数配置

概述: 当决定是否对我们的模型或训练程序进行改变或采用新的超参数配置前进时,我们需要意识到结果中不同的变化来源。

探索结束后

概述: 一旦我们完成了对搜索空间的探索,并决定了哪些超参数应该被调整,贝叶斯优化工具就是一个引人注目的选择。

确定训练steps

当训练不限时时应该训练多长时间

使用学习率扫描为max_train_steps挑选初始值

[Click to expand]

当训练由计算机控制时应该训练多长时间

Round 1

[Click to expand]

Round 2

[Click to expand]

对训练管道的补充指导

优化输入管道

概述: 输入受限于管道的原因和干预措施在很大程度上取决于任务;使用剖析器并注意常见的问题。

评估模型性能

概述: 以比训练更大的批次规模运行评估。以定期的步骤间隔,而不是定期的时间间隔来运行评估。

评估设置

[Click to expand]

设置定期评估

[Click to expand]

选择定期评估的样本

[Click to expand]

保存检查点并回视最佳检查点

概述: 运行训练的固定步数,并回顾性地从运行中选择最佳检查点。

设置实验跟踪

概述: 在跟踪不同的实验时,一定要注意一些要领,如研究中检查点的最佳表现,以及对研究的简短描述。

Batch normalization操作细节

概述: 现在batch norm往往可以用LayerNorm代替,但在不能代替的情况下,在改变批量大小或主机数量时有一些棘手的细节。

多主机管道的注意事项

概述: 对于记录、评估、RNG、检查点和数据分片来说,多主机训练会使其非常容易引入bug!

常见问题

最佳的学习率衰减策略是什么?

[Click to expand]

我应该使用哪种学习率衰减策略作为默认值?

[Click to expand]

为什么有些论文采用复杂的学习率衰减策略?

[Click to expand]

应该如何调整Adam的超参数?

[Click to expand]

为什么在调整的探索阶段使用准随机搜索而不是更复杂的黑箱优化算法?

[Click to expand]

我在哪里可以找到准随机搜索的实现?

[Click to expand]

使用准随机搜索需要多少次试验才能获得好的结果?

[Click to expand]

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 3: 在ImageNet上用100次试验对ResNet-50进行了调参。通过bootstrapping,模拟了不同数量的调参预算。上面绘制了每个试验预算的最佳性能箱形图。

如何对优化失败进行调试和缓解?

[Click to expand]

***概述:*** *如果模型遇到了优化困难,在尝试其他事情之前,解决这些困难是很重要的。诊断和纠正训练失败是一个活跃的研究领域。*

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 4: 在WideResnet中改变单个剩余块(2x2->1x1)的步长会导致训练不稳定。这不会降低低学习率下的性能,但高学习率下由于不稳定而不再训练良好。应用1000步的学习率预热解决了这一特殊的不稳定情况,允许在最大学习率为0.1时进行稳定训练。

识别不稳定的工作负载

注意:有些模型显示出非常早期的不稳定性,然后是恢复,趋于缓慢但稳定的训练。普通的评估策略可能会因为评估不够频繁而错过这些问题!

为了检查这一点,我们可以用lr = 2 * current best来训练一个大约500步的简略运行,但要评估每一步。
Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 5: 如果怀疑模型受到早期训练不稳定的影响,在训练开始时进行频繁的评估,是很有用的。

常见不稳定模式的潜在修复方法

Learning rate warmup

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 6: warmup期间不稳定的一个例子(注意横轴的对数比例)。在这种情况下,需要40000steps热身才能成功训练。

什么时候采用learning rate warmup

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 7a: 一个表现出训练不稳定性的模型超参数轴图的例子。最佳的学习率是在可行的边缘。一个 "不可行 "的试验被定义为产生NaN或高损失值

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 7b: 使用不稳定学习率模型的训练损失

如何应用learning rate warmup

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 8: warmup对解决训练不稳定现象有很好的效果

梯度裁剪

Deep Learning Tuning Playbook(深度学习调参手册中译版)

图 9: 梯度剪裁纠正早期训练不稳定性的说明。

为什么你把学习率和其他优化参数称为超参数?它们不是任何先验分布的参数。

[Click to expand]

为什么不应该调整batch size来直接提高验证集的性能?

[Click to expand]

所有流行的优化算法更新规则是什么?

[Click to expand]

Stochastic gradient descent (SGD)


θ
t
+
1
=
θ
t

η
t

l
(
θ
t
)
\theta_{t+1} = \theta_{t} - \eta_t \nabla \mathcal{l}(\theta_t)
θt+1=θtηtl(θt)

Momentum


v
=
v_0 = 0
v0=0


v
t
+
1
=
γ
v
t
+

l
(
θ
t
)
v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)
vt+1=γvt+l(θt)


θ
t
+
1
=
θ
t

η
t
v
t
+
1
\theta_{t+1} = \theta_{t} - \eta_t v_{t+1}
θt+1=θtηtvt+1

Nesterov


v
=
v_0 = 0
v0=0


v
t
+
1
=
γ
v
t
+

l
(
θ
t
)
v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)
vt+1=γvt+l(θt)


θ
t
+
1
=
θ
t

η
t
(
γ
v
t
+
1
+

l
(
θ
t
)
\theta_{t+1} = \theta_{t} - \eta_t( \gamma v_{t+1} + \nabla \mathcal{l}(\theta_{t})
θt+1=θtηt(γvt+1+l(θt)

RMSProp


v
=
1
,
m
=
v_0 = 1 \text{,} m_0 = 0
v0=1,m0=0


v
t
+
1
=
ρ
v
t
+
(
1

ρ
)

l
(
θ
t
)
2
v_{t+1} = \rho v_{t} + (1 - \rho) \nabla \mathcal{l}(\theta_t)^2
vt+1=ρvt+(1ρ)l(θt)2


m
t
+
1
=
γ
m
t
+
η
t
v
t
+
1
+
ϵ

l
(
θ
t
)
m_{t+1} = \gamma m_{t} + \frac{\eta_t}{\sqrt{v_{t+1} + \epsilon}}\nabla \mathcal{l}(\theta_t)
mt+1=γmt+vt+1+ϵηtl(θt)


θ
t
+
1
=
θ
t

m
t
+
1
\theta_{t+1} = \theta_{t} - m_{t+1}
θt+1=θtmt+1

ADAM


m
=
,
v
=
m_0 = 0 \text{,} v_0 = 0
m0=0,v0=0


m
t
+
1
=
β
1
m
t
+
(
1

β
1
)

l
(
θ
t
)
m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)
mt+1=β1mt+(1β1)l(θt)


v
t
+
1
=
β
2
v
t
+
(
1

β
2
)

l
(
θ
t
)
2
v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l}(\theta_t)^2
vt+1=β2vt+(1β2)l(θt)2


b
t
+
1
=
1

β
2
t
+
1
1

β
1
t
+
1
b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}
bt+1=1β1t+11β2t+1


θ
t
+
1
=
θ
t

α
t
m
t
+
1
v
t
+
1
+
ϵ
b
t
+
1
\theta_{t+1} = \theta_{t} - \alpha_t \frac{m_{t+1}}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}
θt+1=θtαtvt+1+ϵmt+1bt+1

NADAM


m
=
,
v
=
m_0 = 0 \text{,} v_0 = 0
m0=0,v0=0


m
t
+
1
=
β
1
m
t
+
(
1

β
1
)

l
(
θ
t
)
m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)
mt+1=β1mt+(1β1)l(θt)


v
t
+
1
=
β
2
v
t
+
(
1

β
2
)

l
(
θ
t
)
2
v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l} (\theta_t)^2
vt+1=β2vt+(1β2)l(θt)2


b
t
+
1
=
1

β
2
t
+
1
1

β
1
t
+
1
b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}
bt+1=1β1t+11β2t+1


θ
t
+
1
=
θ
t

α
t
β
1
m
t
+
1
+
(
1

β
1
)

l
(
θ
t
)
v
t
+
1
+
ϵ
b
t
+
1
\theta_{t+1} = \theta_{t} - \alpha_t \frac{\beta_1 m_{t+1} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}
θt+1=θtαtvt+1+ϵβ1mt+1+(1β1)l(θt)bt+1

发表回复