学习率调度:PyTorch训练过程动态调整策略
·
学习率调度:PyTorch训练过程动态调整策略
引言:为什么学习率调度如此重要?
在深度学习模型训练过程中,学习率(Learning Rate)是最关键的超参数之一。它决定了模型参数在每次迭代中更新的步长大小。一个合适的学习率可以显著加速模型收敛,提高训练效率,而一个不恰当的学习率则可能导致训练过程发散或陷入局部最优解。
痛点场景:你是否遇到过以下情况?
- 训练初期loss下降迅速,但后期几乎停滞不前?
- 模型在验证集上的表现波动剧烈,难以稳定提升?
- 尝试了各种学习率值,但始终无法找到最优设置?
这些问题往往可以通过智能的学习率调度策略来解决。本文将深入探讨PyTorch中的学习率调度机制,帮助你掌握动态调整学习率的艺术。
学习率调度基础概念
什么是学习率调度?
学习率调度(Learning Rate Scheduling)是指在训练过程中根据预定义的策略动态调整学习率的技术。与使用固定学习率相比,学习率调度能够:
- 加速收敛:在训练初期使用较大学习率快速下降
- 提高精度:在训练后期使用较小学习率精细调优
- 避免震荡:防止在最优解附近来回震荡
- 跳出局部最优:通过周期性调整帮助模型跳出局部最小值
学习率调度策略分类
PyTorch内置学习率调度器详解
1. StepLR:阶梯式下降
StepLR是最简单的学习率调度器,每隔固定步数将学习率乘以一个衰减因子。
import torch
import torch.optim as optim
from torch.optim import lr_scheduler
# 创建模型和优化器
model = torch.nn.Linear(10, 1)
optimizer = optim.SGD(model.parameters(), lr=0.1)
# 创建StepLR调度器
scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
# 训练循环中的使用
for epoch in range(100):
# 训练步骤...
train(...)
# 更新学习率
scheduler.step()
# 打印当前学习率
print(f'Epoch {epoch}, Learning Rate: {scheduler.get_last_lr()}')
参数说明:
step_size:学习率衰减的周期步数gamma:学习率衰减的乘数因子
2. MultiStepLR:多阶段阶梯下降
MultiStepLR允许在多个特定的epoch点进行学习率调整。
# 创建MultiStepLR调度器
scheduler = lr_scheduler.MultiStepLR(
optimizer,
milestones=[30, 80], # 在第30和80个epoch调整学习率
gamma=0.1
)
3. ExponentialLR:指数衰减
ExponentialLR在每个epoch都将学习率乘以gamma因子,实现指数衰减。
scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.95)
4. ReduceLROnPlateau:基于性能调整
这是最实用的调度器之一,当验证指标停止改善时自动降低学习率。
scheduler = lr_scheduler.ReduceLROnPlateau(
optimizer,
mode='min', # 监控指标的模式:min或max
factor=0.1, # 学习率衰减因子
patience=10, # 等待多少个epoch没有改善
verbose=True, # 打印调整信息
threshold=0.0001, # 改善的最小阈值
cooldown=5 # 调整后的冷却期
)
# 训练循环中的使用
for epoch in range(100):
# 训练步骤
train_loss = train(...)
# 验证步骤
val_loss = validate(...)
# 根据验证损失更新学习率
scheduler.step(val_loss)
5. CosineAnnealingLR:余弦退火
CosineAnnealingLR使用余弦函数周期性地调整学习率,有助于跳出局部最优。
scheduler = lr_scheduler.CosineAnnealingLR(
optimizer,
T_max=50, # 半个周期的epoch数
eta_min=0 # 最小学习率
)
高级调度策略组合
OneCycleLR策略
OneCycleLR是一种高效的调度策略,先升温再降温,在一个周期内完成学习率调整。
scheduler = lr_scheduler.OneCycleLR(
optimizer,
max_lr=0.1, # 最大学习率
steps_per_epoch=len(train_loader),
epochs=100,
pct_start=0.3, # 升温阶段占比
div_factor=25, # 初始学习率 = max_lr/div_factor
final_div_factor=1e4 # 最终学习率 = max_lr/final_div_factor
)
自定义调度策略
使用LambdaLR可以创建完全自定义的调度策略:
# 自定义学习率函数
def lambda_rule(epoch):
if epoch < 50:
return 1.0
elif epoch < 100:
return 0.5
else:
return 0.1
scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_rule)
学习率调度实践指南
选择合适调度策略的决策流程
超参数调优建议
| 调度器类型 | 关键参数 | 推荐值范围 | 调整建议 |
|---|---|---|---|
| StepLR | step_size | 20-50 epochs | 根据总epoch数调整,通常占总epoch数的1/3-1/2 |
| MultiStepLR | milestones | [30, 60, 90] | 在训练损失平台期设置里程碑点 |
| ReduceLROnPlateau | patience | 5-15 epochs | 根据验证集波动情况调整,波动大时增大patience |
| CosineAnnealingLR | T_max | 20-100 epochs | 根据问题复杂度调整,复杂问题用较大T_max |
| OneCycleLR | pct_start | 0.3-0.5 | 升温阶段占比,数据量大时用较小值 |
监控与调试技巧
- 学习率曲线可视化
import matplotlib.pyplot as plt
learning_rates = []
for epoch in range(num_epochs):
# ...训练步骤
scheduler.step()
learning_rates.append(scheduler.get_last_lr()[0])
plt.plot(learning_rates)
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('Learning Rate Schedule')
plt.show()
- 多调度器组合使用
# 组合使用多个调度器
scheduler1 = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
scheduler2 = lr_scheduler.ReduceLROnPlateau(optimizer, patience=5)
# 在训练循环中
for epoch in range(100):
train(...)
val_loss = validate(...)
# 先使用StepLR
scheduler1.step()
# 再使用ReduceLROnPlateau
scheduler2.step(val_loss)
实际案例:图像分类任务中的学习率调度
ResNet模型训练配置
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
from torchvision import models
# 加载预训练模型
model = models.resnet50(pretrained=True)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10) # 假设10分类任务
# 配置优化器和调度器
optimizer = optim.SGD(
model.parameters(),
lr=0.01,
momentum=0.9,
weight_decay=1e-4
)
# 使用CosineAnnealingLR调度器
scheduler = lr_scheduler.CosineAnnealingLR(
optimizer,
T_max=100, # 假设训练100个epoch
eta_min=1e-6 # 最小学习率
)
# 训练循环
for epoch in range(100):
# 训练阶段
model.train()
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 更新学习率
scheduler.step()
# 验证阶段
model.eval()
with torch.no_grad():
# ...验证代码
更多推荐


所有评论(0)