从 AdaGrad 到 AdamW:优化器的进化之路
在深度学习的世界里,优化器 (Optimizer) 就像是我们在群山中寻找最低谷(损失函数最小值)的向导。然而大家最常用的是 Adam 以及它的修正版 AdamW。为什么有了 Adam 还要 AdamW?这中间到底发生了什么?
1. 理想很丰满:牛顿法 (Newton’s Method) 🍎
在介绍各种花哨的优化器之前,我们先来看看“上帝视角”的优化方法——牛顿法。
很多时候,我们只知道往哪里走(梯度下降),但牛顿法告诉我们,不仅要看方向,还要看地形的弯曲程度。
-
直观理解:泰勒展开 (Taylor Expansion)
假设我们要优化的损失函数是 f(x)f(x)f(x)。我们可以在当前点 xtx_txt 附近,用一个二次函数来近似它(二阶泰勒展开):
f(x)≈f(xt)+f′(xt)(x−xt)+12f′′(xt)(x−xt)2 f(x) \approx f(x_t) + f'(x_t)(x - x_t) + \frac{1}{2}f''(x_t)(x - x_t)^2 f(x)≈f(xt)+f′(xt)(x−xt)+21f′′(xt)(x−xt)2- f′(xt)f'(x_t)f′(xt) 是 一阶导数(梯度),告诉我们坡度。
- f′′(xt)f''(x_t)f′′(xt) 是 二阶导数,告诉我们坡度的变化率(也就是曲率)。
我们希望找到这个近似函数的最低点。很简单,对 xxx 求导并令其为 0:
f′(x)≈f′(xt)+f′′(xt)(x−xt)=0 f'(x) \approx f'(x_t) + f''(x_t)(x - x_t) = 0 f′(x)≈f′(xt)+f′′(xt)(x−xt)=0解出 xxx(即我们要去的下一步 xt+1x_{t+1}xt+1):
xt+1=xt−f′(xt)f′′(xt) x_{t+1} = x_t - \frac{f'(x_t)}{f''(x_t)} xt+1=xt−f′′(xt)f′(xt) -
公式的含义
注意看最后的公式,更新步长不再是固定的 η\etaη,而是 1f′′(xt)\frac{1}{f''(x_t)}f′′(xt)1。- 如果曲率 f′′f''f′′ 很大(地形很陡峭),分母大,步子就迈小点,防止走过头。
- 如果曲率 f′′f''f′′ 很小(地形很平坦),分母小,步子就迈大点,快速通过平原。
这就是最早的“自适应学习率”思想!
-
为什么不用它?
在多维情况下,二阶导数 f′′f''f′′ 变成了一个巨大的矩阵——海森矩阵 (Hessian Matrix)。
θt+1=θt−H−1gt \theta_{t+1} = \theta_t - H^{-1}g_t θt+1=θt−H−1gt
计算它太贵了!如果有 1 亿个参数,这个矩阵就有 1亿 ×\times× 1亿 个元素,根本算不动。
2. AdaGrad:为每个参数量身定制学习率 📏
承接上文,既然牛顿法的分母 f′′f''f′′(曲率)太难算,AdaGrad 想了一个偷懒的办法:用梯度的历史平方和来模拟曲率。
-
为什么要这样模拟?
牛顿法的核心是:坡度陡(曲率大)的地方步子小,坡度平(曲率小)的地方步子大。
AdaGrad 发现,如果一个参数过去经常有很大的梯度,那它的梯度平方和 ∑g2\sum g^2∑g2 就会很大。如果我们把这个平方和放在分母上,是不是就达到了“大梯度 →\to→ 小步长”的效果?这正是 AdaGrad 的设计初衷。
-
理论支撑:Fisher Information Matrix
你可能会问:凭什么用梯度平方就能代表二阶导数?这不是乱来吗?
其实原论文(以及后来的 Fisher Information 相关研究)给出了证明:
对于常见的损失函数(如对数似然函数),梯度的协方差矩阵(即 g⋅gTg \cdot g^Tg⋅gT)在期望上等于海森矩阵(二阶导数)。
这就是著名的 Fisher Information Matrix ≈\approx≈ Hessian。
AdaGrad 其实就是利用了这一点,用 g2g^2g2 的累积来近似海森矩阵的对角线元素,从而实现了低成本的“准牛顿法”。 -
它是怎么做的?
AdaGrad 引入了 二阶动量 的概念。它会记录每个参数历史上所有梯度的平方和。
Gt=∑i=1tgi2 G_t = \sum_{i=1}^t g_i^2 Gt=i=1∑tgi2
更新时,学习率会除以这个平方和的根号:
wt+1=wt−ηGt+ϵ⋅gt w_{t+1} = w_t - \frac{\eta}{\sqrt{G_t + \epsilon}} \cdot g_t wt+1=wt−Gt+ϵη⋅gt
注:ϵ\epsilonϵ 是防止分母为 0 的小常数。 -
效果分析
- 频繁更新的参数(梯度总是不为 0):分母 GtG_tGt 很大,学习率变小,更新谨慎。
- 稀疏更新的参数(梯度偶尔出现):分母 GtG_tGt 很小,学习率保持较大,一旦出现梯度就能抓住机会大步更新。
这使得 AdaGrad 非常适合处理稀疏数据(如 NLP 中的词向量)。
-
致命缺点
GtG_tGt 是单调递增的(因为它一直在累加正数)。这意味着分母会越来越大,学习率 ηGt\frac{\eta}{\sqrt{G_t}}Gtη 会持续衰减,最终趋近于 0。
导致的结果是:模型还没训练完,学习率就已经死掉了,参数不再更新。
3. RMSProp:别看太远,只看当下 👀
为了解决 AdaGrad 学习率衰减过快的问题,Hinton 大神提出了 RMSProp。
- 它是怎么做的?
它不再简单累加所有历史梯度平方,而是使用 指数加权移动平均 (Exponential Moving Average)。
vt=βvt−1+(1−β)gt2 v_t = \beta v_{t-1} + (1 - \beta) g_t^2 vt=βvt−1+(1−β)gt2
这里的 β\betaβ 通常设为 0.9。这意味着我们主要关注最近的梯度情况,而逐渐“遗忘”很久以前的梯度。 - 效果
这样分母就不会无限变大,学习率就能保持在一个合理的范围内波动。这让算法在非凸优化问题上表现更好。
4. Adam:集大成者 (Momentum + RMSProp) 🌟
Adam (Adaptive Moment Estimation) 是目前的默认首选。它结合了 Momentum (一阶动量) 和 RMSProp (二阶动量) 的优点。
- 它是怎么做的?
Adam 维护了两个状态:- 一阶动量 mtm_tmt (梯度的均值,类似惯性,冲下坡):
mt=β1mt−1+(1−β1)gt m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt=β1mt−1+(1−β1)gt - 二阶动量 vtv_tvt (梯度的未中心化方差,类似 RMSProp,调整步长):
vt=β2vt−1+(1−β2)gt2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt=β2vt−1+(1−β2)gt2
偏差修正 (Bias Correction):
刚开始 m0,v0m_0, v_0m0,v0 都是 0,会导致初期估计偏向 0。所以需要修正:
m^t=mt1−β1t,v^t=vt1−β2t \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} m^t=1−β1tmt,v^t=1−β2tvt
最终更新公式:
wt+1=wt−η⋅m^tv^t+ϵ w_{t+1} = w_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} wt+1=wt−η⋅v^t+ϵm^t
- 一阶动量 mtm_tmt (梯度的均值,类似惯性,冲下坡):
- 地位
Adam 几乎适用于所有场景,收敛快,参数鲁棒。但是,它在某些情况下(如图像分类)的泛化能力(Generalization)有时不如精调过的 SGD。
5. 这里的“坑”:L2 正则化 vs 权重衰减 (Weight Decay) 🕳️
在讲 AdamW 之前,必须先厘清一个长期被误解的概念。
我们为了防止过拟合,通常会使用 L2 正则化 或 权重衰减。在很多教材和框架文档中,这两者被混为一谈,认为它们是等价的。
-
L2 正则化:是在 Loss 函数后面加一项 12λ∣∣w∣∣2\frac{1}{2} \lambda ||w||^221λ∣∣w∣∣2。
Losstotal=Lossoriginal+12λ∣∣w∣∣2 Loss_{total} = Loss_{original} + \frac{1}{2} \lambda ||w||^2 Losstotal=Lossoriginal+21λ∣∣w∣∣2
求导后,梯度变为:gt′=gt+λwtg_t' = g_t + \lambda w_tgt′=gt+λwt。 -
权重衰减 (Weight Decay):是在更新参数时,直接让权重衰减一点点。
wt+1=wt−ηgt−ηλwt w_{t+1} = w_t - \eta g_t - \eta \lambda w_t wt+1=wt−ηgt−ηλwt
关键点来了:
- 在 SGD 中,推导一下你会发现,L2 正则化和权重衰减确实在数学上是等价的。
- 但是在 Adam 这种自适应学习率算法中,它们不等价!
为什么?
如果在 Adam 中使用 L2 正则化(即把 λw\lambda wλw 加到梯度 gtg_tgt 里),这个正则化项会被 Adam 的二阶动量 v^t\sqrt{\hat{v}_t}v^t 给除一下。
这意味着:正则化的力度被参数的梯度的幅度归一化了。
- 梯度大的参数,正则化力度变小了。
- 梯度小的参数,正则化力度变大了。
这显然不是我们想要的。我们希望权重衰减是独立的,不受梯度大小影响。
6. AdamW:修正后的 Adam ✅
这就是 AdamW (Adam with Decoupled Weight Decay) 诞生的原因。
-
它是怎么解决的?
AdamW 将权重衰减从梯度更新中剥离 (Decouple) 出来。
它不再修改梯度 gtg_tgt,而是直接在更新公式的最后一步,减去权重衰减项。AdamW 更新公式:
wt+1=wt−ηm^tv^t+ϵ⏟Adam原本的更新−ηλwt⏟独立的权重衰减 w_{t+1} = \underbrace{w_t - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}}_{\text{Adam原本的更新}} - \underbrace{\eta \lambda w_t}_{\text{独立的权重衰减}} wt+1=Adam原本的更新 wt−ηv^t+ϵm^t−独立的权重衰减 ηλwt -
为什么 AdamW 更好?
- 解耦:学习率和权重衰减超参数不再耦合,调参更容易。
- 泛化能力提升:修复了 Adam 在 L2 正则化下的错误行为,使得 AdamW 在很多任务(尤其是 Transformer、BERT 等大模型训练)中,泛化性能追平甚至超越了 SGD。
总结 📝
| 算法 | 核心思想 | 一句话点评 |
|---|---|---|
| AdaGrad | 累积梯度平方,调整学习率 | 适合稀疏数据,但后期学不动。 |
| RMSProp | 移动平均梯度平方 | 解决了 AdaGrad 衰减过快问题。 |
| Adam | 动量 + RMSProp | 现在的默认王者,但在 L2 正则上有缺陷。 |
| AdamW | 解耦权重衰减 | 修复版王者,大模型训练标配。 |
更多推荐


所有评论(0)