深度学习优化算法:Adam算法

原文链接:动手学深度学习pytorch版:7.8 Adam算法
github:https://github.com/ShusenTang/Dive-into-DL-PyTorch

[1] Kingma, D. P., & Ba, J. (2014). Adam: A method for stochastic optimization. arXiv preprint arXiv:1412.6980.
论文链接

Adam算法

Adam算法在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均 [1]。下面我们来介绍这个算法。

所以Adam算法可以看做是RMSProp算法与动量法的结合。

算法

Adam 算法使用了动量变量 v t v_t vt 和 RMSProp 算法中小批量随机梯度按元素平方的指数加权移动平均变量 s t s_t st,并子时间步0将它们中每个元素初始化为0。给定超参数 0 ≤ β 1 < 1 0 ≤ β_1 < 1 0β1<1 (算法作者建议设置为 0.9),时间步 t t t 的动量变量 v t v_t vt 即小批量随机梯度 g t g_t gt 的质数加权移动平均:
v t ← β 1 v t − 1 + ( 1 − β 1 ) g t {{\text{v}}_{t}}\leftarrow {{\beta }_{1}}{{\text{v}}_{t-1}}+(1-{{\beta }_{1}}){{g}_{t}} vtβ1vt1+(1β1)gt

和RMSProp算法中一样,给定超参数 0 ≤ β 2 < 1 0 ≤ β_2 < 1 0β2<1(算法作者建议设为0.999),将小批量随机梯度按元素平方后的项 g t ⊙ g t {{g}_{t}}\odot {{g}_{t}} gtgt 做指数加权移动平均得到 s t s_t st
s t ← β 2 s t − 1 + ( 1 − β 2 ) g t ⊙ g t {{s}_{t}}\leftarrow {{\beta }_{2}}{{s}_{t-1}}+(1-{{\beta }_{2}}){{g}_{t}}\odot {{g}_{t}} stβ2st1+(1β2)gtgt

由于我们将 v 0 v_0 v0 s 0 s_0 s0 中的元素都初始化为0, 在时间步 t t t 我们得到 v t = ( 1 − β 1 ) ∑ i = 1 t β 1 t − i g i {{v}_{t}}=(1-{{\beta }_{1}})\sum\nolimits_{i=1}^{t}{\beta _{1}^{t-i}{{g}_{i}}} vt=(1β1)i=1tβ1tigi。将过去各时间步小批量随机梯度的权值相加,得到 ( 1 − β 1 ) ∑ i = 1 t β 1 t − i = 1 − β 1 t (1-{{\beta }_{1}})\sum\nolimits_{i=1}^{t}{\beta _{1}^{t-i}=1-}\beta _{1}^{t} (1β1)i=1tβ1ti=1β1t 。需要注意的是,当 t t t 较小时,过去各时间步小批量随机梯度权值之和会较小。例如,当 β 1 = 0.9 {{\beta }_{1}}=0.9 β1=0.9时, v 1 = 0.1 g 1 {{v}_{1}}=0.1{{g}_{1}} v1=0.1g1。为了消除这样的影响,对于任意时间步 t t t,我们可以将 v t v_t vt 再除以 1 − β 1 t 1-\beta _{1}^{t} 1β1t,从而使过去各时间步小批量随机梯度权值之和为1.这也叫做偏差修正。在 Adam 算法中,我们对变量 v t v_t vt s t s_t st 均作偏差修正:
v ^ t ← v t 1 − β 1 t {{\hat{v}}_{t}}\leftarrow \frac{{{v}_{t}}}{1-\beta _{1}^{t}} v^t1β1tvt
s ^ ← s t 1 − β 2 t \hat{s}\leftarrow \frac{{{s}_{t}}}{1-\beta _{2}^{t}} s^1β2tst

