跳到主要内容

CNN 与围棋的结合

当 DeepMind 选择用**卷积神经网络(CNN)**来处理围棋时,这是一个天才的设计决策。

CNN 原本是为图像识别设计的。为什么它也适合围棋?这篇文章将深入探讨 CNN 的运作原理,以及它与围棋的完美契合。


为什么 CNN 适合棋盘?

棋盘是「图像」

从某种角度看,19×19 的围棋棋盘就是一张图像

图像围棋棋盘
像素交叉点
RGB 通道特征平面(黑、白、空...)
224×22419×19
辨识猫狗判断好棋坏棋

这个类比并非偶然。CNN 擅长图像的原因,也让它擅长棋盘。

三个关键特性

CNN 有三个特性,让它特别适合棋盘类型的数据:

1. 局部连接(Local Connectivity)

CNN 的卷积核只看局部区域,这与围棋的特性完美匹配:

图像识别 vs 围棋局部特征比较:

图像识别围棋
猫耳朵是局部特征「眼」是局部棋形
不需要看整张图不需要看整个棋盘

3×3 区域示例(眼位):

·

很多围棋概念都是「局部」的:

  • :2×2 或 3×3 的区域
  • 叫吃:3×3 的区域
  • 接、断:2×2 的区域

2. 权重共享(Weight Sharing)

同一个卷积核会扫描整个棋盘,这意味着:

棋盘左上角的「眼」和右下角的「眼」,用同样的方式识别

这是合理的——围棋规则不因位置而异(边角例外,但可以用边角特征平面处理)。

权重共享也大幅减少了参数量:

方法参数量
全连接网络361 × 361 × 通道数 = 数千万
CNN3 × 3 × 通道数 × 滤波器数 = 数百万

3. 平移等变性(Translation Equivariance)

如果输入平移,CNN 的输出也会相应平移:

输入:                    输出 (高概率区域):
A B C D E A B C D E
1 . . . . . 1 . . . . .
2 . ● . . . → 2 . * . . .
3 . . . . . 3 . . . . .

输入平移后: 输出也平移:
A B C D E A B C D E
1 . . . . . 1 . . . . .
2 . . . . . → 2 . . . . .
3 . . ● . . 3 . . * . .

这对围棋很重要:相同的局部棋形,无论出现在棋盘哪里,应该有类似的评估。


卷积运算

基本原理

卷积运算是 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 区域影响:

多层卷积

堆叠多层卷积后,感受野会扩大:

层数感受野计算
13×33
25×53 + (3-1) = 5
37×75 + (3-1) = 7
.........
1225×253 + 11×2 = 25

AlphaGo 的 12 层卷积给出 25×25 的感受野,已经超过 19×19 的棋盘!

这意味着:

  • 输出的每个位置都能「看到」整个棋盘
  • 但「看」的方式不同:近处细节清楚,远处概括
  • 这与人类棋手的思维方式类似

感受野与围棋

感受野的概念解释了为什么 AlphaGo 能处理「全局」问题:

局部问题(3×3 感受野):     全局问题(25×25 感受野):
- 这里有眼吗? - 这块棋有眼位吗?
- 可以叫吃吗? - 征子有利吗?
- 能接上吗? - 全局形势如何?

浅层处理局部特征,深层处理全局特征。


局部 vs 全局特征

CNN 的层次结构

CNN 自然形成层次结构:

输入层:        黑子、白子、空点

浅层 (1-3): 眼、接、断、叫吃

中层 (4-8): 棋形、活棋、死棋

深层 (9-12): 势力、厚薄、大场

输出层: 落子概率 / 胜率

这与人类学习围棋的过程惊人地相似:

  1. 先学规则(哪里有子)
  2. 再学战术(如何吃子)
  3. 然后学棋形(什么是好形)
  4. 最后学大局观(全局判断)

可视化隐藏层

研究人员发现,CNN 的隐藏层确实学到了有意义的特征:

浅层滤波器

