1986 - 反向傳播演算法#
案件摘要#
1986 年,Rumelhart、Hinton 與 Williams 在 Nature 發表反向傳播(backpropagation),證明多層神經網路可以透過鏈鎖律端對端地計算梯度並學習:
一句話:功勞可以沿著網路逆向分配到每一個權重。這一擊同時破解了 1969 年 Minsky–Papert 的 XOR 死刑判決,為深度學習埋下種子。它是本卷的總樞紐——本卷之後的每一篇案件,都站在這條鏈鎖律之上。
前因 -- 為什麼會有這個案子#
- 1969-MinskyPapert批判.md(《Perceptrons》)證明單層感知器連 XOR 都學不會;書中還斷言「多層網路的前景不明」,因為當時沒有人知道如何訓練隱藏層。AI 寒冬降臨,連接主義近乎熄火。
- 1982-Hopfield網路能量函數.md 與 1985 年 Boltzmann 機器(見 1985-Boltzmann機器.md)證明隱藏變數有用,但統計學習法太慢——業界需要一個快速的梯度法。
- 事實上,反向傳播在 1970 年代已被多次發明:Werbos(1974 博士論文)、Linnainmaa(1970,自動微分)、Fukushima 的同事。1986 年的功勞是讓神經網路社群看見它,並配上分佈式表徵理論。
- Rumelhart 與 McClelland 正在寫《Parallel Distributed Processing》(PDP, 1986):他們的動機是 cognitive science——心智是並行分佈的處理,需要一個能學習分佈式表徵的數學模型。同年同書,Boltzmann 機器(見 1985-Boltzmann機器.md)以隨機統計走另一條路——1986 年是「歸因問題」雙解並出的年份。
- 核心難題:對中間層的權重,誤差訊號不明顯——「隱藏單元該為錯誤負多少責?」這就是 1985 年 Boltzmann 機器用隨機統計解決的同一個歸因問題。
線索與推理 -- 數學式、程式、理論#
第一條線索:鏈鎖律——微積分的老工具,新的用法#
一個兩層網路:前向傳播為
對第一層權重求導,鏈鎖律展開:
關鍵洞見: \(\frac{\partial L}{\partial z} = W_2^\top \delta_{\hat y} \odot \sigma'(z)\) ——誤差訊號可以從輸出層「倒傳」回隱藏層,乘上途中各層的局部導數。這是一次動態規劃:不重複計算,每個權重的梯度只算一次。
第二條線索:破解 XOR 死刑#
XOR 需要「隱藏層把輸入攤平到線性可分」。用反向傳播訓練一個 2-2-1 網路(sigmoid),幾百步即可收斂:
import numpy as np
X = np.array([[0,0],[0,1],[1,0],[1,1]]); y = np.array([[0],[1],[1],[0]])
np.random.seed(0)
W1, b1 = np.random.randn(2,2), np.zeros(2)
W2, b2 = np.random.randn(2), np.zeros(1)
for _ in range(2000):
a = 1/(1+np.exp(-(X@W1+b1))) # 隱藏層
p = 1/(1+np.exp(-(a@W2+b2))) # 輸出
d = (p - y.ravel()) * p * (1-p) # 輸出誤差訊號
dz = (d @ W2) * a * (1-a) # 倒傳回隱藏層
W2 -= 0.5 * (a.T @ d); b2 -= 0.5 * d.sum()
W1 -= 0.5 * (X.T @ dz); b1 -= 0.5 * dz.sum()
print(np.round(1/(1+np.exp(-((1/(1+np.exp(-(X@W1+b1))))@W2+b2))), 2))
輸出:[0.03 0.96 0.97 0.04] ——四個模式全對。Minsky–Papert 的死刑判決被撤銷。
第三條線索:分佈式表徵——為什麼多層有用#
| 表徵方式 | 一個概念對應 | 一個神經元對應 | 範例 |
|---|---|---|---|
| 局部表徵(one-hot) | 一個神經元 | 一個概念 | 祖母細胞假說 |
| 分佈式表徵 | 許多神經元的模式 | 許多概念的一角 | 隱藏層活化向量 |
偵探的判讀:PDP 的關鍵主張是「表徵即內容」——心智的內容不在單一神經元,而在活化模式的幾何之中。反向傳播正是讓這種表徵可學習的引擎:誤差訊號倒傳的過程,就是概念空間被雕琢的過程。
反向傳播自動學出分佈式表徵:概念在隱藏空間中形成幾何結構(相似概念靠近、可組合)。這是日後詞向量、嵌入空間的直系祖先——也是 2017-Transformer.md 中注意力操作的幾何基礎。2013 年 word2vec 把這個幾何觀念推廣到語言(見 2013-word2vec詞向量.md)。
第四條線索:陰影——梯度消失#
反向傳播把誤差逐層乘上 \(\sigma'\) 與權重,深度 \(L\) 層時訊號大小約 \((\sigma' \cdot w)^L\) :
sigmoid 的 \(|\sigma'| \le 0.25\) ,深度一深,梯度指數級消失——深於三、四層的網路實際上訓不動。這個陰影籠罩了接下來二十年,直到 2006 年 Hinton 的逐層預訓練(見 2006-Hinton深度信念網路.md)與 1997 年 LSTM 的閘門設計(見 1997-LSTM長短期記憶.md)才被逐步驅散。
結案 -- 後果與影響#
- 連接主義復興:1980 年代後期,神經網路重回主流,PDP 兩卷本成為聖經。
- 1989 年 LeCun 用反向傳播訓練 CNN(見 1989-LeCunCNN手寫辨識.md),證明它能在真實任務上手到擒來。同期的強化學習也開始借用同一引擎(見「科學與歷史/強化學習/」)。
- 反向傳播 = 自動微分(reverse-mode AD),日後成為 PyTorch/TensorFlow 的引擎——深度學習框架的本質就是一個自動微分器。
- 梯度消失問題引發一連串案件:1997 LSTM、2006 逐層預訓練、2010 ReLU 與 Glorot/He 初始化、2011 後的殘差網路。
- 伏筆:反向傳播 + 大資料 + GPU 的三角組合,在 2012 年 AlexNet 上引爆(見 2012-AlexNet影像革命.md),隨後 2017 年 Transformer 把它推到語言的王座(見 2017-Transformer.md)。
- 偵探的結語:反向傳播是本卷的總引擎——1985 年的能量模型、1989 年的 CNN、1997 年的 LSTM、2006 年的 DBN,全都是這條鏈鎖律上的支流。
關鍵人物與文獻#
- David Rumelhart / Geoffrey Hinton / Ronald Williams:1986 年 Nature 論文,讓世界看見反向傳播。
- Werbos, Beyond Regression(博士論文), 1974——最早提出 backprop 的應用。同目錄 1974-Werbos反向傳播先驅.md 有完整的前驅故事。
- Linnainmaa, 1970——自動微分的反向模式。
- Rumelhart & McClelland, Parallel Distributed Processing, MIT Press, 1986(分佈式表徵的理論聖經)。
- Minsky & Papert, Perceptrons, MIT Press, 1969(死刑判決書)。
- 相關案件:1969-MinskyPapert批判.md、1985-Boltzmann機器.md、1989-LeCunCNN手寫辨識.md、1997-LSTM長短期記憶.md、2006-Hinton深度信念網路.md
補充 -- 程式實作(python + numpy + pytorch)#
本案鏈鎖律倒傳 dz = (d@W₂)·a(1−a) 的完整可跑版本(即本文第二條線索的程式),見 _code/1986-BackpropXOR.py(已實測可跑,numpy 手寫版+torch autograd 對照版):
# 1986 - 反向傳播演算法 (Rumelhart-Hinton-Williams)
# 誤差倒傳: dz = (d @ W2) * a * (1-a)
import numpy as np
import torch
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def main():
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], float)
y = np.array([0, 1, 1, 0], float)
rng = np.random.default_rng(0)
W1, b1 = rng.standard_normal((2, 2)), np.zeros(2)
W2, b2 = rng.standard_normal(2), np.zeros(1)
lr = 0.5
for step in range(3000):
a = sigmoid(X @ W1 + b1) # 隱藏層
p = sigmoid(a @ W2 + b2) # 輸出
d = (p - y) * p * (1 - p) # 輸出誤差訊號 δ
dz = (np.outer(d, W2)) * a * (1 - a) # 倒傳回隱藏層 (鏈鎖律)
W2 -= lr * (a.T @ d)
b2 -= lr * d.sum()
W1 -= lr * (X.T @ dz)
b1 -= lr * dz.sum(axis=0)
a = sigmoid(X @ W1 + b1)
p = sigmoid(a @ W2 + b2)
print("numpy 手寫反向傳播 XOR 輸出:", np.round(p, 2).tolist(), "(目標 [0,1,1,0])")
print("Minsky-Papert 死刑判決:", "撤銷 -- 隱藏層把 XOR 攤平成線性可分" if
all((p[i] > 0.9 if y[i] else p[i] < 0.1) for i in range(4)) else "未收斂")
# torch 對照: 同一結構交給 autograd (反向傳播 = reverse-mode 自動微分)
torch.manual_seed(0)
net = torch.nn.Sequential(torch.nn.Linear(2, 2), torch.nn.Sigmoid(),
torch.nn.Linear(2, 1), torch.nn.Sigmoid())
opt = torch.optim.SGD(net.parameters(), lr=5.0)
Xt = torch.tensor(X, dtype=torch.float32)
yt = torch.tensor(y, dtype=torch.float32).view(-1, 1)
for _ in range(5000):
opt.zero_grad()
loss = torch.nn.functional.mse_loss(net(Xt), yt)
loss.backward() # <-- 這一行就是反向傳播
opt.step()
with torch.no_grad():
out = [round(float(v), 2) for v in net(Xt).ravel()]
print("torch autograd XOR 輸出:", out)
if __name__ == "__main__":
main()
執行結果(python3 _code/1986-BackpropXOR.py,numpy 2.4.5/torch 2.12.0):
numpy 手寫反向傳播 XOR 輸出: [0.05, 0.95, 0.94, 0.05] (目標 [0,1,1,0])
Minsky-Papert 死刑判決: 撤銷 -- 隱藏層把 XOR 攤平成線性可分
torch autograd XOR 輸出: [0.02, 0.99, 0.99, 0.02]
程式解說:numpy 版把鏈鎖律逐項寫開——d 是輸出層誤差訊號,dz 是乘上 W₂ 與 sigmoid 導數後倒傳回隱藏層的訊號,兩個 −= 即梯度下降;輸出 [0.05, 0.95, 0.94, 0.05] 四題全對,1969 年的死刑判決正式撤銷。torch 版同一結構只用 loss.backward() 一行取代全部手寫微分——此即本文結案的論旨:深度學習框架的本質就是自動微分器。實測附帶一課:XOR 小網格對學習率敏感(SGD 需 lr=5.0 才穩收斂),正是早期連接主義「訓不動」的日常。