优化算法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.计算损失函数对于当前参数的梯度: g_t=\nabla loss(w_t)

2.根据历史梯度计算一阶和二阶动量

m_t = \phi(g_1, g_2, \cdots, g_t); V_t = \psi(g_1, g_2, \cdots, g_t)

3.根据当前时刻的梯度,一阶和二阶动量,学习率计算当前时刻的下降梯度:

\eta_t = \alpha \cdot m_t / \sqrt{V_t}

4.根据当前时刻的下降梯度更新参数:w_{t+1} = w_t - \eta_t

其中: w_t 为待优化参数, [公式] 为损失函数, [公式] 为学习率。

那么我们如何计算一阶和二阶动量呢?

SGD

对于最经典的SGD算法,  , [公式] 。也就是没有用到动量的概念,朴实无华。

对于带动量的SGD,m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t, [公式] 。也就是一阶动量不仅要考虑当前时刻的梯度,还考虑到了上一时刻的动量。就像是一辆车,上一时刻在全速向前,这一时刻要刹车,但是不可能立刻停下来。

Adam

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

m_t = \beta_1 \cdot m_{t-1} + (1-\beta_1)\cdot g_t

V_t = \beta_2 * V_{t-1} + (1-\beta_2) g_t^2

参考资料:

一个框架看懂优化算法之异同 SGD/AdaGrad/Adam - 知乎 (zhihu.com)

从动量和矩的角度探讨优化理论的内涵(以动量法、AdaGrad和Adam举例) - 知乎 (zhihu.com)

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值