P5-7.3 自适应 update 的直觉:以 Adam 为例¶
Section ID:
P5-7.3Version:v2026.07.20
在 P5-7.2 里,我们已经看到:即使 gradient 相同,真实的 update 步幅也会因为 learning rate 而不同。走到这里,接下来会自然出现一个新问题:是不是所有参数都应该永远用完全相同的方式去应用这个步幅?
自适应 update(adaptive update)正是从这个问题里出现的。如果最基本的直接 update 只是根据当前 gradient 与 learning rate 移动一次,那么自适应 update 则会进一步把最近的 gradient 流向,以及不同参数坐标之间的差异也一起考虑进来。
这一节会以 Adam(Adaptive Moment Estimation)为代表例子来读这种直觉。这里真正要抓住的,不是 Adam 这个名字本身,而是:为什么 update 规则里会开始加入最近流向和按坐标调节。
如果之后又把基本 update 与自适应 update 的区别混在一起,更适合回到英文概念词汇表里的 gradient descent 条目和optimizer 条目,重新对齐比较基准。
Adam 自适应修正的问题¶
- 自适应 update 试图在基本 gradient update 上补什么?
最近 gradient 流向和按坐标调节这两个核心直觉到底分别是什么意思?- 为什么 Adam 经常被拿来当作自适应 update 的代表例子?
- 虽然 Adam 在实务里经常出现,但为什么不能把它背成绝对优劣结论?
这一节不会先堆更多 optimizer 名称,而是先解释:自适应 update 是从什么问题意识里长出来的。这里真正要读的是:已经算出来的 gradient,到底要按什么规则变成真实 update,以及为什么那个规则开始引入最近流向和按坐标差异。Adam 只是帮助我们抓住这种直觉的代表例子。至于 optimizer 家族名字的更细比较,会放到 P5-7.5;optimizer state 与 parameter-wise update 的进一步区分,则会在 P5-7.7 补充学习里接着说明;regularization 与 generalization 的视角会在 P5-8.1、P5-8.2 重新接回;而 adaptive optimization 的收敛分析则会放到 P5-7.4。
| 现在这一节要区分的 | 为什么重要 |
|---|---|
| 模型结构 | 因为这是在讨论 CNN、RNN、Transformer 之类如何表达输入的结构问题 |
| optimizer 过程 | 因为这是在讨论:同样的结构里,参数到底如何被移动 |
| 与 regularization 的区别 | optimizer 在处理怎么移动,regularization 更偏向不希望哪种解 |
gradient 历史与步幅调节的判断标准¶
- 能把自适应 update 解释成
会把最近 gradient 流向与坐标差异一起反映进去的 update 方式。 - 能理解基本直接 update 与自适应 update 的差别。
- 能说明为什么 Adam 常被作为 adaptive update 的代表例子。
- 能通过可运行的 Python 例子确认不同 update 直觉造成的差异。
理解自适应 update 之前,先要有一个基准线¶
如果一上来就从复杂公式讲起,初学者往往会看不出:到底新增了什么。所以这里先放一个最简单的基准线。当前最先要抓住的,不是某个 optimizer 名字,而是下面这个最基础的直觉:
沿着当前 gradient 指向的方向,用预先设定好的 learning rate 走一步。
这条直觉,正好延续了 P5-7.2 里learning rate 决定步幅的说明。P5-7.2 解释的是步幅本身;这一节则把所有参数都按一个共同标准步幅直接移动看成基准线,然后再比较:自适应 update 又另外加入了什么。
之所以不先把某个名字摆上来,也很明确。当前最需要的不是记名字,而是先建立一个最薄的比较基准。只有先有这个基准线,读者之后才知道:自适应 update 到底在补什么。
- 这个基准线的直觉最简单
- 它能清楚露出 gradient descent 的核心思想
- 它让 update 规则的变化最容易被看见
也就是说,这一节的基准线不是某个特定品牌 optimizer,而是:最简单的直接 update 感觉。
自适应 update 试图补什么¶
自适应 update 会使用比单纯当前 gradient + learning rate更多的信息。以 Adam 为代表例子,大致可以先按下面这些点来理解。
- 它会参考最近 gradient 的方向流向
- 它会尝试按参数坐标分别调节移动量
- 它通常带着让初期学习更快、更稳的实用目的
也就是说,自适应 update 并不满足于所有参数都按同一把尺子走,而是想把那些单纯共用步幅很容易漏掉的信息也一起反映进去。
如果把它压成一句话,就是:
Adam 会同时参考最近 gradient 的流向以及按坐标的大小差异,尝试让每个参数更自适应地移动。
换成更直觉的说法,就是:
- 直接 update 的基准:
看当前 gradient,按共同步幅走一步 - Adam 的直觉:
把最近几步的流向也留下来,并按坐标分别调节步幅
例如,假设某个参数的 gradient 一直很大又摇摆,另一个参数的 gradient 则一直很小但比较稳定。最简单的直接 update 会把它们都按同一 learning rate 往前推;而 Adam 这种自适应方式则会开始问:这个坐标最近是不是摇摆太大?、另一个坐标是不是一直动得太慢? 正因为这样,自适应 update 给人的感觉就不再是所有坐标一视同仁地走同一步,而更接近于每个坐标按自己的状况走不同的一步。
如果以 Adam 为例,会看见什么¶
入门阶段,比起一开始就看复杂公式,下面这张表更重要。
| 项目 | 直接 update 基准 | Adam |
|---|---|---|
| 基本感觉 | 直接走一步 | 反映更多累积信息的自适应 update |
| 优点 | 直觉简单,基准清楚 | 初期学习常显得更快,实务中也比较方便 |
| 注意点 | 可能对 learning rate 很敏感 | 即使看起来方便,也不能直接断言最终 generalization 一定更好 |
这张表最重要的,并不是哪一个绝对更强。更安全的读法是下面这句话。
Adam 是在最基本的 gradient update 之上,再加入最近流向与按坐标调节,因而形成更自适应 update 的代表例子。
为什么 Adam 常被拿来当代表例子¶
在实务里,Adam 被频繁提到。这里读者需要长期留下来的,不是很多人都在用,而是:为什么它常被选来代表自适应 update。
- 它常常在默认设置下也能工作得不错
- 它很容易给人一种
学习初期下降得比较快的体验 - 在大模型或复杂数据上,它会让入门门槛显得低一些
但这里也必须一起保留一个警告。
Adam 虽然常用,但这并不等于它在所有问题里都自动保证更好的最终结果。
也就是说,Adam 的流行,很大一部分来自实用性与方便性;但是否更适合某个任务,仍然是另外一个判断。
如果把前面的意思再压缩一次,自适应 update 就是:在直接 update 之上,再加入最近流向与按坐标调节。 而 Adam 是帮助我们读懂这种直觉的一个代表例子。
如果只把这层 update 规则再画得更紧一点,就是下面这样。
flowchart TD
subgraph SGD["直接 update 的直觉"]
direction TB
A["当前 gradient"] --> B["一个 learning rate"]
B --> C["直接得到 update step"]
end
GAP["比较重点:同一个 gradient 如何变成 step"]
subgraph Adam["Adam 的直觉"]
direction TB
D["当前 gradient"] --> E["最近 gradient 历史"]
E --> F["按坐标调节后的 step"]
end
SGD --> GAP --> Adam
这张图最先要确认的结果,是:如果最基本的直接 update 更接近对当前 gradient 与共同步幅立刻反应,那么 Adam 的直觉则更接近把最近流向与按坐标差异都考虑进去,再调节步幅。
练习与例子¶
下面直接进入例子。这一节的例子不是在完整实现真实 Adam,而是在把自适应 update 的核心直觉拆开来看。示例数据在 optimizer-gradient-history.csv。这个文件记录了 12 个 step 里三个参数收到的 gradient 流:一个坐标收到较大的负 gradient 且逐渐变小,一个坐标收到较小的负 gradient 且逐渐变小,还有一个坐标的方向持续摇摆。
输入:
- 多个 step 里记录的按参数区分的 gradient 流
- 参数名
parameter_name - 学习 step
step - 每个 step 的
gradient
输出:
- 简单直接 update 方式下的参数移动结果
- 简化 Adam-like 累积平均和 second moment 的 update 结果
- 各参数的平均
direct_delta与adam_like_delta - 大 gradient、小 gradient、摇摆 gradient 下移动路径如何不同
问题场景:
- 自适应 update 的差异,比起看公式名称,更适合看按参数区分的 gradient 流如何被变成逐 step update
需要确认的概念:
- 最直接的 update 会对当前 gradient 立即反应
- Adam 类直觉会把最近 gradient 信息累积起来,再调节移动量
- Adam 类直觉还会把不同坐标上的 gradient 尺度差异也一起考虑进去
输入(input):
CSV 里有下面三个坐标的 gradient 流。
| 参数 | gradient 流 | 先预想的事情 |
|---|---|---|
risk_weight | 较大的负 gradient 持续变小 | direct update 会移动得很远,Adam-like 会参考大小历史来调节步幅 |
recovery_weight | 较小的负 gradient 持续变小 | direct update 几乎动不了,Adam-like 会按这个小坐标自己的历史来调节 |
noise_weight | 负 gradient 与正 gradient 交替摇摆 | direct update 会持续改方向,Adam-like 会累积最近流向并减小摇摆 |
这张表的目的不是提前背准确数字。它只是让读者在看代码前先抓住:即使用同一个 learning rate,简单 direct update 会立刻反映当前 gradient,而 Adam-like 会留下最近流向和按坐标的大小历史,于是可能形成不同的移动路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
输出里先要比较的是:在同一个 CSV 输入下,简单 direct update 与 Adam-like 的每一步 update 是怎样分开的。
如果再把这些输出拆成输入 gradient -> 每步 update -> 累积后的 weight三层来读,Adam-like 试图补什么会更清楚。