滤波器 A(眼位检测):

+-+
-+-
+-+

滤波器 B(叫吃检测):

+++
+--
+++

深层滤波器

深层的滤波器更抽象,难以直接解释,但它们捕捉了复杂的棋形模式。


激活函数的选择

ReLU:简单而有效

AlphaGo 在所有卷积层后使用 ReLU(Rectified Linear Unit)

def relu(x):
return max(0, x)

ReLU 函数特性:

  • 当输入 x ≤ 0 时,输出为 0(水平线)
  • 当输入 x > 0 时,输出等于 x(斜率为 1 的直线)
  • 图形呈「折线」状:在原点左侧为零,右侧为线性递增

为什么不用其他函数?

激活函数公式优点缺点
ReLUmax(0, x)计算快、梯度好负值死亡
Sigmoid1/(1+e^-x)输出有界梯度消失
Tanh(e^x-e^-x)/(e^x+e^-x)零中心梯度消失
LeakyReLUmax(0.01x, x)解决死亡问题多一个超参数

对于深度网络,ReLU 的优势明显:

  1. 计算简单:只是比较和取最大值
  2. 梯度不消失:正区间梯度恒为 1
  3. 稀疏激活:很多神经元输出 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 → ...

好处:

  1. 训练更快:可以使用更大的学习率
  2. 更稳定:减少对初始化的敏感性
  3. 正则化效果:有轻微的 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 适合序列数据(如棋局历史),但:

特性RNNCNN
空间处理
序列处理弱(需要历史平面)
并行化
长距离依赖需要 LSTM深层即可

AlphaGo 选择 CNN + 历史平面,而非 CNN + RNN。

残差网络(ResNet)

AlphaGo Zero 升级为 ResNet:

普通 CNN:                ResNet:
x x
↓ ↓
Conv Conv
↓ ↓
ReLU ReLU
↓ ↓
Conv Conv
↓ ↓
y y + x ← 残差连接

残差连接让梯度更容易流动,可以训练更深的网络(40 层 vs 12 层)。

详见 双头网络与残差网络


可视化理解

卷积过程

输入棋盘(简化为 5×5):

ABCDE
1·····
2····
3····
4····
5·····

滤波器(3×3,检测「十字形」):

010
111
010

卷积输出(中心有强响应,十字形匹配):

ABCDE
100000
200000
300100
400000
500000

多层特征

第 1 层输出(192 个通道中的 4 个):

通道 1(眼位):

0000
00.900
0000
0000

通道 2(边线):

0.8000
0.8000
0.8000
0.8000

通道 3(断点):

0000
000.70
0000
0000

通道 4(连接):

0000
00.500
00.800
00.500

这些特征在更深层会被组合成更复杂的概念...


动画对应

本文涉及的核心概念与动画编号:

编号概念物理/数学对应
🎬 D9卷积运算滤波器响应
🎬 D10感受野局部→全局
🎬 D11批次正规化分布稳定
🎬 D1多通道输入张量运算

延伸阅读


关键要点

  1. CNN 天然适合棋盘:局部连接、权重共享、平移等变性
  2. 卷积提取局部特征:3×3 区域的模式识别
  3. 深层网络获得全局视野:12 层 → 25×25 感受野
  4. ReLU 快速有效:简单的非线性激活
  5. BatchNorm 稳定训练:标准化每层输出

CNN 让 AlphaGo 能够「看」棋盘——就像人类用眼睛看图像一样自然。


参考资料

  1. LeCun, Y., Bengio, Y., & Hinton, G. (2015). "Deep learning." Nature, 521, 436-444.
  2. He, K., et al. (2015). "Deep Residual Learning for Image Recognition." CVPR.
  3. Ioffe, S., & Szegedy, C. (2015). "Batch Normalization: Accelerating Deep Network Training." ICML.
  4. Krizhevsky, A., Sutskever, I., & Hinton, G. E. (2012). "ImageNet Classification with Deep Convolutional Neural Networks." NeurIPS.