L2.1 19 分鐘閱讀 2026年9月

L2.1 一個 η 不夠用:動量與 Adam 各買到什麼

本篇重用M0.0霧中下山:Gradient 與方向·M0.2導航的三十秒:Taylor 展開與「假設直線」·M5.2追一隻自己也在跑的狗:移動目標、EMA 與 Stop-Gradient

起點:一個純量背了三個工作

到目前為止,η\eta 已經被要求同時做三件事:

  • 霧中下山,一步該走多大:梯度下降的一頁:它不能超過 2/λmax2/\lambda_{\max},跨過去是 1012210^{122}
  • 同一篇:走完全程需要的步數由條件數 κ=λmax/λmin\kappa=\lambda_{\max}/\lambda_{\min} 決定;那個 toy 上 κ=1.6×107\kappa=1.6\times10^7,所以在門檻上跑兩萬步仍然到不了直接解。
  • 民調只問一千人:小批次與噪聲:它決定噪聲地板的高度(η/B\propto\eta/B)。

三件事的方向彼此衝突:第一件要 η\eta 小,第二件要 η\eta 大,第三件又要 η\eta 小。而它們的根源不同——第一件是最陡方向的曲率,第二件是最平方向的曲率,第三件是抽樣的抖動。

一個純量沒辦法同時服務三個不同的需求。 出路是給最佳化器更多狀態:除了當前位置,再記一點別的東西。

走下山時,如果地面很陡就小步、很平就大步——
這件事能自動化嗎?
自動化之後,我還需要自己標準化特徵嗎?

課堂提問Q1

把「陡就小步、平就大步」翻成數學:最理想的更新是什麼?它為什麼在實務上算不出來?動量與 Adam 各是那個理想的哪一種便宜近似?

先想一想,再展開看整理後的答案

理想的更新是牛頓步。LLθ\theta 附近展開到二階(導航的三十秒:Taylor 展開與「假設直線」),最小化那個二次近似,得到

θk+1=θk[2L(θk)]1L(θk).\theta_{k+1}=\theta_k-\big[\nabla^2L(\theta_k)\big]^{-1}\nabla L(\theta_k).

這一步的意思正是「陡的方向小步、平的方向大步」:Hessian 的逆把每個方向除掉它自己的曲率。在二次問題上它一步到位,而且完全不需要調 η\eta

它算不出來的理由有兩個。 參數有 PP 個時,Hessian 是 P×PP\times P——P=109P=10^9 時它存不下,更別說求逆。而且非凸的地方 Hessian 可能不是正定的,那個「最小化」會把你送到鞍點甚至往上走。

兩種便宜的近似,取的方向不同。

  • 動量不去估 Hessian,改成把過去的梯度累積起來。在細長的碗裡,來回擺盪的分量會互相抵消,而沿著溝底的一致分量會累加——等效於在最平的方向上放大步伐。它是一個純量方法(所有座標共用同一個 η\eta、同一個 β\beta),買到的是有效條件數
  • Adam 反過來:它不管方向之間的耦合,只估每個座標自己的梯度尺度(用平方梯度的 EMA),再把該座標的步伐除掉它。等效於用一個對角矩陣近似 Hessian,買到的是逐座標的尺度

兩者不是同一件事的兩個版本,而是拆了不同的東西:動量處理「方向之間的曲率差」,Adam 處理「座標之間的尺度差」。本篇會在同一個問題上量出它們各買到多少。

兩種鬆綁:記住方向,或記住尺度

動量的圖像是一顆有重量的球。 純 GD 是一個沒有慣性的質點:每一步只看當下的坡度。加上動量之後,球會保留上一步的速度:

vk+1=βvk+L(θk),θk+1=θkηvk+1.v_{k+1}=\beta v_k+\nabla L(\theta_k),\qquad \theta_{k+1}=\theta_k-\eta\,v_{k+1}.

在一個又長又窄的溝裡,橫向的坡度左右交替,累積起來互相抵消;沿著溝底的坡度方向一致,累積起來越滾越快。球在該慢的方向被抵消,在該快的方向被放大——這正是我們想要的「陡就小步、平就大步」,而且完全不需要知道 Hessian。

vv 是梯度的一個幾何加權和:vk=jβjL(θkj)v_k=\sum_{j}\beta^{\,j}\nabla L(\theta_{k-j}),權重以 β\beta 衰減。這和 追一隻自己也在跑的狗:移動目標、EMA 與 Stop-Gradient 的移動平均是同一個物件,所以它的「記憶長度」大約是 1/(1β)1/(1-\beta) 步:β=0.9\beta=0.9 記十步,β=0.999\beta=0.999 記一千步。這個數字就是動量能買到的加速上限,下一節會把它和 κ\sqrt\kappa 對起來。

