此文整理总结github上的一个资料,结尾附上链接。对于工程应用很有现实参考,带入实际工作场景中会有不少的收获。
这份文档旨在帮助工程师和研究人员系统性地优化深度学习模型的性能。它涵盖了从项目启动到模型部署的各个环节,包括:
- 模型选择: 建议从成熟的模型架构开始,并根据需求逐步调整。 优化器选择: 推荐使用流行的优化器,并根据模型和任务进行调整。
- BatchSize: 强调 Batch Size 对训练时间和资源消耗的影响,并提供选择合适 Batch Size 的方法。
- 初始配置: 指导如何选择初始的模型配置、优化器超参数和训练步数。
- 科学方法: 介绍如何使用增量调整策略、探索与利用、以及如何设计实验来提高模型性能。
- 训练运行步数: 解释如何根据训练是否受计算限制来确定训练时间。
- 训练管道:提供优化输入管道、评估模型性能、保存检查点和设置实验跟踪的指导。
- 常见问题: 回答关于学习率衰减、Adam超参数、Quasi-Random-Search 和优化失败的常见问题。
总而言之,这份文档提供了一个全面且实用的指南,帮助深度学习从业者有效地优化模型性能,并提高工作效率。
1 开启新任务准备
1.1 选择模型架构
总结: 从成熟的模型架构开始,并根据需求进行调整。
建议:
- 选择一个完善且常用的模型架构来开始工作。
- 尝试找到一篇尽可能接近手头问题的相关论文,并将复现该论文中的模型作为起点。
1.2 选择优化器
总结: 从针对手头问题类型的最常用的优化器开始。
建议:
- 使用成熟、流行的优化器。如SGD with momentum,Adam,NAdam
- 理解优化器的所有超参数,并做好调整的准备。
- 在项目的初始阶段,从更简单的优化器开始。
1.3 选择 BatchSize
总结: BatchSize 决定训练速度,并且不应该被直接用于调整验证集性能。通常来说,可用硬件支持的最大
Batch Size 是较为理想的数值。
原因:
- 增加 BatchSize 通常会减少训练时间,这对超参数调整和开发周期有利。
- 资源消耗和 BatchSize 之间没有明确的关系。
- 理论上,任何 BatchSize 都能获得相同的最终性能。
选择 BatchSize 的步骤:
- 确定可行的 BatchSize 并估计训练吞吐量。
- 选择合适的 BatchSize 以最小化训练时间。
- 选择合适的 BatchSize 以最小化资源消耗。
- 更改 BatchSize 需要重新调整大多数超参数。
- 考虑 BatchNorm 对 BatchSize 选择的影响。
1.4 选择初始配置
总结: 在开始超参数调整之前,必须确定起点。这包括指定 模型配置(例如层数),优化器超参数(例如学习率),以及训练步数。
原则:
- 选择一个简单、快速、资源消耗相对较低的配置,以获得“合理”的结果。
考虑因素: - 简单:避免花里胡哨的东西,可以以后添加。
- 快速:消耗最少资源,提高超参数调整效率。
- 合理:性能比随机机会好得多。
- 确定训练步数的数量: 平衡训练步数和资源消耗,以及训练步数和调整效率之间的关系。
第 2 章 提高模型性能的科学方法
机器学习开发的最终目标是最大化模型的效用。尽管不同应用场景的开发流程有所不同(例如时间长度、可用计算资源、模型类型等),基本步骤和原则都是相似的。
接下来的指南中我们做出了这些假设:
- 已有能运行且得到不错结果的训练工作流。
- 有足够的计算资源来进行调参实验,至少能够并行发起数个训练流程。
2.1 增量调整策略
总结:从简单的配置开始,循序渐进,同时进一步了解问题。确保任何改进都有据可循,以避免增加不必要的复杂度。我们的最终目标是找到一种训练配置来最大化我们模型的性能。
- 更有效的方法是从简单的配置开始,逐步添加功能并进行改进,同时深化对问题的理解。
- 随着我们的探索,我们自然会找到越来越好的配置,因此我们的 “最佳” 模型将不断改进。
- 当我们更新我们的最佳配置时,我们称之为上线(这不一定对应线上模型的实际上线)。
- 对于每次上线,我们必须确保更改是有据可循的—而不仅仅是碰运气找到的配置—以避免给训练工作流增加不必要的复杂性。
综上所述,我们的增量调优策略需要重复以下四个步骤:
- 为下一轮实验确定适当的目标。
- 设计并展开实验,朝着这个目标取得进展。
- 从实验结果中获取经验。
- 考虑是否上线新的最佳配置。
本节的其余部分将更详细地讲解增量调优策略
2.2 探索与利用
总结:大多数时候,我们的目标是更深入地理解问题。
- 尽管有些人认为我们会花大部分时间来提升验证集的指标,实际上我们把重心放在进一步理解问题上,而不是降低验证集错误率。
- 也就是说,我们大部分时间都花在了 “探索” 上,只有一小部分时间花在了 “利用” 上。
- 从长远来看,如果我们想最大化我们的最终效果,深入理解问题是至关重要的。将深化理解置于短期收益之上可以帮助我们:
最终,我们可以集中提升验证集效果,即便我们无法从新的实验中进一步了解问题的结构了。
2.4 设计下一轮实验
总结:根据实验目标,将超参数分为三类:目标超参数、冗余超参数和固定超参数。创建一系列研究以比较
目标超参数的不同值,同时优化冗余超参数。注意选择冗余超参数的搜索空间,以平衡资源成本与科学价值。
2.4.1 识别目标超参数、冗余超参数和固定超参数
对于给定的目标,所有超参数都将是目标超参数、冗余超参数或固定超参数。
- 目标超参数是指,我们希望测量出其对于模型由何种影响的参数。
- 冗余超参数是指,必须优化才能公平比较不同目标超参数值的参数。类似于统计中的冗余参数。
- 固定超参数是指,在当前轮次实验中取固定值的参数。在比较目标超参数的不同值时,固定超参数的值不需要(或者我们不希望它们)改变。因为实验固定了某些超参数,从实验得出的结论可能对固定超参数的其他值无效。换句话说,固定的超参数对我们的实验结论做了限定。
一个超参数是目标超参数、冗余超参数还是固定超参数是根据实验目标来决定的。
在设计新一轮实验时,我们根据实验目的确定目标超参数。
- 在此阶段,我们将所有其他超参数视为冗余超参数。
- 接下来,我们将一些冗余超参数转作为固定超参数。
尽管超参数的类型取决于实验目标,但对于某些类别的超参数,我们有以下经验法则:
- 在各种优化器超参数(例如学习率、动量、学习率调度参数、Adam 优化器的 beta 等)中,至少有一些是冗余超参数,因为它们往往与其他变化相互影响。
- 相比之下,优化器的选择通常是一个目标超参数或固定超参数。
- 正则化技术引入的超参数通常是冗余超参数,但是否使用正则化技术往往是目标或固定超参数。
- 模型结构超参数通常是目标或固定超参数,因为模型结构变化会影响服务和训练成本、延迟和内存需求。
- 在某些情况下,一个超参数是冗余还是固定超参数将取决于目标超参数的值。
2.4.2 创建一组研究
- 确定了目标和冗余超参数之后,我们会设计一个 “研究” 或一系列研究,以朝着实验目标取得进展。
- 研究的目的是使用目标超参数的不同值运行训练流程,同时 “优化掉”(或 “优化”)冗余超参数,以便公平的比较不同的目标超参数值。
- 在最简单的情况下,我们将对目标超参数的每个配置进行单独研究,其中每个研究都会调整冗余超参数。
- 在更复杂的情况下,我们想要比较大量目标超参数的值,并且我们无法进行大量相对独立的研究,我们可以将目标超参数与冗余超参数放在相同的搜索空间中,并使用搜索算法在单个研究中对两种超参数的值进行采样。
在设计一项研究或一系列研究时,我们需要分配有限的预算,以充分满足以下三个要求:
2.4 从实验结果中获取经验
总结:除了尝试实现每组实验的原始科学目标之外,还要检查其他问题的清单,如果发现问题,请修改实验并重新运行。
- 最终,每组实验都有一个特定的目标,我们想要评估实验为该目标提供的证据。
- 在分析一组给定的实验以朝着最初的目标取得进展之前,我们应该问自己以下额外的问题:
- 如有必要,根据上述问题的答案,改进最近的研究(或研究组)以改进搜索空间和/或抽样更多试验,或采取其他一些纠正措施。
一旦我们回答了上述问题,我们就可以继续评估实验为我们最初的目标提供的证据(例如,评估改变是否有用)。
第3 章 确定每次训练运行的步数
有两种类型的工作模式:受计算限制的和不受计算限制的。
- 当训练为受计算限制时,训练受限于我们愿意等待的时间,而不是受我们拥有多少训练数据或其他因素的限制。
不管一个给定的工作负载是否是计算约束,使用增加梯度方差(跨Batch)的方法通常会导致较慢的训练进度,从而可能增加达到特定验证损失所需的训练步骤。高梯度方差可能是由以下原因造成的。 使用了较小的Batch Size、使用了数据增强技术、添加了一些类型的正则化(例如dropout)
3.1 当训练受计算限制时如何决定该训练多久
- 在某些情况下,训练误差会无限地改善,而我们的耐心和计算资源就成为了限制因素。
- 如果训练误差(或甚至验证误差)可以无限地改善,我们是否应该在我们能接受的情况下一直训练?答案是不必要。
- 因此我们建议在每轮调整中逐渐增加训练步数限制,以在有限的资源和耐心内获得最大的理解,并在最终长时间训练后再进行验证和确认。
- 作为起点,我们建议进行两轮调整:
3.1.1 第一轮
-
遗憾的是,在短时间和不完整训练中找到的超参数在增加训练长度后仍然是好选择的保证是没有的。但是,对于某些类型的超参数,它们通常具有足够的相关性,因此第一轮非常有用。
-
我们期望在短运行中找到的哪些超参数值会转移到更长的训练运行中?对于这一切,我们需要更多的研究。但是根据已有的结论我们可以提出一些猜测,以下是作者的猜测,按转移概率的降序排列:
3.1.2 第二轮
- 运行第一轮中最佳的超参数配置。
- 使用额外的步骤来延长高学习率的训练时间。
- 对于具有非常成熟建模和调整的工作流以及非常长且昂贵的生产训练运行的团队来说,更多回合可能更有意义,但它们通常会过于复杂。
第 4 章 关于训练管道的额外补充
4.1 优化输入管道
总结:输入管道性能受限的原因及干预措施与具体任务高度相关,使用性能分析工具并注意常见的一些问题。
- 使用适当的性能分析工具来诊性能受限的输入管道,例如,用于JAX 的Perfetto 或用于TensorFlow 的Ten- sorFlow profiler。
- 归根结底,具体原因和干预措施将高度依赖于任务。更广泛的工程考虑(如减少磁盘空间占用) 可能会导致较差的输入管道性能。
- 常见问题:
- 常见技巧:
4.2 评估模型性能
总结:使用比训练时更大的batch size 进行评估。在固定步长间隔进行评估,而不是固定的时间间隔。(注:如100 个epoch 评估一次,而不是10 分钟评估一次)。
4.2.1 评估设置
我们可以通过多种方式来评估模型的性能。
- 在线评估-当模型在生产环境中提供预测时收集指标。
- 离线评估-当模型在代表生产环境的离线训练/验证/测试集上运行时,收集指标。
- 定期评估-在模型训练期间收集的指标可能是离线评估的代理,和(或) 离线评估中使用的数据的子集。
- 在线评估是最佳标准,但在模型开发阶段往往是不切实际的。
- 根据问题的不同,离线评估可能会相当复杂,并且计算成本很高。
- 定期评估是最实际和最经济的选择,但可能不能完全代表生产环境。
我们在定期评估时的目标是在训练期间获得可靠信号,使同时尽可能缩短评估时间。
4.2.2 设置定期评估
- 我们在训练期间定期进行评估,以实时监控其进度,以便于追溯模型检查点选择,以便我们可以在训练结束时检查训练曲线。
- 其中最简单的配置是在同一计算实例中执行训练和定期评估,并定期在训练和评估之间交替。(注:比如固定步长间隔评估一次)
- 在这种情况下,用于执行评估的batch size 大小应该至少与用于训练的batch size 大小一样大,因为在评估期间不需要保持模型运行(注:如不用计算梯度之类的),从而降低了每个示例的计算要求。
- 定期评估应在固定步长间隔进行,而不是按时间间隔进行。
4.2.3 选择样本进行定期评估
- 定期评估作业的运行速度可能不够快,无法在合理的时间内计算完整离线评估集的指标。这通常需要对数据进行抽样以进行定期评估。
- 在构建采样数据集时,我们会考虑以下因素:
4.3 保存检查点并追溯选择最佳检查点
总结:运行固定步长的训练,并回顾性地从中选择最佳检查点。
- 大多数深度学习框架都支持模型检查点。模型的当前状态会定期保存在磁盘上。这允许训练作业对计算实例中断具有弹性。
- 最佳检查点并不一定是最后一个检查点,尤其是当验证集性能不会随时间持续增加而是围绕特定值波动时。
- 设置管道以跟踪到目前为止在训练期间看到的N 个最佳检查点。在训练结束时,模型选择就是选择训练期间看到的最佳检查点。我们将此称为回顾性最佳检查点选择。
- 因为预先指定了试验预算并保留了迄今为止看到的N 个最佳检查点,所以通常不必要支持预期提前停止。
4.4 设置实验跟踪
总结:在跟踪不同的实验时,一定要注意一些要点,比如研究中检查点的最佳性能,以及对研究的简短描述。
- 我们发现,在电子表格中跟踪实验结果有助于我们解决各种建模问题。通常有下列:
- 选择一种跟踪系统,能够满足上述信息的记录要求并且对使用者友好易用是非常重要的,未经记录的实验可能不会得到重视。
4.6 多主机管道的注意事项
总结:在日志记录、评估、RNG(随机数生成器)、检查点和数据分片方面,多主机训练非常容易引入错误!
- 保证管道只在一台主机上进行日志记录和检查点
- 确保在运行评估或检查点之前,批处理规范统计信息在主机之间同步
- 保证在多主机之间使用相同的随机数生成器种子(用于模型初始化) 和不同的种子(用于数据混洗和预处理) 是非常重要的,因此请确保合适地标记它们
- 为了提升性能,通常建议将数据文件在多台主机之间进行分片
第5 章 常见问题的回答
5.1 最好的学习率衰减方案是什么
这是一个开放性问题。目前尚不清楚如何构建一组严格的实验来自信地回答最佳的LR 衰减方案是什么。
虽然我们不知道最好的方案是什么,但我们相信尝试一些(非恒定的)方案很重要并且调整它很重要。
在优化过程中,不同的学习率在不同的时间效果最好。有某种衰减方案可以使模型更有可能达到良好的学习率。
5.2 我应该使用哪种学习率衰减方案作为默认值?
我们的偏好是linear decay 或cosine decay,其他一些方案可能也不错。
5.4 Adam 的超参数应该如何调整?
正如之前讨论的那样, 对搜索空间以及应该从搜索空间中采样数量做出概括性陈述是非常困难的。请注意,并非Adam 中的所有超参数都一样重要。以下经验法则对应于研究中试验次数的不同“预算”。
5.8 如何调试和缓解优化失败
总结:如果在优化模型时遇到困难,那么在尝试其他东西之前解决这些问题很重要。诊断和纠正训练失败是一个活跃的研究领域。
5.8.1 识别不稳定的训练任务
- 当学习率过大时,任何训练任务都会变得不稳定,但当不稳定迫使我们使用太小的学习率时,这才会是问题
- 这里至少有两种类型的不稳定的训练任务值得需要进行区分:
- 我们可以采用系统的方法来找出训练任务中存在的稳定性问题.
- 在训练过程中记录全损失梯度的L2 范数的变化(全损失梯度的L2 范数是指在深度学习中,对于每个参数的梯度进行平方并相加后再取平方根的过程,反映了损失函数在当前状态下沿着梯度方向的变化程度。当前状态下的梯度向量越大,说明当前状态下的模型参数需要更大的更新量才能更好的逼近最优解),如果我们发现全损失梯度的L2 范数异常值非常大,这可能表明模型参数在某一时刻发生了非常大的变化,导致训练过程中出现不稳定性(例如误差上升而不下降)。这可以告诉我们该如何选择梯度/更新剪辑。
注意:某些模型会在非常早期的阶段显示出不稳定的情况,随后出现恢复,这会导致出现缓慢但稳定的训练(这可能会成为问题)。为了检查出这一问题,我们可以使用lr = 2 * current best 来进行一次仅包含500 次训练的计划,但每执行一次训练都要进行一次评估。
5.8.2 常见不稳定模式的潜在修复方式
- 使用学习率预热–最适合用于早期训练不稳定的情况。
- 使用梯度截断
- 尝试使用新的优化器
Adam 有时可以处理一些Momentum 无法处理的不稳定影响。这也是该领域的一个活跃研究领域。 - 确保使用最佳实践/初始化:
- 降低学习率。这是最终手段。
如何对学习率进行预热
- 在上面的内容中,我们假设从业者已经确定了让模型变得不稳定的学习率。也就是unstable_base_learning_rate。
- 预热的过程涉及了预先安排一个学习率计划,这个计划会将学习率从0 提升到某个稳定的base_learning_rate,这至少比 unstable_base_learning_rate 要大一个数量级。默认设置是尝试使用unstable_base_learning_rate 10 倍大小的base_learning_rate。
值得注意的是,对于使用例如 100 倍unstable_base_learning_rate 这样的数值,那么可能需要重新运行整个过程。具体安排如下:
- 我们的目标是找到最少的warmup_steps,以此来让我们获得远高unstable_base_learning_rate 的峰值学习率。
- 预热可以独立于现有的衰减计划进行调整。
- 一旦建立了不会破坏以base_learning_rate 进行训练的warmup_steps,就应该将其应用于Baseline 模型。
梯度截断
- 当出现较大或离群的梯度问题时,梯度截断会变得非常有用。
- 梯度截断可以修复早期训练中出现的不稳定性(早期较大的梯度范数),或中期训练中出现的不稳定性(训练中期突然出现的梯度尖峰)。
- 有时,较长的预热时间可以纠正梯度截断无法纠正的不稳定性:。
- 理想的截断阈值要刚好高于“典型的” 梯度范数。 下面是一个关于如何进行梯度截断的案例:
- 在训练期间记录下未截断梯度范数。默认情况下会生成:
- 根据梯度范数的第90 百分位数选择梯度截断阈值。
这个阈值的大小与工作量有关。但90% 是一个很好的选择。但如果这个奏效,那么可以对其进行调优。 - 如果我们尝试梯度截断并不稳定问题仍然存在,那么我们可以更努力地尝试(例如,阈值更小)。
- 极端激进的梯度截断本质上是一种降低学习率的奇怪方式。如果我们发现自己使用了非常激进的截断,那么我们可能应该只降低学习率。
- 我们通常会认为以某种方式将超过50% 的更新剪裁为“极其激进”。
- 如果我们需要进行极其激进的梯度截断来处理我们的不稳定问题,那么我们不妨降低学习率。
总结
欢迎点赞,收藏,关注,支持小生,打造一个好的遥感领域知识分享专栏。
同时欢迎私信咨询讨论学习,咨询讨论的方向不限于:地物分类/语义分割(如水体,云,建筑物,耕地,冬小麦等各种地物类型的提取),变化检测,夜光遥感数据处理,目标检测,图像处理(几何矫正,辐射矫正(大气校正),图像去噪等),遥感时空融合,定量遥感(土壤盐渍化/水质参数反演/气溶胶反演/森林参数(生物量,植被覆盖度,植被生产力等)/地表温度/地表反射率等反演)以及高光谱数据处理等领域以及深度学习,机器学习等技术算法讨论,以及相关实验指导/论文指导等多方面。
参考:
遥感图像处理专栏
深度学习调参