JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

牛頓法與擬牛頓法

梯度下降只知道下坡的方向;在一條被拉長、病態的山谷裡,它會永遠來回鋸齒。牛頓法還讀取曲率——黑塞矩陣——並一步走到二次函數的谷底。這裡說明它為何能治好鋸齒、代價是什麼,以及像 BFGS 這樣的擬牛頓法如何用零頭的價格換來幾乎全部的速度。

從斜率到曲率:為何多一階導數就改變一切

上一篇讓梯度下降在一條又長又窄的山谷裡來回鋸齒。診斷很尖銳:梯度指向下坡,但在病態問題上,「下坡」幾乎垂直於你真正需要前進的方向,於是迭代點在谷壁間彈跳、沿著谷底龜爬。梯度下降永遠只知道斜率——一階導數。本篇的解方是再餵給它曲率——二階導數——讓它能分辨平緩的山谷與陡峭的山谷,並據此縮放步長。就是這一份額外的資訊,把龜爬變成大步。

在一維裡,這想法就是純粹的牛頓法,只是瞄準了正確的目標。要把光滑的 f(x) 最小化,你要找的是斜率消失之處,f'(x) = 0——這就是你在本級第一篇遇過的一階最佳化條件。所以把求根的牛頓法施加在 f' 而非 f 上:在熟悉的迭代裡,把 f 換成 f'、把 f' 換成 f''。單變數更新變成 x_{n+1} = x_n - f'(x_n)/f''(x_n)。你不再追逐函數的零點;你追逐的是它導數的零點,那恰好是一個平坦處——一個候選極小值。

多變數的牛頓步:把黑塞矩陣當作局部地圖

現在把它提升到多變數,這時 x 是個向量。斜率變成梯度 g——偏導數構成的向量,指向上坡——而曲率變成黑塞矩陣 H,所有二階偏導數構成的矩陣。除以 f'' 的純量除法變成求解一個線性系統:牛頓步 s 解 H s = -g,然後更新 x_{n+1} = x_n + s。把它讀作「把負梯度除以曲率矩陣」。黑塞矩陣把原始的下坡方向重新縮放、旋轉,成為指向局部二次碗谷底的方向。

這是讓你恍然大悟的圖像。在 x_n 附近,用二階泰勒模型近似 f——一個二次碗,其線性部分是 g、曲率是 H。牛頓步恰好就是跳到那個碗的極小值,藉由解 H s = -g 一擊命中。若 f 真的是二次的,無論山谷多麼被拉長,牛頓法都會一步落在真正的極小值上。這就是它治好鋸齒的深層原因:梯度下降只看到陡度,在窄方向上過衝、在長方向上又走不夠;牛頓法卻看見整個橢圓的形狀,直接走到中心。

given x, gradient g(x), Hessian H(x):

  repeat:
      g = gradient(x)
      H = hessian(x)
      solve  H s = -g      # one linear solve (e.g. Cholesky)
      x = x + s            # full Newton step
  until ||g|| <= tol

  # 1-D special case:  x = x - f'(x) / f''(x)
整個方法只有五行:算出梯度與黑塞矩陣、解一個線性系統得到步長、移動。停止測試盯著 ||g||,因為極小值就在梯度消失之處。

它換來什麼,又付出什麼

回報就是你在求根時見過的那份耀眼速度:在行為良好的極小值附近,牛頓法二次收斂,每步大致把正確位數翻倍。三、四次迭代就能把你從粗略猜測帶到完整精度。關鍵是,這個速率與山谷的條件無關——黑塞矩陣的求解會自動抵消那個曾讓梯度下降癱瘓的拉伸。一個條件數為 10^6、可能讓梯度下降需要數百萬步的問題,牛頓法用寥寥數步就能解決。這是頭條。

現在是細則,而且分量十足。第一,你必須建出黑塞矩陣——對 n 個變數那是一個 n 乘 n、含 n^2 個二階導數的矩陣,往往痛苦或根本寫不出來。第二,你每次迭代都得解 H s = -g,用直接求解約需 O(n^3) 的工作量(你對 H 做分解,絕不建出它的逆)。當 n 達數百萬——現代神經網路的家常尺寸——n^2 的儲存與 n^3 的求解都直接付不起。第三,與它的求根表親一樣,二次速率只是局部的:從壞起點出發,牛頓法可能過衝、發散,或被引向鞍點或極大值,因為 H s = -g 裡沒有任何東西堅持要往下走。