第一阶段的输入,是 optimizer 尚未改动的 gradient 流。risk_weight 是较大的负 gradient 持续变小,recovery_weight 是较小的负 gradient 持续变小,noise_weight 则方向持续改变。简单 direct update 与 Adam-like 都会收到同一个输入。

delta 阶段开始出现差异。简单 direct update 会几乎原样把 gradient 大小差异转成 update 大小差异。Adam-like 因为同时使用最近流向和按坐标的大小历史,所以大的 gradient 坐标会被相对压住,小的 gradient 坐标也会按自己的历史被调节。

看最终参数路径时,这种差异会累积起来。对于大 gradient 持续出现的 risk_weight,direct update 移动得远得多;对于小 gradient 稳定出现的 recovery_weight,Adam-like 反应更大;对于方向摇摆的 noise_weight,两条路径都没有走得太远。这一步真正改变的不是重新计算了 gradient,而是 optimizer 规则把同一条 gradient 流变成实际 parameter path 的方式。
这个例子并不是完整重现真实 Adam 公式,也不是在判定 direct update 与 Adam 的性能优劣。这里真正要读的是下面几点。
- 简单 direct update 会比较直接地反映当前
gradient - Adam 类想法会累积最近方向和按坐标的大小历史,从而让逐 step update 不同
- optimizer 不是简单地
让它下降,而是在决定同样的 gradient 要变成怎样的 update 路径
读完这个例子后,自适应 update 的补强会分成两个轴。
| 看的轴 | 直接确认到的变化 | 本节要留下来的句子 |
|---|---|---|
| 时间轴 | 最近 gradient 会留在 moving average 里,使逐 step update 更平滑 | 自适应 update 不只看当前 gradient,也会看最近流向 |
| 坐标轴 | 每个参数会分别累积自己的 gradient 大小历史并调节步幅 | 自适应 update 不会把所有参数永远按同一标准步幅去推 |
把这张表读完以后,至少应该能够把自适应 update 说成:把时间轴累积与坐标轴调节都写进 update 规则里的方式。 Adam 则是帮助我们看懂这件事的代表例子,仅此而已。
什么时候要先用自适应 update 视角¶
在已经理解 optimizer 一般角色之后,还要继续判断:现在最简单的直接 update 感觉够不够?还是需要把自适应 update 这层直觉也调出来?
| 先出现的问题场景 | 先想到的 optimizer 视角 | 理由 |
|---|---|---|
| 需要说明 gradient 与步幅最基本的关系 | 先用直接 update 作为基准 | 因为它最清楚地展示了对当前 gradient 立即反应的感觉 |
| 初期学习很粗糙,或不同坐标尺度差异很大 | 先想到自适应 update | 因为此时最近流向与按坐标调节的直觉更重要 |
| 需要说明为什么实务里常提 Adam | 先想到自适应 update,把 Adam 作为代表例子来看 | 因为它的方便与实用性强,但不能把代表例子直接等同于一般原理 |
| 开始有人想把 optimizer 背成绝对优劣表 | 把直接基准与自适应 update 并排放回来看 | 因为速度、稳定性、generalization 不应该被揉成一句话 |
检查清单¶
- 能说明自适应 update 是在基本 update 上又补了什么吗?
- 能把自适应 update 解释成
会更多反映累积信息与按坐标差异的方式吗? - 能把直接 update 与自适应 update 区分成
立刻对当前 gradient 反应和同时参考累积信息与坐标差异两种感觉吗? - 能区分:第一个例子主要在看时间轴累积,第二个例子主要在看坐标轴调节吗?
- 能说明 Adam 只是自适应 update 的代表例子,而不是自动等于绝对更好的 optimizer 吗?
出处与参考资料¶
- Léon Bottou,
Large-Scale Machine Learning with Stochastic Gradient Descent, COMPSTAT, 2010, 确认日期: 2026-07-19. https://doi.org/10.1007/978-3-7908-2604-3_16 - Diederik P. Kingma, Jimmy Ba,
Adam: A Method for Stochastic Optimization, arXiv, 2014, 确认日期: 2026-07-19. https://arxiv.org/abs/1412.6980 - Sebastian Ruder,
An overview of gradient descent optimization algorithms, arXiv, 2016, 确认日期: 2026-07-19. https://arxiv.org/abs/1609.04747