3

我正在尝试重新实现一篇论文,该论文建议调整学习率如下:

在变化值为0.0001的情况下,学习率降低了回归值的一个因子,耐心 epoch 10 。

我应该使用torch.optim.lr_scheduler.ReduceLROnPlateau()吗?

我不确定应该将什么值传递给每个参数。

  1. 语句中的变化值是否表示参数阈值

  2. 语句中的因子是否表示参数因子

4

3 回答 3

9

torch.optim.lr_scheduler.ReduceLROnPlateau确实是您正在寻找的。我为你总结了所有重要的东西。

mode=min:当监控的数量停止减少时,lr将减少

factor: 降低学习率的因素

patience: 没有改善的 epoch 数,之后学习率将降低

threshold:衡量新的最佳值的阈值,只关注重大变化(变化值)。假设我们有threshold=0.0001,如果第 n 阶段的损失为 18.0,第 n +1阶段的损失为 17.9999,那么我们满足了将当前学习率乘以 的标准factor

criterion = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min',
    factor=0.1, patience=10, threshold=0.0001, threshold_mode='abs')

for epoch in range(20):
    # training loop stuff
    loss = criterion(...)
    scheduler.step(loss)

您可以在文档中查看更多详细信息:https ://pytorch.org/docs/stable/optim.html#torch.optim.lr_scheduler.ReduceLROnPlateau

于 2020-07-27T04:03:51.730 回答
3

Pytorch 有很多方法可以让你降低学习率。这里解释得很好:

https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate

@Antonino DiMaggio 很好地解释了 ReduceOnPlateau。我只是想补充一下回复@Yan-JenHuang的评论的答案:

是否可以通过减去一个常数值而不是一个因子来降低 learning_rate?

首先,你应该非常小心避免 lr 的负值!其次,减去学习率的值不是常见的做法。但无论如何...

您必须首先制作一个自定义 lr 调度程序(我修改了 LambdaLR 的代码https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html#LambdaLR):

torch.optim.lr_scheduler import _LRScheduler

class SubtractLR(_LRScheduler):
    def __init__(self, optimizer, lr_lambda, last_epoch=-1, min_lr=e-6):
        self.optimizer = optimizer
        self.min_lr = min_lr  # min learning rate > 0 

        if not isinstance(lr_lambda, list) and not isinstance(lr_lambda, tuple):
            self.lr_lambdas = [lr_lambda] * len(optimizer.param_groups)
        else:
            if len(lr_lambda) != len(optimizer.param_groups):
                raise ValueError("Expected {} lr_lambdas, but got {}".format(
                    len(optimizer.param_groups), len(lr_lambda)))
            self.lr_lambdas = list(lr_lambda)
        self.last_epoch = last_epoch
        super(LambdaLR, self).__init__(optimizer, last_epoch)

    def get_lr(self):
        if not self._get_lr_called_within_step:
            warnings.warn("To get the last learning rate computed by the scheduler, "
                          "please use `get_last_lr()`.")

        return [(max(base_lr - lmbda(self.last_epoch), self.min_lr)
                for lmbda, base_lr in zip(self.lr_lambdas, self.base_lrs)] # reduces the learning rate

比你可以在训练中使用它。

 lambda1 = lambda epoch: e-4 # constant to subtract from lr
 scheduler = SubtractLR(optimizer, lr_lambda=[lambda1])
 for epoch in range(100):
     train(...)
     validate(...)
     scheduler.step()
 lambda1 = lambda epoch: epoch * e-6 # increases the value to subtract lr proportionally to the epoch
 scheduler = SubtractLR(optimizer, lr_lambda=[lambda1])
 for epoch in range(100):
     train(...)
     validate(...)
     scheduler.step()

您还可以修改代码ReduceLROnPlateau以减去学习率而不是相乘。您应该将此行更改new_lr = max(old_lr * self.factor, self.min_lrs[i])为类似new_lr = max(old_lr - self.factor, self.min_lrs[i]). 你可以自己看一下代码:https ://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html#ReduceLROnPlateau

于 2020-07-27T07:33:35.467 回答
2

作为对 ReduceLROnPlateau 上述答案的补充,阈值在 pytorch 的 lr 调度程序中也有模式(rel|abs)(至少对于 vesions>=1.6),默认值为“rel”,这意味着如果您的损失为 18,它将至少更改 18*0.0001=0.0018 以被视为改进。所以,也要注意阈值模式。

于 2021-02-25T23:15:26.000 回答