Soma Zero Tutorials
🔍 搜索功能尚未开启,敬请期待。

2.7 AlphaZero 自对弈强化学习

本章的主力训练章来了。上一节我们承认:经典引擎的棋感全是人喂的,上限受限。这一节就把第一章的迷你 AlphaZero 放大到真正的 15×15,让引擎从零自我对弈、自己学出棋感——你的 5070 Ti 这次要真刀真枪连训几天。架构和井字棋版一模一样,变的只是“规模”。

一、架构:还是那个飞轮,只是放大了

先快速回收第一章 1.7 的核心,因为思想完全没变:一个网络 f(局面) → (策略 p, 价值 v),用它指导 MCTS;MCTS 搜出来的走法比网络张口就来更强,于是拿 MCTS 的结果当老师反过来训练网络;网络变强→MCTS 更强→又是更好的老师……这个自我进化的飞轮不需要任何人类棋谱,也不需要我们写一行棋型规则。

井字棋版几分钟就转完,是因为它状态空间小到可怜。五子棋的飞轮一模一样,只是每一环都要“加码”:网络更大、MCTS 每步搜更多次、自对弈要下成千上万盘。道理你早在第一章就懂了,这一节是把它喂饱算力。

二、网络设计:输入平面、ResNet 主干、双头

井字棋用个两层小 MLP 就够,五子棋得用卷积网络——因为棋型是局部空间模式,卷积天生擅长捕捉。典型设计是 AlphaZero 同款的 ResNet(残差网络)主干 + 策略/价值双头

import torch.nn as nn

class GomokuNet(nn.Module):
    """15x15 策略/价值网络:ResNet 主干 + 双头。"""
    def __init__(self, channels=128, blocks=10):
        super().__init__()
        # 输入 3 个平面:我方棋子 / 对方棋子 / 该谁走(全 0 或全 1)
        self.stem = nn.Conv2d(3, channels, 3, padding=1)
        self.blocks = nn.ModuleList([ResBlock(channels) for _ in range(blocks)])
        self.policy_head = nn.Conv2d(channels, 1, 1)   # → 展平成 225 个落子 logits
        self.value_head  = nn.Sequential(              # → 1 个标量,tanh 到 [-1,1]
            nn.AdaptiveAvgPool2d(1), nn.Flatten(),
            nn.Linear(channels, 64), nn.ReLU(), nn.Linear(64, 1), nn.Tanh())

几个要点:输入用 3 个平面(我方子、对方子、轮到谁),让网络一眼看清敌我和先后手;策略头输出 15×15=225 个落子倾向;价值头输出一个 −1 到 1 的胜算。规模上,channels=128、blocks=10 左右对 16GB 的 5070 Ti 很从容——这卡训 15×15 绰绰有余,真正的瓶颈从来不是显存,而是下面要说的自对弈速度。

三、自对弈数据管线,与 PUCT 选点公式

自对弈时,MCTS 怎么借助网络选点?这里用的是 UCT 的“AlphaZero 升级版”——PUCT。它和 1.6 那个 UCT 形似而神不同:探索项不再用 ln N 那套,而是直接用网络给的先验概率 P 来加权,让网络觉得好的点获得更多探索:

选 a = argmaxa [ Q(s,a)  +  cpuct · P(s,a) · √(∑bN(s,b)) / (1 + N(s,a)) ]

其中 Q(s,a) 是这步棋目前的平均价值(利用)、P(s,a) 是网络给它的先验概率、N(s,a) 是它被访问的次数。对比 1.6 的 UCT 你就懂了:网络的策略输出 P 取代了“一视同仁”的均匀探索——这正是第一章末尾说的“用神经网络补上 MCTS 两个软肋”里的一个。

自对弈跑起来后还有两个工程要点:其一,数据增强——五子棋棋盘有 8 种对称(旋转 + 翻转都等价),每盘棋可以免费扩成 8 份训练数据,大幅提高样本效率;其二,回放缓冲(replay buffer)——把最近若干局的数据混在一起采样训练,避免网络只盯着最新一局过拟合。

四、在 5070 Ti 上把它训出来

环境直接沿用 1.7 搭好的那套——独立 conda 环境 + cu128 版 PyTorch(Blackwell sm_120 用稳定 cu128 轮子即可,本机已验证)。规模放大后,几个实操要点:

  • bf16 混合精度:用 torch.autocast 开 bfloat16,省显存又提速,Blackwell 对 bf16 支持很好。
  • batch 与显存:16GB 下,训练 batch 开到几百、自对弈用较大的批量推理都没问题;先用 nvidia-smi 看占用再往上加。
  • 瓶颈在自对弈不在训练:真正慢的是“跑成千上万盘 MCTS 自对弈”,所以要尽量批量化网络推理、多局并行。
  • checkpoint 与恢复:训练要跑几天,务必定期存盘,支持断点续训。
  • 怎么知道在变强:光看 loss 不够——要定期让新网络和旧网络对战几十盘、用 Elo 等级分衡量棋力是否真的上升(这套对战擂台 1.8 已经搭好,2.10 还会再用)。

训上几天,你会看到一件很奇妙的事:这个从没被教过任何棋理的网络,会自己下出活三、冲四、做杀——而且有时招法连我们写评估函数时都没想到。这就是自我对弈的力量。

五、反思:它很强,但算杀不如那把“专用尺”精确

训练好的 AlphaZero 棋力很高,大局观尤其好。但它有个和经典引擎正好互补的弱点:面对 2.5 那种很深的“连续冲四”强制杀,它偶尔会看走眼。原因在于它的价值是神经网络出来的、MCTS 是采样出来的,都带统计误差;而一条 15 手的 VCF 杀,差一手判断就满盘皆输。这种地方,反倒是上一章那个又笨又精确的 VCF 解算器,几毫秒就能算得分毫不差。

于是一个诱人的想法冒出来了:能不能让神经网络管“大局判断”,让 VCF/VCT 解算器管“精确算杀”,两者各扬其长?——这正是当今最强五子棋引擎(如 Rapfi)走的路,也是下一节的主题。

六、小结与下一节

  • 架构不变:还是 1.7 那个“网络指导 MCTS、MCTS 当老师训网络”的飞轮,只是放大喂算力。
  • 网络:3 输入平面 + ResNet 主干 + 策略头(225)/价值头(1);128 通道×10 块对 16GB 很从容。
  • PUCT:选 a = argmax[ Q + c·P·√(∑N)/(1+N) ],用网络先验 P 取代均匀探索。
  • 训练:cu128 + bf16 + 8 重对称增强 + 回放缓冲;瓶颈在自对弈速度;靠 Elo 对战判断进步;训数天。
  • 互补弱点:大局强、深处算杀偶失准 → 与精确的 VCF 解算器天然互补。

下一节 2.8 混合引擎(Rapfi 风格),我们就把神经网络的“大局观”和经典搜索的“精确算杀”焊在一起,造出本章棋力的项目级 SOTA 终点