技术解析2026年8月5日

围棋 AI 是怎么下棋的?MCTS 蒙特卡洛树搜索入门

从分支爆炸讲清为什么围棋离不开 MCTS,拆解选择/扩展/模拟/回传四步,并结合浏览器可承受的模拟量说明 UCB1 常数、访问分布、开局收窄与收官填眼等真实工程取舍。

围棋之所以难,不只是「规则复杂」,而是空枰上就有上百个几乎等价的合法点。穷举到终局不可能,评估函数又极易写偏;MCTS 用「大量随机对局 + 把算力投到更有希望的分支」在两者之间走出一条可落地的路。

围棋空盘上分支爆炸,MCTS 用随机对局把算力集中到少数有希望的落点

为什么围棋特别适合、也特别依赖 MCTS?

围棋的搜索空间大到无法靠「算到底」解决:19 路空盘约有 361 个空点,合法着法随局面变化,对局长度常超百手。若每步平均还有几十个合理候选,树的宽度与深度都会爆炸;而手写启发式(吃子优先、占角、连气)在空旷开局又容易退化成贴边乱爬。

MCTS(Monte Carlo Tree Search,蒙特卡洛树搜索)不试图穷举,也不依赖一张「全局评分表」。它反复做短局随机对局,用胜负结果回传,把更多模拟预算投给看起来更好的分支。分支因子越大、局面评估越难写准时,这种「用采样代替穷举」的思路越有价值——这也是它在围棋、以及后来许多不完全信息游戏里被广泛采用的原因。

MCTS 的一轮迭代在做什么?

一轮完整的 MCTS 迭代通常拆成四步,循环直到时间或模拟次数用尽:

  1. 选择(Selection):从根出发,按 UCB1 一类公式在已展开的子节点里往下走,平衡「已知胜率高」和「还没试够」;
  2. 扩展(Expansion):走到还有未试过的合法着法时,随机或按某种先验挑一手,长出一个新子节点;
  3. 模拟(Simulation / Rollout):从新局面起双方随机(或弱启发式)下到终局,按规则数子判胜负;
  4. 回传(Backpropagation):把这一局的胜负沿路径写回每个节点的 visits / wins。

最终落子一般取根节点下访问次数最多的子节点(argmax visits),而不是瞬时胜率最高的那个——访问次数本身已经融合了「试过很多次仍站得住」的信息,比早期噪声很大的胜率更稳。

步骤 输入 输出 常见坑
选择 已展开的树 + UCB1 一条通向叶/待扩展节点的路径 探索常数过大 → 访问摊平
扩展 未试过的合法着法 一个新子节点 根上塞进自杀/填眼点会污染终局
模拟 当前局面 一局胜负 模拟阶段若乱填自己的眼,估值失真
回传 胜负 路径上 visits/wins 更新 视角要统一(始终相对同一方)

UCB1 是怎么在「利用」和「探索」之间折中的?

UCB1 给每个子节点打一个分数,大致是:

[ \frac{w_i}{n_i} + C \sqrt{\frac{\ln N}{n_i}} ]

前一项是经验胜率(利用),后一项随该节点访问变少而变大(探索)。(C) 越大,越愿意去试生疏分支。

教科书常取 (C=\sqrt{2}\approx 1.41),那是收益落在 ([0,1])、且子节点不太多时的理论推导。围棋根上往往有几十上百个合法点,而浏览器里一次思考往往只有几千到几万次模拟:此时探索项很容易压过胜率差,结果是访问几乎均匀,首选手占比可掉到约 2%——既选不出好棋,根上的「倾向度」也失去可读性。工程上常把 (C) 下调(例如 0.4),让有限预算更快集中。

一个可观测的收敛信号是根节点首选手的访问占比:同样 9 路局面,约 1200 次模拟时 top1 常只有个位数百分比,两万次可到约 17%,四万次可到约 40% 量级。占比低时,优先怀疑「还没搜够」,而不是「盘上真的到处一样好」。

「倾向度」和最终落子是什么关系?

