torch.optim.lr_scheduler.ReduceLROnPlateau
是 PyTorch 中的一种学习率调度器,主要用于在模型训练过程中根据某些指标(如验证损失)动态调整学习率。它是一种基于性能指标动态调整学习率的策略,而不是预定义的固定时间调整。
主要功能
ReduceLROnPlateau
会监控某个指标(如验证损失),当该指标在若干个 epoch 中停止改善时(即进入"平台"期),将学习率按一定的比例降低,从而帮助模型更好地收敛。
常用参数
初始化 ReduceLROnPlateau
时,可以设置以下参数:
-
optimizer
:- 目标优化器(如 SGD, Adam),学习率调度器会更新此优化器中的学习率。
-
mode
:- 决定监控指标是否需要"最小化"或"最大化"。
'min'
:监控指标越小越好(例如验证损失)。'max'
:监控指标越大越好(例如验证精度)。
-
factor
:- 学习率降低的比例,新的学习率为
lr = lr * factor
。 - 默认值:
0.1
(学习率每次降低为原来的 10%)。
- 学习率降低的比例,新的学习率为
-
patience
:- 容忍的连续 epoch 数,在这段时间内监控指标没有改善,但不会立即降低学习率。
- 默认值:
10
。
-
threshold
:- 判断监控指标是否改善的阈值。
- 默认值:
1e-4
(小于这个值的变化会被认为没有改善)。
-
threshold_mode
:'rel'
:相对变化(即与前一个值相比的比例变化)。'abs'
:绝对变化。
-
cooldown
:- 每次调整学习率后等待的 epoch 数,在此期间不会检测指标改善。
- 默认值:
0
。
-
min_lr
:- 学习率的下限,确保学习率不会被降低到此值以下。
- 默认值:
0
。
-
eps
:- 学习率变化的最小值,防止浮点数精度问题导致学习率更新失败。
- 默认值:
1e-8
。
常见用法
以下是使用 ReduceLROnPlateau
的典型步骤:
-
初始化优化器和调度器:
import torch import torch.nn as nn import torch.optim as optim# 假设有一个模型和一个损失函数 model = nn.Linear(10, 1) criterion = nn.MSELoss() optimizer = optim.Adam(model.parameters(), lr=0.01)# 初始化调度器 scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10)
-
在训练循环中调用:
每个 epoch 完成后,使用验证集的性能指标来调用调度器:for epoch in range(50):# 训练过程model.train()for data, target in train_loader:optimizer.zero_grad()output = model(data)loss = criterion(output, target)loss.backward()optimizer.step()# 验证过程model.eval()val_loss = 0with torch.no_grad():for data, target in val_loader:output = model(data)val_loss += criterion(output, target).item()# 调度器监控验证损失scheduler.step(val_loss)# 打印当前学习率print(f"Epoch {epoch+1}: Learning rate: {optimizer.param_groups[0]['lr']}")
工作原理
-
监控指标:
- 每次调用
scheduler.step(metric)
,都会检查传入的metric
(如验证损失或验证精度)是否在过去patience
个 epoch 中有所改善。
- 每次调用
-
判断是否降低学习率:
- 根据
mode
和threshold
,决定当前指标是否"足够好"。 - 如果监控指标在
patience
个 epoch 内未改善,则将学习率乘以factor
。
- 根据
-
冷却期:
- 调整学习率后,进入
cooldown
冷却期,冷却期内不会监控指标。
- 调整学习率后,进入
-
最小学习率限制:
- 如果新的学习率低于
min_lr
,则不再继续降低。
- 如果新的学习率低于
代码示例
假设验证损失在第 15 个 epoch 开始停滞:
Epoch 10: val_loss = 0.50, lr = 0.01
Epoch 11: val_loss = 0.49, lr = 0.01
...
Epoch 15: val_loss = 0.48, lr = 0.01 (No significant improvement for 10 epochs)
Epoch 16: val_loss = 0.47, lr = 0.001 (Reduce learning rate by factor of 0.1)
...
Epoch 25: val_loss = 0.46, lr = 0.001 (No significant improvement for 10 epochs)
Epoch 26: val_loss = 0.45, lr = 0.0001 (Reduce learning rate again)
注意事项
-
适用场景:
- 常用于训练到一定阶段后,指标改善速度减慢时,动态调整学习率有助于提高模型性能。
- 尤其适合学习率对训练敏感的优化器(如 SGD)。
-
与其他调度器对比:
StepLR
和CosineAnnealingLR
是预定义的固定时间调整学习率。ReduceLROnPlateau
是基于性能指标的动态调整,更加灵活。
-
使用正确的监控指标:
- 确保传入的指标与训练目标一致(如验证损失应与
mode='min'
一起使用)。
- 确保传入的指标与训练目标一致(如验证损失应与
通过动态调整学习率,ReduceLROnPlateau
可以帮助优化训练过程,特别是在模型性能进入瓶颈阶段时,非常有效。