擬牛頓法:幾乎全部的速度,卻不用黑塞矩陣

黑塞矩陣是那個昂貴的原料,所以顯而易見的問題是:我們能否在沒有它的情況下得到牛頓式的步?這正是擬牛頓法所做的事。這想法精打細算得漂亮。你從不計算 H。取而代之,你維護一個對黑塞矩陣(或更聰明地,對它的逆)的滾動近似 B,並用你早已在收集的資訊免費地改進它——也就是梯度如何從一步變化到下一步。若你移動 s 時梯度位移了 y,那麼一個好的曲率模型應該滿足割線條件 B s = y,這是「用兩個一階導數樣本估二階導數」在多維的回聲。

最著名的配方是 BFGS。它每一步對逆黑塞估計做一個小小的、秩為二的修正,使割線條件成立,同時保持對稱與正定(於是步永遠是下降方向)。因為 BFGS 直接更新那個,每步只花 O(n^2)——矩陣向量的工作,沒有 n^3 的求解、完全不用二階導數,只用梯度。值得注意的結果是:BFGS 超線性收斂,比梯度下降的線性龜爬快,實務上幾乎與真正的牛頓法一樣快,卻從未建出或分解過一個黑塞矩陣。

當 n 達到數百萬時,連 O(n^2) 的儲存都太多。答案是 L-BFGS(「有限記憶」BFGS),這個版本才是真正在訓練大型模型的那個。它根本不儲存任何矩陣;只保留最後幾組(比方 5 到 20 組)「步長與梯度變化」向量對,並用一個巧妙的雙迴圈遞迴,重建「近似逆黑塞矩陣作用在梯度上」的效果。記憶體與每步成本降到 O(n) 乘一個小常數。L-BFGS 是無數科學與機器學習函式庫裡預設的重型最佳化器,正因為它能擴展到龐大的 n,同時保留了牛頓法大部分的曲率智慧。

它的位置,以及它在哪裡失靈

退一步,看看這道方法的階梯,每一層都用不同的貨幣買速度。梯度下降只用梯度:每步便宜,但線性、又被條件數拖垮。牛頓法用梯度與完整黑塞矩陣:二次、不怕條件數,但 O(n^2) 記憶體與每步 O(n^3)。擬牛頓法(BFGS、L-BFGS)介於兩者之間,靠從梯度差學習曲率:超線性、只用梯度、每步 O(n) 到 O(n^2)。在它們之間選擇,是一場「每步成本」對「步數」的審慎權衡——這正是貫穿整個本級的工程判斷。

對極限要誠實。這三者都是局部下降法:在非凸地景上,它們找到某個鄰近的極小值,從不保證是全域的那個——換個起點,你可能落在別處。這裡的每個量都在浮點數裡計算,所以梯度、黑塞矩陣的求解、與 BFGS 的更新都帶著捨入誤差;一個接近奇異的黑塞矩陣(非常平坦或非常被拉長的極小值)是病態的,會如浮點那一級所警告的那樣流失位數——準確度等於條件數乘穩定度,穩定的最佳化器在病態的碗上仍會掙扎。而這些方法所需的梯度,通常不是手算,而是由自動微分提供,那台引擎才讓大規模最佳化得以實際可行。

那麼,既然 L-BFGS 這麼好,深度學習為何不直接用它?因為下一篇改變了規則。當目標函數是「數百萬個資料點上的平均」時,連一個精確梯度都貴得算不起,於是我們退而求其次,用隨機小批次取得一個便宜、帶雜訊的梯度。那份雜訊悄悄毒害了 BFGS 所依賴的曲率估計——梯度差不再是可信的曲率訊號。因此機器學習的主力根本不是牛頓法或擬牛頓法,而是帶動量的隨機梯度下降,這正是我們接下來要轉向的主題。