根上各子节点的 visits / Σvisits 可以读成相对倾向度:搜索把算力投到了哪里。UI 若展示 top-N 候选,通常就是按 visits 排序后截断;最终一手仍取 visits 最大者。

几条读数时容易忽略的边界:

  • 总和一般小于 1:长尾候选被过滤掉后,展示集合的概率和会小于 1,这是刻意的——top1 占比本身在说「有多确定」;
  • 模拟量不足时分布很平:19 路把几千次模拟摊到上百空点,每点只有几十次,倾向度接近噪声;
  • 不要用温度采样去「故意下弱」:在尚未收敛的分布上按 visits 采样,会把本就平坦的分布变得更接近均匀,棋力会塌成乱下。弱化更干净的做法是减少模拟预算,仍用 argmax 选点。

开局为什么不能靠「少想一会儿」提速?

空枰合法点最多,单点分到的模拟最少,恰恰是全局最缺算力的阶段。一种直觉是:「首手 top1 只有个位数百分比,说明各点差不多,少搜一点也没事。」自对弈会打脸:同强度引擎,开局砍预算的一方可到约 2:8 的惨败。正确读法是——占比低 = 还没收敛,不是「已经等价」。

更稳妥的提速是开局知识收窄根候选:把根上的未试着法限制在少数公认成立的要点(例如仍空着的角星),分支从上百降到个位数,每个候选反而能分到数百次模拟。等角被占满、或要点周边开始接触、或盘上出现只剩一气的紧急棋块,就整体退回全盘搜索。这种做法在大棋盘上通常既省时间又提高单点信噪比;在 9 路这类分支本就不算夸张的盘上,强行收窄反而可能是净损失,需要按盘面规模开关。

收官阶段为什么要显式避开「自己的眼」?

围棋里往自己的真眼里落子通常合法却极差——等于自杀气。随机模拟若不禁止填眼,估值会被大量自毁棋污染;根节点若不排除自己的眼,收官时「已无棋可下」的一方还可能去填眼把活棋走死,而不是停手。

因此成熟一点的纯 MCTS 围棋实现会在两处同时处理:模拟阶段不走填眼;根候选里也滤掉己方眼位。只剩眼可填时,正确动作是停一手,让双方进入数子流程。

纯 MCTS 的能力边界在哪里?

理解边界比背公式更重要:

维度 纯 MCTS(随机 rollout) 带策略/价值网络的 MCTS
先验 几乎没有,靠访问慢慢集中 网络给出着法先验与局面价值
同等时间棋力 受模拟量硬约束,大棋盘噪声大 通常显著更强
可解释的「倾向度」 直接来自 visits 分布 还混有网络先验,需分开读
实现与算力 可在浏览器 Web Worker 里跑 通常需要模型权重与更大算力
弱化难度 maxSims / 时间即可 还要调温度、噪声等

此外还有几条工程边界:没有神经网络时,19 路短时搜索的倾向度只宜作参考;中国数子与日本点目的终局定义不同,模拟终点的计分规则必须与产品规则一致;劫争、自杀合法性要在「合法着法生成」里处理正确,否则树会学到非法捷径。

小结

MCTS 用「选择 → 扩展 → 模拟 → 回传」把有限算力投向更有希望的分支,最终常按访问次数最多的一手落子。围棋根上分支极多,UCB1 的探索常数、开局是否收窄候选、模拟是否禁填眼,都会在真实预算下决定棋力与可读性。读 visits 占比时,先问「这盘棋搜了多少次」——收敛之前,平坦的分布说明的是算力不够,而不是棋盘上到处都是好点。

本文用到的工具

常见问题

不是。MCTS 是一种用大量随机对局估计落子价值的搜索框架;AlphaGo / AlphaZero 是在 MCTS 外面再套策略网络与价值网络,用神经网络给先验和局面评估。纯 MCTS 没有棋谱训练,棋力完全依赖模拟量与规则知识;有网络的引擎在同样时间预算下强得多。