在PyTorch中定义Adam优化器的最佳方式是什么?

3
对于大多数 PyTorch 代码,我们使用以下 Adam 优化器的定义:
optim = torch.optim.Adam(model.parameters(), lr=cfg['lr'], weight_decay=cfg['weight_decay'])

然而,经过反复试验,我发现下面的Adam定义提供了比较大的1.5dB更高的峰值信噪比。

optim = torch.optim.Adam(
            [
                {'params': get_parameters(model, bias=False)},
                {'params': get_parameters(model, bias=True), 'lr': cfg['lr'] * 2, 'weight_decay': 0},
            ],
            lr=cfg['lr'],
            weight_decay=cfg['weight_decay'])

这个模型是一个常规的U-Net,其参数在initforward action中定义,就像其他任何PyTorch模型一样。

get_parameters函数定义如下。

def get_parameters(model, bias=False):
    for k, m in model._modules.items():
        print("get_parameters", k, type(m), type(m).__name__, bias)
        if bias:
            if isinstance(m, nn.Conv2d):
                yield m.bias
        else:
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.ConvTranspose2d):
                yield m.weight

有人能解释一下后一个定义为什么比前一个好吗?

2
这两个定义是不同的。第二个定义为偏置参数提供了双倍的学习率,而第一个定义则为所有参数提供相同的学习率。第二种情况的改进原因可能不容易直观地识别。这可能是由于您的数据集和网络选择更好地调整了Adam算法。 - akshayk07
1个回答

2
在第二种方法中,我们使用针对优化器的每个参数的选项来提供不同的配置以更新权重和偏置。这是通过per-parameter options实现的。
optim = torch.optim.Adam(
            [
                {'params': get_parameters(model, bias=False)},
                {'params': get_parameters(model, bias=True), 'lr': cfg['lr'] * 2, 'weight_decay': 0},
            ],
            lr=cfg['lr'],
            weight_decay=cfg['weight_decay'])

根据此,偏差的学习速率是权重的两倍,而权重衰减为0。
现在,这么做的原因可能是网络没有正确地学习。更多信息请参见:为什么偏差的学习速率通常是权重的两倍?

感谢您的解释和资源。get_parameter是否足够通用,即适用于任何神经网络?您能否简要地解释一下这个函数?使用model.parameters()而不是model._modules.items()会更好吗? - Mohit Lamba
1
是的,它非常通用。你可以使用 parameters(),但我认为这里还有一层类型检查。工作原理是:迭代 modules,然后检查它是哪种类型的层实例(例如 conv),此外,如果函数参数中 bias=True,则返回偏置,否则返回权重。希望清楚明白。 - kHarshit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接