Adam 的圖像是每個座標自己的一把尺。 它同時維護梯度的一階與二階 EMA,再用後者當分母:

mk=β1mk1+(1β1)gk,sk=β2sk1+(1β2)gk2,θk+1=θkηm^ks^k+ϵm_k=\beta_1m_{k-1}+(1-\beta_1)g_k,\quad s_k=\beta_2s_{k-1}+(1-\beta_2)g_k^2,\quad \theta_{k+1}=\theta_k-\eta\,\frac{\hat m_k}{\sqrt{\hat s_k}+\epsilon}

m^,s^\hat m,\hat s 是除掉初期偏差的版本,見下面的 <Remark>)。關鍵在那個分母是逐座標的:如果某個座標的梯度一直是 10610^{6}、另一個一直是 10610^{-6},兩者除完之後步伐都是 η\eta 的量級。

這給了 Adam 一個很好用的性質,也給了它一個很容易被誤解的性質。 好用的是:把某個座標的梯度乘上一個常數,Adam 的軌跡不變——所以「特徵尺度不一致」這個 霧中下山,一步該走多大:梯度下降的一頁 的老病,它免疫。誤解的是:每一步移動的距離大約就是 η\eta,與梯度多大無關。這意味著如果正確答案要求某個座標移動 101010^{-10}、另一個座標移動 11,一個共用的 η\eta 仍然辦不到。本篇最後會把這件事跑出來。

動量的加速由 β 決定,Adam 的步長由 η 決定

動量。 在二次問題上,帶動量的迭代對每個特徵值 λ\lambda 的分量是一個二階遞迴,它的收縮率由 β\betaηλ\eta\lambda 共同決定。最佳的一組是

β=(κ1κ+1)2,每步收縮率=κ1κ+1,\beta^\star=\left(\frac{\sqrt\kappa-1}{\sqrt\kappa+1}\right)^2, \qquad \text{每步收縮率}=\frac{\sqrt\kappa-1}{\sqrt\kappa+1},

對照 GD 的 κ1κ+1\frac{\kappa-1}{\kappa+1}κ\kappa 換成 κ\sqrt\kappa——這就是動量的全部收益,而且它是理論上單靠一階資訊能拿到的最好結果。

但要注意 β\beta^\star 這個式子:κ\kappa 越大,β\beta^\star 越靠近 1。本篇 toy 的 κ=1.6×107\kappa=1.6\times10^7κ3995\sqrt\kappa\approx3995,代進去得 β0.999\beta^\star\approx0.999

β=0.9\beta=0.9 的動量只買到大約 1/(1β)=101/(1-\beta)=10 倍;要吃到 κ\sqrt\kappaβ\beta 必須跟著 κ\kappa 一起長。

這條式子解釋了一個很常見的失望:「我加了動量,可是沒什麼差」——因為 β\beta 被當成一個不用調的預設值,而它其實是這個方法唯一的旋鈕。

Adam。 因為分母是梯度自己的尺度,η\eta 的單位變成「參數空間裡每一步走多遠」,不再和損失的尺度綁在一起。後果是 η\eta 好調得多——下一節會看到 η\eta 掃過 30 倍給同一個結果。代價寫在下面的 <Remark> 裡。

補充Adam 的兩個細節:偏差修正與 ε

偏差修正。 m0=s0=0m_0=s_0=0,所以前幾步的 mkm_ksks_k 都被那個零拉小。第 kk 步時 mkm_k 的權重總和是 1β1k1-\beta_1^k,所以除掉它:m^k=mk/(1β1k)\hat m_k=m_k/(1-\beta_1^k)s^k=sk/(1β2k)\hat s_k=s_k/(1-\beta_2^k)β2=0.999\beta_2=0.9991β2k1-\beta_2^kk=100k=100 還只有 0.0950.095——不修正的話前一千步的步伐會被系統性地放大十倍,這是實作上最常見的 bug 之一。

ϵ\epsilon 不只是防除以零。 它同時是一個「地板」:梯度小到遠低於 ϵ\epsilon 的座標,步伐會回到與梯度成正比(也就是退化成 GD)。ϵ\epsilon 設得太大,Adam 的逐座標尺度就失效;設得太小,一個長期梯度接近零的座標會被放大到不穩。本篇最後那個實驗把 ϵ\epsilon10810^{-8} 調到 101210^{-12} 也救不回來——那不是 ϵ\epsilon 的問題。

展開細節Adam 的收斂性、AdamW,以及「Adam 泛化較差」這個說法

