说来惭愧,一直在用的两个经典的优化器,几行代码就完成了参数更新,但是却一直没有深入的了解其中的原理。
improt torch
...
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
...
optimizer.zero_grad()
...
optimizer.step()
首先贴一下pytorch的官方文档
torch.optim — PyTorch 1.8.0 documentation
不同的优化器都采用相同的参数更新步骤,即
1.计算损失函数对于当前参数的梯度:
2.根据历史梯度计算一阶和二阶动量
3.根据当前时刻的梯度,一阶和二阶动量,学习率计算当前时刻的下降梯度:
4.根据当前时刻的下降梯度更新参数:
其中: 为待优化参数,
为损失函数,
为学习率。
那么我们如何计算一阶和二阶动量呢?
对于最经典的SGD算法, ,
。也就是没有用到动量的概念,朴实无华。
对于带动量的SGD,,
。也就是一阶动量不仅要考虑当前时刻的梯度,还考虑到了上一时刻的动量。就像是一辆车,上一时刻在全速向前,这一时刻要刹车,但是不可能立刻停下来。
Adam算法引入了二阶动量的概念,二阶动量是什么呢,是历史动量的平方和,可以理解为这个参数他更新的频率大小,二阶动量大就说明这个参数经常更新,我们就希望这个经常更新的参数可以慢一点更新,很少更新的参数每次更新的步子就大一点,但是如果选取历史动量的平方和,随着时间的累计这个值会特别大,导致下降梯度近似于0,无法继续训练,于是我们定义如下,在加上之前SGD的一阶动量,就构成了Adam算法的核心。
AdamW修正了Adam算法和weight decay一起使用时存在的BUG,具体可以参考下边的博客。
fast.ai - AdamW and Super-convergence is now the fastest way to train neural nets
电 话:400-123-4567
传 真:+86-123-4567
手 机:13800000000
邮 箱:admin@eyoucms.com
地 址:广东省广州市天河区88号