第 14 讲:蒙特卡洛树搜索与 AlphaGo / AlphaZero

Reinforcement Learning · Lecture 14。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应:Stanford CS234 Lecture 15(Monte Carlo Tree Search, AlphaGo) 配套代码:code/lecture14/(只需 numpy) 预计阅读时间:3.5 小时


0. 本讲导航

0.1 本讲要回答的问题

当世界的规则完全已知,但状态多到无法枚举时,怎样做出高质量的决策?

2016 年 3 月,AlphaGo 以 4:1 击败世界顶尖棋手李世石。在此之前,很多人认为计算机下围棋达到人类顶尖水平还需要十年。围棋的规则极其简单,模型完全已知——但它约有 1017010^{170} 个合法局面,比宇宙中的原子数还多得多。第 2 讲的动态规划需要遍历所有状态,完全不可能。

这一讲讲述 AlphaGo 背后的两个关键思想:

  1. 只为当前局面做规划:不求全局的最优策略,只在当前局面附近向前搜索。
  2. 有选择地搜索:用模拟来评估局面,用 UCB(第 11 讲!)决定搜索树往哪里生长——这就是蒙特卡洛树搜索(MCTS)。

然后我们会看到 AlphaGo Zero / AlphaZero 如何把 MCTS 与深度学习、自我对弈结合起来:网络提供直觉,搜索提供深思熟虑,自我对弈让两者互相提升。

0.2 学完本讲,你应该能够

  1. 区分全局规划(动态规划)与前向搜索;描述极小极大、negamax、α-β 剪枝。
  2. 解释为什么有限深度搜索需要评估函数,以及它的代价。
  3. 解释平坦蒙特卡洛的系统性偏差,以及”树”如何解决它。
  4. 完整描述 MCTS 的四个步骤和 UCT 的树策略。
  5. 描述 AlphaGo、AlphaGo Zero、AlphaZero 的演化,写出 PUCT 公式和 AlphaZero 的训练目标。
  6. 用策略迭代的观点解释”自我对弈 + MCTS”为什么能不断变强。

0.3 先修知识

知识点用在哪里最低要求
第 2 讲:动态规划、策略迭代第 1、6 节必须
第 3 讲:蒙特卡洛评估第 2 节必须
第 6 讲:策略梯度第 5 节(AlphaGo)了解即可
第 8 讲:行为克隆、DAgger第 6 节了解即可
第 11 讲:UCB第 3 节必须
递归第 1 节知道”函数调用自己”即可

0.4 本讲地图

第1节 前向搜索:博弈树、极小极大、α-β 剪枝、有限深度 + 评估函数
   │
第2节 蒙特卡洛评估:随机走子;平坦蒙特卡洛的偏差
   │
第3节 蒙特卡洛树搜索:四个步骤;UCT;为什么"树"很关键
   │
第4节 MCTS 的实验与实践细节
   │
第5节 AlphaGo → AlphaGo Zero → AlphaZero → MuZero
   │
第6节 为什么自我对弈 + 搜索能不断变强:策略迭代的视角

0.5 本讲的实验平台:井字棋

围棋太大,没法验证一个搜索算法”下得对不对”。井字棋只有 4520 个未结束的局面,可以用极小极大精确地算出每个局面的最优着法——给了我们一个”标准答案”。评测时主要使用 3191 个关键局面:至少有一步会让结果变差的局面(其余局面怎么下都一样)。算法与围棋中用的完全相同,只是规模小得多。代码见 tictactoe.py。


1. 前向搜索

1.1 从全局规划到前向搜索

第 2 讲的动态规划计算所有状态的价值。但下棋时,我们只关心”当前这个局面该怎么走”。

前向搜索:从当前状态出发,把”我走这步、对手走那步、我再走……”展开成一棵树,从叶子往回算出每一步的价值。只涉及从当前状态能到达的状态,这比全部状态少得多——但仍然随深度指数增长。

1.2 极小极大与 negamax

两人零和博弈中,我想最大化我的结果,对手想最小化它:

V(s)={max⁡aV(s′)轮到我min⁡aV(s′)轮到对手V(s) = \begin{cases} \max_a V(s') & \text{轮到我} \\ \min_a V(s') & \text{轮到对手} \end{cases}

negamax 写法把两者统一:从”轮到走棋的一方”的角度定义价值,对手的好就是我的坏:

V(s)=max⁡a[−V(play(s,a))]V(s) = \max_a \left[ -V(\text{play}(s, a)) \right]

这就是第 2 讲的贝尔曼最优方程在双人博弈中的形式(没有折扣,奖励只在终局出现)。

代码 01_minimax_search.py 演示 1–2:

  • 井字棋的完整博弈树有 549,946 个节点、255,168 局不同的对局;但不同的未结束局面只有 4,520 个——同一个局面可以由不同的走棋顺序到达。记忆化(国际象棋程序中叫”置换表”)能省下一百多倍的计算。
  • 空棋盘的价值是 0:双方完美下棋是和棋。
  • 一个局面(X 在 0、8,O 在 4,轮到 O):走边(1、3、5、7)和棋,走角(2、6)会输——走角之后,X 可以一步同时制造两个威胁(“双杀”)。这种”看起来很自然、其实会输”的着法,需要往前看好几步才能发现。

1.3 α-β 剪枝

思想:维护一个窗口 [α,β][\alpha, \beta]——α\alpha 是”我已经确定能拿到的最好结果”,β\beta 是”对手已经确定能把我压到的最坏结果”。如果某个分支的价值已经 ≥β\ge \beta,对手绝不会让棋局走到这里,剩下的着法不用看了。

演示 3:结果与极小极大完全相同,但只访问了 18,297 个节点(按编号顺序)或 7,275 个节点(按”中心、角、边”的顺序),而完整的树有 549,946 个。着法顺序越好,剪掉的越多;最理想时,同样的计算量能搜索大约两倍的深度。1997 年击败卡斯帕罗夫的”深蓝”,核心就是 α-β 搜索 + 人工设计的评估函数。

1.4 有限深度 + 评估函数

即使有剪枝,完整搜索围棋仍然不可能。常用的办法:只往前看 dd 步,到达深度限制时用一个评估函数估计局面的价值——这正是价值函数的近似。

演示 4:用一个简单的人工评估函数(按每条线上双方棋子的情况打分),在 3191 个关键局面上:

深度选到最优着法的比例从空棋盘搜索的节点数
196.1%9
296.8%81
398.2%585
499.2%3,609
599.6%18,729
9(完整)100.0%549,945
  • 看得越深越好,但节点数指数增长(每深一层乘以 5~9)。
  • 这个评估函数设计得不错,深度 1 就有 96%——好的评估函数能大大减少所需的搜索。

两个出路,正是本讲的两个主题:

  1. 不要平均地展开每个分支,把计算集中在有希望的着法上——MCTS;
  2. 用更好的评估函数,看得浅一些也能判断准确——从数据中学出来的价值网络。

围棋的困难在于:人们设计不出好的评估函数(局面的好坏很难用规则描述),而且分支因子太大(每步约 250 种选择)。这就是在 AlphaGo 之前,围棋程序长期停留在业余水平的原因。


2. 蒙特卡洛评估

2.1 随机走子

没有评估函数怎么办?第 3 讲的蒙特卡洛思想:从这个局面开始,双方随机落子直到终局,看谁赢。重复很多次,赢的比例就是一个(有噪声的)局面评估。

它完全不需要领域知识,只需要能模拟游戏。2006 年前后,基于随机模拟的围棋程序首次在 9×9 棋盘上取得突破。

2.2 平坦蒙特卡洛与它的偏差

平坦蒙特卡洛:对根节点的每个着法,各做若干次随机走子,选平均得分最高的着法。

代码 02_mcts_uct.py 演示 1,还是 1.2 节那个局面(O 必须走边):

方法模拟次数选择
平坦蒙特卡洛1002(输棋)
平坦蒙特卡洛1,0002(输棋)
平坦蒙特卡洛10,0002(输棋)
MCTS1005(和棋)
MCTS1,0005(和棋)
MCTS10,0007(和棋)

平坦蒙特卡洛系统性地选择了会输的角,模拟再多也纠正不了。原因:它评估的是”O 走这步之后,双方都随机下”的胜率。在随机对局中,占角看起来很好——因为随机的 X 很少能找到那步”双杀”。它假设对手随机下,而真正的对手不会。

这是一种偏差,不是随机误差,所以模拟再多也无济于事。


3. 蒙特卡洛树搜索

3.1 四个步骤

MCTS 逐步构建一棵搜索树。每次模拟重复以下四步:

  1. 选择(Selection):从根节点出发,在已经展开的树中,按”树策略”一路往下选,直到遇到一个还有没试过的着法的节点。
  2. 扩展(Expansion):在这个节点上选一个没试过的着法,给树加一个新节点。
  3. 模拟(Simulation):从新节点出发,双方随机落子直到终局(“走子策略”,rollout policy)。
  4. 回传(Backup):把胜负沿着刚才的路径传回根节点,更新每个节点的访问次数 NN 和总得分 WW。

模拟足够多次后,选根节点下访问次数最多的着法。代码见 mcts.py。

3.2 UCT:把 UCB 用在树上

树策略怎么选?每个节点处的选择,本身就是一个多臂老虎机问题:几个着法,价值未知,每次模拟相当于”拉一次臂”。Kocsis & Szepesvári (2006) 直接用了第 11 讲的 UCB:

a=arg⁡max⁡a[W(s,a)N(s,a)+cln⁡N(s)N(s,a)]a = \arg\max_{a} \left[ \frac{W(s, a)}{N(s, a)} + c\sqrt{\frac{\ln N(s)}{N(s, a)}} \right]

这就是 UCT(Upper Confidence bounds applied to Trees)。每个节点记录”走到这个节点的那一方”的平均得分,所以父节点挑选子节点时,挑的正是对自己最有利的那个——双方都在用 UCB 最大化自己的得分。

3.3 为什么”树”很关键?

  • 不对称的生长:UCB 把模拟集中在有希望的着法上,树在好棋的方向上长得很深,在坏棋的方向上只浅浅地看几眼。这正是有限深度搜索(平均地展开每个分支)所缺少的。
  • 对手也”认真下棋”:在树的内部,对手的着法也由 UCB 选择——对手会很快找到最好的应对。在 2.2 节的例子中,O 走角之后,X 那一层很快发现了”双杀”,O 走角的分支的平均得分随之大幅下降。评估从”对手随机下”逐渐变成”对手认真下”,平坦蒙特卡洛的偏差因此被消除。
  • 随时可停(anytime):任何时候停下来,都能给出当前最好的着法;时间越多,下得越好。

理论保证(Kocsis & Szepesvári, 2006):模拟次数趋于无穷时,UCT 在根节点选错着法的概率趋于 0,价值估计收敛到极小极大值。

3.4 收敛是慢的

演示 2:空棋盘上,MCTS 对 X 每个第一步的平均得分(真实值全是 0 = 和棋):

模拟次数中心(4)角(0)边(1)
100+0.619+0.333−0.200
1,000+0.420+0.228+0.200
10,000+0.312+0.195+0.127
100,000+0.067+0.039+0.040

模拟少时,估计值反映的是”接近随机对局”的胜率(先手在随机对局中占很大优势)。模拟越多,树越深,估计值逐渐靠近真实值 0。收敛很慢,因为平均得分包含了早期那些”随便下”的模拟。但选着法看的是访问次数,而访问次数会很快集中到好棋上——下得对,比估得准来得早。


4. MCTS 的实验与实践细节

4.1 下得对不对?

演示 3:1000 个关键局面上选到最优着法的比例:

模拟次数MCTS(UCT,c=1.4c = 1.4)平坦蒙特卡洛
1083.1%78.6%
3094.5%89.8%
10098.6%94.5%
30099.6%95.5%
1,00099.9%95.7%
3,000100.0%95.7%

MCTS 趋近 100%;平坦蒙特卡洛停在 95.7%——系统性偏差。

4.2 实战

演示 4:MCTS 执 X、执 O 各 100 盘:

MCTS 模拟次数对手MCTS 胜和MCTS 负
10完美051149
10随机1552223
100完美015545
100随机187103
1,000完美01973
1,000随机188120

对完美对手,“不输”就是满分;1000 次模拟时,200 盘只输了 3 盘。

4.3 探索常数

演示 5(每步 100 次模拟):

cc00.250.51.01.441030100
正确率93.0%96.4%97.1%98.2%98.2%98.2%96.3%94.0%80.2%
  • c=0c = 0:纯贪心,某个着法早期运气好就一直被选——和老虎机中的贪心”卡住”一样。
  • cc 在 0.5~4 之间效果差不多:在井字棋上,UCT 对 cc 不太敏感。
  • cc 很大时明显变差:探索项压倒了平均得分,模拟几乎被平均分配,树长不深;而且访问次数几乎一样时,“选访问最多的”就接近随机了。

4.4 其他实践细节

  • 最终选择:通常选访问次数最多的着法(最”稳健”),而不是平均得分最高的(可能只被访问了几次、运气好)。
  • 走子策略的质量很重要:随机走子引入偏差;更聪明的走子(比如”能赢就赢、该堵就堵”)能显著改善评估(练习 5)。AlphaGo 的第一版用一个从人类棋谱中学到的快速走子策略。
  • 树的复用:走了一步之后,对应子树的统计量可以保留给下一步继续用。
  • 并行化:多个线程同时做模拟,用”虚拟损失”避免它们都挤到同一条路径上。

5. AlphaGo → AlphaGo Zero → AlphaZero → MuZero

5.1 AlphaGo(Silver et al., 2016)

AlphaGo 把 MCTS 与深度神经网络结合:

  1. 监督学习的策略网络 pσ(a∣s)p_\sigma(a \mid s):在 3000 万个人类棋谱的局面上做行为克隆(第 8 讲),预测”人类高手会怎么走”,准确率约 57%。
  2. 强化学习的策略网络 pρp_\rho:从 pσp_\sigma 出发,通过自我对弈 + 策略梯度(第 6 讲的 REINFORCE!)继续提升。
  3. 价值网络 vθ(s)v_\theta(s):用 pρp_\rho 自我对弈产生的局面和最终胜负,回归”这个局面的胜率”。
  4. MCTS:用策略网络的输出作为着法的先验,引导搜索;叶子节点的评估 = 价值网络与快速走子结果的加权平均。

5.2 AlphaGo Zero(Silver et al., 2017)

“Zero”意味着不使用任何人类棋谱,从随机下棋开始完全靠自我对弈学习。它还做了大幅简化:

  • 一个网络(残差网络)同时输出策略 pp 和价值 vv:(p,v)=fθ(s)(\mathbf{p}, v) = f_\theta(s);
  • 不再做随机走子:叶子节点直接用 vv 评估;
  • 训练目标完全来自 MCTS:
L(θ)=(z−v)2⏟价值:拟合实际胜负  −  π⊤log⁡p⏟策略:模仿搜索的访问分布  +  c∥θ∥2\mathcal{L}(\theta) = \underbrace{(z - v)^2}_{\text{价值:拟合实际胜负}} \;-\; \underbrace{\boldsymbol{\pi}^\top \log \mathbf{p}}_{\text{策略:模仿搜索的访问分布}} \;+\; c\|\theta\|^2

其中 π(a)∝N(s,a)1/τ\boldsymbol\pi(a) \propto N(s, a)^{1/\tau} 是 MCTS 在局面 ss 上的访问次数分布,zz 是这盘棋的最终结果。

它在 3 天的训练后以 100:0 击败了击败李世石的 AlphaGo 版本。

5.3 PUCT:带先验的 UCB

AlphaGo 系列的树策略不是 UCT,而是 PUCT:

a=arg⁡max⁡a[Q(s,a)+cpuct P(s,a)N(s)1+N(s,a)]a = \arg\max_a \left[ Q(s, a) + c_{\mathrm{puct}} \, P(s, a) \frac{\sqrt{N(s)}}{1 + N(s, a)} \right]

与 UCT 的区别:

  • 先验 P(s,a)P(s, a)(策略网络的输出)决定了每个着法的探索奖励有多大——“直觉”认为好的着法先看、多看,明显的坏棋几乎不看。围棋每步约 250 种选择,没有先验,每个着法都要先试一次,搜索根本长不深。
  • 探索项是 N(s)/(1+N(s,a))\sqrt{N(s)}/(1 + N(s, a)),而不是 ln⁡N(s)/N(s,a)\sqrt{\ln N(s)/N(s, a)}。
  • 自我对弈时,在根节点的先验上混入 Dirichlet 噪声 P←(1−ε)P+ε Dir(α)P \leftarrow (1 - \varepsilon) P + \varepsilon\,\mathrm{Dir}(\alpha),保证即使网络”很确定”,也会探索其他着法——又一次是探索!

5.4 AlphaZero 与 MuZero

  • AlphaZero(Silver et al., 2018):同一个算法,不做任何针对性的修改,分别在国际象棋、日本将棋、围棋上达到超越所有已有程序的水平。它证明了”自我对弈 + MCTS + 深度网络”是一个通用的方法。
  • MuZero(Schrittwieser et al., 2020):连游戏规则都不需要——它学习一个模型,在学到的模型里做 MCTS。这把本讲的”已知模型的规划”推广到了”学到的模型的规划”,也就是下一讲的基于模型的强化学习。MuZero 在 Atari 游戏上也取得了当时最好的结果。

5.5 实验:AlphaZero 的骨架

代码 03_alphazero_lite.py 实现了 AlphaZero 的完整训练循环:PUCT 搜索、自我对弈(带 Dirichlet 噪声)、用访问分布训练策略、用胜负训练价值。唯一的简化:为了只用 numpy、并看清每个数字,“网络”是一张查找表(每个局面各存一组策略和一个价值)。

演示 1:训练过程(每轮 50 盘自我对弈,每步 64 次 PUCT 模拟):

轮次累计对局见过的局面价值误差*只用策略在见过的关键局面上的正确率对完美对手输的盘数(只用策略 / PUCT 16 次)
000——83 / 80
1502290.29991.3%48 / 69
52505710.04393.0%27 / 32
105007640.03794.8%30 / 40
2010009730.02395.9%13 / 39
40200011990.02297.8%17 / 19

(* 训练 ≥ 10 次的局面上,价值与极小极大真实值之差的绝对值的平均;对局各 100 盘。)

  • 价值误差迅速降到很小:自我对弈的胜负结果教会了它”这个局面会怎样”。
  • **只用策略(完全不搜索)**的水平大幅提高:策略的训练目标是搜索后的访问分布,它把搜索的结论”蒸馏”成了直觉。
  • 对局成绩不是单调的(100 盘的随机波动不小),而且训练后仍会输一些棋:完美对手会把棋局带到自我对弈中从没出现过的局面,查找表在那里一无所知。

演示 2:直觉让搜索更高效(关键局面上选到最优着法的比例):

自我对弈中见过的关键局面(829 个);只用训练后的策略、不搜索:97.8%

模拟次数PUCT + 训练后的表PUCT + 没训练的表UCT(随机走子)
489.6%47.0%48.3%
1696.0%72.5%74.7%
6498.4%92.5%93.4%
25699.8%97.8%98.3%

自我对弈中没见过的关键局面(2362 个);只用训练后的策略:40.8%

模拟次数PUCT + 训练后的表PUCT + 没训练的表UCT(随机走子)
468.1%66.4%59.8%
1691.3%89.5%93.4%
6498.3%98.2%98.5%
25699.9%99.7%99.8%
  1. 见过的局面:训练后的表让搜索高效得多——4 次模拟的正确率就远高于没训练的表和 UCT。先验告诉搜索”先看哪几步”,价值代替了粗糙的随机走子。
  2. 搜索次数很少时,搜索反而不如直接用策略(4、16 次时低于 97.8%):只有几次访问时,“访问最多”是一个很粗糙的信号。模拟够多(64、256)时,搜索才超过策略。这就是 AlphaZero 每步要做几百上千次模拟的原因:搜索要足够深,才能改进直觉。
  3. 没见过的局面:训练后的表和没训练的表几乎一样——查找表不能泛化。真正的 AlphaZero 用神经网络,从见过的局面中学到的模式能泛化到从没见过的局面。围棋的局面多到自我对弈永远不可能见全,泛化是一切的前提。

演示 3:没见过的关键局面中,84.6% 已经”分出胜负”(见过的只有 46.1%)。自我对弈的双方都在认真下棋,没见过的局面大多要有一方先下出明显的错着才会出现。这类局面往往是”一步杀”或”必须堵”,靠搜索很容易解决。自我对弈把学习集中在高水平对局会遇到的局面上——这也是训练时需要 Dirichlet 噪声和开局随机性的原因:让自我对弈见识更多样的局面。


6. 为什么自我对弈 + 搜索能不断变强?

6.1 策略迭代的视角

回忆第 2 讲的策略迭代:

  1. 策略评估:计算当前策略的价值;
  2. 策略改进:根据价值贪心地改进策略。

AlphaZero 的循环正是近似的策略迭代:

策略迭代AlphaZero
当前策略 π\pi网络的策略头 p\mathbf{p}
策略改进:π′=greedy(Qπ)\pi' = \text{greedy}(Q^\pi)MCTS:以 p\mathbf{p} 为先验、vv 为评估做搜索,得到更强的访问分布 π\boldsymbol\pi
策略评估:Vπ′V^{\pi'}用 π\boldsymbol\pi 自我对弈,用胜负 zz 训练价值头 vv
用 π′\pi' 替换 π\pi训练策略头去模仿 π\boldsymbol\pi

MCTS 是一个”策略改进算子”:给它一个策略和价值,它输出一个更强的策略(演示 2:搜索够多时,正确率高于策略本身)。网络再去学习这个更强的策略,下一轮的搜索从更好的起点出发……如此循环。

6.2 模仿学习的视角

从第 8 讲的角度看:MCTS 是专家,网络是学习者,策略的训练就是行为克隆。而且训练数据来自网络自己的自我对弈——学习者访问的状态分布,这正是 DAgger 的思想:在学习者自己会遇到的状态上,向专家请教。不同的是,这里的”专家”不是人,而是”学习者 + 搜索”——学习者越强,专家也越强。这被称为专家迭代(Expert Iteration,Anthony et al., 2017)。

6.3 超越棋类

“学到的直觉 + 搜索”这个组合远不止用于下棋:

  • AlphaTensor(2022):把”找更快的矩阵乘法算法”变成一个游戏,用 AlphaZero 式的方法发现了新的算法;
  • AlphaDev(2023):发现了更快的排序程序,已被合并进 C++ 标准库;
  • 大语言模型的推理:在”推理步骤”上做树搜索,用学到的价值模型评估中间步骤——第 16 讲会继续讨论。

7. 本讲总结

7.1 核心概念清单

  1. 前向搜索:只为当前状态规划,展开博弈树;不需要遍历所有状态,但树随深度指数增长。
  2. 极小极大 / negamax:V(s)=max⁡a−V(s′)V(s) = \max_a -V(s');记忆化合并相同局面。
  3. α-β 剪枝:结果不变,跳过不可能影响决策的分支;着法顺序越好剪得越多。
  4. 有限深度 + 评估函数:看得越深越好,代价指数增长;好的评估函数能减少所需的搜索。
  5. 蒙特卡洛评估:随机走子到终局,不需要领域知识。
  6. 平坦蒙特卡洛的偏差:假设双方随机下,系统性地误判,模拟再多也纠正不了。
  7. MCTS:选择、扩展、模拟、回传;不对称地生长;随时可停。
  8. UCT:每个节点都是一个老虎机,用 UCB 选择;树让对手也”认真下棋”,收敛到极小极大值。
  9. AlphaGo:人类棋谱的行为克隆 + 策略梯度自我对弈 + 价值网络 + MCTS。
  10. AlphaGo Zero / AlphaZero:无人类数据;一个网络输出 (p,v)(\mathbf{p}, v);PUCT;损失 (z−v)2−π⊤log⁡p(z-v)^2 - \boldsymbol\pi^\top\log\mathbf{p}。
  11. 自我对弈为什么有效:MCTS 是策略改进算子,网络训练是策略评估与蒸馏——近似的策略迭代 / 专家迭代。
  12. 泛化:神经网络能把学到的东西推广到没见过的局面,这是在巨大状态空间中成功的前提。

7.2 公式速查表

名称公式
negamaxV(s)=max⁡a[−V(play(s,a))]V(s) = \max_a [-V(\text{play}(s,a))]
UCTarg⁡max⁡aW(s,a)N(s,a)+cln⁡N(s)N(s,a)\arg\max_a \frac{W(s,a)}{N(s,a)} + c\sqrt{\frac{\ln N(s)}{N(s,a)}}
PUCTarg⁡max⁡aQ(s,a)+cpuctP(s,a)N(s)1+N(s,a)\arg\max_a Q(s,a) + c_{\mathrm{puct}} P(s,a)\frac{\sqrt{N(s)}}{1+N(s,a)}
根节点噪声P←(1−ε)P+ε Dir(α)P \leftarrow (1-\varepsilon)P + \varepsilon\,\mathrm{Dir}(\alpha)
访问分布π(a)∝N(s,a)1/τ\pi(a) \propto N(s,a)^{1/\tau}
AlphaZero 损失(z−v)2−π⊤log⁡p+c∥θ∥2(z - v)^2 - \boldsymbol\pi^\top\log\mathbf{p} + c\|\theta\|^2

7.3 中英术语对照表

中文英文中文英文
前向搜索Forward search博弈树Game tree
极小极大Minimax负极大Negamax
α-β 剪枝Alpha-beta pruning置换表 / 记忆化Transposition table / memoization
评估函数Evaluation function随机走子Rollout / playout
平坦蒙特卡洛Flat Monte Carlo蒙特卡洛树搜索Monte Carlo Tree Search (MCTS)
树策略Tree policy走子策略Rollout / default policy
选择、扩展、模拟、回传Selection, expansion, simulation, backup随时可停Anytime
UCTUpper Confidence bounds applied to TreesPUCTPredictor + UCT
策略网络 / 价值网络Policy network / value network自我对弈Self-play
专家迭代Expert iteration策略改进算子Policy improvement operator

8. 练习题

练习 1(negamax):用 negamax 的思路,手工计算下面这个局面(轮到 X)的价值:

X O X
O O X
_ X O
参考答案

只剩一个空位(左下角,编号 6)。X 走 6 之后,棋盘下满,检查所有的线:没有三连(第一列 X O X、第三行 X X O、对角线 2-4-6 为 X O X……),是和棋,价值 0。所以这个局面的价值是 0。

练习 2(α-β 剪枝):为什么着法顺序会影响 α-β 剪枝的效率?如果每次都能先看到最好的着法,会发生什么?

参考答案

剪枝发生在”已经找到一个足够好的着法,使得对手不会让棋局走到这里”的时候。如果先看到最好的着法,α\alpha 很早就变得很大,后面的着法只要发现”对手有一个应对能把我压到 α\alpha 以下”就能立刻停止——需要看的节点最少。理论上,完美的着法顺序能把需要访问的节点数从 bdb^d 降到约 bd/2b^{d/2},相当于同样的计算量能搜索两倍的深度。这也是为什么好的着法排序(比如用上一轮搜索的结果、或者一个策略网络)如此重要。

练习 3(平坦蒙特卡洛):用自己的话解释:为什么平坦蒙特卡洛在 2.2 节的例子中,模拟再多也会选错?这种错误属于偏差还是方差?

参考答案

平坦蒙特卡洛估计的是”我走这步之后,双方随机下”的期望结果,模拟次数越多,这个估计越准——但它估计的量本身就不是我们关心的量(“对手认真下时”的结果)。随机的 X 很少走出”双杀”,所以 O 走角看起来还不错。这是偏差:估计量收敛到了一个错误的值,增加样本只能减小方差,不能减小偏差。MCTS 让对手在树中也按 UCB 认真选着法,才消除了这个偏差。

练习 4(UCT 与老虎机):在 MCTS 的每个节点上用 UCB 选择,与第 11 讲的老虎机有什么不同?(提示:每个”臂”的奖励分布是固定的吗?)

参考答案

老虎机中每个臂的奖励分布是固定的。而在 MCTS 中,一个子节点的”奖励”取决于它下面的子树中的选择——随着子树中的搜索不断改进(对手越来越”认真”),这个子节点的平均得分会变化(演示 2 中价值估计从 +0.6 一路降到接近 0)。所以每个节点面对的是一个非平稳的老虎机。这正是 UCT 的理论分析比 UCB 更复杂的原因(Kocsis & Szepesvári 需要处理奖励的”漂移”),也是它收敛较慢的原因之一。

练习 5(动手)★:把 mcts.py 中的随机走子换成”能一步赢就赢;否则如果对手能一步赢就堵;否则随机”。平坦蒙特卡洛在 2.2 节的局面上还会选错吗?它在关键局面上的正确率能达到 100% 吗?

参考答案

实测:换成这种走子策略后,平坦蒙特卡洛在这个局面上给两个角的评分都是 −1.0(O 走角后,X 按”该堵就堵”的规则堵住 O 的斜线,恰好形成双杀),能正确地选择走边。在 1000 个关键局面上的正确率从 95.7% 提高到约 98.5%(100 次模拟 98.3%,1000 次 98.7%),但仍然达不到 100%——更聪明的走子策略减小了偏差,但只要走子不是完美的,偏差就不会消失。同样的走子策略下,MCTS 在 100 次模拟时就达到 99.7%。这说明走子策略的质量很重要(AlphaGo 第一版专门训练了快速走子网络),而树搜索能在此基础上进一步消除剩余的偏差。

练习 6(AlphaZero 的损失):AlphaZero 的策略目标为什么是 MCTS 的访问分布 π\boldsymbol\pi,而不是”实际走的那一步”(独热向量)?

参考答案

访问分布包含了更多信息:不只是”哪步最好”,还有”其他着法有多好”(第二好的着法也被访问了很多次,说明它也不错)。这种”软目标”让网络学到更丰富的偏好,训练更稳定,也更容易泛化。此外,实际走的那一步可能是按温度随机选的(开局阶段),不一定代表搜索的最佳判断。这与知识蒸馏中”用教师模型的软概率训练学生模型”是同一个道理。

练习 7(策略迭代):用 6.1 节的对应关系解释:如果 MCTS 的模拟次数太少(比如 4 次),AlphaZero 的训练会出现什么问题?结合演示 2 的结果。

参考答案

策略迭代能不断改进的前提是”策略改进”这一步真的产生了更好的策略。演示 2 显示,4 次或 16 次模拟的 PUCT 在见过的局面上正确率(89.6%、96.0%)低于策略本身(97.8%)——搜索没有改进策略,反而让它变差了。如果用这样的访问分布做训练目标,网络就会去模仿一个比自己还差的”专家”,训练会停滞甚至退化。所以训练时每步的模拟次数必须足够多,让搜索确实比网络更强(AlphaGo Zero 自我对弈时每步 1600 次模拟)。

练习 8(思考题):MCTS 需要一个模拟器(能从任意状态出发模拟未来)。在哪些 RL 问题中这个要求可以满足,哪些不能?MuZero 是怎样绕开这个要求的?

参考答案

棋类游戏、电子游戏(能保存和读取状态)、某些物理仿真器可以满足;真实世界中的机器人、医疗、推荐系统通常不行——你不能把真实的病人”回退”到昨天,再试另一种治疗。MuZero 的做法是学习一个模型:学一个表示函数把观察编码成隐状态,一个动力学函数预测”做了动作之后的隐状态和奖励”,一个预测函数输出策略和价值;然后在这个学到的模型中做 MCTS。它不需要模型能还原真实的观察,只需要模型对规划有用的量(奖励、价值、策略)预测准确。这就是下一讲”基于模型的 RL”的一个代表。


9. 延伸阅读

  • CS234 Spring 2024 Lecture 15 录像与课件。
  • Browne et al. (2012),A Survey of Monte Carlo Tree Search Methods:MCTS 的全面综述。
  • Kocsis & Szepesvári (2006),Bandit Based Monte-Carlo Planning:UCT 的原始论文。
  • Silver et al. (2016),Mastering the Game of Go with Deep Neural Networks and Tree Search(AlphaGo)。
  • Silver et al. (2017),Mastering the Game of Go without Human Knowledge(AlphaGo Zero)。
  • Silver et al. (2018),A General Reinforcement Learning Algorithm that Masters Chess, Shogi, and Go through Self-Play(AlphaZero)。
  • Schrittwieser et al. (2020),Mastering Atari, Go, Chess and Shogi by Planning with a Learned Model(MuZero)。
  • Anthony, Tian & Barber (2017),Thinking Fast and Slow with Deep Learning and Tree Search(专家迭代)。
  • Russell & Norvig,Artificial Intelligence: A Modern Approach,第 5 章(对抗搜索)。

10. 下一讲预告

本讲假设模型已知(游戏规则)。MuZero 已经暗示了下一步:如果模型未知,能不能先学一个模型,再在模型里规划?

下一讲是基于模型的强化学习:

  • Dyna 架构:用真实经验学习模型,再用模型生成”想象的经验”来加速学习——样本效率能提高多少?
  • 模型误差:模型不完美时,在模型里规划会发生什么?为什么”想象”走得越远,误差越大(复合误差)?
  • 环境变化时,模型会过时——怎样发现并纠正?
  • 世界模型、MuZero 与现代的基于模型的方法。

下一讲之前,建议你:跑通 code/lecture14/ 下的 3 个脚本,完成练习 1、3、4、6,并尝试练习 5。

← 返回课程目录