Adam 的原始論文給的收斂證明後來被指出有誤(Reddi et al., ICLR 2018 的 AMSGrad 一文給了一個 β2\beta_2 下 Adam 不收斂的反例),修法是對 sks_k 取歷史最大值。實務上這個修正很少被採用,因為它在多數任務上沒有可觀察的差別——這是一個「理論反例存在但實務影響小」的例子,值得知道它存在,不必為它改預設值。

AdamW 改的是另一件事。原本的實作把 weight decay 當成一個加在梯度上的項 gg+λθg\leftarrow g+\lambda\theta,於是它也會被那個 s^\sqrt{\hat s} 分母除掉——梯度大的座標,衰減被除得比較小,衰減強度變成隱含地依賴梯度尺度。AdamW 把衰減直接寫在更新上(θθηm^/(s^+ϵ)ηλθ\theta\leftarrow\theta-\eta\hat m/(\sqrt{\hat s}+\epsilon)-\eta\lambda\theta),讓它回到「與梯度尺度無關」。這件事與 限制筆記頁數,或考前一天停止補習:正則化與提早停止 的內容接在一起。

至於「Adam 泛化比 SGD 差」:這個說法在影像分類上有不少支持的實驗,在語言模型上則幾乎相反(那裡 Adam 家族是唯一實用的選擇)。目前沒有一個乾淨的機制解釋,而且大多數比較都沒有把 η\eta 與 weight decay 同時調到各自的最佳。這一篇不下這個結論,只記錄:換最佳化器會改變你走到哪個解,那件事本身要用留出資料量,不能用直覺判。

回到情境:哪個病用哪個旋鈕

把三個「η\eta 背的工作」對回三個旋鈕:

症狀根源該動的旋鈕
訓練幾百步後突然 NaNη\eta 越過 2/λmax2/\lambda_{\max}η\eta、加 warmup
穩定但慢到走不完條件數大動量(β\beta 要跟著 κ\kappa 調)、標準化、Adam
座標之間的梯度差好幾個數量級特徵/參數尺度不一致Adam、標準化、正規化層
曲線已經平了但停在高處噪聲地板η\eta、加 BB、學習率衰減

這一切依賴什麼。 一,上面動量的 κ\sqrt\kappa二次問題的結果;真實網路的 Hessian 會隨訓練變動,β\beta^\star 也跟著動,所以實務上 β\beta 是掃出來的而不是算出來的。二,Adam 的尺度免疫是對梯度的尺度,不是對參數該有的量級——這是下一節那個實驗的重點。三,這裡全部用全批次梯度量;加了 minibatch 噪聲之後,動量還多一個副作用:它同時平滑掉噪聲(記憶長度 1/(1β)1/(1-\beta) 步的平均),所以 β\beta 也在偷偷改變 民調只問一千人:小批次與噪聲 的地板高度。

回到情境:在同一個問題上量三個方法

霧中下山,一步該走多大:梯度下降的一頁 的同一組設定:共用 toy n=30n=30、五次多項式特徵(不標準化),λmax=1.803\lambda_{\max}=1.803κ=1.6×107\kappa=1.6\times10^7、直接解的訓練 MSE =0.01466=0.01466。每個方法都跑兩萬步,各自用它能穩定的最大 η\eta

import numpy as np
from ml_toy import toy_1d

x, y = toy_1d(n=30, seed=0)
V = np.vander(x, 6, increasing=True); n = len(x)

def final(kind, eta, mom=0.9, T=20000):
    w = np.zeros(6); v = np.zeros(6); s = np.zeros(6)
    for t in range(1, T+1):
        g = (V.T @ (V@w - y))/n
        if kind == "gd":       w -= eta*g
        elif kind == "mom":    v = mom*v + g; w -= eta*v
        elif kind == "adam":
            v = 0.9*v + 0.1*g;  s = 0.999*s + 0.001*g*g
            w -= eta*(v/(1-0.9**t))/(np.sqrt(s/(1-0.999**t)) + 1e-8)
    return ((V@w - y)**2).mean()
直接解 0.01466;兩萬步之後的訓練 MSE
  GD        η=0.3   0.03213      momentum β=0.9    η=0.11  0.02638
  GD        η=0.7   0.02891      momentum β=0.99   η=0.11  0.01668
  GD        η=1.05  0.02666      momentum β=0.999  η=0.11  0.01596
  GD        η=1.15  發散         momentum β=0.9999 η=0.002 0.02393

  Adam η=0.003  0.01647     Adam η=0.01  0.01638
  Adam η=0.03   0.01638     Adam η=0.1   0.01646

三個結論,三個不同的性質。

