学习率(Learning Rate):模型训练的油门踏板

学习率,我习惯叫它「步长」。说白了,就是模型每次更新参数时,往梯度方向迈多大一步。

你想想看,梯度下降就像在山上摸黑往下走。学习率就是你每一步的步幅。步子太小,走到天亮都到不了山脚;步子太大,一脚踩空直接滚下山崖。

这个参数,是调参时第一个要盯住的东西。我见过太多新手上来就调网络结构,结果模型根本不收敛——回头一看,学习率设错了。

学习率到底在控制什么?

公式很简单:

θ_new = θ_old - η * ∇L(θ_old)

其中 η 就是学习率。它控制着参数更新的幅度。

每次迭代,我们计算损失函数对参数的梯度 ∇L。这个梯度告诉模型:「往哪个方向走,损失下降最快」。学习率则决定:「这次走多远」。

核心直觉:学习率 = 信任梯度的程度 × 更新步幅

梯度方向对了,步幅大点没问题。梯度有噪声,步幅就得收一收。

学习率过大:模型在「震荡」中迷失

学习率设太大,模型参数会在最优值附近来回震荡,甚至直接发散。

我记得有一次训练一个图像分类模型,loss 曲线像心电图一样上下乱跳。我盯着屏幕看了半天,心想「这模型怕不是疯了」。后来把学习率从 0.1 降到 0.01,loss 曲线瞬间变得丝滑。

典型症状:

  • Loss 曲线不下降,反而上升
  • Loss 剧烈震荡,毫无收敛趋势
  • 训练初期 loss 就变成 NaN(梯度爆炸了)
  • 验证集准确率忽高忽低

我曾经踩过的坑:有一次用 Adam 优化器,默认学习率 0.001,训练一个 NLP 模型。跑了 10 个 epoch,loss 死活不降。我以为是数据问题,折腾了两天。最后发现——学习率设成 0.01 就好了。Adam 虽然自适应,但初始学习率依然敏感。

学习率过小:模型在「龟速」中煎熬

学习率太小,模型确实能收敛,但慢得让人抓狂。

你想想看,本来 100 个 epoch 能解决的问题,因为学习率设小了 10 倍,得跑 1000 个 epoch。算力成本翻 10 倍,时间成本翻 10 倍。

典型症状:

  • Loss 缓慢下降,但始终降不到理想值
  • 训练几百个 epoch 后 loss 还在缓慢下降
  • 模型容易陷入局部最优,跳不出来
  • 训练时间异常长

我的经验:如果训练 10 个 epoch 后 loss 下降不到初始值的 50%,大概率是学习率偏小了。可以尝试把学习率翻 3-5 倍看看效果。

固定学习率 vs 动态学习率

固定学习率,就是整个训练过程用一个 η 值。简单粗暴,但问题很明显:

  • 初期需要大步子快速下山,后期需要小步子精细调整
  • 一个固定值很难同时满足「快」和「稳」

动态学习率,就是让学习率随着训练过程变化。这是目前的主流做法。

策略 做法 适用场景 我的评价
固定学习率 全程不变 小数据集、快速实验 简单但低效,不推荐
Step Decay 每 N 个 epoch 乘以一个衰减因子 CV 任务、经典模型 好用,但需要手动调衰减时机
Exponential Decay η = η₀ * e^(-kt) 需要平滑衰减的场景 衰减太快,容易过早停滞
Cosine Annealing 按余弦曲线衰减,周期重启 需要跳出局部最优 我最近很喜欢用这个
ReduceLROnPlateau 验证 loss 不降时自动衰减 不确定衰减策略时 省心,但可能错过最佳时机
Warmup + Decay 先从小 lr 线性增加到目标 lr,再衰减 大模型、Transformer 稳定训练初期的必备技巧

为什么动态学习率更有效?

原因其实很直观:

  1. 训练初期:参数离最优解很远,梯度方向大致正确。大步子快速接近目标区域。
  2. 训练中期:参数进入最优解附近,梯度方向开始摇摆。步幅需要收窄,避免震荡。
  3. 训练后期:参数在最优解周围微调。小步幅精细搜索,找到真正的谷底。

动态学习率正好模拟了这个「先快后慢」的过程。

我的习惯:新项目我一般先用 Cosine Annealing + Warmup。Warmup 稳定初期,Cosine 平滑衰减,效果稳定。如果发现模型收敛太快,再换成 ReduceLROnPlateau 做自适应调整。

学习率与优化器的搭配

不同优化器对学习率的敏感度不一样:

  • SGD:对学习率最敏感。需要精细调参,建议用 0.01 或 0.1 起步。
  • Adam:相对鲁棒。默认 0.001 通常能 work,但未必最优。
  • AdamW:和 Adam 类似,但 weight decay 和解耦后,学习率可以稍微大一点。
  • RMSprop:适合 RNN,学习率建议 0.001 左右。

注意:不要盲目相信优化器的默认学习率。我见过太多人用 Adam 默认 0.001 训练一个模型,结果效果不好。其实把学习率调到 0.0005 或 0.002,效果可能天差地别。

学习率调参实战建议

这里分享几个我常用的方法:

  1. 学习率范围测试(LR Range Test):从一个很小的 lr 开始,每个 batch 指数增加 lr,观察 loss 变化。找到 loss 下降最快的 lr 区间。
  2. 先跑 5-10 个 epoch:观察 loss 曲线。如果 loss 震荡,降低 lr;如果 loss 下降太慢,提高 lr。
  3. 用 Cosine Annealing 兜底:不确定用什么策略时,Cosine Annealing 是个安全的选择。
  4. 记录每次实验的 lr:我习惯在实验日志里记下每次的 lr 和对应的收敛速度。时间久了,你会形成直觉。

一个小技巧:如果你用 PyTorch,可以用 torch.optim.lr_scheduler 里的 LambdaLR 自定义学习率曲线。我经常用它实现一些奇奇怪怪的衰减策略,比如先指数衰减再余弦重启。

学习率与损失景观的关系

为什么学习率这么重要?因为损失函数的表面(Loss Landscape)不是平滑的碗状,而是崎岖的山脉。

我画了一张图,帮你理解学习率在损失景观中的作用:

学习率在损失景观中的作用 全局最优 局部最优 鞍点 学习率过大:跳过最优,震荡发散 学习率过小:陷入局部最优 合适的学习率:稳步收敛到全局最优 损失表面 过大 lr 过小 lr 合适 lr

从这张图可以看得很清楚:

  • 学习率过大(红色虚线):一步跨过最优区域,在谷底来回震荡
  • 学习率过小(绿色虚线):在局部最优里打转,永远出不来
  • 合适的学习率(橙色虚线):稳步沿着下坡走,最终到达全局最优

总结一下

学习率是模型训练中最关键的超参数,没有之一。它决定了模型能否收敛、收敛多快、收敛到多好。

我的建议是:

  • 新项目先用动态学习率,别用固定的
  • Warmup + Cosine Annealing 是个不错的起点
  • 多跑几次学习率范围测试,找到合适的区间
  • 记录每次实验的学习率,形成自己的经验库

调学习率这件事,说白了就是找平衡。步子太大容易扯着蛋,步子太小走不到头。找到那个「刚刚好」的节奏,模型训练就稳了。