使用ExponentialLR调度器时学习率未更新的问题排查
问题分析与解决方案
核心问题
- 调度器与优化器被重复初始化:你的
train_step函数每次调用都会新建SGD优化器和ExponentialLR调度器实例。调度器需要在整个训练周期内保持状态才能逐步调整学习率,每次重新初始化会导致它从头开始,学习率自然不会变化。 - 手动更新参数与优化器操作冲突:你在
with torch.no_grad()里手动更新w和b,之后又调用optimizer.step(),这不仅重复操作,还绕开了优化器的内部状态管理(比如动量),导致调度器依赖的优化器学习率跟踪逻辑失效。
修复方案
- 将优化器和调度器初始化移到训练循环外:确保整个训练过程中只有一个优化器和调度器实例,保留它们的状态。
- 移除手动参数更新代码:完全依赖
optimizer.step()来更新参数,这是PyTorch的标准流程。 - 规范梯度清零操作:使用
optimizer.zero_grad()替代手动清零梯度,避免梯度累积问题。
修改后的代码示例
初始化部分(仅执行一次)
# 提前初始化可训练变量、优化器和调度器 trainable_variables = [w, bias] optimizer = torch.optim.SGD(trainable_variables, lr=learning_rate, momentum=0.9) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.01)
训练步骤函数
def train_step(): optimizer.zero_grad() # 清空上一轮的梯度 loss = loss_function() loss.backward() # 反向传播计算梯度 optimizer.step() # 优化器更新参数 scheduler.step() # 调度器更新学习率
调用训练步骤
train_step() # 每次训练迭代调用一次
额外说明
- 可以通过
print(optimizer.param_groups[0]['lr'])在每次train_step后打印学习率,验证是否正常下降。 ExponentialLR的gamma=0.01意味着每次step学习率乘以0.01,这个衰减幅度非常大,可能导致模型快速收敛到局部最优,建议根据实际情况调整(比如设为0.9或0.95)。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

