PyTorch Optimizer 与 Scheduler 指南

PyTorch Optimizer 与 Scheduler 指南


📑 目录

  1. 背景与动机
  2. 核心概念与定义
  3. [Optimizer 深入理解](#Optimizer 深入理解)
  4. [Scheduler 深入理解](#Scheduler 深入理解)
  5. [Optimizer 与 Scheduler 的关系](#Optimizer 与 Scheduler 的关系)
  6. [常用 Scheduler 详解](#常用 Scheduler 详解)
  7. 训练循环集成
  8. [PyTorch Lightning 集成](#PyTorch Lightning 集成)
  9. 高级技巧与策略
  10. 常见问题与最佳实践
  11. 扩展阅读与进阶方向

1. 背景与动机

1.1 为什么需要学习率调度?

在深度学习训练中,学习率(Learning Rate) 是最重要的超参数之一。

问题场景

固定学习率的局限

python 复制代码
# 使用固定学习率训练
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

# 问题:
# 1. 训练初期:学习率太大 → 震荡、不稳定
# 2. 训练后期:学习率太大 → 难以收敛到最优点
# 3. 全程使用:无法适应训练的不同阶段

训练曲线示意

复制代码
Loss
 │
 │  固定学习率(lr=0.1)
 │    ╱╲  ╱╲  ╱╲  ╱╲
 │   ╱  ╲╱  ╲╱  ╲╱  ╲  ← 后期震荡,难以收敛
 │  ╱
 │ ╱
 │╱
 └────────────────────> Epochs
 
 │  动态学习率(使用 Scheduler)
 │  ╱╲
 │ ╱  ╲___________  ← 后期学习率降低,平滑收敛
 │╱
 └────────────────────> Epochs

1.2 Scheduler 的核心价值

优势 说明
加速收敛 初期大学习率快速下降 loss
提升性能 后期小学习率精细调优
避免震荡 动态调整避免参数更新过大
泛化能力 特定策略(如余弦退火)提升泛化
自动化 无需手动调整学习率

1.3 实际案例

ImageNet 训练典型策略

python 复制代码
# ResNet 训练方案(论文标准)
optimizer = SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = MultiStepLR(optimizer, milestones=[30, 60, 90], gamma=0.1)

# 学习率变化:
# Epoch 0-29:   lr = 0.1
# Epoch 30-59:  lr = 0.01   (降低 10 倍)
# Epoch 60-89:  lr = 0.001  (再降低 10 倍)
# Epoch 90+:    lr = 0.0001

2. 核心概念与定义

2.1 什么是 Optimizer?

Optimizer(优化器) 是根据损失函数的梯度来更新模型参数的算法。

核心任务

复制代码
参数更新公式(简化版):
θ_new = θ_old - lr × gradient

其中:
- θ: 模型参数
- lr: 学习率
- gradient: 梯度(损失函数对参数的偏导数)

常见 Optimizer

  • SGD: 随机梯度下降
  • Adam: 自适应学习率优化器
  • AdamW: 修正权重衰减的 Adam
  • RMSprop: 自适应学习率方法

2.2 什么是 Scheduler?

Scheduler(学习率调度器) 是动态调整 Optimizer 学习率的策略。

核心任务

复制代码
在训练过程中,根据预定规则调整学习率:
lr(epoch) = f(initial_lr, epoch, ...)

常见策略:
- 阶梯式衰减(StepLR)
- 指数衰减(ExponentialLR)
- 余弦退火(CosineAnnealingLR)
- 基于指标(ReduceLROnPlateau)

2.3 两者的关系

复制代码
关系模型:

┌─────────────────────────────────────┐
│         Training Loop               │
│                                     │
│  ┌──────────────┐                  │
│  │   Model      │                  │
│  └──────┬───────┘                  │
│         │                          │
│         ▼                          │
│  ┌──────────────┐                  │
│  │ Loss & Grad  │                  │
│  └──────┬───────┘                  │
│         │                          │
│         ▼                          │
│  ┌──────────────┐                  │
│  │  Optimizer   │ ◄─────┐          │
│  │  (更新参数)   │       │          │
│  └──────┬───────┘       │          │
│         │            读取/修改 lr   │
│         │               │          │
│  ┌──────▼──────────────┴──┐        │
│  │     Scheduler          │        │
│  │  (调整学习率)          │        │
│  └────────────────────────┘        │
│                                     │
└─────────────────────────────────────┘

关键点:
1. Scheduler 不直接更新参数
2. Scheduler 通过修改 Optimizer 的学习率来影响训练
3. 一个 Optimizer 可以配合多个 Scheduler(链式调度)

3. Optimizer 深入理解

3.1 Optimizer 的内部结构

python 复制代码
import torch.optim as optim

# 创建 Optimizer
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# 查看内部结构
print(optimizer.state_dict())
# 输出:
# {
#   'state': {},  # 优化器状态(如动量)
#   'param_groups': [
#       {
#           'lr': 0.01,
#           'momentum': 0.9,
#           'params': [参数ID列表],
#           ...
#       }
#   ]
# }

关键组成部分

组件 作用 示例
param_groups 参数组列表,每组有独立的超参数 不同层使用不同学习率
lr 学习率 0.01
state 优化器内部状态 Adam 的一阶、二阶动量
params 要优化的参数 model.parameters()

3.2 param_groups 详解

param_groups 是 Scheduler 修改学习率的核心

python 复制代码
# 单个参数组
optimizer = optim.Adam(model.parameters(), lr=0.001)
print(len(optimizer.param_groups))  # 输出: 1

# 访问学习率
current_lr = optimizer.param_groups[0]['lr']
print(f"当前学习率: {current_lr}")

# 手动修改学习率(Scheduler 就是这样做的)
optimizer.param_groups[0]['lr'] = 0.0001

多参数组示例(不同层不同学习率):

python 复制代码
optimizer = optim.SGD([
    {'params': model.base.parameters(), 'lr': 1e-3},  # 参数组 0
    {'params': model.classifier.parameters(), 'lr': 1e-2}  # 参数组 1
], momentum=0.9)

print(len(optimizer.param_groups))  # 输出: 2

# Scheduler 会同时调整两个参数组的学习率

3.3 常用 Optimizer 对比

Optimizer 特点 适用场景 学习率敏感度
SGD 简单、稳定 CV 任务、需要最佳性能 高(需精细调参)
SGD + Momentum 加速收敛、减少震荡 大部分任务
Adam 自适应学习率、快速收敛 NLP、快速原型
AdamW 修正权重衰减 Transformer 模型
RMSprop 适应不同梯度尺度 RNN、强化学习

4. Scheduler 深入理解

4.1 Scheduler 的工作原理

核心机制 :通过修改 optimizer.param_groups[i]['lr'] 来调整学习率。

python 复制代码
# Scheduler 的简化实现
class SimpleScheduler:
    def __init__(self, optimizer, gamma=0.1):
        self.optimizer = optimizer
        self.gamma = gamma
    
    def step(self):
        """每次调用时降低学习率"""
        for param_group in self.optimizer.param_groups:
            param_group['lr'] *= self.gamma
            print(f"学习率更新为: {param_group['lr']}")

# 使用
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = SimpleScheduler(optimizer, gamma=0.1)

scheduler.step()  # lr: 0.1 → 0.01
scheduler.step()  # lr: 0.01 → 0.001

4.2 Scheduler 的分类

复制代码
Scheduler 分类
│
├─ 基于 Epoch 的调度
│  ├─ StepLR (阶梯式)
│  ├─ MultiStepLR (多阶梯)
│  ├─ ExponentialLR (指数衰减)
│  ├─ CosineAnnealingLR (余弦退火)
│  └─ PolynomialLR (多项式)
│
├─ 基于指标的调度
│  └─ ReduceLROnPlateau (性能停滞时降低)
│
├─ 循环调度
│  ├─ CyclicLR (周期性变化)
│  └─ OneCycleLR (单周期策略)
│
└─ 链式调度
   └─ ChainedScheduler (组合多个 Scheduler)

4.3 调用时机

Scheduler 类型 调用位置 调用时机 示例
基于 Epoch epoch 结束后 scheduler.step() StepLR, CosineAnnealingLR
基于 Step 每个 batch 后 scheduler.step() OneCycleLR
基于指标 validation 后 scheduler.step(metric) ReduceLROnPlateau

5. Optimizer 与 Scheduler 的关系

5.1 依赖关系

python 复制代码
# Scheduler 依赖于 Optimizer
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
                                      # ↑ 必须传入 optimizer

# Scheduler 保存了对 Optimizer 的引用
print(scheduler.optimizer is optimizer)  # True

5.2 协作流程

python 复制代码
# 完整训练循环
for epoch in range(num_epochs):
    # 1. 训练阶段
    for batch in train_loader:
        optimizer.zero_grad()        # 清零梯度
        output = model(batch)
        loss = criterion(output, target)
        loss.backward()              # 计算梯度
        optimizer.step()             # 更新参数(使用当前 lr)
    
    # 2. 验证阶段
    val_loss = validate(model, val_loader)
    
    # 3. 学习率调度
    scheduler.step()                 # 调整学习率(for next epoch)
    
    # 4. 日志记录
    current_lr = optimizer.param_groups[0]['lr']
    print(f"Epoch {epoch}, LR: {current_lr}, Val Loss: {val_loss}")

5.3 数据流向

复制代码
训练迭代中的数据流:

Epoch N:
  Train:  optimizer.step() with lr=0.01
  Val:    compute val_loss
  Update: scheduler.step() → lr 变为 0.001
  
Epoch N+1:
  Train:  optimizer.step() with lr=0.001  ← 使用新学习率
  ...

5.4 关键原理

Scheduler 如何修改学习率

python 复制代码
# 查看 PyTorch 源码(简化版)
class StepLR:
    def __init__(self, optimizer, step_size, gamma=0.1):
        self.optimizer = optimizer
        self.step_size = step_size
        self.gamma = gamma
        self.last_epoch = 0
        
        # 保存初始学习率
        self.base_lrs = [group['lr'] for group in optimizer.param_groups]
    
    def step(self):
        self.last_epoch += 1
        
        # 计算新学习率
        if self.last_epoch % self.step_size == 0:
            for i, param_group in enumerate(self.optimizer.param_groups):
                # 直接修改 optimizer 的 lr
                param_group['lr'] = self.base_lrs[i] * (self.gamma ** (self.last_epoch // self.step_size))

6. 常用 Scheduler 详解

6.1 StepLR - 阶梯式衰减

原理:每隔固定 epoch 数,学习率乘以 gamma。

python 复制代码
from torch.optim.lr_scheduler import StepLR

optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = StepLR(
    optimizer,
    step_size=10,    # 每 10 个 epoch 降低一次
    gamma=0.1        # 每次降为原来的 0.1 倍
)

# 学习率变化:
# Epoch 0-9:   lr = 0.1
# Epoch 10-19: lr = 0.01
# Epoch 20-29: lr = 0.001
# Epoch 30+:   lr = 0.0001

可视化

复制代码
lr
0.1 │████████████
    │
0.01│            ████████████
    │
0.001           │            ████████████
    └────────────┴────────────┴────────────> Epoch
         10           20           30

适用场景

  • 训练周期较长的任务
  • 需要明确的学习率下降节点

6.2 MultiStepLR - 多阶梯衰减

原理:在指定的 epoch 降低学习率。

python 复制代码
from torch.optim.lr_scheduler import MultiStepLR

scheduler = MultiStepLR(
    optimizer,
    milestones=[30, 60, 90],  # 在这些 epoch 降低
    gamma=0.1
)

# 学习率变化:
# Epoch 0-29:  lr = 0.1
# Epoch 30-59: lr = 0.01
# Epoch 60-89: lr = 0.001
# Epoch 90+:   lr = 0.0001

适用场景

  • 复现论文配置(如 ResNet 训练)
  • 需要灵活控制降低时机

6.3 ExponentialLR - 指数衰减

原理:每个 epoch 学习率乘以 gamma。

python 复制代码
from torch.optim.lr_scheduler import ExponentialLR

scheduler = ExponentialLR(optimizer, gamma=0.95)

# 学习率变化:
# Epoch 0: lr = 0.1
# Epoch 1: lr = 0.1 × 0.95 = 0.095
# Epoch 2: lr = 0.095 × 0.95 = 0.09025
# ...
# Epoch n: lr = 0.1 × (0.95^n)

可视化

复制代码
lr
0.1 │╲
    │ ╲___
    │     ╲___
    │         ╲___
0.0 └─────────────────> Epoch

适用场景

  • 需要平滑衰减
  • 长期训练任务

6.4 CosineAnnealingLR - 余弦退火

原理:学习率按余弦函数变化。

python 复制代码
from torch.optim.lr_scheduler import CosineAnnealingLR

scheduler = CosineAnnealingLR(
    optimizer,
    T_max=100,       # 周期长度(epoch 数)
    eta_min=1e-6     # 最小学习率
)

# 学习率公式:
# lr(epoch) = eta_min + (lr_initial - eta_min) * (1 + cos(π × epoch / T_max)) / 2

可视化

复制代码
lr
0.1 │╲       ╱
    │ ╲     ╱
    │  ╲   ╱
    │   ╲ ╱
0.0 └────▼─────────> Epoch
         T_max

适用场景

  • Transformer 训练(BERT、GPT)
  • 需要在训练末期探索更好的局部最优
  • 周期性任务

优势

  • 平滑过渡
  • 后期缓慢下降利于收敛

6.5 ReduceLROnPlateau - 基于指标自适应

原理:当监控指标停滞时降低学习率。

python 复制代码
from torch.optim.lr_scheduler import ReduceLROnPlateau

scheduler = ReduceLROnPlateau(
    optimizer,
    mode='min',          # 'min' 或 'max'
    factor=0.1,          # 降低倍数
    patience=10,         # 容忍多少 epoch 不改善
    threshold=1e-4,      # 改善的最小阈值
    verbose=True
)

# 使用方式不同:需要传入指标
for epoch in range(num_epochs):
    train(...)
    val_loss = validate(...)
    scheduler.step(val_loss)  # ← 传入验证指标

工作逻辑

复制代码
Epoch 1-10:  val_loss 持续下降 → lr 保持 0.1
Epoch 11-20: val_loss 停滞不降 → 等待(patience)
Epoch 21:    超过 patience → lr 降为 0.01
...

适用场景

  • 不确定何时降低学习率
  • 基于验证集性能自适应
  • 调试阶段

6.6 OneCycleLR - 单周期策略

原理:学习率先增后减,配合动量变化。

python 复制代码
from torch.optim.lr_scheduler import OneCycleLR

scheduler = OneCycleLR(
    optimizer,
    max_lr=0.1,              # 最大学习率
    total_steps=len(train_loader) * num_epochs,  # 总步数
    pct_start=0.3,           # 增长阶段占比(30%)
    anneal_strategy='cos',   # 'cos' 或 'linear'
    div_factor=25,           # 初始 lr = max_lr / div_factor
    final_div_factor=1e4     # 最终 lr = max_lr / final_div_factor
)

# 在每个 batch 后调用
for epoch in range(num_epochs):
    for batch in train_loader:
        optimizer.zero_grad()
        loss = ...
        loss.backward()
        optimizer.step()
        scheduler.step()  # ← 每个 step 调用

学习率曲线

复制代码
lr
    │      ╱╲
0.1 │     ╱  ╲
    │    ╱    ╲
    │   ╱      ╲___
    │  ╱           ╲___
    │ ╱                ╲___
0.0 └────────────────────────> Steps
      增长  峰值     衰减
      30%   点      70%

适用场景

  • 快速收敛(fastai 推荐)
  • 训练周期较短的任务
  • 配合较大 batch size

6.7 CyclicLR - 周期性学习率

原理:学习率在 base_lr 和 max_lr 之间周期性变化。

python 复制代码
from torch.optim.lr_scheduler import CyclicLR

scheduler = CyclicLR(
    optimizer,
    base_lr=0.001,
    max_lr=0.1,
    step_size_up=2000,     # 上升阶段步数
    mode='triangular',     # 'triangular', 'triangular2', 'exp_range'
)

# 每个 batch 后调用
for batch in train_loader:
    ...
    scheduler.step()

模式对比

复制代码
triangular (三角波):
    ╱╲  ╱╲  ╱╲
   ╱  ╲╱  ╲╱  ╲

triangular2 (递减三角):
    ╱╲  ╱╲ ╱
   ╱  ╲╱  ▼

exp_range (指数):
    ╱╲ ╱╲╱
   ╱  ▼

适用场景

  • 避免陷入局部最优
  • 探索不同学习率区间

6.8 Scheduler 对比表

Scheduler 调用时机 主要参数 适用场景 学习率变化
StepLR epoch 结束 step_size, gamma 简单任务 阶梯式
MultiStepLR epoch 结束 milestones, gamma 论文复现 多阶梯
ExponentialLR epoch 结束 gamma 长期训练 指数衰减
CosineAnnealingLR epoch 结束 T_max, eta_min Transformer 余弦曲线
ReduceLROnPlateau validation 后 patience, factor 自适应场景 基于指标
OneCycleLR 每个 batch max_lr, total_steps 快速收敛 单周期
CyclicLR 每个 batch base_lr, max_lr 探索最优 周期性

7. 训练循环集成

7.1 基础训练循环(基于 Epoch 的 Scheduler)

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR

# 1. 准备模型、优化器、调度器
model = MyModel()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = CosineAnnealingLR(optimizer, T_max=100)

criterion = nn.CrossEntropyLoss()

# 2. 训练循环
num_epochs = 100
for epoch in range(num_epochs):
    # ========== 训练阶段 ==========
    model.train()
    train_loss = 0.0
    
    for batch_idx, (data, target) in enumerate(train_loader):
        # 前向传播
        output = model(data)
        loss = criterion(output, target)
        
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        train_loss += loss.item()
    
    avg_train_loss = train_loss / len(train_loader)
    
    # ========== 验证阶段 ==========
    model.eval()
    val_loss = 0.0
    
    with torch.no_grad():
        for data, target in val_loader:
            output = model(data)
            loss = criterion(output, target)
            val_loss += loss.item()
    
    avg_val_loss = val_loss / len(val_loader)
    
    # ========== 学习率调度 ==========
    scheduler.step()  # 调整学习率
    
    # ========== 日志记录 ==========
    current_lr = optimizer.param_groups[0]['lr']
    print(f"Epoch {epoch+1}/{num_epochs}")
    print(f"  Train Loss: {avg_train_loss:.4f}")
    print(f"  Val Loss: {avg_val_loss:.4f}")
    print(f"  Learning Rate: {current_lr:.6f}")

7.2 使用 ReduceLROnPlateau

python 复制代码
from torch.optim.lr_scheduler import ReduceLROnPlateau

optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = ReduceLROnPlateau(
    optimizer, 
    mode='min', 
    factor=0.5, 
    patience=5,
    verbose=True
)

for epoch in range(num_epochs):
    # 训练
    train_loss = train_epoch(model, train_loader, optimizer, criterion)
    
    # 验证
    val_loss = validate(model, val_loader, criterion)
    
    # 学习率调度(传入验证指标)
    scheduler.step(val_loss)  # ← 关键:传入 metric
    
    # 日志
    current_lr = optimizer.param_groups[0]['lr']
    print(f"Epoch {epoch}, Val Loss: {val_loss:.4f}, LR: {current_lr:.6f}")

7.3 使用 OneCycleLR(基于 Step)

python 复制代码
from torch.optim.lr_scheduler import OneCycleLR

# 计算总步数
total_steps = len(train_loader) * num_epochs

optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = OneCycleLR(
    optimizer,
    max_lr=0.1,
    total_steps=total_steps,
    pct_start=0.3
)

for epoch in range(num_epochs):
    model.train()
    
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        
        # 每个 batch 后调用
        scheduler.step()  # ← 关键:每步调用
        
        # 可选:打印当前学习率
        if batch_idx % 100 == 0:
            current_lr = optimizer.param_groups[0]['lr']
            print(f"Epoch {epoch}, Batch {batch_idx}, LR: {current_lr:.6f}")

7.4 链式 Scheduler(组合多个策略)

python 复制代码
from torch.optim.lr_scheduler import SequentialLR, LinearLR, CosineAnnealingLR

# 前 10 个 epoch 线性增长(warmup),之后余弦退火
scheduler1 = LinearLR(optimizer, start_factor=0.1, total_iters=10)
scheduler2 = CosineAnnealingLR(optimizer, T_max=90)

scheduler = SequentialLR(
    optimizer,
    schedulers=[scheduler1, scheduler2],
    milestones=[10]  # 在 epoch 10 切换
)

for epoch in range(100):
    train(...)
    scheduler.step()

7.5 完整示例:ResNet 训练配置

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import MultiStepLR
from torchvision.models import resnet50

# 1. 模型和数据
model = resnet50(pretrained=False, num_classes=10)
train_loader = ...  # 你的数据加载器
val_loader = ...

# 2. 优化器配置(ImageNet 标准)
optimizer = optim.SGD(
    model.parameters(),
    lr=0.1,
    momentum=0.9,
    weight_decay=1e-4
)

# 3. 学习率调度器(ImageNet 标准)
scheduler = MultiStepLR(
    optimizer,
    milestones=[30, 60, 90],
    gamma=0.1
)

# 4. 损失函数
criterion = nn.CrossEntropyLoss()

# 5. 训练循环
num_epochs = 100
best_acc = 0.0

for epoch in range(num_epochs):
    # 训练
    model.train()
    for data, target in train_loader:
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
    
    # 验证
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for data, target in val_loader:
            output = model(data)
            _, predicted = output.max(1)
            total += target.size(0)
            correct += predicted.eq(target).sum().item()
    
    acc = 100. * correct / total
    
    # 学习率调度
    scheduler.step()
    
    # 保存最佳模型
    if acc > best_acc:
        best_acc = acc
        torch.save(model.state_dict(), 'best_model.pth')
    
    # 日志
    current_lr = optimizer.param_groups[0]['lr']
    print(f"Epoch {epoch+1}/{num_epochs}")
    print(f"  Accuracy: {acc:.2f}%")
    print(f"  Best Accuracy: {best_acc:.2f}%")
    print(f"  Learning Rate: {current_lr}")

8. PyTorch Lightning 集成

8.1 基础配置方法

在 PyTorch Lightning 中,通过 configure_optimizers() 方法返回 Optimizer 和 Scheduler。

python 复制代码
import pytorch_lightning as pl
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR

class MyLightningModel(pl.LightningModule):
    def __init__(self, lr=0.001):
        super().__init__()
        self.lr = lr
        self.model = ...  # 你的模型
    
    def configure_optimizers(self):
        # 方式1:仅返回 optimizer
        optimizer = optim.Adam(self.parameters(), lr=self.lr)
        return optimizer
    
    # 其他方法:training_step, validation_step, etc.

8.2 配置 Optimizer + Scheduler

python 复制代码
class MyLightningModel(pl.LightningModule):
    def configure_optimizers(self):
        optimizer = optim.Adam(self.parameters(), lr=0.001)
        scheduler = CosineAnnealingLR(optimizer, T_max=100)
        
        # 返回字典格式
        return {
            'optimizer': optimizer,
            'lr_scheduler': {
                'scheduler': scheduler,
                'interval': 'epoch',  # 'epoch' 或 'step'
                'frequency': 1,       # 每隔多少 interval 调用一次
                'monitor': 'val_loss',  # 用于 ReduceLROnPlateau
            }
        }

8.3 完整配置选项

python 复制代码
def configure_optimizers(self):
    optimizer = optim.SGD(self.parameters(), lr=0.1, momentum=0.9)
    scheduler = MultiStepLR(optimizer, milestones=[30, 60], gamma=0.1)
    
    return {
        'optimizer': optimizer,
        'lr_scheduler': {
            'scheduler': scheduler,
            
            # 调用时机
            'interval': 'epoch',      # 'epoch' 或 'step'
            'frequency': 1,           # 每 N 个 interval 调用一次
            
            # 用于 ReduceLROnPlateau
            'monitor': 'val_loss',    # 监控的指标
            'strict': True,           # 如果 monitor 不存在是否报错
            
            # 其他
            'name': 'my_scheduler',   # TensorBoard 中显示的名称
        }
    }

8.4 使用 ReduceLROnPlateau

python 复制代码
from torch.optim.lr_scheduler import ReduceLROnPlateau

class MyModel(pl.LightningModule):
    def configure_optimizers(self):
        optimizer = optim.Adam(self.parameters(), lr=0.001)
        scheduler = ReduceLROnPlateau(
            optimizer, 
            mode='min', 
            factor=0.5, 
            patience=10
        )
        
        return {
            'optimizer': optimizer,
            'lr_scheduler': {
                'scheduler': scheduler,
                'monitor': 'val_loss',  # 关键:必须指定 monitor
                'interval': 'epoch',
            }
        }
    
    def validation_step(self, batch, batch_idx):
        # 确保记录了 val_loss
        loss = ...
        self.log('val_loss', loss)  # ← 必须记录
        return loss

8.5 使用 OneCycleLR

python 复制代码
from torch.optim.lr_scheduler import OneCycleLR

class MyModel(pl.LightningModule):
    def __init__(self, total_steps):
        super().__init__()
        self.total_steps = total_steps
    
    def configure_optimizers(self):
        optimizer = optim.SGD(self.parameters(), lr=0.1, momentum=0.9)
        scheduler = OneCycleLR(
            optimizer,
            max_lr=0.1,
            total_steps=self.total_steps,
        )
        
        return {
            'optimizer': optimizer,
            'lr_scheduler': {
                'scheduler': scheduler,
                'interval': 'step',  # 关键:每个 step 调用
            }
        }

# 使用时计算 total_steps
total_steps = len(train_loader) * num_epochs
model = MyModel(total_steps=total_steps)
trainer = pl.Trainer(max_epochs=num_epochs)

8.6 多个 Optimizer 和 Scheduler

python 复制代码
class MyGAN(pl.LightningModule):
    def configure_optimizers(self):
        # 生成器优化器
        opt_g = optim.Adam(self.generator.parameters(), lr=0.0002)
        # 判别器优化器
        opt_d = optim.Adam(self.discriminator.parameters(), lr=0.0002)
        
        # 生成器调度器
        sch_g = CosineAnnealingLR(opt_g, T_max=100)
        # 判别器调度器
        sch_d = CosineAnnealingLR(opt_d, T_max=100)
        
        return [opt_g, opt_d], [sch_g, sch_d]

8.7 自动记录学习率

PyTorch Lightning 会自动记录学习率到日志(需要配合 LearningRateMonitor):

python 复制代码
from pytorch_lightning.callbacks import LearningRateMonitor

# 创建 Callback
lr_monitor = LearningRateMonitor(logging_interval='epoch')

# 训练
trainer = pl.Trainer(
    max_epochs=100,
    callbacks=[lr_monitor]
)
trainer.fit(model)

# 学习率会自动记录到 TensorBoard/WandB

8.8 完整 Lightning 示例

python 复制代码
import pytorch_lightning as pl
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim.lr_scheduler import CosineAnnealingLR
from pytorch_lightning.callbacks import ModelCheckpoint, LearningRateMonitor

class MyClassifier(pl.LightningModule):
    def __init__(self, input_dim, num_classes, lr=0.001):
        super().__init__()
        self.save_hyperparameters()
        
        self.model = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Linear(128, num_classes)
        )
        self.criterion = nn.CrossEntropyLoss()
    
    def forward(self, x):
        return self.model(x)
    
    def training_step(self, batch, batch_idx):
        x, y = batch
        y_hat = self(x)
        loss = self.criterion(y_hat, y)
        
        # 记录指标
        self.log('train_loss', loss, on_step=False, on_epoch=True)
        return loss
    
    def validation_step(self, batch, batch_idx):
        x, y = batch
        y_hat = self(x)
        loss = self.criterion(y_hat, y)
        
        acc = (y_hat.argmax(dim=1) == y).float().mean()
        
        # 记录指标
        self.log('val_loss', loss, prog_bar=True)
        self.log('val_acc', acc, prog_bar=True)
    
    def configure_optimizers(self):
        optimizer = optim.Adam(self.parameters(), lr=self.hparams.lr)
        scheduler = CosineAnnealingLR(optimizer, T_max=100)
        
        return {
            'optimizer': optimizer,
            'lr_scheduler': {
                'scheduler': scheduler,
                'interval': 'epoch',
            }
        }

# 使用
model = MyClassifier(input_dim=784, num_classes=10, lr=0.001)

trainer = pl.Trainer(
    max_epochs=100,
    callbacks=[
        ModelCheckpoint(monitor='val_loss', mode='min'),
        LearningRateMonitor(logging_interval='epoch'),
    ],
)

trainer.fit(model, train_loader, val_loader)

9. 高级技巧与策略

9.1 Warmup 策略

概念:训练初期使用较小的学习率,逐步增加到目标值,避免初期梯度过大导致不稳定。

方法 1:使用 LinearLR + SequentialLR
python 复制代码
from torch.optim.lr_scheduler import LinearLR, CosineAnnealingLR, SequentialLR

optimizer = optim.Adam(model.parameters(), lr=0.001)

# Warmup: 前 5 个 epoch 从 0.0001 线性增长到 0.001
warmup_scheduler = LinearLR(
    optimizer,
    start_factor=0.1,  # 初始 lr = 0.001 × 0.1 = 0.0001
    total_iters=5      # 5 个 epoch
)

# 主调度器
main_scheduler = CosineAnnealingLR(optimizer, T_max=95)

# 组合
scheduler = SequentialLR(
    optimizer,
    schedulers=[warmup_scheduler, main_scheduler],
    milestones=[5]  # 在 epoch 5 切换
)

# 使用
for epoch in range(100):
    train(...)
    scheduler.step()
方法 2:自定义 Warmup Scheduler
python 复制代码
class WarmupScheduler:
    """带 Warmup 的调度器"""
    
    def __init__(self, optimizer, warmup_epochs, base_scheduler):
        self.optimizer = optimizer
        self.warmup_epochs = warmup_epochs
        self.base_scheduler = base_scheduler
        self.current_epoch = 0
        
        # 保存初始学习率
        self.base_lrs = [group['lr'] for group in optimizer.param_groups]
    
    def step(self):
        if self.current_epoch < self.warmup_epochs:
            # Warmup 阶段:线性增长
            warmup_factor = (self.current_epoch + 1) / self.warmup_epochs
            for i, param_group in enumerate(self.optimizer.param_groups):
                param_group['lr'] = self.base_lrs[i] * warmup_factor
        else:
            # 主调度阶段
            self.base_scheduler.step()
        
        self.current_epoch += 1

# 使用
optimizer = optim.Adam(model.parameters(), lr=0.001)
base_scheduler = CosineAnnealingLR(optimizer, T_max=95)
scheduler = WarmupScheduler(optimizer, warmup_epochs=5, base_scheduler=base_scheduler)

for epoch in range(100):
    train(...)
    scheduler.step()
PyTorch Lightning 中的 Warmup
python 复制代码
from torch.optim.lr_scheduler import LambdaLR

class MyModel(pl.LightningModule):
    def configure_optimizers(self):
        optimizer = optim.Adam(self.parameters(), lr=0.001)
        
        # 使用 LambdaLR 实现 Warmup + Cosine
        def lr_lambda(epoch):
            warmup_epochs = 5
            max_epochs = 100
            
            if epoch < warmup_epochs:
                # Warmup
                return (epoch + 1) / warmup_epochs
            else:
                # Cosine Annealing
                progress = (epoch - warmup_epochs) / (max_epochs - warmup_epochs)
                return 0.5 * (1 + math.cos(math.pi * progress))
        
        scheduler = LambdaLR(optimizer, lr_lambda)
        
        return {'optimizer': optimizer, 'lr_scheduler': scheduler}

9.2 不同层不同学习率

概念:对模型不同部分使用不同的学习率(常用于迁移学习)。

python 复制代码
# 场景:微调预训练模型
import torchvision.models as models

model = models.resnet50(pretrained=True)

# 冻结早期层,仅微调后期层
for param in model.layer1.parameters():
    param.requires_grad = False
for param in model.layer2.parameters():
    param.requires_grad = False

# 不同层使用不同学习率
optimizer = optim.SGD([
    {'params': model.layer3.parameters(), 'lr': 1e-4},  # 小学习率
    {'params': model.layer4.parameters(), 'lr': 1e-3},  # 中等学习率
    {'params': model.fc.parameters(), 'lr': 1e-2}       # 大学习率
], momentum=0.9)

# Scheduler 会同时调整所有参数组的学习率
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)

# 查看各组学习率
for i, param_group in enumerate(optimizer.param_groups):
    print(f"参数组 {i} 学习率: {param_group['lr']}")

PyTorch Lightning 中的实现

python 复制代码
class FineTuneModel(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.backbone = models.resnet50(pretrained=True)
        self.classifier = nn.Linear(2048, 10)
    
    def configure_optimizers(self):
        # 不同部分使用不同学习率
        optimizer = optim.Adam([
            {'params': self.backbone.parameters(), 'lr': 1e-4},
            {'params': self.classifier.parameters(), 'lr': 1e-3}
        ])
        
        scheduler = CosineAnnealingLR(optimizer, T_max=100)
        
        return {'optimizer': optimizer, 'lr_scheduler': scheduler}

9.3 梯度累积与学习率

当使用梯度累积时,可能需要调整学习率:

python 复制代码
# 等效 batch size = batch_size × accumulate_grad_batches
# 建议按比例调整学习率

accumulate_grad_batches = 4
base_lr = 0.001

# 调整学习率(线性缩放规则)
adjusted_lr = base_lr * accumulate_grad_batches

optimizer = optim.Adam(model.parameters(), lr=adjusted_lr)

在 PyTorch Lightning 中

python 复制代码
trainer = pl.Trainer(
    accumulate_grad_batches=4,  # 每 4 个 batch 更新一次
)

# 模型中相应调整学习率
class MyModel(pl.LightningModule):
    def configure_optimizers(self):
        # 考虑梯度累积的学习率
        accumulate = self.trainer.accumulate_grad_batches
        adjusted_lr = self.hparams.lr * accumulate
        
        optimizer = optim.Adam(self.parameters(), lr=adjusted_lr)
        # ...

9.4 学习率查找器(LR Finder)

概念:通过逐步增加学习率找到最优初始值。

python 复制代码
from torch_lr_finder import LRFinder

# 创建模型和优化器
model = MyModel()
optimizer = optim.Adam(model.parameters(), lr=1e-7)
criterion = nn.CrossEntropyLoss()

# LR Finder
lr_finder = LRFinder(model, optimizer, criterion)
lr_finder.range_test(train_loader, start_lr=1e-7, end_lr=10, num_iter=100)

# 绘制曲线
lr_finder.plot()  # 查看 loss vs lr 曲线

# 选择最优学习率(通常选择下降最快的点)
best_lr = lr_finder.history['lr'][lr_finder.history['loss'].index(min(lr_finder.history['loss']))]
print(f"建议学习率: {best_lr}")

# 重置模型
lr_finder.reset()

在 PyTorch Lightning 中

python 复制代码
from pytorch_lightning.tuner import Tuner

model = MyModel()
trainer = pl.Trainer()

# 自动查找学习率
tuner = Tuner(trainer)
lr_finder = tuner.lr_find(model, train_loader)

# 查看结果
fig = lr_finder.plot(suggest=True)
fig.show()

# 更新模型学习率
model.hparams.lr = lr_finder.suggestion()

9.5 周期性重启(Cosine Annealing with Warm Restarts)

python 复制代码
from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts

optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = CosineAnnealingWarmRestarts(
    optimizer,
    T_0=10,      # 第一个周期的长度
    T_mult=2,    # 每次重启后周期长度乘以的倍数
    eta_min=1e-6 # 最小学习率
)

# 学习率变化:
# Epoch 0-9:   第一个周期(余弦下降)
# Epoch 10-29: 第二个周期(长度 × 2 = 20)
# Epoch 30-69: 第三个周期(长度 × 2 = 40)

学习率曲线

复制代码
lr
    │╲    ╱╲        ╱╲
0.1 │ ╲  ╱  ╲      ╱  ╲
    │  ╲╱    ╲    ╱    ╲
    │   ▼     ╲  ╱      ╲___
    │          ╲╱
0.0 └────────────────────────────> Epoch
       10      30         70
       ↑       ↑          ↑
      重启    重启        重启

10. 常见问题与最佳实践

10.1 常见错误

错误 1:Scheduler 调用时机错误
python 复制代码
# ❌ 错误:在 optimizer.step() 之前调用
optimizer.step()
scheduler.step()  # 正确位置

scheduler.step()  # ❌ 错误位置
optimizer.step()

# ✅ 正确顺序
for epoch in range(num_epochs):
    for batch in train_loader:
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()  # 先更新参数
    scheduler.step()      # 再调整学习率
错误 2:忘记调用 scheduler.step()
python 复制代码
# ❌ 错误:创建了 Scheduler 但忘记调用
scheduler = StepLR(optimizer, step_size=10)

for epoch in range(num_epochs):
    train(...)
    # 忘记调用 scheduler.step()

# 结果:学习率始终不变
错误 3:ReduceLROnPlateau 没有传入 metric
python 复制代码
# ❌ 错误
scheduler = ReduceLROnPlateau(optimizer, mode='min')
scheduler.step()  # 缺少参数

# ✅ 正确
val_loss = validate(...)
scheduler.step(val_loss)
错误 4:OneCycleLR 使用错误的调用频率
python 复制代码
# ❌ 错误:OneCycleLR 应该每个 batch 调用,而非每个 epoch
scheduler = OneCycleLR(optimizer, max_lr=0.1, total_steps=total_steps)

for epoch in range(num_epochs):
    train(...)
    scheduler.step()  # ❌ 错误:应该在 batch 循环内

# ✅ 正确
for epoch in range(num_epochs):
    for batch in train_loader:
        ...
        optimizer.step()
        scheduler.step()  # ✅ 每个 batch 调用
错误 5:修改学习率后没有更新 Scheduler
python 复制代码
# ❌ 错误:手动修改学习率会导致 Scheduler 失效
optimizer.param_groups[0]['lr'] = 0.0001  # 手动修改
scheduler.step()  # Scheduler 基于旧的 base_lr 计算

# ✅ 正确:重新创建 Scheduler
optimizer.param_groups[0]['lr'] = 0.0001
scheduler = StepLR(optimizer, step_size=10)

10.2 调试技巧

技巧 1:打印学习率变化
python 复制代码
class LRLogger:
    """记录学习率变化"""
    def __init__(self, optimizer):
        self.optimizer = optimizer
        self.lr_history = []
    
    def log(self, epoch):
        lr = self.optimizer.param_groups[0]['lr']
        self.lr_history.append(lr)
        print(f"Epoch {epoch}, LR: {lr:.6f}")
    
    def plot(self):
        import matplotlib.pyplot as plt
        plt.plot(self.lr_history)
        plt.xlabel('Epoch')
        plt.ylabel('Learning Rate')
        plt.title('Learning Rate Schedule')
        plt.show()

# 使用
logger = LRLogger(optimizer)

for epoch in range(num_epochs):
    train(...)
    scheduler.step()
    logger.log(epoch)

logger.plot()
技巧 2:验证 Scheduler 配置
python 复制代码
def verify_scheduler(optimizer, scheduler, num_epochs=20):
    """验证 Scheduler 行为"""
    print("验证学习率调度:")
    print("-" * 50)
    
    for epoch in range(num_epochs):
        lr = optimizer.param_groups[0]['lr']
        print(f"Epoch {epoch:3d}: LR = {lr:.6f}")
        scheduler.step()

# 使用
optimizer = optim.SGD(model.parameters(), lr=0.1)
scheduler = StepLR(optimizer, step_size=5, gamma=0.1)
verify_scheduler(optimizer, scheduler)
技巧 3:使用 TensorBoard 可视化
python 复制代码
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('runs/lr_schedule')

for epoch in range(num_epochs):
    train(...)
    
    # 记录学习率
    lr = optimizer.param_groups[0]['lr']
    writer.add_scalar('Learning Rate', lr, epoch)
    
    scheduler.step()

writer.close()

10.3 最佳实践

✅ 推荐做法

1. 明确调用时机

python 复制代码
# 基于 Epoch 的 Scheduler
for epoch in range(num_epochs):
    train_one_epoch(...)
    validate(...)
    scheduler.step()  # epoch 结束后

# 基于 Step 的 Scheduler
for epoch in range(num_epochs):
    for batch in train_loader:
        optimizer.step()
        scheduler.step()  # 每个 batch 后

2. 记录学习率到日志

python 复制代码
# PyTorch Lightning 自动记录
from pytorch_lightning.callbacks import LearningRateMonitor
trainer = pl.Trainer(callbacks=[LearningRateMonitor()])

# 手动记录
self.log('learning_rate', optimizer.param_groups[0]['lr'])

3. 保存和恢复 Scheduler 状态

python 复制代码
# 保存
checkpoint = {
    'model': model.state_dict(),
    'optimizer': optimizer.state_dict(),
    'scheduler': scheduler.state_dict(),  # 保存 Scheduler 状态
    'epoch': epoch,
}
torch.save(checkpoint, 'checkpoint.pth')

# 加载
checkpoint = torch.load('checkpoint.pth')
model.load_state_dict(checkpoint['model'])
optimizer.load_state_dict(checkpoint['optimizer'])
scheduler.load_state_dict(checkpoint['scheduler'])

4. 使用 Warmup

python 复制代码
# 大模型训练建议使用 Warmup
warmup_scheduler = LinearLR(optimizer, start_factor=0.1, total_iters=5)
main_scheduler = CosineAnnealingLR(optimizer, T_max=95)
scheduler = SequentialLR(optimizer, [warmup_scheduler, main_scheduler], milestones=[5])

5. 文档化配置

python 复制代码
# 在代码中明确注释 Scheduler 配置
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = CosineAnnealingLR(
    optimizer,
    T_max=100,  # 训练 100 个 epoch
    eta_min=1e-6  # 最小学习率
)
# 学习率从 0.001 余弦退火到 1e-6
❌ 避免的做法

1. 混用不兼容的 Scheduler

python 复制代码
# ❌ 错误:同时使用多个 Scheduler(未使用 ChainedScheduler)
scheduler1 = StepLR(optimizer, step_size=10)
scheduler2 = ExponentialLR(optimizer, gamma=0.9)

for epoch in range(num_epochs):
    scheduler1.step()
    scheduler2.step()  # 会相互干扰

2. 在错误的地方修改学习率

python 复制代码
# ❌ 错误:在训练循环内手动修改
for epoch in range(num_epochs):
    for batch in train_loader:
        optimizer.param_groups[0]['lr'] *= 0.99  # 每个 batch 都修改

3. 忽略 Scheduler 的返回值

python 复制代码
# 某些 Scheduler 可能返回有用信息
# 虽然大多数情况下可以忽略,但了解返回值有助于调试

10.4 性能优化

技巧 1:避免频繁创建 Scheduler

python 复制代码
# ❌ 低效
for epoch in range(num_epochs):
    scheduler = StepLR(optimizer, step_size=10)  # 每次都创建
    scheduler.step()

# ✅ 高效
scheduler = StepLR(optimizer, step_size=10)  # 创建一次
for epoch in range(num_epochs):
    scheduler.step()

技巧 2:使用 Scheduler 的 state_dict 减少内存

python 复制代码
# 如果只保存检查点,不需要完整 Scheduler 对象
scheduler_state = scheduler.state_dict()  # 仅状态字典

10.5 常见场景推荐

场景 推荐 Scheduler 配置建议
CV 分类(ResNet 风格) MultiStepLR milestones=[30, 60, 90], gamma=0.1
Transformer 训练 CosineAnnealingLR + Warmup T_max=max_epochs, warmup=5-10%
迁移学习/微调 ReduceLROnPlateau patience=5-10, factor=0.5
快速原型开发 OneCycleLR max_lr=1e-3, pct_start=0.3
长期训练(>100 epochs) CosineAnnealingWarmRestarts T_0=10, T_mult=2
调试阶段 StepLR step_size=5, gamma=0.1(简单可控)

11. 扩展阅读与进阶方向

11.1 官方文档

11.2 经典论文

学习率调度相关论文
  1. Cyclical Learning Rates for Training Neural Networks

    • 作者: Leslie N. Smith
    • 介绍: CyclicLR 的原理和应用
  2. SGDR: Stochastic Gradient Descent with Warm Restarts

    • 作者: Ilya Loshchilov, Frank Hutter
    • 介绍: CosineAnnealingWarmRestarts
  3. Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates

    • 作者: Leslie N. Smith, Nicholay Topin
    • 介绍: OneCycleLR(1cycle policy)
  4. Decoupled Weight Decay Regularization

    • 作者: Ilya Loshchilov, Frank Hutter
    • 介绍: AdamW 优化器

11.3 高级主题

11.3.1 自定义 Scheduler
python 复制代码
from torch.optim.lr_scheduler import _LRScheduler

class CustomScheduler(_LRScheduler):
    """自定义学习率调度器"""
    
    def __init__(self, optimizer, max_epochs, last_epoch=-1):
        self.max_epochs = max_epochs
        super().__init__(optimizer, last_epoch)
    
    def get_lr(self):
        """计算当前学习率"""
        # 自定义调度逻辑
        progress = self.last_epoch / self.max_epochs
        
        # 示例:平方根衰减
        factor = (1 - progress) ** 0.5
        
        return [base_lr * factor for base_lr in self.base_lrs]

# 使用
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = CustomScheduler(optimizer, max_epochs=100)
11.3.2 集成外部库

使用 transformers 的 Scheduler:

python 复制代码
from transformers import get_cosine_schedule_with_warmup

optimizer = optim.AdamW(model.parameters(), lr=5e-5)
scheduler = get_cosine_schedule_with_warmup(
    optimizer,
    num_warmup_steps=500,
    num_training_steps=10000
)

使用 timm 的 Scheduler:

python 复制代码
from timm.scheduler import CosineLRScheduler

scheduler = CosineLRScheduler(
    optimizer,
    t_initial=100,
    warmup_t=5,
    warmup_lr_init=1e-6,
)

11.4 实战项目推荐

  1. 复现 ImageNet 训练:使用标准的 MultiStepLR 配置
  2. 训练 BERT/GPT:实现 Warmup + Cosine Annealing
  3. 对比实验:在同一任务上对比不同 Scheduler 的效果
  4. 超参数搜索:使用 Optuna/Ray Tune 自动搜索最优 Scheduler 配置

11.5 相关工具

  • TensorBoard: 可视化学习率曲线
  • WandB: 实验追踪,对比不同 Scheduler
  • Optuna: 超参数优化,包括 Scheduler 参数
  • Ray Tune: 分布式超参数搜索

📌 总结

核心要点回顾

  1. Optimizer 与 Scheduler 的关系:

    • Optimizer 负责更新参数
    • Scheduler 负责调整 Optimizer 的学习率
    • Scheduler 通过修改 optimizer.param_groups[i]['lr'] 实现
  2. 关键概念:

    • param_groups: Optimizer 的参数组,存储学习率等超参数
    • 调用时机: 基于 epoch/step/metric 的不同调度策略
    • Warmup: 训练初期逐步增加学习率的策略
  3. 常用 Scheduler:

    • StepLR/MultiStepLR: 阶梯式衰减(CV 常用)
    • CosineAnnealingLR: 余弦退火(Transformer 常用)
    • ReduceLROnPlateau: 自适应调整(调试友好)
    • OneCycleLR: 快速收敛(fastai 推荐)
  4. PyTorch Lightning 集成:

    • 通过 configure_optimizers() 返回配置
    • 使用 LearningRateMonitor 自动记录
  5. 最佳实践:

    • 明确调用时机(epoch vs step)
    • 使用 Warmup 提升稳定性
    • 记录学习率到日志
    • 保存 Scheduler 状态到检查点

Optimizer + Scheduler 快速参考

基础模板:

python 复制代码
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = CosineAnnealingLR(optimizer, T_max=100)

for epoch in range(num_epochs):
    train_one_epoch(model, train_loader, optimizer)
    validate(model, val_loader)
    scheduler.step()

PyTorch Lightning 模板:

python 复制代码
def configure_optimizers(self):
    optimizer = optim.Adam(self.parameters(), lr=0.001)
    scheduler = CosineAnnealingLR(optimizer, T_max=100)
    return {'optimizer': optimizer, 'lr_scheduler': scheduler}

常用配置:

python 复制代码
# CV 任务
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = MultiStepLR(optimizer, milestones=[30, 60, 90], gamma=0.1)

# Transformer
optimizer = optim.AdamW(model.parameters(), lr=5e-5)
scheduler = CosineAnnealingLR(optimizer, T_max=100)

# 快速收敛
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
scheduler = OneCycleLR(optimizer, max_lr=0.1, total_steps=total_steps)

相关推荐
AngelPP1 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年1 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
AI探索者1 小时前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者2 小时前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
九狼2 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS2 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区3 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈3 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
FishCoderh3 小时前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅3 小时前
Python函数入门详解(定义+调用+参数)
python