BlaXuan 发表于 2022-1-19 10:43

优化算法SGD与Adam

说来惭愧,一直在用的两个经典的优化器,几行代码就完成了参数更新,但是却一直没有深入的了解其中的原理。
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.计算损失函数对于当前参数的梯度:    https://www.zhihu.com/equation?tex=g_t%3D%5Cnabla+loss%28w_t%29
2.根据历史梯度计算一阶和二阶动量

https://www.zhihu.com/equation?tex=m_t+%3D+%5Cphi%28g_1%2C+g_2%2C+%5Ccdots%2C+g_t%29%3B+V_t+%3D+%5Cpsi%28g_1%2C+g_2%2C+%5Ccdots%2C+g_t%29
3.根据当前时刻的梯度,一阶和二阶动量,学习率计算当前时刻的下降梯度:

https://www.zhihu.com/equation?tex=%5Ceta_t+%3D+%5Calpha+%5Ccdot+m_t+%2F+%5Csqrt%7BV_t%7D
4.根据当前时刻的下降梯度更新参数:https://www.zhihu.com/equation?tex=w_%7Bt%2B1%7D+%3D+w_t+-+%5Ceta_t
其中: https://www.zhihu.com/equation?tex=w_t 为待优化参数, https://www.zhihu.com/equation?tex=+loss%28x%29 为损失函数, https://www.zhihu.com/equation?tex=%5Calpha 为学习率。
那么我们如何计算一阶和二阶动量呢?
SGD

对于最经典的SGD算法, https://www.zhihu.com/equation?tex=m_t+%3D+g_t ,。也就是没有用到动量的概念,朴实无华。
对于带动量的SGD,,。也就是一阶动量不仅要考虑当前时刻的梯度,还考虑到了上一时刻的动量。就像是一辆车,上一时刻在全速向前,这一时刻要刹车,但是不可能立刻停下来。
Adam

Adam算法引入了二阶动量的概念,二阶动量是什么呢,是历史动量的平方和,可以理解为这个参数他更新的频率大小,二阶动量大就说明这个参数经常更新,我们就希望这个经常更新的参数可以慢一点更新,很少更新的参数每次更新的步子就大一点,但是如果选取历史动量的平方和,随着时间的累计这个值会特别大,导致下降梯度近似于0,无法继续训练,于是我们定义如下,在加上之前SGD的一阶动量,就构成了Adam算法的核心。



https://www.zhihu.com/equation?tex=+V_t++%3D++%5Cbeta_2+%2A+V_%7Bt-1%7D+%2B+%281-%5Cbeta_2%29+g_t%5E2
参考资料:
一个框架看懂优化算法之异同 SGD/AdaGrad/Adam - 知乎 (zhihu.com)
从动量和矩的角度探讨优化理论的内涵(以动量法、AdaGrad和Adam举例) - 知乎 (zhihu.com)
页: [1]
查看完整版本: 优化算法SGD与Adam