技术博客

SGD 动量的物理类比:速度变量的指数平均为什么管用

第 125 / 147 篇 · 2026-09-26 · ai · 优化器SGD训练理论

优化器系列从最简单的 SGD 开始。裸 SGD 的更新是 $\theta_{t+1} = \theta_t - \eta g_t$——每走一步只看当前梯度,梯度一变脸就转向。真实训练里梯度有两个让裸 SGD 难受的性质:高度相关的序列结构(连续几百步的梯度方向大致一致)和大噪声(单个 batch 的梯度是随机采样出来的,方向抖动剧烈)。动量法(Polyak, 1964)用一行改动同时缓解这两个问题:

$$ v_t = \beta\, v_{t-1} + g_t, \qquad \theta_{t+1} = \theta_t - \eta\, v_t . $$

存一个速度变量,把历史梯度按指数衰减加权累加。为什么这个形式是对的?物理类比给出直觉,展开 $v_t$ 给出定量账。

heavy ball:从物理模型到更新公式

想象一个小球在 loss 景观的山谷里滚动,位置 $\theta$,受三个力:重力沿坡面的分量 $-\nabla f$、粘性阻力 $-\gamma \dot\theta$(与速度成正比)、惯性 $m\ddot\theta$。牛顿方程:

$$ m\,\ddot\theta = -\nabla f(\theta) - \gamma\,\dot\theta . $$

对这个二阶方程做离散化:用中心差分近似二阶导数,$\ddot\theta \approx (\theta_{t+1} - 2\theta_t + \theta_{t-1}) / \eta^2$,一阶导数 $\dot\theta \approx (\theta_{t+1} - \theta_{t-1}) / (2\eta)$。整理后得到

$$ \theta_{t+1} = \theta_t - \frac{\eta^2/m}{1 + \gamma\eta/(2m)}\,\nabla f(\theta_t) + \frac{\gamma\eta/(2m)}{1 + \gamma\eta/(2m)}\,(\theta_t - \theta_{t-1}), $$

即"当前位置 − 有效步长 × 梯度 + 惯性系数 × 上一步的位移"。把位移差写成速度形式,就是动量更新——动量法不是对 SGD 的启发式补丁,它是带阻尼的二阶动力学方程的一阶化。惯性系数 $\beta$ 对应物理里的"阻力小、质量大":$\beta \to 1$ 是小球在光滑面上几乎不减速,$\beta = 0$ 退化为裸 SGD(阻力无穷大,速度瞬间归零)。

这个对应还解释了动量的核心行为:小球滚进细长山谷时,横向震荡被阻力耗散掉(每个来回都损失能量),纵向分量被惯性保留(下坡方向持续加速)——动量天然地在"震荡方向减速、前进方向加速",这正是我们希望优化器在病态曲率(ill-conditioned)景观里做的事。

定量账:一致方向加速多少,噪声抑制多少

把 $v_t$ 展开成历史梯度的加权和:$v_t = \sum_{k=0}^{t} \beta^k g_{t-k}$。

一致方向的增益。 若梯度在有效窗口内近似恒定 $g$(连续 $N$ 步同向,$N \gg 1/(1-\beta)$),稳态速度是几何级数

$$ v = g\sum_{k=0}^{\infty}\beta^k = \frac{g}{1-\beta}. $$

$\beta = 0.9$ 时单方向的等效步长被放大 10 倍。换句话说,固定学习率 $\eta$ 配动量 $\beta$,等效于在一致方向上用 $\eta/(1-\beta)$ 走裸 SGD——这就是为什么开了动量之后学习率要按同样倍数重新调,两套参数耦合在一起。

噪声方向的抑制。 设真实梯度 $\bar g$ 上叠加零均值噪声,每步噪声独立、方差 $\sigma^2 I$。$v_t$ 的噪声分量是 $\sum_k \beta^k \varepsilon_{t-k}$,方差为

$$ \mathrm{Var} = \sigma^2 \sum_{k=0}^{t} \beta^{2k} \;\xrightarrow{t \to \infty}\; \frac{\sigma^2}{1-\beta^2}. $$

