-1

使用 SGD 时,学习率不应在 epoch 期间更改,但确实如此。请帮助我理解为什么会发生这种情况以及如何防止这种 LR 改变?

import torch
params = [torch.nn.Parameter(torch.randn(1, 1))]
optimizer = torch.optim.SGD(params, lr=0.9)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9)
for epoch in range(5):
    print(scheduler.get_lr())
    scheduler.step()

输出是:

[0.9]
[0.7290000000000001]
[0.6561000000000001]
[0.5904900000000002]
[0.5314410000000002]

我的手电筒版本是 1.4.0

4

3 回答 3

1

由于您使用的是命令 torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9)(实际上是torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.9)),因此您将学习率乘以gamma=0.9step_size=1一步:

  • 0.9 = 0.9
  • 0.729 = 0.9*0.9*0.9
  • 0.6561 = 0.9*0.9*0.9*0.9
  • 0.59049 = 0.9*0.9*0.9*0.9*0.9

唯一的“奇怪”点是它在第二步缺少 0.81=0.9*0.9 (更新:请参阅Szymon Maszke 答案以获得解释)

为了防止过早减少,如果您的数据集中有N样本,并且批量大小为 D,则设置torch.optim.lr_scheduler.StepLR(optimizer, step_size=N/D, gamma=0.9)为在每个时期减少。减少每个 E epoch 集torch.optim.lr_scheduler.StepLR(optimizer, step_size=E*N/D, gamma=0.9)

于 2020-05-04T19:05:42.023 回答
1

这正是torch.optim.lr_scheduler.StepLR应该做的。它改变了学习率。来自 pytorch 文档:

每 step_size epochs 衰减每个参数组的学习率。请注意,这种衰减可能与此调度程序外部对学习率的其他更改同时发生。当 last_epoch=-1 时,设置初始 lr 为 lr

如果您正在尝试优化params,您的代码应该看起来更像这样(只是一个玩具示例,具体形式loss取决于您的应用程序)

for epoch in range(5):
  optimizer.zero_grad()
  loss = (params[0]**2).sum()
  loss.backward()
  optimizer.step()
于 2020-05-04T19:07:36.770 回答
1

要扩展xiawi关于“奇怪”行为的答案(0.81缺失):这是 PyTorch 自1.1.0发布以来的默认方式,请查看文档,即这部分:

[...] 如果您 scheduler.step()在优化器更新(调用)之前 使用学习率调度程序(调用optimizer.step()),这将跳过学习率调度的第一个值。

此外,您应该UserWarning在第一次调用后被此函数抛出,get_lr()因为您根本不调用optimizer.step()

于 2020-05-04T20:21:15.453 回答