CNN 與圍棋的結合
當 DeepMind 選擇用**卷積神經網路(CNN)**來處理圍棋時,這是一個天才的設計決策。
CNN 原本是為圖像識別設計的。為什麼它也適合圍棋?這篇文章將深入探討 CNN 的運作原理,以及它與圍棋的完美契合。
為什麼 CNN 適合棋盤?
棋盤是「圖像」
從某種角度看,19×19 的圍棋棋盤就是一張圖像:
| 圖像 | 圍棋棋盤 |
|---|---|
| 像素 | 交叉點 |
| RGB 通道 | 特徵平面(黑、白、空...) |
| 224×224 | 19×19 |
| 辨識貓狗 | 判斷好棋壞棋 |
這個類比並非偶然。CNN 擅長圖像的原因,也讓它擅長棋盤。
三個關鍵特性
CNN 有三個特性,讓它特別適合棋盤類型的資料:
1. 局部連接(Local Connectivity)
CNN 的卷積核只看局部區域,這與圍棋的特性完美匹配:
| 圖像識別 | 圍棋 |
|---|---|
| 貓耳朵是局部特徵 | 「眼」是局部棋形 |
| 不需要看整張圖 | 不需要看整個棋盤 |
3×3 區域範例(眼位):
| ○ | ● | ○ |
| ● | · | ● |
| ○ | ● | ○ |
很多圍棋概念都是「局部」的:
- 眼:2×2 或 3×3 的區域
- 叫吃:3×3 的區域
- 接、斷:2×2 的區域
2. 權重共享(Weight Sharing)
同一個卷積核會掃描整個棋盤,這意味著:
棋盤左上角的「眼」和右下角的「眼」,用同樣的方式識別
這是合理的——圍棋規則不因位置而異(邊角例外,但可以用邊角特徵平面處理)。
權重共享也大幅減少了參數量:
| 方法 | 參數量 |
|---|---|
| 全連接網路 | 361 × 361 × 通道數 = 數千萬 |
| CNN | 3 × 3 × 通道數 × 濾波器數 = 數百萬 |
3. 平移等變性(Translation Equivariance)
如果輸入平移,CNN 的輸出也會相應平移:
輸入與輸出(高機率區域):
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | · | · | · | · | · |
| 2 | · | ● | · | · | · |
| 3 | · | · | · | · | · |
輸出 → B2 位置有高機率(*)
輸入平移後,輸出也平移:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | · | · | · | · | · |
| 2 | · | · | · | · | · |
| 3 | · | · | ● | · | · |
輸出 → C3 位置有高機率(*)
這對圍棋很重要:相同的局部棋形,無論出現在棋盤哪裡,應該有類似的評估。
卷積運算
基本原理
卷積運算是 CNN 的核心。它是一種「滑動窗口」操作:
計算過程(以中心點為例):
輸出[2,2] = 1×1 + 1×0 + 1×1 +
1×0 + 1×1 + 1×0 +
1×1 + 1×0 + 1×1
= 1 + 0 + 1 + 0 + 1 + 0 + 1 + 0 + 1
= 5
多通道卷積
當輸入有多個通道(如 48 個特徵平面)時,卷積核也變成 3D:
每個卷積核會跨所有輸入通道計算,產生一個輸出通道。
多個濾波器
AlphaGo 使用 192 個濾波器,每個濾波器學習不同的特徵:
每個濾波器可能學到不同的棋形:
- 濾波器 1:眼位檢測
- 濾波器 2:斷點檢測
- 濾波器 3:連接檢測
- ...
- 濾波器 192:某種複雜模式
感受野
什麼是感受野?
**感受野(Receptive Field)**是指輸出的一個位置,受到輸入的哪些位置影響。
單層卷積
使用 3×3 卷積核時,輸出的每個位置只受輸入 3×3 區域影響:
輸入(感受野 3x3 標記為 X):
| · | · | · | · | · |
| · | X | X | X | · |
| · | X | X | X | · |
| · | X | X | X | · |
| · | · | · | · | · |
輸出(對應位置標記為 Y):
| · | · | · | · |
| · | Y | · | · |
| · | · | · | · |
| · | · | · | · |
多層卷積
堆疊多層卷積後,感受野會擴大:
| 層數 | 感受野 | 計算 |
|---|---|---|
| 1 | 3×3 | 3 |
| 2 | 5×5 | 3 + (3-1) = 5 |
| 3 | 7×7 | 5 + (3-1) = 7 |
| ... | ... | ... |
| 12 | 25×25 | 3 + 11×2 = 25 |
AlphaGo 的 12 層卷積給出 25×25 的感受野,已經超過 19×19 的棋盤!
這意味著:
- 輸出的每個位置都能「看到」整個棋盤
- 但「看」的方式不同:近處細節清楚,遠處概括
- 這與人類棋手的思維方式類似
感受野與圍棋
感受野的概念解釋了為什麼 AlphaGo 能處理「全局」問題:
| 局部問題(3x3 感受野) | 全局問題(25x25 感受野) |
|---|---|
| 這裡有眼嗎? | 這塊棋有眼位嗎? |
| 可以叫吃嗎? | 征子有利嗎? |
| 能接上嗎? | 全局形勢如何? |
淺層處理局部特徵,深層處理全局特徵。
局部 vs 全局特徵
CNN 的層次結構
CNN 自然形成層次結構:
這與人類學習圍棋的過程驚人地相似:
- 先學規則(哪裡有子)
- 再學戰術(如何吃子)
- 然後學棋形(什麼是好形)
- 最後學大局觀(全局判斷)
視覺化隱藏層
研究人員發現,CNN 的隱藏層確實學到了有意義的特徵:
淺層濾波器
濾波器 A(眼位檢測):
| + | - | + |
| - | + | - |
| + | - | + |
濾波器 B(叫吃檢測):
| + | + | + |
| + | - | - |
| + | + | + |
深層濾波器
深層的濾波器更抽象,難以直接解釋,但它們捕捉了複雜的棋形模式。
激活函數的選擇
ReLU:簡單而有效
AlphaGo 在所有卷積層後使用 ReLU(Rectified Linear Unit):
def relu(x):
return max(0, x)
ReLU 函數的特性:當輸入為負數時輸出為 0,當輸入為正數時輸出等於輸入本身。這是一條從原點開始、斜率為 1 的直線(僅在正半軸)。
為什麼不用其他函數?
| 激活函數 | 公式 | 優點 | 缺點 |
|---|---|---|---|
| ReLU | max(0, x) | 計算快、梯度好 | 負值死亡 |
| Sigmoid | 1/(1+e^-x) | 輸出有界 | 梯度消失 |
| Tanh | (e^x-e^-x)/(e^x+e^-x) | 零中心 | 梯度消失 |
| LeakyReLU | max(0.01x, x) | 解決死亡問題 | 多一個超參數 |
對於深度網路,ReLU 的優勢明顯:
- 計算簡單:只是比較和取最大值
- 梯度不消失:正區間梯度恆為 1
- 稀疏激活:很多神經元輸出 0,提高效率
ReLU 在圍棋中的含義
ReLU 的稀疏性在圍棋中有有趣的解釋:
某個濾波器檢測「斷點」:
- 有斷點 → 正值輸出(激活)
- 無斷點 → 零輸出(不激活)
這就像棋手只關注「有事」的位置
批次正規化
什麼是批次正規化?
**批次正規化(Batch Normalization)**是一種技術,讓每層的輸出維持穩定的分布:
def batch_norm(x, gamma, beta):
# 計算批次的均值和標準差
mean = x.mean(axis=0)
std = x.std(axis=0)
# 正規化
x_norm = (x - mean) / (std + 1e-8)
# 縮放和平移
return gamma * x_norm + beta
為什麼需要?
內部協變量偏移
當網路訓練時,每層的輸入分布會隨著前面層的權重變化而改變。這被稱為「內部協變量偏移」:
第一層權重更新 → 第一層輸出分布改變
↓
第二層輸入分布改變 → 第二層需要重新適應
↓
... (傳遞下去)
批次正規化通過強制每層輸入有固定的分布(均值 0,標準差 1),來穩定訓練。
在 AlphaGo 中的應用
AlphaGo 在每個卷積層後、激活函數前使用批次正規化:
Conv → BatchNorm → ReLU → Conv → BatchNorm → ReLU → ...
好處:
- 訓練更快:可以使用更大的學習率
- 更穩定:減少對初始化的敏感性
- 正則化效果:有輕微的 dropout 效果
推理時的處理
訓練時,使用當前批次的統計量。推理時,使用整個訓練集的統計量(移動平均):
# 訓練時
mean = batch_mean
var = batch_var
# 推理時
mean = running_mean # 訓練期間累積的均值
var = running_var # 訓練期間累積的方差
AlphaGo 的具體配置
完整架構
輸入: 19×19×48
第 1 層:
Conv2D(5×5, 192 filters, padding='same')
BatchNorm
ReLU
輸出: 19×19×192
第 2-12 層 (共 11 層):
Conv2D(3×3, 192 filters, padding='same')
BatchNorm
ReLU
輸出: 19×19×192
輸出層 (Policy):
Conv2D(1×1, 1 filter)
Flatten
Softmax
輸出: 361 維機率
輸出層 (Value):
Conv2D(1×1, 1 filter)
Flatten
Dense(256)
ReLU
Dense(1)
Tanh
輸出: 單一數值
參數配置
| 參數 | 數值 | 說明 |
|---|---|---|
| 輸入通道 | 48 | 特徵平面數 |
| 濾波器數 | 192 | 每層的通道數 |
| 卷積核大小 | 3×3(第一層 5×5) | 感受野 |
| 層數 | 13(含輸出層) | 深度 |
| 激活函數 | ReLU | 非線性 |
| 正規化 | BatchNorm | 穩定訓練 |
PyTorch 實現
import torch
import torch.nn as nn
class AlphaGoCNN(nn.Module):
def __init__(self, input_channels=48, num_filters=192, num_layers=12):
super().__init__()
# 第一層(5×5 卷積)
self.conv1 = nn.Sequential(
nn.Conv2d(input_channels, num_filters, kernel_size=5, padding=2),
nn.BatchNorm2d(num_filters),
nn.ReLU(inplace=True)
)
# 中間層(3×3 卷積)
self.conv_layers = nn.Sequential(*[
nn.Sequential(
nn.Conv2d(num_filters, num_filters, kernel_size=3, padding=1),
nn.BatchNorm2d(num_filters),
nn.ReLU(inplace=True)
)
for _ in range(num_layers - 1)
])
# Policy 輸出頭
self.policy_head = nn.Sequential(
nn.Conv2d(num_filters, 1, kernel_size=1),
nn.Flatten(),
nn.Softmax(dim=1)
)
# Value 輸出頭
self.value_head = nn.Sequential(
nn.Conv2d(num_filters, 1, kernel_size=1),
nn.Flatten(),
nn.Linear(361, 256),
nn.ReLU(inplace=True),
nn.Linear(256, 1),
nn.Tanh()
)
def forward(self, x):
# 共享特徵提取
x = self.conv1(x)
x = self.conv_layers(x)
# 分頭輸出
policy = self.policy_head(x)
value = self.value_head(x)
return policy, value
與其他架構的比較
全連接網路
如果用全連接網路處理圍棋:
| 特性 | 全連接 | CNN |
|---|---|---|
| 參數量 | 極大(數億) | 較小(數百萬) |
| 位置不變性 | 無 | 有 |
| 局部特徵 | 難學 | 自然捕捉 |
| 訓練效率 | 低 | 高 |
全連接網路無法利用棋盤的空間結構,效率極低。
循環神經網路(RNN)
RNN 適合序列資料(如棋局歷史),但:
| 特性 | RNN | CNN |
|---|---|---|
| 空間處理 | 弱 | 強 |
| 序列處理 | 強 | 弱(需要歷史平面) |
| 並行化 | 難 | 易 |
| 長距離依賴 | 需要 LSTM | 深層即可 |
AlphaGo 選擇 CNN + 歷史平面,而非 CNN + RNN。
殘差網路(ResNet)
AlphaGo Zero 升級為 ResNet:
殘差連接讓梯度更容易流動,可以訓練更深的網路(40 層 vs 12 層)。
詳見 雙頭網路與殘差網路。
視覺化理解
卷積過程
輸入棋盤(簡化為 5x5):
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | · | · | · | · | · |
| 2 | · | ● | · | · | · |
| 3 | · | · | ○ | · | · |
| 4 | · | · | · | ● | · |
| 5 | · | · | · | · | · |
濾波器(3x3,檢測「十字形」):
| 0 | 1 | 0 |
| 1 | 1 | 1 |
| 0 | 1 | 0 |
卷積輸出:
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 0 | 0 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 | 0 |
| 4 | 0 | 0 | 0 | 0 | 0 |
| 5 | 0 | 0 | 0 | 0 | 0 |
C3 位置有強響應(十字形匹配)。
多層特徵
第 1 層輸出(192 個通道中的 4 個):
通道 1(眼位):
| 0 | 0 | 0 | 0 |
| 0 | 0.9 | 0 | 0 |
| 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 |
通道 2(邊線):
| 0.8 | 0 | 0 | 0 |
| 0.8 | 0 | 0 | 0 |
| 0.8 | 0 | 0 | 0 |
| 0.8 | 0 | 0 | 0 |
通道 3(斷點):
| 0 | 0 | 0 | 0 |
| 0 | 0 | 0.7 | 0 |
| 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 0 |
通道 4(連接):
| 0 | 0 | 0 | 0 |
| 0 | 0.5 | 0 | 0 |
| 0 | 0.8 | 0 | 0 |
| 0 | 0.5 | 0 | 0 |
這些特徵在更深層會被組合成更複雜的概念...
動畫對應
本文涉及的核心概念與動畫編號:
| 編號 | 概念 | 物理/數學對應 |
|---|---|---|
| 🎬 D9 | 卷積運算 | 濾波器響應 |
| 🎬 D10 | 感受野 | 局部→全局 |
| 🎬 D11 | 批次正規化 | 分布穩定 |
| 🎬 D1 | 多通道輸入 | 張量運算 |
延伸閱讀
關鍵要點
- CNN 天然適合棋盤:局部連接、權重共享、平移等變性
- 卷積提取局部特徵:3×3 區域的模式識別
- 深層網路獲得全局視野:12 層 → 25×25 感受野
- ReLU 快速有效:簡單的非線性激活
- BatchNorm 穩定訓練:標準化每層輸出
CNN 讓 AlphaGo 能夠「看」棋盤——就像人類用眼睛看圖像一樣自然。
參考資料
- LeCun, Y., Bengio, Y., & Hinton, G. (2015). "Deep learning." Nature, 521, 436-444.
- He, K., et al. (2015). "Deep Residual Learning for Image Recognition." CVPR.
- Ioffe, S., & Szegedy, C. (2015). "Batch Normalization: Accelerating Deep Network Training." ICML.
- Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). "ImageNet Classification with Deep Convolutional Neural Networks." NeurIPS.
本文重點:
- CNN 的局部連接、權重共享和平移等變性三大特性,讓它天然適合處理棋盤資料
- 12 層卷積堆疊產生 25x25 的感受野,讓輸出每個位置都能「看到」整個棋盤
- BatchNorm 和 ReLU 的組合確保深度網路的穩定訓練
常見問題
為什麼 CNN 比全連接網路更適合圍棋?
CNN 利用棋盤的空間結構,通過權重共享大幅減少參數量(數百萬 vs 數千萬),同時自然捕捉局部棋形特徵,訓練效率遠高於全連接網路。
感受野在圍棋中的意義是什麼?
感受野決定了網路能「看到」多大的範圍。淺層處理局部特徵(眼、叫吃),深層處理全局特徵(勢力、厚薄)。12 層網路的 25x25 感受野已超過 19x19 棋盤。
為什麼 AlphaGo 使用 ReLU 而非其他激活函數?
ReLU 計算簡單、梯度不消失,且產生稀疏激活(很多神經元輸出 0),這在圍棋中可解釋為「只關注有事的位置」,提高效率的同時保持良好的訓練特性。