对比增益:信号放大 $1/(1-\beta)$ 倍(幅度),噪声只放大 $1/\sqrt{1-\beta^2}$ 倍。以 $\beta=0.9$ 计,信噪比提升约

$$ \frac{1/(1-\beta)}{1/\sqrt{1-\beta^2}} = \sqrt{\frac{1+\beta}{1-\beta}} = \sqrt{19} \approx 4.4 \text{ 倍}. $$

这就是动量在噪声大、batch 小的场景里"像用了大 batch 一样稳"的数学来源——它用梯度的时间相关性做了一次免费的方差缩减。

细长山谷中的两种轨迹:裸 SGD 锯齿震荡 vs 动量平滑滚动(示意) 裸 SGD:跨谷震荡,每步都浪费 动量:横向被阻力耗散,纵向惯性保留 一致性放大 1/(1−β)=10×;噪声放大 1/√(1−β²)≈2.3×;信噪比净赚 √((1+β)/(1−β))≈4.4×

β 的选择与一个常被漏掉的点

时间常数视角。 $\beta^k$ 衰减到 $1/e$ 需要 $k = 1/(1-\beta)$ 步:$\beta=0.9$ 的记忆窗口约 10 步,$\beta=0.95$ 约 20 步,$\beta=0.99$ 约 100 步。窗口要盖住梯度"一致性"的持续时间才有加速收益——batch 很小、梯度噪声大时,单步梯度方向的相关系数衰减很快,10–20 步的窗口(0.9–0.95)就够;窗口开太大(0.999)会累积过多过时方向,在山谷转弯处表现为明显的"冲过头"。大 batch 训练(数千至上万)的趋势是把 $\beta$ 提到 0.95 甚至更高:大 batch 本身降低了单步噪声,更长的窗口换来更彻底的方差缩减。

$\beta$ 和学习率是同一枚硬币。 由上面的稳态分析,$(\eta, \beta)$ 和 $(\eta/(1-\beta), 0)$ 在一致方向上动力等价。改 $\beta$ 必须联动改 $\eta$,只调一个是常见的调参事故源。Adam 系沿用这个耦合:动量项 $m_t$ 就是梯度的 EMA($\beta_1 = 0.9$),而 Adam 的偏差修正 $m_t / (1-\beta_1^t)$ 正是为了训练最初几十步 EMA 还没积累够、$m_t$ 系统性偏小的问题—— warmup 必需性那篇会展开二阶矩的同类问题。

Nesterov 改进一步。 Nesterov 动量把梯度计算点从 $\theta_t$ 挪到 $\theta_t + \beta(\theta_t - \theta_{t-1})$("先看一眼惯性带我到哪,在那测坡度")。在强凸问题上它有最优收敛率,实际训练中表现为震荡略小;现代实现里 Nesterov 版本常作为默认(SGD + Nesterov 在视觉任务上仍是很多强基线)。

动量在深度学习语境下的边界

动量解决的是"梯度方向有时间相关性"和"梯度有噪声"两个问题,不解决"曲率病态"本身——它缓解震荡但不改变条件数。真正的曲率自适应要等二阶信息(Adam 的二阶矩是粗糙近似,Lion/Sophia/Muon 那几篇展开各自的取舍)。另外动量累积的是梯度序列的统计,数据顺序被打乱时(标准的 shuffle 训练)它才有意义;如果数据有系统性排序(课程学习或按域分段的预训练),动量会累积段间的分布漂移方向,造成额外的不稳定——这也是预训练普遍 shuffle 的一个隐性理由。

小结

动量更新是带阻尼小球动力学的离散化:速度变量按指数衰减累加历史梯度。定量上,一致方向获得 $1/(1-\beta)$ 的步长放大,独立噪声只获得 $1/\sqrt{1-\beta^2}$,净信噪比提升 $\sqrt{(1+\beta)/(1-\beta)}$——$\beta=0.9$ 时是 4.4 倍。记忆窗口 $1/(1-\beta)$ 决定 β 的选型:小 batch 配 0.9,大 batch 可上到 0.95+。学习率和 β 耦合联动,改一个必须动另一个。它缓解震荡但不治曲率,这留给 Adam 和后面的二阶近似方法。