深入浅出图解CosineAnnealingLR:从数学公式到PyTorch代码,一次搞懂余弦退火

在深度学习训练过程中,学习率调度策略往往能显著影响模型收敛速度和最终性能。不同于传统的固定学习率或阶梯式下降方法,**余弦退火学习率(CosineAnnealingLR)**通过模拟余弦函数的特性,实现了学习率的平滑周期性变化。这种策略不仅数学优雅,在实际项目中也展现出强大的适应性——从计算机视觉到自然语言处理,我们都能看到它的身影。

理解CosineAnnealingLR的核心在于把握三个关键点:余弦函数的数学特性如何转化为学习率曲线PyTorch如何将公式转化为可执行代码,以及这种调度策略相比传统方法的优势体现在哪些方面。本文将用可视化图表+代码对照的方式,带你彻底掌握这一重要技术。

1. 余弦函数与学习率曲线的数学映射

余弦函数在区间[0, π]的变化呈现出独特的"慢-快-慢"节奏。具体来看:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, np.pi, 100)
cos_x = np.cos(x)
plt.plot(x, cos_x, label='cos(x)')
plt.plot(x, (1+cos_x)/2, label='(1+cos(x))/2')
plt.legend()

这段代码生成的图像会清晰展示两个重要特征:

  1. 原始cos(x)在[0, π]区间从1平滑下降到-1
  2. 经过变换的(1+cos(x))/2将值域压缩到[0,1]区间

学习率调度公式正是基于这个特性构建:

$$ \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})(1 + \cos(\frac{T_{cur}}{T_{max}}\pi)) $$

公式中各参数的实际意义:

  • $\eta_t$:当前epoch的学习率
  • $\eta_{min}$:允许的最小学习率(默认通常设为0)
  • $\eta_{max}$:优化器初始设定的最大学习率
  • $T_{cur}$:当前epoch计数
  • $T_{max}$:半个周期包含的epoch数

注意:这里的"半个周期"概念很关键。当$T_{cur}=T_{max}$时,$\cos(\pi)=-1$,学习率正好降到$\eta_{min}$。

2. PyTorch实现深度解析

PyTorch提供了两种余弦退火实现,我们先看基础版本CosineAnnealingLR的典型用法:

import torch
from torch.optim import SGD
from torch.optim.lr_scheduler import CosineAnnealingLR

model = ...  # 你的模型定义
optimizer = SGD(model.parameters(), lr=0.1)  # 初始学习率即η_max
scheduler = CosineAnnealingLR(optimizer, T_max=50, eta_min=0.001)

for epoch in range(100):
    train(...)
    validate(...)
    scheduler.step()  # 每个epoch更新学习率

关键参数对照表:

公式符号 PyTorch参数 典型值 作用
$\eta_{max}$ optimizer.lr 0.1 学习率上限
$\eta_{min}$ eta_min 0.001 学习率下限
$T_{max}$ T_max 50 半周期长度
$T_{cur}$ last_epoch + 1 - 当前进度

参数设置的艺术

  • T_max等于总epoch数时,学习率从$\eta_{max}$单调下降到$\eta_{min}$
  • T_max小于总epoch数时,学习率会在每个T_max间隔内完成一次下降-上升的完整周期

实际训练中,第二种方式更为常见。例如设置T_max=10训练100个epoch,会产生10个完整周期:

# 多周期示例
scheduler = CosineAnnealingLR(optimizer, T_max=10, eta_min=0.001)

lrs = []
for epoch in range(100):
    optimizer.step()
    scheduler.step()
    lrs.append(optimizer.param_groups[0]['lr'])

plt.plot(lrs)  # 将显示清晰的周期性波动

3. 对比实验:从MNIST看不同调度策略

为了直观展示CosineAnnealingLR的优势,我们在MNIST分类任务上对比三种策略:

from torch.optim.lr_scheduler import StepLR

# 三种调度器配置
fixed_lr = SGD(model.parameters(), lr=0.1)  # 固定学习率
step_lr = StepLR(SGD(model.parameters(), lr=0.1), step_size=30, gamma=0.1)
cos_lr = CosineAnnealingLR(SGD(model.parameters(), lr=0.1), T_max=50)

strategies = {'Fixed': fixed_lr, 'Step': step_lr, 'Cosine': cos_lr}
results = {}

for name, optim in strategies.items():
    model = ...  # 重置模型
    train_loss = []
    for epoch in range(100):
        loss = train_epoch(model, optim)
        train_loss.append(loss)
        if hasattr(optim, 'step'):  # 对调度器执行step
            optim.step()
    results[name] = train_loss

实验数据对比(模拟结果):

策略 最终准确率 收敛速度 超参数敏感性
固定LR 98.2%
StepLR 98.5% 中等 中等
CosineAnnealingLR 99.1%

关键发现:余弦退火在保持较快收敛的同时,对初始学习率的选择不敏感,这使得它在实际应用中更加鲁棒。

4. 进阶技巧:热重启与周期扩展

PyTorch还提供了CosineAnnealingWarmRestarts变体,它在每个周期结束时直接重置学习率而非缓慢上升:

from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts

scheduler = CosineAnnealingWarmRestarts(
    optimizer,
    T_0=50,        # 初始周期长度
    T_mult=2,      # 周期倍增因子
    eta_min=0.001
)

lrs = []
for epoch in range(150):
    scheduler.step()
    lrs.append(optimizer.param_groups[0]['lr'])

plt.plot(lrs)  # 将显示周期长度倍增的锯齿波

热重启的核心优势

  1. 周期性重置有助于逃离局部最优
  2. 配合T_mult参数可实现周期长度动态调整
  3. 特别适合长时间训练和复杂损失曲面

实际项目中,我通常在以下场景选择热重启版本:

  • 训练数据存在明显噪声时
  • 损失函数曲线出现长时间平台期
  • 需要超长时间训练(如1000+epoch)

5. 实战经验与调参技巧

经过多个项目的实践验证,我总结了以下实用经验:

参数设置黄金法则

  1. T_max设为batch数的1-2倍(例如CIFAR-10约50000/128≈390)
  2. eta_min通常设为eta_max的1/10到1/100
  3. 配合早停机制使用效果更佳

常见问题排查表

现象 可能原因 解决方案
训练初期震荡大 eta_max过高 降低初始学习率
后期收敛缓慢 eta_min过高 减小最小学习率
周期性波动剧烈 T_max过小 增大周期长度

一个典型的生产级配置示例:

optimizer = Adam(model.parameters(), lr=3e-4)
scheduler = CosineAnnealingWarmRestarts(
    optimizer,
    T_0=100,
    T_mult=1,
    eta_min=1e-6,
)

在NLP任务中,配合线性warmup使用效果更佳:

from torch.optim.lr_scheduler import LinearLR

warmup = LinearLR(optimizer, start_factor=0.01, total_iters=10)
cosine = CosineAnnealingLR(optimizer, T_max=90)
scheduler = SequentialLR(optimizer, [warmup, cosine], [10, 90])

这种组合策略在Transformer类模型中表现尤为出色。

Logo

免费领 100 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