Value Network 详解
如果说 Policy Network 告诉 AlphaGo「下一步应该下哪里」,那么 Value Network 回答的是一个更根本的问题:
「这盘棋,我会赢吗?」
什么是 Value Network?
核心功能
Value Network 是一个深度卷积神经网络,它的任务是:
给定当前棋盘状态,预测最终的胜率
用数学表示:
v = f_θ(s)
其中:
s:当前棋盘状态f_θ:Value Network(θ 是网络参数)v:一个介于 -1 到 +1 之间的数值
输出的含义
| 输出值 | 含义 |
|---|---|
| +1 | 当前玩家必胜 |
| +0.5 | 当前玩家约 75% 胜率 |
| 0 | 双方胜率相等 |
| -0.5 | 当前玩家约 25% 胜率 |
| -1 | 当前玩家必败 |
为什么需要单一数值?
比较不同选择
在下棋时,我们经常需要在多个选项中做选择。Value Network 让这个比较变得简单:
选项 A 的局面价值:0.3
选项 B 的局面价值:0.5
选项 C 的局面价值:0.2
→ 选择 B(最高的价值)
如果没有单一数值,我们如何比较「吃掉对方一块棋」和「围住一大块空」哪个更好?
取代大量模拟
在传统的蒙地卡罗树搜索中,评估一个局面需要进行 随机模拟(rollout):
- 从当前局面开始
- 双方随机下棋直到游戏结束
- 记录胜负
- 重复数千次,计算胜率
这非常慢。Value Network 可以一次前向传播就给出评估,速度快几个数量级。
| 方法 | 评估时间 | 精度 |
|---|---|---|
| 1000 次随机模拟 | ~2000 毫秒 | 较低 |
| 15000 次随机模拟 | ~30000 毫秒 | 中等 |
| Value Network | ~3 毫秒 | 高(等价于 15000 次模拟) |
网络架构
与 Policy Network 的相似性
Value Network 的架构与 Policy Network 非常相似,都是深度卷积神经网络:
输入层
与 Policy Network 相同,输入是 19×19×49 的特征张量:
- 19×19:棋盘大小
- 49:48 个特征平面 + 1 个表示当前轮到谁的平面
多出的 1 个平面很重要:Value Network 需要知道是谁的回合,因为同一局面对黑棋和白棋的价值是相反的。
卷积层
与 Policy Network 相同:
- 12 层卷积层
- 192 个滤波器
- 3×3 卷积核(第一层 5×5)
- ReLU 激活函数
输出层的差异
这是 Value Network 与 Policy Network 的关键差异:
Policy Network 输出
19×19×192 → 1×1 卷积 → 19×19×1 → 展平 → 361维 → Softmax → 概率分布
Value Network 输出
19×19×192 → 1×1 卷积 → 19×19×1 → 展平 → 361维 → 全连接256 → ReLU → 全连接1 → Tanh → 单一数值
Tanh 激活函数
Value Network 的最后一层使用 Tanh(双曲正切)函数:
Tanh(x) = (e^x - e^(-x)) / (e^x + e^(-x))
Tanh 的输出范围是 (-1, +1),正好对应胜负。
为什么用 Tanh 而非 Sigmoid?
Sigmoid 的输出范围是 (0, 1),也可以表示胜率。但 Tanh 有几个优点:
- 对称性:以 0 为中心,输出可正可负
- 梯度更好:在 0 附近梯度接近 1
- 语意清晰:正值赢、负值输、零是平局
完整架构图
参数数量
| 层 | 计算 | 参数数量 |
|---|---|---|
| 卷积层 | 同 Policy Network | ~3.9M |
| 全连接层 1 | 361×256 + 256 | 92,672 |
| 全连接层 2 | 256×1 + 1 | 257 |
| 总计 | ~4.0M |
约 400 万个参数,比 Policy Network 略多。
训练的挑战
过拟合问题
Value Network 的训练比 Policy Network 困难得多。主要问题是过拟合。
什么是过拟合?
过拟合是指模型「记住」了训练资料,而非学会泛化。表现为:
- 训练集上表现很好
- 测试集上表现很差
为什么 Value Network 容易过拟合?
考虑一盘棋的资料:
局面 1 → 局面 2 → 局面 3 → ... → 局面 200 → 结果:黑胜
如果直接用这些资料训练:
- 这 200 个局面有很强的相关性
- 它们来自同一盘棋,有相同的结果
- 模型可能学会「认出」这盘棋,而非理解局面
DeepMind 发现:如果用相同的人类棋谱训练 Policy 和 Value Network,Value Network 会严重过拟合。
解决方案:自我对弈资料
DeepMind 的解决方案是用自我对弈生成新的训练资料:
1. 用训练好的 RL Policy Network 自我对弈
2. 从每盘棋中只取一个局面(避免相关性)
3. 这个局面的标签是该盘棋的最终结果
4. 生成 3000 万个这样的样本
为什么这能解决过拟合?
- 资料量大:3000 万个独立的局面
- 无相关性:每盘棋只取一个局面
- 分布不同:自我对弈的局面分布不同于人类棋谱
训练资料的产生
# 伪代码
training_data = []
for game_id in range(30_000_000):
# 自我对弈一盘
states, result = self_play(rl_policy_network)
# 随机选取一个局面
random_index = random.randint(0, len(states) - 1)
state = states[random_index]
# 记录局面和结果
training_data.append((state, result))
训练目标与方法
均方误差损失
Value Network 使用**均方误差(MSE)**作为损失函数:
L(θ) = (1/n) × Σ (v_θ(s) - z)²
其中:
v_θ(s):模型预测的价值z:实际结果(+1 或 -1)
为什么用 MSE 而非交叉熵?
- 交叉熵适合分类问题(离散的标签)
- MSE 适合回归问题(连续的数值)
虽然结果只有 +1 或 -1,但模型预测的是连续值(-1 到 +1 之间的任何数)。MSE 让模型学会预测接近 +1 或 -1 的值。
训练过程
# 伪代码
for epoch in range(num_epochs):
for batch in dataloader:
states, outcomes = batch
# 前向传播
values = network(states) # (batch, 1)
# 计算损失(MSE)
loss = mse_loss(values, outcomes)
# 反向传播
loss.backward()
optimizer.step()
训练细节:
- 优化器:SGD with momentum
- 学习率:0.003
- 批次大小:32
- 训练时间:约 1 周(50 GPUs)
准确度分析
与随机模拟的比较
DeepMind 在论文中进行了详细的比较:
| 评估方法 | 预测误差 |
|---|---|
| 1000 次随机模拟 | 较高 |
| 15000 次随机模拟 | 中等 |
| Value Network | 与 15000 次模拟相当 |
这意味着一次 Value Network 评估 ≈ 15000 次随机模拟,但速度快约 1000 倍。
各阶段的准确度
Value Network 的准确度取决于游戏进程:
| 阶段 | 剩余手数 | 预测难度 | 准确度 |
|---|---|---|---|
| 开局 | ~300 | 很难 | 较低 |
| 中盘 | ~150 | 困难 | 中等 |
| 收官 | ~50 | 较易 | 较高 |
| 终局 | ~10 | 简单 | 很高 |
这是直觉上合理的:越接近游戏结束,结果越确定。
输出分布
一个训练良好的 Value Network 的输出分布:
频率
|
| *
| * *
| * *
| * *
|* *
+----+----+---- 输出值
-1 0 +1
大多数输出集中在 -1 和 +1 附近
(因为大多数局面有明确的胜负倾向)
不确定的局面
当 Value Network 输出接近 0 时,表示局面非常复杂,胜负难料。这些局面通常是:
- 大型战斗中
- 双方势均力敌
- 存在多个可能的变化
在 MCTS 中,这些节点会获得更多的搜索资源(因为不确定性高)。
在 MCTS 中的作用
叶节点评估
Value Network 在 MCTS 的 Evaluation 阶段发挥关键作用:
MCTS 搜索树:
根节点 (当前局面)
/ \
A B
/ \ / \
A1 A2 B1 B2 ← 叶节点
↓ ↓ ↓ ↓
评估 评估 评估 评估
当 MCTS 到达一个叶节点时,需要评估这个局面的价值。有两种方法:
- 随机模拟(Rollout):从叶节点随机下到游戏结束
- Value Network 评估:直接用神经网络预测
AlphaGo 结合了两者:
V(leaf) = (1-λ) × V_network(leaf) + λ × V_rollout(leaf)
其中 λ = 0.5,即各占一半权重。
为什么要结合?
- Value Network 更准确,但可能有系统性偏差
- 随机模拟 较不准确,但提供独立的估计
- 结合两者可以互补
AlphaGo Zero 的简化
后来的 AlphaGo Zero 完全弃用了随机模拟:
V(leaf) = V_network(leaf)
这大大简化了系统,同时棋力更强。这证明了 Value Network 足够可靠,不需要随机模拟的「保险」。
回溯更新
评估完叶节点后,这个值会沿路径回溯更新:
v3 = V(leaf) = 0.6
↑
A2 的 Q 值更新
↑
A 的 Q 值更新
↑
根节点的统计更新
每个节点维护的 Q 值是所有经过它的叶节点评估的平均:
Q(s, a) = (1/N(s,a)) × Σ V(leaf)
视觉化分析
价值曲面
想像一个简化的 3×3 棋盘。Value Network 学到的是一个「价值曲面」:
价值矩阵示例(黑子位置 vs 白子位置)
| 黑\白 | 1 | 2 | 3 |
|---|---|---|---|
| 1 | +0.3 | -0.1 | +0.2 |
| 2 | -0.2 | +0.5 | -0.3 |
| 3 | +0.1 | -0.2 | +0.4 |
这个曲面告诉我们每个位置组合的价值。正值有利于黑棋,负值有利于白棋。
训练过程中的演变
随着训练进行,Value Network 的预测逐渐变得更准确:
训练进程中的预测误差
| 训练步数 | 预测误差 |
|---|---|
| 0 | 1.0 |
| 100K | 0.6 |
| 500K | 0.15 |
| 1M | 0.1 |
误差会快速下降,然后趋于稳定。
困难局面的识别
Value Network 可以帮助识别困难局面:
| 输出 | 含义 | 应对策略 |
|---|---|---|
| 接近 +1 | 大优 | 稳健下法 |
| 接近 -1 | 大劣 | 寻找翻盘机会 |
| 接近 0 | 复杂局面 | 需要深入计算 |
AlphaGo 会在接近 0 的局面投入更多思考时间。
实作要点
PyTorch 实现
import torch
import torch.nn as nn
import torch.nn.functional as F
class ValueNetwork(nn.Module):
def __init__(self, input_channels=49, num_filters=192, num_layers=12):
super().__init__()
# 第一卷积层(5×5)
self.conv1 = nn.Conv2d(input_channels, num_filters,
kernel_size=5, padding=2)
# 中间卷积层(3×3)×11
self.conv_layers = nn.ModuleList([
nn.Conv2d(num_filters, num_filters,
kernel_size=3, padding=1)
for _ in range(num_layers - 1)
])
# 输出卷积层
self.conv_out = nn.Conv2d(num_filters, 1, kernel_size=1)
# 全连接层
self.fc1 = nn.Linear(361, 256)
self.fc2 = nn.Linear(256, 1)
def forward(self, x):
# x: (batch, 49, 19, 19)
# 卷积层
x = F.relu(self.conv1(x))
for conv in self.conv_layers:
x = F.relu(conv(x))
x = self.conv_out(x)
# 展平
x = x.view(x.size(0), -1) # (batch, 361)
# 全连接层
x = F.relu(self.fc1(x))
x = torch.tanh(self.fc2(x))
return x.squeeze(-1) # (batch,)
训练循环
def train_value_network(model, optimizer, states, outcomes):
"""
states: (batch, 49, 19, 19) - 棋盘特征
outcomes: (batch,) - 游戏结果 (+1 或 -1)
"""
# 前向传播
values = model(states) # (batch,)
# MSE 损失
loss = F.mse_loss(values, outcomes)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 计算准确率(预测正确的胜负)
predictions = (values > 0).float() * 2 - 1 # 转换为 +1/-1
accuracy = (predictions == outcomes).float().mean()
return loss.item(), accuracy.item()
避免过拟合的技巧
# 1. 资料增强(8重对称性)
def augment(state, outcome):
augmented = []
for rotation in [0, 90, 180, 270]:
s = rotate(state, rotation)
augmented.append((s, outcome))
augmented.append((flip(s), outcome))
return augmented
# 2. Dropout
class ValueNetworkWithDropout(ValueNetwork):
def __init__(self, *args, dropout_rate=0.5, **kwargs):
super().__init__(*args, **kwargs)
self.dropout = nn.Dropout(dropout_rate)
def forward(self, x):
# ... 卷积层 ...
x = self.dropout(x) # 在全连接层前 dropout
# ... 全连接层 ...
# 3. 早停(Early Stopping)
best_val_loss = float('inf')
patience = 10
counter = 0
for epoch in range(max_epochs):
train_loss = train_one_epoch()
val_loss = evaluate()
if val_loss < best_val_loss:
best_val_loss = val_loss
save_model()
counter = 0
else:
counter += 1
if counter >= patience:
print("Early stopping!")
break
与 Policy Network 的协作
互补关系
Policy Network 和 Value Network 在 AlphaGo 中互补:
| 网络 | 回答的问题 | 输出 | MCTS 角色 |
|---|---|---|---|
| Policy | 下一步下哪里? | 概率分布 | 引导搜索方向 |
| Value | 这盘棋会赢吗? | 单一数值 | 评估叶节点 |
统一的双头网络
在 AlphaGo Zero 中,这两个网络被合并成一个双头网络:
这种设计的优点:
- 参数共享:减少计算量
- 特征共享:Policy 和 Value 使用相同的特征
- 训练更稳定:两个目标互相正则化
详见 双头网络与残差网络。
动画对应
本文涉及的核心概念与动画编号:
| 编号 | 概念 | 物理/数学对应 |
|---|---|---|
| 🎬 E2 | Value Network | 势能面 |
| 🎬 D4 | 价值函数 | 期望报酬 |
| 🎬 C6 | 叶节点评估 | 函数逼近 |
| 🎬 H3 | 时序差分 | 引导学习 |
延伸阅读
- 上一篇:Policy Network 详解 — 策略网络如何选择着法
- 下一篇:输入特征设计 — 48 个特征平面详解
- 进阶主题:MCTS 与神经网络的结合 — 完整的搜索流程
关键要点
- Value Network 预测胜率:输出 -1 到 +1 之间的单一数值
- Tanh 输出:确保输出在正确的范围内
- MSE 损失:将预测值逼近实际结果
- 过拟合挑战:需要用自我对弈资料来避免
- 取代随机模拟:一次评估 ≈ 15000 次模拟
Value Network 是 AlphaGo 的「判断力」——它让 AI 能够评估任何局面的好坏,而不需要穷尽所有可能。
参考资料
- Silver, D., et al. (2016). "Mastering the game of Go with deep neural networks and tree search." Nature, 529, 484-489.
- Silver, D., et al. (2017). "Mastering the game of Go without human knowledge." Nature, 551, 354-359.
- Sutton, R. S., & Barto, A. G. (2018). Reinforcement Learning: An Introduction. MIT Press.
- Tesauro, G. (1995). "Temporal difference learning and TD-Gammon." Communications of the ACM, 38(3), 58-68.