资讯详情

学习率η调优实战:从原理到LR Range Test的完整指南

📅 2026/10/14 8:07:56 | 华诺云谱 👁 阅读
学习率η调优实战:从原理到LR Range Test的完整指南
1. 为什么超参 η 值得单独拎出来讲但凡动手训过模型的人大概率都有过这种体验网络结构调了半天数据清洗做得一丝不苟结果模型死活不收敛loss 曲线像心电图一样上蹿下跳。最后一查问题出在学习率上——那个看起来最不起眼的 η。我见过太多项目架构选型讨论了两周学习率随手填了个 0.01然后花三天时间怀疑人生。学习率 ηeta是梯度下降类优化算法里最核心的超参数没有之一。它直接决定了每次参数更新的步长步子迈小了收敛慢到让人想砸键盘步子迈大了直接跨过最优点loss 震荡甚至发散。更麻烦的是它跟 batch size、优化器类型、网络深度、数据分布全都耦合在一起没有一个放之四海皆准的魔法数字。这篇内容适合谁看如果你正在训模型但 loss 不收敛或者收敛了但效果总差那么一口气又或者你带团队做项目想建立一套靠谱的超参调优流程那接下来的内容应该能帮你省下不少试错时间。我会从理论直觉讲到实操细节包括我踩过的坑和总结出来的排查套路尽量让刚入门的朋友也能跟上。2. 学习率 η 的核心原理与直觉理解2.1 从梯度下降到步长选择梯度下降的更新公式很简洁θ θ - η · ∇J(θ)。这里 ∇J(θ) 是损失函数对参数的梯度η 就是学习率。你可以把优化过程想象成下山梯度告诉你哪个方向是下坡η 告诉你每步走多远。如果山势平缓梯度小你需要大一点的步长才能快速下降如果山势陡峭梯度大步长太大会直接冲过头。问题在于真实的损失曲面不是均匀的斜坡而是坑坑洼洼的高维地形。有些方向梯度极大有些方向梯度极小这就是所谓的“病态条件数”问题。固定学习率在这种曲面上很难同时兼顾所有方向——在陡峭方向震荡在平坦方向爬行。理解这一点后面所有的学习率策略就都说得通了。2.2 学习率与 batch size 的耦合关系很多人忽略了一个事实学习率的最优值跟 batch size 是强相关的。经验规则是当 batch size 扩大 k 倍时学习率也应该相应扩大线性缩放规则或者取平方根缩放。背后的直觉是更大的 batch 意味着梯度估计的方差更小方向更准所以可以放心迈大步。但这个规则有边界。当 batch size 大到一定程度梯度方差已经很小了再线性放大学习率反而会导致训练不稳定。我实测下来线性缩放规则在 batch size 从 32 扩到 256 这个区间内比较靠谱再往上就得谨慎了。另外如果你用了 Batch Normalization这个耦合关系会变得更复杂因为 BN 本身对 batch 统计量敏感。2.3 学习率过大和过小的典型症状判断学习率是否合适最直接的方式是看 loss 曲线。学习率过大时loss 会剧烈震荡甚至出现 NaN学习率过小时loss 下降极其缓慢曲线几乎是一条平缓的斜线。还有一种隐蔽的情况学习率略大loss 前期下降很快但到某个点后卡住不降了这是因为步长太大参数在最优点附近来回跳始终落不到坑底。注意不要只看训练 loss。有时候训练 loss 降得很好但验证 loss 很早就开始上升这可能是学习率过大导致模型在训练集上过拟合。验证集表现才是判断学习率是否合适的最终标准。3. 主流学习率调度策略拆解3.1 Step Decay最经典但也最需要调参Step Decay 的思路很直接每隔固定的 epoch 数把学习率乘以一个衰减因子通常是 0.1。比如初始学习率 0.1每 30 个 epoch 衰减一次。这个策略在早期深度学习时代非常流行因为实现简单效果也还过得去。但它的问题也很明显衰减的时机和幅度都是超参数需要根据具体任务调。衰减太早模型还没充分探索就进入精细调整阶段衰减太晚前期震荡浪费大量计算资源。我一般会先跑一个短周期的实验观察 loss 曲线什么时候开始进入平台期然后把衰减点设在平台期之前一点。3.2 Cosine Annealing平滑衰减的优雅方案Cosine Annealing 让学习率按照余弦曲线从初始值平滑衰减到接近零。公式是 η_t η_min 0.5(η_max - η_min)(1 cos(tπ/T))。这种策略的好处是前期衰减慢、中期快、后期又慢下来整体比较符合训练过程中对步长的需求变化。实际用的时候我通常配合 warm restarts 一起用也就是每隔 T 个 epoch 把学习率重置回初始值然后重新走一遍余弦衰减。这个做法在图像分类任务上效果很好因为重启可以帮助模型跳出局部最优。不过 warm restarts 的周期 T 需要调太短了模型还没收敛就重启太长了又失去了重启的意义。3.3 Warmup为什么前期需要“热身”Warmup 是在训练最开始的一小段时间内让学习率从很小的值线性增加到初始学习率。这个策略在 Transformer 类模型上几乎是标配。为什么需要 warmup因为训练初期参数是随机初始化的梯度方向可能非常混乱如果直接用大学习率很容易把参数推到不好的区域后面很难拉回来。Warmup 的步数一般设为总步数的 5% 到 10%。我试过在 ResNet 上不加 warmup 直接用大学习率结果前几个 epoch loss 直接飙到 NaN加了 warmup 之后就稳了。但 warmup 也不是万能的如果你的模型本身很浅、初始化方式又比较合理加 warmup 反而会拖慢前期收敛速度。3.4 自适应优化器把 η 交给算法自己调Adam、RMSProp 这类自适应优化器会为每个参数维护独立的学习率根据梯度的一阶矩和二阶矩估计动态调整。这在一定程度上减轻了手动调学习率的负担但并不意味着学习率这个超参数就不重要了——你仍然需要设置初始学习率而且 Adam 的默认学习率 0.001 并不是对所有任务都最优。我的经验是Adam 在大多数任务上确实比 SGD 更容易调但最终效果往往不如精心调过的 SGD Momentum。如果你追求极致性能SGD 配合学习率调度仍然是首选如果你追求快速出结果Adam 是更稳妥的选择。4. 实操如何系统性地找到合适的学习率4.1 LR Range Test用一次实验锁定候选区间Leslie Smith 提出的 LR Range Test 是我最推荐的学习率搜索方法。具体做法是从一个极小的学习率比如 1e-7开始每处理一个 batch 就把学习率按指数增长直到达到一个较大的值比如 10同时记录每个学习率对应的 loss。然后画出 loss vs 学习率的曲线找到 loss 下降最快的区间那个区间对应的学习率就是比较好的候选值。实操细节上我一般会跑 100 到 200 个 iteration学习率从 1e-7 增长到 1。增长方式用指数增长η_t η_0 · exp(t · k)其中 k 控制增长速度。跑完之后取 loss 曲线最低点之前、下降斜率最大的那个学习率通常再除以 3 到 5 作为最终初始学习率因为实际训练时 batch 间梯度有噪声需要留一点余量。4.2 网格搜索 vs 随机搜索别在低效方法上浪费时间如果你只有两三个学习率候选值要试网格搜索没问题。但如果你要同时调学习率、weight decay、dropout 等多个超参数网格搜索的效率极低。Bergstra 和 Bengio 的经典实验表明随机搜索在同样的计算预算下找到好超参的概率远高于网格搜索。我的做法是先用 LR Range Test 锁定学习率的大致范围然后在这个范围内用随机搜索采样 10 到 20 个值每个值跑一个短周期比如 10 个 epoch看验证集表现。选出最好的两三个值再跑完整训练。这样一轮下来通常两三天就能找到比较满意的配置。4.3 用验证集曲线判断学习率是否合适训练过程中我会同时监控训练 loss 和验证 loss。如果训练 loss 震荡但验证 loss 平稳下降说明学习率略大但还能接受如果两者都震荡说明学习率太大了如果训练 loss 下降很慢验证 loss 也下降很慢说明学习率太小了。还有一个技巧观察训练 loss 的移动平均。如果移动平均曲线在某个点后斜率明显变缓但还没有收敛可能是学习率需要衰减了。这时候手动衰减一次学习率往往能看到 loss 再往下走一截。5. 常见问题与排查技巧实录5.1 Loss 变成 NaN 了怎么办NaN 是学习率过大最典型的症状。排查顺序是先把学习率降低 10 倍试试如果还是 NaN再降 10 倍。如果降了好几次还是 NaN那可能不是学习率的问题而是数据里有异常值、梯度爆炸、或者某个层的初始化有问题。我遇到过一次学习率降到 1e-6 还是 NaN最后发现是数据预处理时有一列特征没做归一化数值范围到了 1e8导致梯度爆炸。所以遇到 NaN先检查数据再检查梯度裁剪有没有开最后才怀疑学习率。5.2 训练 loss 不下降的几种可能学习率太小是最常见的原因但也不是唯一原因。如果学习率已经调到 1e-2 了 loss 还不降那可能是模型初始化有问题比如全零初始化、损失函数写错了、数据标签对不上、或者梯度被某个操作截断了。我一般会先用一个极小的数据集比如 10 个样本过拟合一下如果连 10 个样本都过拟合不了那肯定是代码有 bug跟学习率无关。5.3 学习率调度器的坑step 和 epoch 的区别PyTorch 的 lr_scheduler 有 step 和 epoch 两种模式用错了会导致学习率衰减时机完全不对。StepLR 默认是按 epoch 衰减但如果你在 batch 循环里调用了 scheduler.step()那就变成按 batch 衰减了学习率会降得飞快。我见过有人把 StepLR 的 step_size 设成 30结果在 batch 循环里调用30 个 batch 后学习率就降到接近零了模型根本没训起来。提示用 scheduler 之前先确认它的 step 是按什么单位计的。PyTorch 官方文档里每个 scheduler 的示例代码都写得很清楚花两分钟看一眼能省两小时 debug。5.4 迁移学习时学习率该怎么设迁移学习时通常会对预训练层用较小的学习率对新加的层用较大的学习率。比如预训练层用 1e-5新层用 1e-3。这个做法叫 discriminative fine-tuning在 NLP 和 CV 任务里都很常用。但也不是绝对的如果你的新数据集和预训练数据集分布很接近所有层用同一个学习率也没问题。我一般会先冻结预训练层只训新层几个 epoch等新层稳定了再解冻全部层一起微调。这样比一上来就全量微调更稳也不容易把预训练学到的特征破坏掉。6. 一些不那么常见但很有用的技巧6.1 用学习率找模型的问题学习率不仅能用来优化还能用来诊断模型。如果你发现某个学习率下模型表现异常差但换个学习率就好了那说明模型对这个超参数过于敏感可能存在结构上的问题。比如某些层的梯度尺度差异太大导致学习率很难同时适配所有层。这时候可以考虑加梯度裁剪、用 Layer Normalization、或者换用自适应优化器。6.2 Cyclical Learning Rate让学习率周期性变化CLR 让学习率在设定的最小值和最大值之间周期性变化而不是单调衰减。这个做法的好处是学习率增大时可以帮助模型跳出局部最优学习率减小时又可以让模型在好的区域精细搜索。我试过在几个图像分类任务上用 triangular CLR效果比 Step Decay 好而且需要调的参数更少——只需要设最小学习率、最大学习率和周期长度。6.3 学习率与 weight decay 的联合调参学习率和 weight decay 是耦合的。weight decay 越大相当于对参数施加了更强的约束这时候学习率可以适当大一点。反过来如果 weight decay 很小学习率太大容易过拟合。我一般会固定一个 weight decay先调学习率然后再微调 weight decay。如果两个一起调搜索空间太大很难找到最优组合。7. 我个人的实操体会调了这么多年模型我最大的体会是学习率没有“最优值”只有“最适合当前配置的值”。同一个模型换个 batch size、换个优化器、甚至换个随机种子最优学习率都可能不一样。所以与其花大量时间去找那个精确的最优值不如建立一个快速试错的流程能在半天内筛出几个靠谱的候选值然后选一个跑完整训练。另外不要迷信默认值。Adam 的 0.001 在大多数任务上确实能用但如果你追求更好的效果花点时间做 LR Range Test 是值得的。我见过太多人直接用默认学习率跑完实验然后抱怨模型效果不好其实只要把学习率调一调效果就能提升好几个点。最后分享一个小技巧如果你不确定学习率该设多少先设一个偏小的值比如 1e-4跑几个 epoch 看看 loss 下降速度。如果下降太慢就乘以 3 再试如果震荡就除以 3。这样迭代几次很快就能找到一个可用的学习率。这个方法虽然土但实测下来比很多花哨的自动调参方法都靠谱。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