一句话版:学习率(LR)是油门,调度 是"踩油门的节奏"。前期 warmup 防打滑,中后期 余弦退火 让你平顺地收尾;若想"快上坡、稳下坡",OneCycle 用一次升降的曲线把速度与稳定兼顾。
1. 为什么要做学习率调度?
把训练看做开车下山:
- 固定 LR:一路同速,容易一会儿太快(震荡),一会儿太慢(磨蹭)。
- 调度 LR :前期大胆找方向(较大 LR),后期精修(较小 LR)。
好处:
- 更快收敛:用大 LR 跨过"平坦区/鞍点";
- 更稳:后期小 LR 精调,避免错过谷底;
- 更好泛化:合适的调度配合 SGD 噪声,经常带来更好的验证集表现。
2. "通用菜单"与选择套路
常见策略:
- 常数(baseline);
- Step/多步衰减:到某轮把 LR 乘以 γ;
- 指数/线性衰减;
- Warmup:先从很小的 LR 线性/指数升到目标 LR;
- 余弦退火 (Cosine Annealing / SGDR)与带重启的余弦;
- OneCycle :单周期"升--降"并反向调动量。
经验选型(粗略):
- Transformer / ViT / LLM 微调:Warmup + 余弦退火(或余弦+重启);
- CV 大批量训练:OneCycle(SGD 或 AdamW 都可);
- 小数据/凸问题:Step/多步;
- 在线/流式:指数/线性衰减更易管控。
3. Warmup:先热车,再提速
思想 :一上来模型的梯度与统计量还不稳定(尤其有 BN/LayerNorm、自适应优化的二阶动量),用很小 LR 开始,逐步升到目标 LR。
3.1 线性 warmup(最常见)
设总 warmup 步数 T w T_w Tw,目标 LR 为 η max \eta_{\max} ηmax:
η t = η max ⋅ t T w , t = 1 , ... , T w . \eta_t = \eta_{\max}\cdot \frac{t}{T_w},\quad t=1,\dots,T_w. ηt=ηmax⋅Twt,t=1,...,Tw.
3.2 指数 warmup(更平滑)
η t = η max ⋅ ( η min η max ) 1 − t T w ( η min ≪ η max ) \eta_t=\eta_{\max}\cdot\left(\frac{\eta_{\min}}{\eta_{\max}}\right)^{1-\frac{t}{T_w}} \quad(\eta_{\min}\ll\eta_{\max}) ηt=ηmax⋅(ηmaxηmin)1−Twt(ηmin≪ηmax)
小贴士
- Warmup 步数 常占总步数的 1%--10% 或若干千步(取决于 batch/任务);
- 大批量 、Adam/AdamW 、深网络更偏爱 warmup;
- Warmup 结束后,接余弦/线性/多步均可。
4. 余弦退火(Cosine Annealing):优雅收尾
无重启版本(总训练步数 T T T):
η t = η min + 1 2 ( η max − η min ) ( 1 + cos ( π t T ) ) , 0 ≤ t ≤ T . \eta_t=\eta_{\min}+\tfrac12(\eta_{\max}-\eta_{\min})\Big(1+\cos(\pi \tfrac{t}{T})\Big), \quad 0\le t\le T. ηt=ηmin+21(ηmax−ηmin)(1+cos(πTt)),0≤t≤T.
- 早期下降慢、后期下降快,平滑且易用;
- 常与 Warmup 组合:Warmup 到 η max \eta_{\max} ηmax,再走余弦到 η min \eta_{\min} ηmin。
带重启(SGDR)
把训练分成多个周期 T 0 , T 1 , ... T_0,T_1,\dots T0,T1,...,到期重启 LR 到较高值、再余弦降回;有助于跳出次优解。周期可递增(如每次 ×2)。
5. OneCycle:升--降"一次到位",动量反向走
核心 (Smith 思想):在一个训练周期内,先把 LR 从低升到高 (探索),再从高降到更低 (收敛);同时动量反向调:LR 高时动量小(更活跃),LR 低时动量大(更稳)。
5.1 分段公式(线性版本,易实现)
设总步 T T T、上升比例 p ∈ ( 0 , 1 ) p\in(0,1) p∈(0,1),最小/最大学习率 η min , η max \eta_{\min},\eta_{\max} ηmin,ηmax:
η t = { η min + ( η max − η min ) t p T , 0 ≤ t < p T η max − ( η max − η final ) t − p T ( 1 − p ) T , p T ≤ t ≤ T \eta_t= \begin{cases} \eta_{\min} + (\eta_{\max}-\eta_{\min})\dfrac{t}{pT}, & 0\le t<pT\\[6pt] \eta_{\max} - (\eta_{\max}-\eta_{\text{final}})\dfrac{t-pT}{(1-p)T}, & pT\le t\le T \end{cases} ηt=⎩ ⎨ ⎧ηmin+(ηmax−ηmin)pTt,ηmax−(ηmax−ηfinal)(1−p)Tt−pT,0≤t<pTpT≤t≤T
- 常取 p ≈ 0.3 ∼ 0.4 p\approx 0.3\sim0.4 p≈0.3∼0.4, η final \eta_{\text{final}} ηfinal 可比 η min \eta_{\min} ηmin 更小(例如 η max / 25 ∼ η max / 100 \eta_{\max}/25\sim\eta_{\max}/100 ηmax/25∼ηmax/100)。
- 动量 m t m_t mt 反向:上升段从 m max → m min m_{\max}\to m_{\min} mmax→mmin,下降段从 m min → m max m_{\min}\to m_{\max} mmin→mmax。
5.2 优点 & 适用
- 快速:通常在相同步数内更快提升指标;
- 鲁棒:对初始 LR 较不敏感;
- 常用于:图像/语音/表格任务的大批量训练,AdamW/SGD 均可。
6. 三者"时间轴"示意(中文)
1970-01-01 1970-01-01 1970-01-01 1970-01-01 1970-01-01 1970-01-01 1970-01-01 Warmup(升) LR升 动量降 余弦(降) LR降 动量升 Warmup + 余弦 OneCycle 常见调度的时间轴(相对步数)
说明 :上图横轴是相对训练步数(0--100)。Warmup 只在初期出现;OneCycle 的 LR 与动量反向变化。
7. 代码骨架(PyTorch 风格,易复制)
下面展示"Warmup+余弦 "和"OneCycle "两种最常用实现思路。真实项目可直接用
torch.optim.lr_scheduler里的官方实现(CosineAnnealingLR/OneCycleLR等),或自定义 Lambda。
7.1 Warmup + 余弦(单组 LR)
python
import math
class WarmupCosine:
def __init__(self, optimizer, T_total, warmup_steps=0, lr_max=3e-4, lr_min=0.0):
self.opt = optimizer
self.T_total = T_total
self.warm = warmup_steps
self.lr_max = lr_max
self.lr_min = lr_min
self.t = 0
def step(self):
self.t += 1
if self.t <= self.warm and self.warm > 0:
lr = self.lr_max * self.t / self.warm
else:
t = min(self.t - self.warm, self.T_total - self.warm)
T = max(1, self.T_total - self.warm)
lr = self.lr_min + 0.5*(self.lr_max - self.lr_min)*(1 + math.cos(math.pi * t / T))
for pg in self.opt.param_groups:
pg["lr"] = lr
7.2 OneCycle(线性升降 + 反向动量)
python
class OneCycleSimple:
def __init__(self, optimizer, T_total, lr_min, lr_max, pct_up=0.4,
mom_max=0.95, mom_min=0.85):
self.opt = optimizer
self.T_total = T_total
self.up = int(T_total * pct_up)
self.lr_min, self.lr_max = lr_min, lr_max
self.mom_max, self.mom_min = mom_max, mom_min
self.t = 0
def step(self):
self.t += 1
if self.t <= self.up:
# LR up, Momentum down
lr = self.lr_min + (self.lr_max - self.lr_min) * (self.t / self.up)
mom = self.mom_max - (self.mom_max - self.mom_min) * (self.t / self.up)
else:
# LR down, Momentum up
t2 = self.t - self.up
T2 = max(1, self.T_total - self.up)
lr = self.lr_max - (self.lr_max - self.lr_min/25.0) * (t2 / T2)
mom = self.mom_min + (self.mom_max - self.mom_min) * (t2 / T2)
for pg in self.opt.param_groups:
pg["lr"] = lr
if "momentum" in pg: # SGD
pg["momentum"] = mom
if "betas" in pg: # Adam/AdamW
b1, b2 = pg["betas"]
pg["betas"] = (1 - (1-mom), b2) # 仅示意:等价调 b1≈动量
提示:对 Adam/AdamW,OneCycle 通常调 **β1(动量)**而非 β2(长记忆二阶);实际调参可更细分层。
8. 选择流程(中文流程图)
是
是
否
否
是
否
确定任务与优化器
批量是否很大?
希望一次性训练完?
OneCycle 调度
余弦+重启 (SGDR)
模型是否深/自适应优化?
Warmup + 余弦
Step/多步/线性/指数衰减
监控验证集并微调超参
说明:大批量 → OneCycle 很香;深网络+AdamW → Warmup+余弦是默认安全选择。
9. 工程心得与参数建议
- Warmup 长度 :太短没稳定作用,太长会拖慢;先用 1%--5% 总步数起步,观察曲线再微调。
- 余弦最低 LR :不是必须 0。设定一个 lr_min = (0.01--0.1)·lr_max 往往更稳。
- OneCycle 的 lr_max :可以比常规更激进(如常规的 2--5 倍),配合 梯度裁剪。
- 动量的反向调 :OneCycle 里 LR 高 → 动量低 (更探索),LR 低 → 动量高(更收敛)。
- 分层/分组调度:Transformer/多分支网络可对不同层/参数组使用不同初始 LR 或衰减(靠近输出层更大)。
- 与权重衰减 :AdamW 中解耦衰减 与 LR 调度独立存在;通常 wd 固定,不要跟着 LR 同步变化。
- 监控指标 :训练/验证 loss、学习率、动量/β1、梯度范数;曲线异常(锯齿/发散)优先检查 warmup 与 lr_max。
10. 常见坑与排错
-
warmup 后忘记切换到退火 → LR 卡在高位,loss 在高原区抖动。
- 解决:检查调度器
step()调用时机(per-step vs per-epoch)。
- 解决:检查调度器
-
OneCycle 的 lr_max 过大 → 早期直接发散。
- 解决:减小 lr_max 或增加 梯度裁剪(如 1.0)。
-
余弦最低 LR 取 0 导致训练"停摆"(尤其 AdamW)
- 解决:给 η min \eta_{\min} ηmin 一点余量(如 1 e − 6 ∼ 1 e − 5 1e{-6}\sim1e{-5} 1e−6∼1e−5 或相对值)。
-
多优化器/多 param group:只更新了一个组的 LR。
- 解决:循环 param_groups,并核对打印。
-
per-epoch 调度用于超长 epoch 的任务 → 粒度太粗。
- 解决:改为 per-step 调度,使曲线更平滑、控制更精细。
11. 小练习(含提示)
- 推导余弦调度 :从"圆周投影"的角度推导 η t \eta_t ηt 公式,并解释为什么前后平滑。
- 玩具对比:在同一 CNN 上对比固定 LR、Step、Warmup+Cosine、OneCycle 的训练/验证曲线。
- 寻找 lr_max :用"学习率范围测试"(LR range test),地图式地找合适
lr_min, lr_max。 - OneCycle 的动量:实现反向动量日程,比较固定动量 vs 反向动量的差异。
- 分层 LR:对 Transformer 做 layer-wise lr decay(靠输入侧层更小),与统一 LR 对比。
- Cosine 重启:实现 SGDR 的周期递增重启,观察跳出次优的现象。
12. 小结(带走三句话)
- Warmup 保前期稳定;余弦退火 平滑收尾;OneCycle 一次升降兼顾探索与收敛。
- 默认靠谱的配方:Warmup + 余弦(AdamW) ;大批量或想提速:OneCycle。
- 任何调度都别离开良好的监控与裁剪 :看曲线,勤复盘,让 LR 曲线服务于你的损失曲线。