Learning Objectives
- 用兩層神經元手動解出 XOR,說明隱藏層做了什麼
- 寫出每一層的矩陣形狀,算出網路的參數個數
- 說明層與層之間為什麼一定要有非線性的活化函數
- 用 numpy 寫出前向傳播,並從實驗判斷神經元太少時會發生什麼
一條線不夠,就用兩條
上一課看到,一個神經元的決策邊界是一條直線,所以學不會 XOR。解法是把神經元疊起來:
輸入層 → 隱藏層 → 輸出層
中間那一層叫隱藏層(hidden layer),因為訓練資料只告訴我們輸入和答案,沒有告訴我們中間應該是什麼。這種網路叫多層感知器(multilayer perceptron,MLP)。資料從左到右算一次的過程叫前向傳播(forward propagation)。
先不訓練,自己動手設定權重解一次 XOR,看隱藏層到底做了什麼。想法是:XOR 等於「至少一個是 1」而且「不是兩個都是 1」,也就是 OR 和 NAND 再做一次 AND。
逐步看:手動設定權重解 XOR
X @ W1 一次算完四筆資料、兩個神經元:W1 的每一欄是一個隱藏神經元的權重。看 H 這張表(隱藏層的輸出),最後對照兩張圖。
每一層都是矩陣乘法
實際的網路一次處理很多筆資料,每一層都是一次矩陣運算:
z = X @ W + b
a = 活化函數(z)
形狀的規則只有一條:前一層有幾個值,W 就有幾列;這一層有幾個神經元,W 就有幾欄。
| 位置 | 形狀 | 意思 |
|---|---|---|
X |
(筆數, 輸入個數) | 4 筆資料、2 個特徵:(4, 2) |
W1 |
(輸入個數, 隱藏神經元數) | (2, 3) |
b1 |
(隱藏神經元數,) | (3,),靠廣播加到每一筆 |
| 隱藏層輸出 | (筆數, 隱藏神經元數) | (4, 2) @ (2, 3) 得到 (4, 3) |
W2 |
(隱藏神經元數, 輸出個數) | (3, 1) |
| 輸出 | (筆數, 輸出個數) | (4, 3) @ (3, 1) 得到 (4, 1) |
權重和偏差項都是模型要學的參數。一層的參數個數是 輸入個數 × 神經元數 + 神經元數。
逐步看:2-3-1 網路每一步的形狀
權重用亂數產生(固定種子),還沒有訓練。這個範例只看形狀怎麼一路變化,輸出的數字還沒有意義。
為什麼中間一定要有活化函數
如果層與層之間沒有活化函數,每一層都只是矩陣乘法,而矩陣乘法可以合併:
(X @ W1) @ W2 = X @ (W1 @ W2)
不管疊幾層,都等於一個新的權重矩陣,也就是一層。疊再多層也還是一條直線。中間的非線性函數才是讓多層有意義的關鍵。
逐步看:兩層合併成一層
五筆亂數資料。比較「兩層、沒有活化函數」和「一層、權重是兩個矩陣的乘積」,再比較中間加上 tanh 的結果。
逐步看:任意層數的前向傳播
把網路寫成一個串列:每一層是一組 (W, b)。forward 依序算過每一層,隱藏層用 tanh,最後一層用 sigmoid。這裡的網路是 2-4-3-1。
多試幾種組合
完成任務之後可以再試:
- XOR 配 2 個神經元:這一課手動解 XOR 就是用 2 個,所以 2 個一定表示得出來,但訓練不一定找得到。預設的初始權重會卡在準確率約 0.8,按「換一組初始權重」再訓練看看。模型表示得出來,不等於訓練一定找得到。
- 同一份資料把活化函數換成 relu,邊界會變成一段一段的直線,tanh 則比較圓滑。
- 隱藏層多不一定比較好:參數變多、訓練更慢,第 23 課會看到它也更容易過擬合。
實作:寫前向傳播與參數個數
完成兩個函數:
forward(X, W1, b1, W2, b2):隱藏層用 tanh、輸出層用 sigmoid,回傳(h, p)。count_params(sizes):sizes是各層大小,例如[2, 2, 1],回傳權重與偏差項的總數。
這組權重和前面手動解 XOR 的想法相同,只是把數字放大,讓 tanh 接近階梯。
小測驗:形狀與隱藏層
下面程式會印出什麼?
import numpy as np
X = np.zeros((10, 4))
W1 = np.zeros((4, 6))
W2 = np.zeros((6, 2))
h = np.tanh(X @ W1)
print(h.shape, (h @ W2).shape)
網路是 3-5-1(3 個輸入、5 個隱藏神經元、1 個輸出),權重加偏差項共有幾個參數?
把網路所有的活化函數都拿掉,疊 10 層,能力相當於?
手動解 XOR 時,隱藏層的作用最接近哪一句?
下面程式會印出什麼?
sizes = [4, 8, 8, 1]
print(list(zip(sizes[:-1], sizes[1:])))
重點整理
- 隱藏層把資料換到新座標,讓後面的層比較容易分開;XOR 用 OR、NAND 再做 AND 就解得出來。
- 形狀規則:W 的列數是前一層的值個數、欄數是這一層的神經元數;每一層的輸出是 (筆數, 神經元數)。一層的參數個數是
輸入 × 神經元 + 神經元。 - 層與層之間要有非線性,否則疊幾層都等於一層。
- 神經元太少時邊界畫不出需要的形狀(欠擬合);神經元夠多也不保證訓練找得到好的權重,初始值會有影響。
- 這一課的權重都是手動設定或亂數,輸出沒有經過訓練。下一課用反向傳播算出每個權重該往哪裡調。