Adam(Adaptive Moment Estimation)优化器是一种基于梯度下降法的优化算法,它结合了动量法(见文章指数移动平均)和自适应学习率的方法,通过计算梯度的一阶矩(平均值)和二阶矩(方差)来调整每个参数的学习率,从而加速训练并提高收敛性。
传统梯度下降法的缺点
在深度学习中,优化算法的目标是通过反向传播来更新神经网络的参数,使得损失函数尽量减小。最基本的优化方法是梯度下降。梯度下降法 的核心思想是:
- 计算损失函数相对于模型参数的梯度(即参数的导数)。
- 按照梯度的方向更新参数: θ t + 1 = θ t − α ⋅ ∇ θ L ( θ t ) \theta_{t+1} = \theta_t - \alpha \cdot \nabla_{\theta} L(\theta_t) θt+1=θt−α⋅∇θL(θt),其中, θ t \theta_t θt 是第 t t t 次迭代时的参数, ∇ θ L ( θ t ) \nabla_{\theta} L(\theta_t) ∇θL(θt) 是参数的梯度, α \alpha α 是学习率,控制每次更新的步长。
标准的梯度下降有一个缺点,就是学习率是固定的,在处理不同参数时,可能有些参数更新过快,而有些参数更新过慢。
Adam优化器通过计算 一阶矩 和 二阶矩 来解决梯度下降法的这个问题,使得每个参数有自己独立的、自适应的学习率。
Adam原理
Adam优化器结合了以下两种技术:
- 动量法:通过累积过去梯度的加权平均,减小参数更新过程中的震荡,加速收敛。(见文章指数移动平均)
- 自适应学习率(RMSProp):通过考虑梯度的平方的指数加权平均,调整每个参数的学习率,避免学习率过大或过小。
Adam优化器的详细步骤:
-
初始化
Adam优化器首先初始化两个动量变量: m t = 0 m_t = 0 mt=0(一阶矩,梯度的平均值), v t = 0 v_t = 0 vt=0(二阶矩,梯度的平方的平均值)。
并设置一些超参数:- 学习率: α \alpha α,通常设置为0.001。
- 一阶矩衰减因子: β 1 \beta_1 β1,通常取值为0.9。
- 二阶矩衰减因子: β 2 \beta_2 β2,通常取值为0.999。
- 平滑项: ϵ \epsilon ϵ,一个小常数(如 1 0 − 8 10^{-8} 10−8),防止在更新过程中出现除零错误。
-
计算梯度
在每次迭代时,首先需要计算损失函数对当前参数的梯度: g t = ∇ θ L ( θ t ) , g_t = \nabla_{\theta} L(\theta_t), gt=∇θL(θt), 其中 g t g_t gt 是第 t t t 步的梯度。 -
更新一阶矩和二阶矩
-
一阶矩 m t m_t mt 是梯度的加权平均,表示梯度的动量,它使得参数更新方向更加平滑。公式为: m t = β 1 ⋅ m t − 1 + ( 1 − β 1 ) ⋅ g t , m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g_t, mt=β1⋅mt−1+(1−β1)⋅gt, 其中, m t − 1 m_{t-1} mt−1 是上一步的动量, g t g_t gt 是当前的梯度, β 1 \beta_1 β1 是衰减因子,控制了动量的 记忆程度。通常, β 1 \beta_1 β1 接近 1(如0.9),意味着 动量主要由过去的梯度决定,当前的梯度影响较小。
-
二阶矩 v t v_t vt 是梯度的平方的加权平均,表示梯度的方差,它帮助调整每个参数的学习率。公式为: v t = β 2 ⋅ v t − 1 + ( 1 − β 2 ) ⋅ g t 2 , v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g_t^2, vt=β2⋅vt−1+(1−β2)⋅gt2,其中, v t − 1 v_{t-1} vt−1 是上一步的二阶矩, g t 2 g_t^2 gt2 是当前梯度的平方, β 2 \beta_2 β2 控制了二阶矩的衰减,通常取0.999,这意味着 二阶矩更多地由过去的 梯度平方 决定。
-
-
偏差修正
由于在训练的初期, m t m_t mt 和 v t v_t vt 都是初始化为0的,这会导致它们在训练初期的估计值偏向0。为次,Adam引入了 偏差修正。-
对一阶矩的偏差修正: m ^ t = m t 1 − β 1 t , \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, m^t=1−β1tmt, 其中, β 1 t \beta_1^t β1t 是在第 t t t 次迭代时的 β 1 \beta_1 β1 的幂次,随着迭代的进行,修正项会逐渐增大,避免初期偏差的影响。
在迭代初期,受初始化的影响, m t m_t mt 的值偏向0。所以迭代初期, 1 − β 1 t 1 - \beta_1^t 1−β1t 的值较小,相当于给 m t m_t mt 乘上了一个较大的系数来进行修正(如 t = 1 t=1 t=1时, 1 − β 1 t = 0.1 1 - \beta_1^t=0.1 1−β1t=0.1, m ^ t = 10 × m t \hat{m}_t =10\times m_t m^t=10×mt)。随着迭代进行, 1 − β 1 t 1 - \beta_1^t 1−β1t 的值越来越大,接近于1,这时对 m t m_t mt 的修正作用越来越弱。
-
对二阶矩的偏差修正: v ^ t = v t 1 − β 2 t , \hat{v}_t = \frac{v_t}{1 - \beta_2^t}, v^t=1−β2tvt, 同理,二阶矩的偏差修正随着迭代的进行逐渐减小。
-
-
更新参数
在计算出 偏差修正后的 一阶矩和二阶矩后,接下来就是更新参数了。更新规则为: θ t = θ t − 1 − α ⋅ m ^ t v ^ t + ϵ , \theta_t = \theta_{t-1} - \alpha \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}, θt=θt−1−α⋅v^t+ϵm^t, 其中, θ t − 1 \theta_{t-1} θt−1 是上一步的参数值; m ^ t \hat{m}_t m^t 是一阶矩的修正值,表示梯度的平均方向; v ^ t \hat{v}_t v^t 是二阶矩的修正值,表示梯度的方差; α \alpha α 是学习率; ϵ \epsilon ϵ 是一个很小的常数(如 1 0 − 8 10^{-8} 10−8),用来防止在计算更新时除零。为什么除以梯度方差的平方根 v ^ t \sqrt{\hat{v}_t} v^t?
通过 除以梯度的方差的平方根 来调整学习率,目的是平衡每个参数的更新步长,避免由于梯度的波动造成的过大或过小的更新。
梯度波动性:梯度的大小通常会在每次迭代中波动。固定学习率可能导致某些参数更新过快(梯度大时),而其他参数更新过慢(梯度小或稳定时)。如果梯度波动很大,更新步长也应适当缩小,避免过大的更新。
通过计算梯度的 方差(即梯度的波动程度),Adam会根据每个参数的历史梯度信息自动调整学习率。对于梯度波动大的参数,学习率会自动减小;对于梯度波动小的参数,学习率会增大。
举例
假设有两个参数:
θ 1 \theta_1 θ1:梯度 g 1 = 0.1 g_1 = 0.1 g1=0.1,方差 v 1 = 0.01 v_1 = 0.01 v1=0.01(稳定)。
θ 2 \theta_2 θ2:梯度 g 2 = 1.0 g_2 = 1.0 g2=1.0,方差 v 2 = 1.0 v_2 = 1.0 v2=1.0(波动大)。
如果使用固定学习率 α = 0.01 \alpha = 0.01 α=0.01,更新步长会不均衡。但在Adam中,经过方差调整后:
Δ θ 1 = 0.01 ⋅ 0.1 0.01 = 0.01 , Δ θ 2 = 0.01 ⋅ 1.0 1.0 = 0.01 , \Delta \theta_1 = \frac{0.01 \cdot 0.1}{\sqrt{0.01}} = 0.01, \quad \Delta \theta_2 = \frac{0.01 \cdot 1.0}{\sqrt{1.0}} = 0.01, Δθ1=0.010.01⋅0.1=0.01,Δθ2=1.00.01⋅1.0=0.01, 这样,两个参数的更新步长变得一致,避免了梯度波动大时步长过大的问题。通过这种方式,Adam在每次更新时会自动根据梯度的历史信息调整每个参数的学习率。