1990-Elman循環神經網路#
案件摘要#
1990 年,UCSD 的認知科學家 Jeffrey Elman 在《Cognitive Science》發表《Finding Structure in Time》,提出 Simple Recurrent Network(SRN,俗稱 Elman 網路)。這個網路把「上一刻的隱層狀態」複製回輸入端,讓網路第一次真正擁有了「時間的記憶」。Elman 用它做了一個驚人的實驗:只訓練網路預測下一個詞,隱層表示中竟自動浮現出名詞、動詞、生命體等語法類別——不需要任何手工標記。這是詞向量(word embedding)思想的哲學先聲,也是循環神經網路成為序列建模標準的破案時刻。
前因 -- 為什麼會有這個案子#
- 前饋網路(perceptron、多層感知器)的輸入是固定長度的向量,但語言是變長的序列:「我昨天去了書店」和「去」的長度天差地遠,前饋網路無從下手。
- 1987 年 Waibel 等人的時間延遲網路(TDNN)用固定長度的滑動視窗處理語音,仍只能看見有限窗口內的線索,記不住遠處的上下文。
- 1986 年 Rumelhart、Hinton、Williams 在《Nature》發表反傳播(backpropagation),多層網路的訓練難題已解,工具箱齊備。
- 1986 年 Michael Jordan 在《Serial Order: A Parallel Distributed Processing Approach》中提出輸出回饋式的循環架構(Jordan 網路),證明「回饋」是處理序列的可行路線。
- Elman 的核心疑問:網路能不能自己發現詞的語法類別,而不靠語言學家手工標記?要回答這題,網路必須能「記得」剛剛看過什麼。
線索與推理 -- 數學式、程式、理論#
Elman 網路(SRN)的架構#
Elman 的關鍵手法:把隱層在時刻 \(t-1\) 的狀態 \(h_{t-1}\) 複製到一組 context unit,與當前輸入 \(x_t\) 一起送入隱層:
其中 \(\sigma\) 是 sigmoid 函數。context unit 就像偵探的筆記本:每次看新線索前,先把上一頁的筆記攤在桌上。隱層因此同時「看到」現在與(壓縮後的)過去。
BPTT:沿時間展開的反傳播#
訓練時,把循環網路沿時間展開成 \(T\) 層的深層前饋網路,再用標準反傳播。隱層梯度沿時間倒傳:
這條式子預告了下一個案子:若 \(W_{hh}\) 的譜半徑小於 1,梯度會連乘而消失;大於 1 則爆炸(vanishing/exploding gradient,Hochreiter 1991、Bengio 1994 將正式立案)。
破案時刻:隱層聚類自動浮現語法類別#
Elman 訓練小型人工文法生成的句子,任務只有一個:預測下一個詞。訓練完後對隱層表示做階層式聚類,樹狀圖上自動分出名詞/動詞、有生命/無生命等類別。網路從「預測下一詞」這個單純的監督訊號中,自己學出了語法結構——這正是今日「分散式語義表示」的哲學起點。
對照:Jordan 網路#
Jordan(1986)回饋的是輸出層 \(h_t = \sigma(W_{hx} x_t + W_{ho}\, y_{t-1})\) ;Elman 回饋的是隱層。隱層是可學習的壓縮表示,容量遠大於輸出,這是 SRN 勝出的關鍵差異。
Python 示範:numpy 手刻 SimpleRNN#
以下用 numpy 手刻 Elman 網路,訓練它預測人工文法的下一個詞,並展示隱層自動分群:
import numpy as np
rng = np.random.default_rng(0)
words = ["boy", "girl", "chase", "see", "dog", "cat"]
V = len(words); w2i = {w: i for i, w in enumerate(words)}
def sample_sentence():
# 簡單文法: [N-life N] [V] [N-life]
s = [["boy", "girl"][rng.random() < .5], ["dog", "cat"][rng.random() < .5]]
s += [["chase", "see"][rng.random() < .5], ["boy", "girl"][rng.random() < .5]]
return s
def onehot(i):
v = np.zeros(V); v[i] = 1.0; return v
d = 12 # Elman 網路參數
Wx = rng.normal(0, .3, (d, V)); Wh = rng.normal(0, .3, (d, d)); b = np.zeros(d)
Wy = rng.normal(0, .3, (V, d)); by = np.zeros(V)
sigmoid = lambda z: 1 / (1 + np.exp(-z))
softmax = lambda z: np.exp(z - z.max()) / np.exp(z - z.max()).sum()
lr = 0.3
for epoch in range(300):
sent = sample_sentence()
xs = [onehot(w2i[w]) for w in sent]
T = len(xs)
hs = [np.zeros(d)]
for t in range(T): # 前向
h = sigmoid(Wx @ xs[t] + Wh @ hs[-1] + b)
hs.append(h)
# 簡化 BPTT:只對最後數步截斷反傳(truncated BPTT)
K = min(3, T)
dWh = np.zeros_like(Wh); dWx = np.zeros_like(Wx)
dWy = np.zeros_like(Wy); dby = np.zeros_like(by); db = np.zeros_like(b)
dh_next = np.zeros(d)
for t in range(T - 1, T - 1 - K, -1):
y = softmax(Wy @ hs[t + 1] + by)
dy = y.copy(); dy[w2i[sent[t]]] -= 1
dh = Wy.T @ dy + dh_next
dWy += np.outer(dy, hs[t + 1]); dby += dy
dh_raw = dh * hs[t + 1] * (1 - hs[t + 1])
dWh += np.outer(dh_raw, hs[t]); dWx += np.outer(dh_raw, xs[t])
dh_next = Wh.T @ dh_raw
for P, G in [(Wx, dWx), (Wh, dWh), (b, db), (Wy, dWy), (by, dby)]:
P -= lr * G
# Elman 式觀察:收集每個詞在各上下文中出現時的隱層狀態,比較類內/跨類相似度
H = {w: [] for w in words}
for _ in range(3000):
sent = sample_sentence(); h = np.zeros(d)
for w in sent:
h = sigmoid(Wx @ onehot(w2i[w]) + Wh @ h + b)
H[w].append(h.copy())
cos = lambda a, c: float(a @ c / (np.linalg.norm(a) * np.linalg.norm(c)))
mn = lambda w: np.mean(H[w], axis=0)
nouns, verbs = ["boy", "girl", "dog", "cat"], ["chase", "see"]
intra = np.mean([cos(mn(a), mn(c)) for a in nouns for c in nouns if a < c])
cross = np.mean([cos(mn(a), mn(v)) for a in nouns for v in verbs])
print("類內(名詞-名詞)相似度:", round(intra, 3), "| 跨類(名詞-動詞):", round(cross, 3))
print("差異:", round(intra - cross, 3), "(>0 代表語法類別在隱層中自動分離)")
結案 -- 後果與影響#
- 循環神經網路(RNN)正式成為變長序列建模的標準架構,語言與語音研究有了新武器。
- BPTT 的梯度消失問題隨後被正式立案(Hochreiter 1991、Bengio et al. 1994),埋下 LSTM(1997)的伏筆;Elman 的隱層聚類實驗則是現代詞嵌入的哲學先聲——「預測下一詞就能學出語義結構」在 word2vec(2013)應驗。
- RNN 在 2010 年代成為語音辨識與 NLP 主力(2014 年 Seq2Seq 的編碼器就是 RNN);「連結主義 vs 規則主義」之爭也因 SRN 出現新戰場。
關鍵人物與文獻(條列,含真實文獻書目)#
- Jeffrey L. Elman (1990). Finding Structure in Time. Cognitive Science, 14(2), 179–211.
- Michael I. Jordan (1986). Serial Order: A Parallel Distributed Processing Approach. ICS Report 8604, UC San Diego.
- Rumelhart, Hinton & Williams (1986). Learning representations by back-propagating errors. Nature, 323, 533–536.
- Hochreiter (1991). Untersuchungen zu dynamischen neuronalen Netzen. Diploma thesis, TU München.
- Bengio, Simard & Frasconi (1994). Learning Long-Term Dependencies with Gradient Descent is Difficult. IEEE Trans. Neural Networks, 5(2), 157–166.