一本系统地教你将深度学习模型的性能最大化的战术手册。
See the code这不是官方认证的 Google 产品。
Varun Godbole † , George E. Dahl † , Justin Gilmer † , Christopher J. Shallue ‡ , Zachary Nado †
† 谷歌研究,谷歌大脑团队
‡ 哈佛大学
本文档适用于对最大化深度学习的性能感兴趣的工程师和研究人员(包括个人和团队)。我们假定您具备机器学习和深度学习概念的基本知识。
我们的重点是超参数调优的过程,但我们还涉及深度学习学习的其他方面。例如工作流实施和优化,但这些方面并不详尽
我们假设机器学习问题是监督学习或类似的东西(例如自监督学习)。但是,本文档中描述的技术也可能适用于其他类型的问题。
目前,要使深度神经网络在实践中正常运行,需要付出大量的努力和猜测。更糟糕的是,目前很少有人记录下那些深度学习中获得良好结果的实际方法。一方面,通常,论文忽略了导致最终结果的过程,以呈现更清晰的原理。另一方面,处理商业问题的机器学习工程师很少有时间回顾并概括他们的调参过程。教科书也往往回避实用指南,而偏重于基本原理,即使它们的作者具有在应用工作中提供有用建议的经验。在准备创建此文档时,我们找不到任何系统性的资料来解释如何使用深度学习获得良好的结果. 相反,我们看到了博客文章和社交媒体上的建议片段、从研究论文附录中收集的技巧、特定项目或工作流的偶然案例研究,以及很多困惑。在深度学习领域,专家和新手用着表面上类似的方法,但所取得的结果之间存在着巨大的差距。与此同时,这些专家也很乐意承认他们所做的一些事情可能没有充分的理由。随着深度学习的成熟并对世界产生更大的影响,社区需要更多涵盖有用方法的资源,包括对于获得良好结果至关重要的所有实用细节。
我们是一个由五名研究人员和工程师组成的团队,多年来一直致力于深度学习。我们已经将深度学习应用到从语音识别到天文学的方方面面,并在此过程中学到了很多东西。本文档源于我们自己训练神经网络、教授学生以及为我们的同事提供实践建议的经验。虽然深度学习已经从少数学术研究实验室中实践的机器学习方法发展成为为数十亿人使用的产品提供动力的技术,但深度学习在工程领域仍处于起步阶段,我们希望本文档能鼓励其他人也来帮助系统化该领域的实验细节。
这份文件是在我们试图实现我们自己的深度学习方法时产生的,因此它只代表作者在撰写本文时的观点,而不是任何客观事实。它被特别强调是因为我们在调整超参数方面遇到了困难,但它也涵盖了我们在工作中遇到(或看到出错)的其他重要问题。我们希望这项工作成为一份活的文件,能随着我们理解的改变从而成长和演变。例如,一份关于如何调试和如何减少训练失败的文档在两年前是不可能写出来的,因为它这得基于最近的结果和正在进行的研究。不可避免地,我们的在此文档中一些建议也将需要更新以考虑新的结果和改进的工作流程。我们不知道最好的深度学习秘诀,但在大众开始记录它并讨论各个步骤之前,我们不能指望找到它。为此,我们鼓励发现我们的建议存在问题的读者提出替代建议以及令人信服的证据,以便我们更新建议。我们也希望看到可能有不同建议的替代指南和方式,以帮助大众追求最佳方法。最后,任何标有🤖表情符号的地方是我们要进一步调查的地方。只有在尝试编写这本 playbook 之后,我们才完全清楚在深度学习从业者的工作流程中可以找到多少有趣及被忽视的研究问题。
在调优过程中的许多抉择,我们可以在项目开始时一次性做出决定。只有偶尔在情况发生变化时,才需要重新考虑。
在开始调优之前,请确保您满足以下假设:
总结: 在开始一个新项目时,尽量重用有效的模型。
总结: 从针对手头问题类型的最常用的优化器开始。
没有一个优化器是适用于所有类型的机器学习问题和模型架构的‘最佳’优化器。即使只是 比较优化器的性能也是一项艰巨的任务。 🤖
我们建议坚持使用成熟、流行的优化器,尤其是在开始新项目时。
做好关注选择的优化器的 *所有* 超参数的准备。
具有更多超参数的优化器可能需要更多的调优工作才能找到最佳配置。
当我们试图找到各种其他超参数(例如架构超参数)的最佳值时,将优化器超参数视为冗余参数是有意义的,这在项目的初始阶段尤其重要。
在项目的初始阶段,从更简单的优化器开始会更可取(例如,具有固定动量的 SGD 或具有固定 $\epsilon$、$\beta_{1}$ 和 $\beta_{2}$ 的 Adam ) ,之后可以切换到更通用的优化器。
常用且较为完善的优化器包括(但不限于):
总结: Batch Size决定训练速度,并且不应该被直接用于调整验证集性能。通常来说,可用硬件支持的最大Batch Size是较为理想的数值。
训练吞吐量 =每秒处理的样本数量
或者,我们可以估计每步时间 :
每步时间 =(Batch Size)/(训练吞吐量)
训练时间 =(每步时间)x(总步数)
如果增加 batch size有很大的前期成本,那么直到项目成熟且容易权衡成本效益前,推迟其的增加可能更好。实施多机并行训练程序可能会引入错误和一些棘手的细节,所以无论如何,一开始最好是用一个比较简单的工作流。(另一方面,当需要进行大量的调优实验时,训练时间的大幅加速可能会在过程的早期非常有利)。
我们把总的使用成本(可能包括多种不同类型的成本)称为 "资源消耗 "。我们可以将资源消耗分解为以下几个部分。
资源消耗 = (每步的资源消耗) x (总步数)
增加 batch size通常可以减少总步骤数。资源消耗是增加还是减少,将取决于每步的消耗如何变化。
Batch norm 很复杂,一般来说,应该使用与计算梯度不同的 batch size 来计算统计数据(像Ghost Batch Norm采用固定值的batch size)。有关详细讨论,请参阅BatchNorm的实现细节
机器学习开发的最终目标是最大化模型的效用。尽管不同应用场景的开发流程有所不同(例如时间长度、可用计算资源、模型类型等),基本步骤和原则都是相似的。
接下来的指南中我们做出了这些假设:
总结: 从简单的配置开始,循序渐进,同时进一步了解问题。确保任何改进都有据可循,以避免增加不必要的复杂度。
综上所述,我们的增量调优策略需要重复以下四个步骤:
本节的其余部分将更详细地讲解增量调优策略。
总结: 大多数时候,我们的目标是更深入地理解问题。
总结: 每轮实验都应该有一个明确的目标,并且范围要足够小,这样实验才能真正朝着目标取得进展。
总结: 根据实验目标,将超参数分为三类:目标超参数、冗余超参数和固定超参数。创建一系列研究以比较目标超参数的不同值,同时优化冗余超参数。注意选择冗余超参数的搜索空间,以平衡资源成本与科学价值。
optimizer,它的值是 {"Nesterov_momentum", "Adam"}。值 optimizer="Nesterov_momentum" 引入了冗余/固定超参数 {learning_rate, momentum},但值 optimizer="Adam" 引入了冗余/固定超参数 {learning_rate, beta1, beta2, epsilon}。learning_rate 对于 optimizer="Nesterov_momentum" 与 optimizer="Adam" 是不同的条件超参数. 它在两种算法中的作用相似(尽管不完全相同),但在每个优化器中运行良好的值范围通常相差几个数量级。optimizer="Nesterov_momentum" 和冗余超参数为 {learning_rate, momentum}。然后创建另一项研究,并设置 optimizer="Adam" 和冗余超参数为 {learning_rate, beta1, beta2, epsilon}。最后通过比较两个研究中的最优试验来比较这两个优化器。总结: 除了尝试实现每组实验的原始科学目标之外,还要检查其他问题的清单,如果发现问题,请修改实验并重新运行。
图 1:不良的搜索空间边界和可接受的搜索空间边界示例。
总结: 检查训练曲线是识别常见故障的一种简单方法,也可以帮助我们优先考虑下一步采取什么行动。
图 2:研究在 ImageNet 上训练的 ResNet-50 的最佳权重衰减值的isolation图。
总结: 当决定是否对我们的模型或训练程序进行改变或采用新的超参数配置时,我们需要理解导致我们结果中不同的变化的来源。
总结: 一旦我们完成了对“好”的搜索空间的探索,并决定了哪些超参数甚至应该被调整,贝叶斯优化工具就是一个值得考虑的选择。
max_train_steps 以获得更好的效果。我们只需要选择一个值并将其用于所有试验。从这些试验中,绘制回顾检查点选择发现的训练steps,以优化max_train_steps的数值。
max_train_steps选择初始候选值。
max_train_steps可能需要增加起始值。
max_train_steps。
max_train_steps应该有一个确定的值可以完美地拟合训练集;找到这个值作为max_train_stepsd的起点NN 步骤。max_train_steps 的初步猜测。max_train_steps的值是必要的。Round i → Round i+1 的最大问题是如何调整学习率衰减计划。
max_train_steps。总结: 输入管道性能受限的原因及干预措施与具体任务高度相关,使用性能分析工具并注意常见的一些问题。
总结: 使用比训练时更大的 batch size 进行评估。在固定步长间隔进行评估,而不是固定的时间间隔。(注:如100个epoch评估一次,而不是10分钟评估一次)。
总结:运行固定步长的训练,并回顾性地从中选择最佳检查点。
总结:在跟踪不同的实验时,一定要注意一些要点,比如研究中检查点的最佳性能,以及对研究的简短描述。
总结:目前Batch Norm通常可以用Layer Norm代替,但在不能替换的情况下,在更改批大小或主机数量时会有一些棘手的细节。
总结: 在日志记录、评估、RNG(随机数生成器)、检查点和数据分片方面,多主机训练非常容易引入错误!
Figure 3: ResNet-50 在 ImageNet 上进行了 100 次试验调整。 通过自举,模拟了不同数量的调整预算。 上面绘制了每个试验预算的最佳性能的箱线图。
Figure 4: 在 WideResnet 中更改单个残差块 (2x2 -> 1x1) 中的步幅会导致训练不稳定。 这不会降低在低学习率下的性能,但由于不稳定的影响,高学习率不再能很好地进行训练。 使用1000步的学习率预热可以解决这种特殊的不稳定情况,允许以 0.1 的最大学习率进行稳定训练。
注意: 某些模型会在非常早期的阶段显示出不稳定的情况,随后出现恢复,这会导致出现缓慢但稳定的训练(这可能会成为问题)。 常见的评估方法可能会因为评估不够频繁而错过这些问题!
为了检查出这一问题,我们可以使用 lr = 2 * current best 来进行一次仅包含500次训练的计划,但每执行一次训练都要进行一次评估。
Figure 5: 该图展示的是训练开始时频繁更新评估的结果。如果怀疑模型受到早期训练不稳定的影响,则很有用。
Figure 6: 预热期间不稳定的示例(注意横轴的刻度是以对数的形式展示)。 在这种情况下,成功训练需要4万次的预热。
Figure 7a: 表现出训练不稳定性的模型的超参数轴图示例。 最佳学习率处于可行的边缘。 “不可行”试验被定义为产生 NaN 或异常高的损失值的试验。
Figure 7b: 模型训练损失中不稳定的学习率
Figure 8: 学习率预热对解决训练不稳定性的有益影响
unstable_base_learning_rate。base_learning_rate,这至少比 unstable_base_learning_rate要大一个数量级。
默认设置是尝试使用 unstable_base_learning_rate 10倍大小的 base_learning_rate。值得注意的是,对于使用例如100倍
unstable_base_learning_rate这样的数值,那么可能需要重新运行整个过程。具体安排如下:
warmup_steps的过程中,将数值从0提升到 base_learning_rate。post_warmup_steps的过程中,以一个恒定的速率进行训练。warmup_steps,以此来让我们获得远高于unstable_base_learning_rate的峰值学习率。base_learning_rate来说, 我们需要对 warmup_steps 以及post_warmup_steps进行调优。 通常将 post_warmup_steps 设定为warmup_steps的两倍就可以了。warmup_steps 应该以几个不同的数量级进行扫描。例如,在样本学习中可以以[10, 103, 104,105]这样的数量级进行尝试。最大的搜索值不应超过max_train_steps的10%。base_learning_rate 进行训练的warmup_steps,就应该将其应用于Baseline模型。
本质上,我们将这个安排添加到现有安排上,并使用上面讨论中选择的最佳检查点来将这个实验与Baseline进行比较。例如,如果我们一开始的max_train_steps的值是10000,
并进行了1000次warmup_steps。那么,新的训练过程总共应当进行了11000次。warmup_steps(大于max_train_steps的5%),则可能需要增加max_train_steps来解决这个问题。标准值。有些模型可能只需要100次训练,然而有些模型则可能需要4万次以上的训练,尤其是Transformer类。
Figure 9: 梯度截断纠正早期训练不稳定性的图示。
$$\theta_{t+1} = \theta_{t} - \eta_t \nabla \mathcal{l}(\theta_t)$$
$$v_0 = 0$$
$$v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - \eta_t v_{t+1}$$
$$v_0 = 0$$
$$v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - \eta_t( \gamma v_{t+1} + \nabla \mathcal{l}(\theta_{t})$$
$$v_0 = 1 \text{,} m_0 = 0$$
$$v_{t+1} = \rho v_{t} + (1 - \rho) \nabla \mathcal{l}(\theta_t)^2$$
$$m_{t+1} = \gamma m_{t} + \frac{\eta_t}{\sqrt{v_{t+1} + \epsilon}}\nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - m_{t+1}$$
$$m_0 = 0 \text{,} v_0 = 0$$
$$m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)$$
$$v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l}(\theta_t)^2$$
$$b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}$$
$$\theta_{t+1} = \theta_{t} - \alpha_t \frac{m_{t+1}}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}$$
$$m_0 = 0 \text{,} v_0 = 0$$
$$m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)$$
$$v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l} (\theta_t)^2$$
$$b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{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}$$
@misc{tuningplaybookgithub,
author = {Varun Godbole and George E. Dahl and Justin Gilmer and Christopher J. Shallue and Zachary Nado},
title = {Deep Learning Tuning Playbook},
url = {http://github.com/google-research/tuning_playbook},
year = {2023},
note = {Version 1.0}
}
这并不是一款由谷歌官方所支持的产品。
我们欢迎听到来自您的反馈。
正如在序言中所讨论的,这是一份在线文档。我们会定期进行大大小小的修改。如果你想获取相关通知,请关注我们的仓库 (具体配置请查看 操作指南).
请不要在未通过问题跟踪系统与作者协调的情况下提交pull request。
对该项目的贡献必须附有贡献者许可协议 (CLA)。 对于你(或你的雇主)所贡献的内容将保留其相关版权; 这只是允许我们使用和重新分配您的贡献作为项目的一部分。 请前往 https://cla.developers.google.com/ 查看您当前存档的协议或签署新协议。
通常,您只需要签署一次CLA协议即可。因此,如果您已经签署过一次(即使针对的是其他项目),那么您可能无需再次签署。
所有的提交(包括来自项目成员的提交)都需要进行审核。出于这个目的,我们会使用Github提供的pull request功能来进行代码审核。 关于如何使用pull request,请查看 GitHub Help 获取更多信息.
本项目遵循 谷歌开源社区指南.
Ben Recht 和 Kevin Jamieson 指出 使用2倍预算随机搜索作为Baseline有多强大(Hyperband的论文也有类似的观点),但肯定有可能找到最先进的贝叶斯优化技术可以击败两倍预算随机搜索的搜索空间和问题。然而,根据我们的经验,在高并行机制中击败 2 倍预算的随机搜索变得更加困难,因为贝叶斯优化没有机会观察先前试验的结果。 ↩
一本系统地教你将深度学习模型的性能最大化的战术手册。
See the code这不是官方认证的 Google 产品。
Varun Godbole † , George E. Dahl † , Justin Gilmer † , Christopher J. Shallue ‡ , Zachary Nado †
† 谷歌研究,谷歌大脑团队
‡ 哈佛大学
本文档适用于对最大化深度学习的性能感兴趣的工程师和研究人员(包括个人和团队)。我们假定您具备机器学习和深度学习概念的基本知识。
我们的重点是超参数调优的过程,但我们还涉及深度学习学习的其他方面。例如工作流实施和优化,但这些方面并不详尽
我们假设机器学习问题是监督学习或类似的东西(例如自监督学习)。但是,本文档中描述的技术也可能适用于其他类型的问题。
目前,要使深度神经网络在实践中正常运行,需要付出大量的努力和猜测。更糟糕的是,目前很少有人记录下那些深度学习中获得良好结果的实际方法。一方面,通常,论文忽略了导致最终结果的过程,以呈现更清晰的原理。另一方面,处理商业问题的机器学习工程师很少有时间回顾并概括他们的调参过程。教科书也往往回避实用指南,而偏重于基本原理,即使它们的作者具有在应用工作中提供有用建议的经验。在准备创建此文档时,我们找不到任何系统性的资料来解释如何使用深度学习获得良好的结果. 相反,我们看到了博客文章和社交媒体上的建议片段、从研究论文附录中收集的技巧、特定项目或工作流的偶然案例研究,以及很多困惑。在深度学习领域,专家和新手用着表面上类似的方法,但所取得的结果之间存在着巨大的差距。与此同时,这些专家也很乐意承认他们所做的一些事情可能没有充分的理由。随着深度学习的成熟并对世界产生更大的影响,社区需要更多涵盖有用方法的资源,包括对于获得良好结果至关重要的所有实用细节。
我们是一个由五名研究人员和工程师组成的团队,多年来一直致力于深度学习。我们已经将深度学习应用到从语音识别到天文学的方方面面,并在此过程中学到了很多东西。本文档源于我们自己训练神经网络、教授学生以及为我们的同事提供实践建议的经验。虽然深度学习已经从少数学术研究实验室中实践的机器学习方法发展成为为数十亿人使用的产品提供动力的技术,但深度学习在工程领域仍处于起步阶段,我们希望本文档能鼓励其他人也来帮助系统化该领域的实验细节。
这份文件是在我们试图实现我们自己的深度学习方法时产生的,因此它只代表作者在撰写本文时的观点,而不是任何客观事实。它被特别强调是因为我们在调整超参数方面遇到了困难,但它也涵盖了我们在工作中遇到(或看到出错)的其他重要问题。我们希望这项工作成为一份活的文件,能随着我们理解的改变从而成长和演变。例如,一份关于如何调试和如何减少训练失败的文档在两年前是不可能写出来的,因为它这得基于最近的结果和正在进行的研究。不可避免地,我们的在此文档中一些建议也将需要更新以考虑新的结果和改进的工作流程。我们不知道最好的深度学习秘诀,但在大众开始记录它并讨论各个步骤之前,我们不能指望找到它。为此,我们鼓励发现我们的建议存在问题的读者提出替代建议以及令人信服的证据,以便我们更新建议。我们也希望看到可能有不同建议的替代指南和方式,以帮助大众追求最佳方法。最后,任何标有🤖表情符号的地方是我们要进一步调查的地方。只有在尝试编写这本 playbook 之后,我们才完全清楚在深度学习从业者的工作流程中可以找到多少有趣及被忽视的研究问题。
在调优过程中的许多抉择,我们可以在项目开始时一次性做出决定。只有偶尔在情况发生变化时,才需要重新考虑。
在开始调优之前,请确保您满足以下假设:
总结: 在开始一个新项目时,尽量重用有效的模型。
总结: 从针对手头问题类型的最常用的优化器开始。
没有一个优化器是适用于所有类型的机器学习问题和模型架构的‘最佳’优化器。即使只是 比较优化器的性能也是一项艰巨的任务。 🤖
我们建议坚持使用成熟、流行的优化器,尤其是在开始新项目时。
做好关注选择的优化器的 *所有* 超参数的准备。
具有更多超参数的优化器可能需要更多的调优工作才能找到最佳配置。
当我们试图找到各种其他超参数(例如架构超参数)的最佳值时,将优化器超参数视为冗余参数是有意义的,这在项目的初始阶段尤其重要。
在项目的初始阶段,从更简单的优化器开始会更可取(例如,具有固定动量的 SGD 或具有固定 $\epsilon$、$\beta_{1}$ 和 $\beta_{2}$ 的 Adam ) ,之后可以切换到更通用的优化器。
常用且较为完善的优化器包括(但不限于):
总结: Batch Size决定训练速度,并且不应该被直接用于调整验证集性能。通常来说,可用硬件支持的最大Batch Size是较为理想的数值。
训练吞吐量 =每秒处理的样本数量
或者,我们可以估计每步时间 :
每步时间 =(Batch Size)/(训练吞吐量)
训练时间 =(每步时间)x(总步数)
如果增加 batch size有很大的前期成本,那么直到项目成熟且容易权衡成本效益前,推迟其的增加可能更好。实施多机并行训练程序可能会引入错误和一些棘手的细节,所以无论如何,一开始最好是用一个比较简单的工作流。(另一方面,当需要进行大量的调优实验时,训练时间的大幅加速可能会在过程的早期非常有利)。
我们把总的使用成本(可能包括多种不同类型的成本)称为 "资源消耗 "。我们可以将资源消耗分解为以下几个部分。
资源消耗 = (每步的资源消耗) x (总步数)
增加 batch size通常可以减少总步骤数。资源消耗是增加还是减少,将取决于每步的消耗如何变化。
Batch norm 很复杂,一般来说,应该使用与计算梯度不同的 batch size 来计算统计数据(像Ghost Batch Norm采用固定值的batch size)。有关详细讨论,请参阅BatchNorm的实现细节
机器学习开发的最终目标是最大化模型的效用。尽管不同应用场景的开发流程有所不同(例如时间长度、可用计算资源、模型类型等),基本步骤和原则都是相似的。
接下来的指南中我们做出了这些假设:
总结: 从简单的配置开始,循序渐进,同时进一步了解问题。确保任何改进都有据可循,以避免增加不必要的复杂度。
综上所述,我们的增量调优策略需要重复以下四个步骤:
本节的其余部分将更详细地讲解增量调优策略。
总结: 大多数时候,我们的目标是更深入地理解问题。
总结: 每轮实验都应该有一个明确的目标,并且范围要足够小,这样实验才能真正朝着目标取得进展。
总结: 根据实验目标,将超参数分为三类:目标超参数、冗余超参数和固定超参数。创建一系列研究以比较目标超参数的不同值,同时优化冗余超参数。注意选择冗余超参数的搜索空间,以平衡资源成本与科学价值。
optimizer,它的值是 {"Nesterov_momentum", "Adam"}。值 optimizer="Nesterov_momentum" 引入了冗余/固定超参数 {learning_rate, momentum},但值 optimizer="Adam" 引入了冗余/固定超参数 {learning_rate, beta1, beta2, epsilon}。learning_rate 对于 optimizer="Nesterov_momentum" 与 optimizer="Adam" 是不同的条件超参数. 它在两种算法中的作用相似(尽管不完全相同),但在每个优化器中运行良好的值范围通常相差几个数量级。optimizer="Nesterov_momentum" 和冗余超参数为 {learning_rate, momentum}。然后创建另一项研究,并设置 optimizer="Adam" 和冗余超参数为 {learning_rate, beta1, beta2, epsilon}。最后通过比较两个研究中的最优试验来比较这两个优化器。总结: 除了尝试实现每组实验的原始科学目标之外,还要检查其他问题的清单,如果发现问题,请修改实验并重新运行。
图 1:不良的搜索空间边界和可接受的搜索空间边界示例。
总结: 检查训练曲线是识别常见故障的一种简单方法,也可以帮助我们优先考虑下一步采取什么行动。
图 2:研究在 ImageNet 上训练的 ResNet-50 的最佳权重衰减值的isolation图。
总结: 当决定是否对我们的模型或训练程序进行改变或采用新的超参数配置时,我们需要理解导致我们结果中不同的变化的来源。
总结: 一旦我们完成了对“好”的搜索空间的探索,并决定了哪些超参数甚至应该被调整,贝叶斯优化工具就是一个值得考虑的选择。
max_train_steps 以获得更好的效果。我们只需要选择一个值并将其用于所有试验。从这些试验中,绘制回顾检查点选择发现的训练steps,以优化max_train_steps的数值。
max_train_steps选择初始候选值。
max_train_steps可能需要增加起始值。
max_train_steps。
max_train_steps应该有一个确定的值可以完美地拟合训练集;找到这个值作为max_train_stepsd的起点NN 步骤。max_train_steps 的初步猜测。max_train_steps的值是必要的。Round i → Round i+1 的最大问题是如何调整学习率衰减计划。
max_train_steps。总结: 输入管道性能受限的原因及干预措施与具体任务高度相关,使用性能分析工具并注意常见的一些问题。
总结: 使用比训练时更大的 batch size 进行评估。在固定步长间隔进行评估,而不是固定的时间间隔。(注:如100个epoch评估一次,而不是10分钟评估一次)。
总结:运行固定步长的训练,并回顾性地从中选择最佳检查点。
总结:在跟踪不同的实验时,一定要注意一些要点,比如研究中检查点的最佳性能,以及对研究的简短描述。
总结:目前Batch Norm通常可以用Layer Norm代替,但在不能替换的情况下,在更改批大小或主机数量时会有一些棘手的细节。
总结: 在日志记录、评估、RNG(随机数生成器)、检查点和数据分片方面,多主机训练非常容易引入错误!
Figure 3: ResNet-50 在 ImageNet 上进行了 100 次试验调整。 通过自举,模拟了不同数量的调整预算。 上面绘制了每个试验预算的最佳性能的箱线图。
Figure 4: 在 WideResnet 中更改单个残差块 (2x2 -> 1x1) 中的步幅会导致训练不稳定。 这不会降低在低学习率下的性能,但由于不稳定的影响,高学习率不再能很好地进行训练。 使用1000步的学习率预热可以解决这种特殊的不稳定情况,允许以 0.1 的最大学习率进行稳定训练。
注意: 某些模型会在非常早期的阶段显示出不稳定的情况,随后出现恢复,这会导致出现缓慢但稳定的训练(这可能会成为问题)。 常见的评估方法可能会因为评估不够频繁而错过这些问题!
为了检查出这一问题,我们可以使用 lr = 2 * current best 来进行一次仅包含500次训练的计划,但每执行一次训练都要进行一次评估。
Figure 5: 该图展示的是训练开始时频繁更新评估的结果。如果怀疑模型受到早期训练不稳定的影响,则很有用。
Figure 6: 预热期间不稳定的示例(注意横轴的刻度是以对数的形式展示)。 在这种情况下,成功训练需要4万次的预热。
Figure 7a: 表现出训练不稳定性的模型的超参数轴图示例。 最佳学习率处于可行的边缘。 “不可行”试验被定义为产生 NaN 或异常高的损失值的试验。
Figure 7b: 模型训练损失中不稳定的学习率
Figure 8: 学习率预热对解决训练不稳定性的有益影响
unstable_base_learning_rate。base_learning_rate,这至少比 unstable_base_learning_rate要大一个数量级。
默认设置是尝试使用 unstable_base_learning_rate 10倍大小的 base_learning_rate。值得注意的是,对于使用例如100倍
unstable_base_learning_rate这样的数值,那么可能需要重新运行整个过程。具体安排如下:
warmup_steps的过程中,将数值从0提升到 base_learning_rate。post_warmup_steps的过程中,以一个恒定的速率进行训练。warmup_steps,以此来让我们获得远高于unstable_base_learning_rate的峰值学习率。base_learning_rate来说, 我们需要对 warmup_steps 以及post_warmup_steps进行调优。 通常将 post_warmup_steps 设定为warmup_steps的两倍就可以了。warmup_steps 应该以几个不同的数量级进行扫描。例如,在样本学习中可以以[10, 103, 104,105]这样的数量级进行尝试。最大的搜索值不应超过max_train_steps的10%。base_learning_rate 进行训练的warmup_steps,就应该将其应用于Baseline模型。
本质上,我们将这个安排添加到现有安排上,并使用上面讨论中选择的最佳检查点来将这个实验与Baseline进行比较。例如,如果我们一开始的max_train_steps的值是10000,
并进行了1000次warmup_steps。那么,新的训练过程总共应当进行了11000次。warmup_steps(大于max_train_steps的5%),则可能需要增加max_train_steps来解决这个问题。标准值。有些模型可能只需要100次训练,然而有些模型则可能需要4万次以上的训练,尤其是Transformer类。
Figure 9: 梯度截断纠正早期训练不稳定性的图示。
$$\theta_{t+1} = \theta_{t} - \eta_t \nabla \mathcal{l}(\theta_t)$$
$$v_0 = 0$$
$$v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - \eta_t v_{t+1}$$
$$v_0 = 0$$
$$v_{t+1} = \gamma v_{t} + \nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - \eta_t( \gamma v_{t+1} + \nabla \mathcal{l}(\theta_{t})$$
$$v_0 = 1 \text{,} m_0 = 0$$
$$v_{t+1} = \rho v_{t} + (1 - \rho) \nabla \mathcal{l}(\theta_t)^2$$
$$m_{t+1} = \gamma m_{t} + \frac{\eta_t}{\sqrt{v_{t+1} + \epsilon}}\nabla \mathcal{l}(\theta_t)$$
$$\theta_{t+1} = \theta_{t} - m_{t+1}$$
$$m_0 = 0 \text{,} v_0 = 0$$
$$m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)$$
$$v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l}(\theta_t)^2$$
$$b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{t+1}}$$
$$\theta_{t+1} = \theta_{t} - \alpha_t \frac{m_{t+1}}{\sqrt{v_{t+1}} + \epsilon} b_{t+1}$$
$$m_0 = 0 \text{,} v_0 = 0$$
$$m_{t+1} = \beta_1 m_{t} + (1 - \beta_1) \nabla \mathcal{l} (\theta_t)$$
$$v_{t+1} = \beta_2 v_{t} + (1 - \beta_2) \nabla \mathcal{l} (\theta_t)^2$$
$$b_{t+1} = \frac{\sqrt{1 - \beta_2^{t+1}}}{1 - \beta_1^{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}$$
@misc{tuningplaybookgithub,
author = {Varun Godbole and George E. Dahl and Justin Gilmer and Christopher J. Shallue and Zachary Nado},
title = {Deep Learning Tuning Playbook},
url = {http://github.com/google-research/tuning_playbook},
year = {2023},
note = {Version 1.0}
}
这并不是一款由谷歌官方所支持的产品。
我们欢迎听到来自您的反馈。
正如在序言中所讨论的,这是一份在线文档。我们会定期进行大大小小的修改。如果你想获取相关通知,请关注我们的仓库 (具体配置请查看 操作指南).
请不要在未通过问题跟踪系统与作者协调的情况下提交pull request。
对该项目的贡献必须附有贡献者许可协议 (CLA)。 对于你(或你的雇主)所贡献的内容将保留其相关版权; 这只是允许我们使用和重新分配您的贡献作为项目的一部分。 请前往 https://cla.developers.google.com/ 查看您当前存档的协议或签署新协议。
通常,您只需要签署一次CLA协议即可。因此,如果您已经签署过一次(即使针对的是其他项目),那么您可能无需再次签署。
所有的提交(包括来自项目成员的提交)都需要进行审核。出于这个目的,我们会使用Github提供的pull request功能来进行代码审核。 关于如何使用pull request,请查看 GitHub Help 获取更多信息.
本项目遵循 谷歌开源社区指南.
Ben Recht 和 Kevin Jamieson 指出 使用2倍预算随机搜索作为Baseline有多强大(Hyperband的论文也有类似的观点),但肯定有可能找到最先进的贝叶斯优化技术可以击败两倍预算随机搜索的搜索空间和问题。然而,根据我们的经验,在高并行机制中击败 2 倍预算的随机搜索变得更加困难,因为贝叶斯优化没有机会观察先前试验的结果。 ↩