本文最后更新于:2024年5月7日 下午

Adam 是深度学习中常用的优化器,我在使用时遇到了一点问题,弄清楚后记录下来。

Adam

Adam(Adaptive Moment Estimation)优化器是一种广泛使用的优化算法,在深度学习训练中特别流行。它结合了两种不同的优化算法的优点:Momentum 和 RMSprop。下面是 Adam 优化器的工作原理的简要概述:

  1. 动量(Momentum): Adam 优化器计算梯度的指数加权移动平均(也称为一阶矩估计),这有助于加速梯度下降过程中的收敛速度,并帮助克服局部最小值和鞍点。这个概念类似于物理学中的动量,可以使参数更新朝着更一致的方向移动。
  2. RMSprop: Adam 同时计算梯度的平方的指数加权移动平均(二阶矩估计)。这有助于调整学习率,对每个参数进行自适应的学习率调整。参数的更新速度依赖于其梯度的大小,较大的梯度意味着较小的学习率,反之亦然。
  3. 偏差修正: 在初始阶段,由于一阶矩估计和二阶矩估计都被初始化为零向量,Adam 会应用偏差修正来防止估计值在训练初期偏向零,尤其是当衰减率非常高时。
  4. 参数更新: 结合以上两点,Adam 优化器在每次迭代中更新每个参数,使用的是基于一阶矩和二阶矩调整后的梯度。

Adam 优化器的关键优势在于其自适应学习率的特性,这使得它在处理不同参数的更新时更为灵活,尤其是在处理稀疏梯度或不同量级的梯度时。Adam 通常需要更少的手动超参数调整,尤其是学习率。

Adam 优化器的核心公式如下:

公式 用途
$m_t=\beta_1m_{t-1}+(1-\beta_1)g_t$ 更新一阶矩估计
$v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2$ 更新二阶矩估计
$\hat{m}_{t}=\frac{m_{t}}{1-\beta_{1}^{t}}$ 一阶矩估计的偏差修正
$\hat{v}_{t}=\overline{1-\beta_{2}^{2}}$ 二阶矩估计的偏差修正
$\theta_{t+1}=\theta_t-\frac\eta{\sqrt{\hat{v}_t}+\epsilon}\hat{m}_t$ 参数更新

其中,$\theta$是需要优化的参数,$g_t$ 是在时间步$t$ 的梯度,$m_t$ 和$v_t$ 分别是一阶矩和二阶矩的估计,$\beta_1$和$\beta_2$是衰减率 (通常设为接近1的值),$\eta$是学习率,而$\epsilon$是为了数值稳定性而添加的一个小常数。

理解

概念 理解
动量(一阶矩) 梯度变化带有噪声,我们需要梯度修正保持一定趋势,需要给梯度更新一定的惯性令其克服噪声向正确的方向前进
二阶矩 不是所有参数都适用于相同的学习率,我们需要根据梯度大小自适应调整每个参数的学习率,这是二阶矩的作用
偏差修正 更新初期,一阶矩和二阶矩均为 0,因此它们会被低估——特别是在迭代的早期阶段,因此除一个随着迭代轮数增加更接近 1 的数字可以在更新初期放大一二阶矩的估计值,同时迭代轮数多了不会影响正常的估计进行

问题记录

我在使用 Adam 优化器优化参数时遇到了稍微复杂的情况:

我的优化器 A 同时管理参数 B, C,但是在某一阶段的网络训练中,我确定 C 不会参与梯度回传,需要 A 优化 B

中的参数即可。这是我的需求,目的是更新 B 不更新 C 。

我知道 Adam 有动量的概念,那么直接将 C 的 grad 置零是没用的,因为残留的动量会使得参数更新时重新变化出梯度 grad 来,那么我在开始训练 B 之前将 A 中所有的一二阶矩全部置零,同时将所有梯度 grad 全部置零:

1
2
3
4
5
6
7
# 梯度置零
optimizer.zero_grad()
# 一二阶矩 置零
for param in optimizer.state_dict()['state']:
if param is param_to_reset:
optimizer.state_dict()['state'][param]['exp_avg'].zero_()
optimizer.state_dict()['state'][param]['exp_avg_sq'].zero_()

但是在训练 B 的过程中, C 的参数还是会被更新,当时我没有想通问题出在哪。

问题原因

经过翻查源码,发现 Adam 中集成了正则化 L2 Loss —— weight_decay,该参数将当前需要更新的数据的值直接乘起来加到梯度上,本意是减小参数绝对值,令其更加鲁棒,但是对我的需求便是灭顶之灾,经过多轮训练后所有没有梯度回传的参数都会减小到接近 0.

问题解决

找到原因就好办了,源码中会对优化器管理的参数做一个筛选,如果当前参数没有 grad 信息,那么优化器会将其跳过,所以训练前把所有优化器中参数的 grad 设置为 None(不是置零)即可。

原始论文

参考资料



文章链接:
https://www.zywvvd.com/notes/study/deep-learning/optimizer/adam/adam/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

Adam 优化器
https://www.zywvvd.com/notes/study/deep-learning/optimizer/adam/adam/
作者
Yiwei Zhang
发布于
2024年1月10日
许可协议