接下来,Adam算法使用以上偏差修正后的变量 v ^ t {{{\hat{v}}}_{t}} v^t s ^ {\hat{s}} s^ ,将模型参数中每个元素的学习率通过按元素运算重新调整:
g ′ t ← η v ^ t s ^ t + ε g{{'}_{t}}\leftarrow \frac{\eta {{{\hat{v}}}_{t}}}{\sqrt{{{{\hat{s}}}_{t}}}+\varepsilon } gts^t +εηv^t
其中 η \eta η 是学习率, ϵ \epsilon ϵ 是为了维持数值稳定性而添加的常数,如 1 0 − 8 10^{-8} 108。和 AdaGrad 算法、RMSProp 算法以及AdaDelta 算法一样,目标函数自变量中每个元素都分别拥有自己的学习率。最后,使用 g t ′ g'_t gt 迭代自变量:
x t ← x t − 1 − g t ′ {{x}_{t}}\leftarrow {{x}_{t-1}}-g_{t}^{'} xtxt1gt

从零开始实现

我们按照Adam算法中的公式实现该算法。其中时间步 t t t 通过 hyperparams 参数传入 adam 函数。

%matplotlib inline
import torch
import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l

features, labels = d2l.get_data_ch7()

def init_adam_states():
    v_w, v_b = torch.zeros((features.shape[1], 1), dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
    s_w, s_b = torch.zeros((features.shape[1], 1), dtype=torch.float32), torch.zeros(1, dtype=torch.float32)
    return ((v_w, s_w), (v_b, s_b))

def adam(params, states, hyperparams):
    beta1, beta2, eps = 0.9, 0.999, 1e-6
    for p, (v, s) in zip(params, states):
        v[:] = beta1 * v + (1 - beta1) * p.grad.data
        s[:] = beta2 * s + (1 - beta2) * p.grad.data**2
        v_bias_corr = v / (1 - beta1 ** hyperparams['t'])
        s_bias_corr = s / (1 - beta2 ** hyperparams['t'])
        p.data -= hyperparams['lr'] * v_bias_corr / (torch.sqrt(s_bias_corr) + eps)
    hyperparams['t'] += 1

使用学习率为0.01的Adam算法来训练模型。

d2l.train_ch7(adam, init_adam_states(), {'lr': 0.01, 't': 1}, features, labels)

输出:

loss: 0.245370, 0.065155 sec per epoch

请添加图片描述

简洁实现

通过名称为“Adam”的优化器实例,我们便可使用PyTorch提供的Adam算法。

d2l.train_pytorch_ch7(torch.optim.Adam, {'lr': 0.01}, features, labels)

输出:

loss: 0.242066, 0.056867 sec per epoch

请添加图片描述

小结

  • Adam算法在RMSProp算法的基础上对小批量随机梯度也做了指数加权移动平均。
  • Adam算法使用了偏差修正。
### Adam优化算法详解 #### 原理概述 Adam是一种用于训练神经网络和其他机器学习模型的梯度下降优化算法的变体。此算法由Diederik Kingma和Jimmy Lei Ba于2014年提出,在论文“Adam:随机优化方法”中进行了详细介绍[^1]。其核心目标在于加速优化流程,比如降低到达最优解所需的迭代次数或者提升最终解决方案的质量。 #### 关键特性 - **自适应学习率**:不同于传统的固定学习率设置,Adam能够针对不同的参数动态调整学习速率。具体来说,它会基于历史梯度信息来估计一阶矩(均值)m_t以及二阶矩(未中心化的方差)v_t,并据此调节每次更新的步伐大小。 - **动量机制**:为了克服局部极小值问题并加快收敛速度,Adam引入了来自经典动量法的思想。通过累积过去几次迭代中的梯度方向,可以使得当前步长更加稳定和平滑地朝着全局最小值前进。初始时,动量因子β_1一般设为接近但小于1的数值,如0.9[^2]。 - **偏差校正**:由于初期阶段的一阶与二阶矩估算可能存在较大误差,因此需要对其进行适当修正以确保准确性。公式表达如下: \[ \hat{m}_t=\frac{m_t}{1-\beta^{t}_{1}}, \quad \hat{v}_t=\frac{v_t}{1-\beta^{t}_{2}} \] 其中\( m_t \)表示经过衰减后的梯度平均值;而 \( v_t \)则代表平方梯度的移动平均数。上述两个表达式的分母部分即是对原始估计值所做的偏差补偿操作。 #### 参数更新规则 给定时间戳t处的目标函数相对于权重w_j的偏导数g_{jt} ,Adam按照下述方式进行参数更新: ```python import math def adam_update(w, g, t, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8): """ w: 权重向量/矩阵 g: 当前时刻的梯度 t: 迭代轮次计数器 (从1开始) lr: 学习率,默认值为0.001 beta1,beta2: 衰减速率超参 eps: 防止除零的小常量 返回新的权重 """ # 初始化或加载先前的状态 if 'mt' not in locals(): mt = np.zeros_like(g) vt = np.zeros_like(g) # 更新一阶矩估计(momentum term) mt = beta1 * mt + (1-beta1)*g # 更新二阶矩估计(RMSprop-like scaling factor) vt = beta2*vt+(1-beta2)*(g*g) # 应用偏差矫正 m_hat = mt / (1-math.pow(beta1,t)) v_hat = vt / (1-math.pow(beta2,t)) # 执行实际的参数更新 delta_w = -lr*m_hat/(np.sqrt(v_hat)+eps) return w+delta_w ``` #### 实际应用领域 Adam因其高效性和鲁棒性而在众多场景得到广泛应用,特别是在处理大规模数据集上的深度学习任务方面表现尤为突出。例如图像识别、自然语言处理等领域内的卷积神经网络(CNNs),循环神经网络(RNNs)等架构都广泛采用了这种优化策略[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值