動量的旋鈕是 β\beta,不是「有沒有加」。 β=0.9\beta=0.90.026380.02638,而 GD 在門檻上是 0.026660.02666——差 1%1\%,實務上看不出來。把 β\beta 推到 0.990.99 才掉到 0.016680.016680.9990.9990.015960.01596。而理論算出來的 β=0.998999\beta^\star=0.998999 正好落在後兩者之間,0.99990.9999 又太大(0.023930.02393,過衝)。理論值直接命中實測的最佳位置。

Adam 幾乎不用調。 η\eta0.0030.0030.10.1(30 倍)給的結果都在 0.016380.016380.016470.01647,而且全部優於任何 β\beta 的動量。原因是那個逐座標的分母把 x0x^0x5x^5 六個欄位的尺度差先除掉了——它處理的正是這個問題真正的病。

最好的動量與 Adam 差不多。 0.015960.015960.016380.01638。所以在這個問題上兩條路都通,差別是 Adam 用預設值就到,動量要找對 β\beta

刻意違反:把 xx 換成「民國年」。 這是 霧中下山,一步該走多大:梯度下降的一頁 那個實驗——同一份資料,只把 x[0,1]x\in[0,1] 換成 t=100+10xt=100+10x,於是 λmax\lambda_{\max}1.8031.803 變成 1.75×10201.75\times10^{20}。GD 的門檻掉到 1.14×10201.14\times10^{-20}。Adam 對梯度尺度免疫,它應該沒事吧?

這組特徵的直接解 MSE = 0.01867
直接解的各座標量級:2.0e-03  8.5e-02  2.2e+00  6.4e-02  6.1e-04  1.9e-06

  GD       η=1e-24   兩萬步後  0.36383
  momentum η=1e-24   兩萬步後  0.36377
  Adam     η=0.1     二十萬步後  21547
  Adam     η=1e-3    二十萬步後  7.6e+07
  Adam     η=1e-6    二十萬步後  169.56
  Adam     η=1e-9    二十萬步後  0.21414
  Adam     η=1e-12   二十萬步後  0.21416

  每欄標準化之後:Adam η=0.01,兩萬步後 0.01466(=直接解)

沒有一個 η\eta 讓 Adam 走到 0.01870.0187 最好的是 η=109\eta=10^{-9}0.2140.214——比 GD 的 0.3640.364 好,但距離直接解還有一個數量級。而每欄標準化之後,Adam 用預設的 η=0.01\eta=0.01 兩萬步就走到 0.014660.01466正好是直接解

原因在第二行那個量級表:正確答案要求 w22.2w_2\approx2.2w51.9×106w_5\approx1.9\times10^{-6},差六個數量級。Adam 每一步在每個座標上都移動大約 η\eta,所以 η\eta 要小到能刻出 10610^{-6}w2w_2 就得走兩百萬步;η\eta 大到能快速刻出 2.22.2w5w_5 就一步跨過去然後開始震盪。

Adam 對「每個座標的梯度尺度」免疫,對「每個座標該有的參數量級」不免疫。

所以那條很常聽到的建議——「用 Adam 就不用管特徵標準化了」——只對了一半。標準化不可省,因為它改的是參數該有的量級(霧中下山,一步該走多大:梯度下降的一頁 說它在改碗的形狀),而最佳化器改的只是走路的方式。

三個方法、三個旋鈕,在同一個碗上

互動 demo:三種模式:正常、損失乘一千、民國年。動量買有效條件數,Adam 買逐座標的尺度。

先消化一下

想一想

一個團隊在一個條件數很大的問題上「加了動量(β=0.9\beta=0.9)」但幾乎沒有改善,結論是「動量對我們的問題沒用」。最準確的評論是:

想一想

關於「用 Adam 就不需要標準化特徵」,根據本篇的實測,正確的說法是:

想一想

Adam 的偏差修正(m^=m/(1β1k)\hat m=m/(1-\beta_1^k)s^=s/(1β2k)\hat s=s/(1-\beta_2^k))如果被漏掉,最直接的後果是:

想一想

下列哪一句不對

參考文獻

  1. Polyak, B. T. Some methods of speeding up the convergence of iteration methods. USSR Computational Mathematics and Mathematical Physics 1964.(heavy-ball 動量的原始論文與 κ\sqrt\kappa 收縮率。)
  2. Kingma, D., Ba, J. Adam: A Method for Stochastic Optimization. ICLR 2015.(更新式、偏差修正、ϵ\epsilon 的角色與預設值的來源。)
  3. Goh, G. Why Momentum Really Works. Distill 2017.(動量在二次問題上的逐特徵值分析與可調的視覺化,本篇 β\beta^\star 的推導在這裡有完整版本。)