03.2 反向傳播演算法#
本章導讀#
泛近似定理說「學得到」的函數存在,但沒說怎麼找。 答案是微積分裡最古老的一行公式——鏈鎖律——配上聰明的計算順序。 反向傳播(Backpropagation)不是新理論,而是鏈鎖律的動態規劃:每個參數只算一次。
淺顯說明#
想像一條工廠生產線:原料(輸入)→ 組裝 → 品檢 → 出貨(輸出)。 出貨品質不合格(損失很大),要追責任:
- 前向:順著生產線算出輸出與損失。
- 反向:從損失往回走,把「責任」(梯度)一層層分回去—— 離損失越近的工序,責任越大;每一站的責任 = 上游責任 × 本站敏感度。
關鍵省力技巧:先用前向把每站的中間結果存起來,回程直接查表乘一乘—— 否則每個參數都要重跑整條生產線,計算量會爆炸。
正規理論#
問題設定#
\(L\) 層前饋網路:
目標:計算 \(\dfrac{\partial L}{\partial W^{(l)}}\) (所有層)。
鏈鎖律與誤差項#
定義第 \(l\) 層的誤差向量:
反向遞推(鏈鎖律的核心):
其中 \(\odot\) 是逐元素乘(Hadamard 積)。梯度:
推導#
對單一權重 \(W^{(l)}_{ij}\) (連接 \(a^{(l-1)}_j\) 到 \(z^{(l)}_i\) ), \(z^{(l)}_i = \sum_k W^{(l)}_{ik} a^{(l-1)}_k + b^{(l)}_i\) 直接偏導得 \(\partial z^{(l)}_i / \partial W^{(l)}_{ij} = a^{(l-1)}_j\) ,故
而 \(\boldsymbol{\delta}^{(l)}\) 的遞推由鏈鎖律:
計算複雜度#
反向傳播把梯度計算從 \(O(P \cdot F)\) ( \(P\) 個參數、每次前向 \(F\) )降到與前向同階: 總計算量約為前向的 2–3 倍。這是自動微分「反向模式」的特例—— 一個輸出、多個輸入時,反向模式壓倒性地快,而神經網路訓練恰好就是這種情形(損失是唯一輸出)。
自動微分#
現代框架(PyTorch/JAX)把每個基本運算記錄成計算圖,自動執行上述過程:
Diff-Physics 等可微物理引擎更讓梯度穿透物理模擬流動(08.1 節)。
簡易範例:兩層網路手算#
網路: \(z^{(1)} = w_1 x\) , \(a^{(1)} = \sigma(z^{(1)})\) , \(z^{(2)} = w_2 a^{(1)}\) , \(L = \frac{1}{2}(z^{(2)} - y)^2\) 。 取 \(x = 1\) , \(w_1 = 1\) , \(w_2 = 1\) , \(y = 0\) , \(\sigma = \tanh\) 。
前向: \(z^{(1)} = 1\) , \(a^{(1)} = \tanh 1 \approx 0.7616\) , \(z^{(2)} = 0.7616\) , \(L \approx 0.290\) 。
反向:
梯度:
用 \(\eta = 0.5\) 更新後 \(L\) 立即下降——誤差自己教了網路。
歷史典故#
- 1974 年 Werbos 的先驅工作:見卷宗 ../1974-Werbos反向傳播先驅.md——博士論文裡的鏈鎖律,早了 12 年無人問津。
- 1986 年反向傳播演算法:見 ../1986-反向傳播演算法.md——Rumelhart、Hinton、Williams 的 Nature 論文,讓寒冬結束。
習題#
- 對上例多算一步:更新後的 \(w_1, w_2\) 與新的 \(L\) ,驗證損失下降。
- 證明:對 softmax 輸出加交叉熵損失, \(\boldsymbol{\delta}^{(L)} = \hat{\mathbf{y}} - \mathbf{y}\) (形式極簡)。
- 若網路有 10 個輸出與 1 個輸入,前向模式與反向模式自動微分哪個快?為什麼?
補充#
1. 數學推導證明#
證明(習題 2):softmax + 交叉熵損失的誤差項 \(\boldsymbol{\delta}^{(L)} = \hat{\mathbf{y}} - \mathbf{y}\) 。
設輸出 \(\hat{y}_k = \mathrm{softmax}(\mathbf{z})_k = \dfrac{e^{z_k}}{\sum_{k'} e^{z_{k'}}}\) ,損失用交叉熵( \(y\) 為 one-hot):
先算 softmax 的偏導:記 \(S = \sum_{k'} e^{z_{k'}}\) ,則
再由鏈鎖律( \(y\) 是常數):
因 \(\sum_k y_k = 1\) (one-hot),得
意義:誤差項就是「預測減答案」——預測錯得越離譜,梯度越大。這是深度學習框架中 softmax 輸出層幾乎總是搭配交叉熵的原因:兩者相減後對數項恰好抵消,梯度既簡潔又數值穩定。 \(\blacksquare\)
2. 簡易範例#
範例一(習題 1):更新一步驗證損失下降。 沿用本章手算例( \(x=1\) , \(y=0\) , \(\sigma=\tanh\) ),用 \(\eta = 0.5\) 更新後 \(w_1 \approx 0.8396\) 、 \(w_2 \approx 0.7099\) ,新損失 \(L \approx 0.152\) ,比原來的 \(0.290\) 下降近一半——誤差自己教了網路。
範例二:手算 backprop 並用數值差分驗證。 程式見 _code/03.2-backprop-manual.py:實作一個 2-2-1 的兩層網路(tanh 活化、均方誤差),先用鏈鎖律解析算出 \(\partial L / \partial W\) ,再用中心差分
逐參數驗證。輸出顯示解析梯度與數值梯度在 \(10^{-9}\) 級完全一致——反向傳播確實是鏈鎖律的正確實作。