Lecture 14: 蒙特卡洛树搜索深入与 AI 伦理 —— UCT 的深入分析与价值对齐(MCTS in Depth: UCT, and Ethics and Society)
Lecture 14: 蒙特卡洛树搜索深入与 AI 伦理 —— UCT 的深入分析与价值对齐(MCTS in Depth: UCT, and Ethics and Society)
对应材料:官方
lecture14pre/post.pdf(30 页,内容相同)+ 伦理与社会客座独立讲义ethics_society_234_2.pdf(cs234/clean/ethics.txt,21 页,Wanheng Hu《VALUE ALIGNMENT PART II》)|W10 周一 Mar 9, 2026(W9 周三 Mar 4 为 In-Class Quiz,W10 周三 Mar 11 为 Poster Session)|参考阅读 SB Chp 8、MuZero(Schrittwieser et al. 2020) 一句话定位:L13 建立了 MCTS 的四阶段骨架与影响分析的直觉;本讲把骨架拆到”一轮自我对弈的数据如何变成训练信号“的工程细节,把 UCT 的探索 bonus 从”借来的启发式”提升为带 Hoeffding 论证的统计决策规则,并把镜头从”如何搜索得更好”切换到”我们到底想让智能体优化什么“——由 STS 学者 Wanheng Hu 主讲的价值对齐(Value Alignment)第二部分。
14.1 概述
本讲由两条表面无关、内核相通的线索组成。第一条线索是 UCT(Upper Confidence Tree, 置信上界树)搜索的深入解剖与 AlphaGo/AlphaZero 自我对弈闭环:讲义第 3 页重申 Monte Carlo 树搜索(Monte Carlo Tree Search, MCTS)的五大优势,第 12–22 页把 L13 一笔带过的”自我对弈 → 训练网络”展开成完整的数据生成—标签构造—参数更新回路,第 26–28 页则回到 UCT 本身,追问一个 L13 没有回答的问题:“把每个树节点当成多臂老虎机来解,这件事在逻辑上其实略微奇怪,为什么它仍然有效?” 第二条线索是价值对齐(Value Alignment):上一讲(L10 客座第一部分)把”对齐”理解为”做用户真正想要的”,本讲立即补上一个被遗漏的维度——用户之外的人——并系统比较”自上而下给定道德原则”与”自下而上从示例学习道德”两条技术路线各自的哲学困难与工程陷阱。
两条线索通过一个共同的母题缝合:目标(objective)一旦写错,搜索得越好,后果越坏。AlphaZero 的 1600 次模拟(此为 AlphaGo Zero 论文配置,本课程讲义未给出该数值)让策略网络逼近搜索分布,这是”搜索即策略改进算子”的技术胜利;而 Paperclip AI 的悲剧恰恰是”最大化回形针产量”这个目标被完美优化。奖励函数写得对不对与策略优化得好不好这两件事合起来,才构成一个负责任的 RL 系统——任何一件做错,另一件做得越好反而越危险。
本讲的官方结构(讲义第 2 页):”Last time: MCTS and guest lecture Shane Gu from DeepMind on World Models. This Time: MCTS and Ethics and Society Guest Lecture Part 2. Next time: Quiz.”
14.2 核心概念的数学形式化
本讲引入或深化 7 个关键概念。按 SPEC.md §2 的要求,每个概念给出「严格定义 → 直观解释 → 具体示例 → 与监督学习/前序方法的对比」。
14.2.1 UCT 选择规则(置信上界树)
严格定义. 设搜索树中节点 $i$ 表示状态 $s$,在其上可执行动作集合 $\mathcal{A}(i)\subseteq\mathcal{A}$。记 $N(i,a)$ 为在节点 $i$ 选择动作 $a$ 的累计模拟次数,$G_k(i,a)$ 为第 $k$ 次从节点 $i$ 执行 $a$ 后沿模拟轨迹得到的折扣回报。UCT 为每条边维护
\[Q(i,a)=\frac{1}{N(i,a)}\sum_{k=1}^{N(i,a)}G_k(i,a),\qquad \mathrm{UCT}(i,a)=Q(i,a)+c\sqrt{\frac{\ln N(i)}{N(i,a)}},\quad c>0,\]其中 $N(i)=\sum_{a\in\mathcal{A}(i)}N(i,a)$。模拟时选择
\[a_{\text{sim}}=\arg\max_{a\in\mathcal{A}(i)}\ \mathrm{UCT}(i,a).\]对照 L13 的写法 $Q(s,a,i)=\frac{1}{N(i,a)}\sum_k G_k(i,a)+c\sqrt{\frac{O(\log N(i))}{N(i,a)}}$:L13 保留了大 $O$ 记号以强调”这是个渐近量级”,本讲把它落实为 $c\sqrt{\ln N(i)/N(i,a)}$,从而可以实际数值计算并做校准实验(见 14.4)。
直观解释. 想象一个赌徒面对一排老虎机(多臂老虎机,Multi-Armed Bandit, MAB)。他既想多拉已经证明高回报的那台(利用, exploitation),又不得不给还没拉过的机器一些机会(探索, exploration)。UCB1 给出的黄金法则是:“一个臂的可信上界 = 它的平均收益 + 一个随样本数递减的不确定性补偿”。UCT 把这个法则搬到树的每一个节点上:把”从该节点出发、经动作 $a$ 能拿到的未来折扣回报”当作臂的收益。
具体示例(本讲代码所用的 4×4 GridWorld). 状态 16 个、动作 4 个(上/下/左/右),陷阱在 $(1,1),(2,2)$,目标在 $(3,3)$,$\gamma=0.9$,滑倒概率 $\varepsilon=0.1$(以 0.1 概率改为均匀随机走)。真值迭代给出 $V^(s_0)=0.4898$、$V^(\text{目标左侧})=0.9399$。在根节点 $s_0$(左上角),
\[Q^*(s_0,\cdot)=\bigl[\,0.4434,\ 0.4898,\ 0.4434,\ 0.4898\,\bigr]\]即”下”与”右”并列最优(都朝目标方向,对称);”上”与”左”因撞墙原地不动而被折扣压制。取 $c=0$ 时 UCT 退化为贪心,第一次采样若恰好撞上某个动作能拿到偏高回报,就会把绝大部分模拟全投给它——实测(L14_snippet2.py,500 次模拟、四动作为 上/下/左/右):$c=0$ 时 $N=[11,2,484,3]$,$484/500$ 的预算被锁死在动作 2(左)上,而真正最优的动作 3(右)只拿到 3 次;取 $c=8$ 时 bonus 量级达 $1.7\sim2.0$($U=[1.692,1.799,1.686,2.015]$),远超 $Q$ 的 $[-1,1]$ 范围,访问分布被强行拉平为 $N=[139,123,140,98]$。这个 $c$ 的两难正是 14.4 第三个实验的靶子。
与监督学习的对比. 监督学习里没有”该看哪个样本”的问题——数据是给定的。UCT 要解决的是主动采样问题:树中每个节点每次被访问都消耗一次模拟预算,所以”下一条模拟走哪条路径”本身就是一个序贯决策问题。这与 L9 的 UCB regret 最小化同源,但收益结构完全不同(见 14.2.6)。
14.2.2 自我对弈闭环(Self-Play Loop)
严格定义. 设参数化网络 $f_\theta(s)=(\mathbf{p}\theta(\cdot\vert s),\,v\theta(s))$,其中 $\mathbf{p}\theta\in\Delta^{\vert \mathcal{A}\vert }$ 是动作先验、$v\theta(s)\in[-1,1]$ 是胜率价值。第 $k$ 轮迭代执行:
- 数据生成:用当前 $f_{\theta_k}$ 驱动 MCTS 与自身对弈若干局,每局在时刻 $t$ 产生 $s_t$、根节点访问分布 $\boldsymbol{\pi}_t$(其中 $\pi_t(a)\propto N(s_t,a)^{1/\tau}$)、以及终局结果 $z\in\{-1,+1\}$;
- 标签构造:把 $\boldsymbol{\pi}_t$ 当作策略头的回归目标,把 $z$ 当作价值头的回归目标;
- 参数更新:$\theta_{k+1}$ 最小化 \(L(\theta)=\underbrace{\bigl(z-v_\theta(s)\bigr)^2}_{\text{价值头}}-\underbrace{\boldsymbol{\pi}_t^{\top}\log \mathbf{p}_\theta(\cdot\vert s_t)}_{\text{策略头交叉熵}}+\underbrace{c_{\text{reg}}\vert \theta\vert ^2}_{\text{正则}}\)
用同一份 $f_\theta$ 生成的 $\boldsymbol{\pi}$ 去监督 $f_\theta$ 自己,就构成一个自举(bootstrap)闭环。
直观解释. 这是一个学生—老师角色互换的循环:MCTS 是”老师”,因为它把 1600 次模拟(此为 AlphaGo Zero 论文配置,本课程讲义未给出该数值)的算力兑换成一个比原始网络更好的决策分布;网络是”学生”,它把这个分布压缩成一次前向传播。学生变强后,下一轮它给老师提供的先验更好,老师能看得更深更准——搜索与网络互相抬轿子。
具体示例. 讲义第 15 页的标题即”Train Neural Network to Predict Policies and Values”:网络同时被两个目标监督。注意标签 $\boldsymbol{\pi}_t$ 不是人对局数据,而是搜索自己的统计量,因此不存在”人类标注噪声”,但存在”搜索自身的偏差被网络固化”的风险(若搜索长期低估某类布局,网络也学会忽略它)。
与监督学习/模仿学习的对比. 形式上与 L8 的模仿学习(Behavior Cloning)完全同构——都是交叉熵拟合一个 teacher 分布。差别在 teacher 的来源:模仿学习的 teacher 是人类专家(外部、固定、有上限),AlphaZero 的 teacher 是自己的搜索(内部、随训练共同进化、上限是搜索算力与价值估计精度)。这正是讲义第 13–14 页”Advantages of Self Play for Go”的两点:瓶颈只是算力、不需要人类,且对手水平天然匹配。讲义第 14 页进一步回答了”奖励稠密吗”——”Rewards will be quite dense as both players are evenly matched. This provides a form of curriculum learning.”(双方势均力敌 ⇒ 胜负有来有回 ⇒ 终局信号提供了类似课程学习的渐进难度)。
14.2.3 策略改进算子(Policy Improvement Operator)视角下的 MCTS
严格定义. L13 已给出:从真实状态 $s_t$ 出发做 $K$ 次模拟后取 $\hat a_t=\arg\max_a Q(s_t,a)$,这”essentially doing 1 step of policy improvement”。形式化地,若模拟策略为 $\pi$、模型为 $\hat M$,则 MCTS 输出
\[\pi_{\text{MCTS}}(a\vert s_t)=\frac{N(s_t,a)^{1/\tau}}{\sum_{a^{\prime}}N(s_t,a^{\prime})^{1/\tau}},\qquad \tau>0,\ \tau\to 0^+\text{ 即退化为 argmax}.\]策略改进定理给出:当 $Q$ 估计无偏时,贪心化的新策略满足对所有 $s$ 有 $V^{\pi^{\prime}}(s)\ge V^{\pi}(s)$,且只要 $\pi$ 非最优该不等式在某状态严格成立。
直观解释. MCTS 不是”查表求最优”,而是”把算力兑换成一次更好的决策“。这个兑换率不需要改变参数即可发生——同一套网络权重,模拟 1 次和 800 次得到的是两个强度不同的棋手。这就是讲义第 16 页那六条特征里”Strategic Computation”(策略性计算)与”Local Computation”(局部计算:只算当前这一步)的含义。六条特征是:Self Play(自我对弈)、Strategic Computation、Highly selective best-first search(高度选择性的最佳优先搜索)、Power of Averaging(平均的力量:$Q$ 是多次模拟回报的均值,方差随 $K$ 下降)、Local Computation、Learn and Update Heuristics(学习并更新启发式)。
具体示例. 14.4.1 给出的实测序列(4×4 GridWorld,完美价值网络):先验为”指向目标”时,根节点决策正确率从 $K=1$ 的 0.769 升到 $K=5$ 的 1.000。同一先验下若把先验换成”系统性指错方向”,正确率在 $K=1,5,20$ 全部为 0.000,直到 $K=100$ 才升到 0.077(4×4 环境)、$K=500$ 到 0.154。这说明改进幅度强烈依赖 $K$ 与先验质量的组合,不是单纯”多算就好”。
与 L5–L7 的对比. 策略梯度用梯度改进策略,每次更新改变 $\theta$;MCTS 用算力改进策略,参数不动。两者可以叠加(AlphaZero 正是用 MCTS 改进后的分布去监督策略头),因此 MCTS 可以看作一种”以搜索算子形式出现、”免参数”的策略改进步骤”。
14.2.4 搜索放大先验 / 搜索补偿网络容量
严格定义. 设先验为 $\mathbf{p}$、价值估计误差为 $\epsilon_v$、模拟次数为 $K$。MCTS 的根节点决策误差可以粗略分解为两个竞争项:随 $K$ 单调下降的采样方差项 $O(\sigma^2/K)$,以及不随 $K$ 消失的偏差项——它由先验偏差 $\Delta_{\mathbf p}$ 与价值系统偏差 $\Delta_v$ 决定。于是
\[\mathrm{Err}(K;\mathbf p,\epsilon_v)\ \approx\ \underbrace{\frac{C_1}{K}}_{\text{可用算力降低}}\ +\ \underbrace{g(\Delta_{\mathbf p},\Delta_v)}_{\text{算力无法消除}}.\]直观解释. 搜索是一个放大器:先验指向哪,它就在哪个子树上花预算;先验指错方向时,放大器把错误一起放大。因此”搜索能否补救差先验”的答案是有条件的——只有当价值网络能识别出”先验推荐的方向其实很差”时,$Q$ 项才有力气把 bonus 项压下去。
具体示例(本讲主实验,6×6 GridWorld,31 个自由状态). 先验 top-1 与 $Q^$ 一致率:uniform 0.000、good 0.645、bad 0.000。固定叶子价值为 medium 质量价值网络(对 $V^$ 的 MSE $=0.0672$,相关系数 $0.902$)后,单步决策精度随 $K$ 的变化是:
| 先验(策略网络) | K=1 | K=5 | K=20 | K=100 | K=500 |
|---|---|---|---|---|---|
uniform(均匀) | 0.000 | 0.161 | 0.323 | 0.613 | 0.548 |
good(指向目标) | 0.645 | 0.806 | 0.806 | 0.871 | 0.903 |
bad(系统性指错) | 0.000 | 0.032 | 0.065 | 0.161 | 0.258 |
与监督学习的对比. 监督模型里”训练集固定 ⇒ 能力上限固定”;MCTS 里”推理时多算 ⇒ 能力上限抬高”,这是典型的训练/推理非对称范式(类似 LLM 的 test-time compute)。
14.2.5 PUCT 与 AlphaZero 的选择规则
严格定义. AlphaGo/AlphaZero 不用纯 UCT,而用 PUCT(Predictor + UCT,讲义第 6 页:”Inspired by Upper Confidence Tree Search but many changes. Use PUCT.”):
\[a_t=\arg\max_{a}\Bigl(Q(s_t,a)+c_{\text{puct}}\,P_\theta(a\vert s_t)\,\frac{\sqrt{\sum_{a^{\prime}}N(s_t,a^{\prime})}}{1+N(s_t,a)}\Bigr),\]其中 $P_\theta(a\vert s_t)$ 是策略网络给出的先验概率。
直观解释. UCT 的 bonus 是”次数少 ⇒ 我不了解你 ⇒ 给你机会”;PUCT 的 bonus 是”次数少 而且 网络看好你 ⇒ 才给你机会”。先验因此充当了一个乘性门控,让搜索在大动作空间(围棋 361 点)中把预算集中到网络认为有希望的少数分支,这是把”大动作空间”变可行的关键。
具体示例. 14.4.2 的 PUCT 对照:同样在完美价值网络下,纯 UCB1(忽略先验)的精度是 0.581–0.710 区间,而「good 先验 + PUCT」在 $K=20$ 时为 $0.871$(后悔 $0.0039$),$K=100$ 时为 $0.806$(后悔 $0.0574$),$K=500$ 时为 $0.806$(后悔 $0.0064$)。这里必须诚实指出一个反直觉的事实:PUCT 的精度并未随预算单调提升,$K=100$ 时($0.806$)甚至低于同预算下 good+zero 与 good+exact 的 $0.871$。原因是先验把搜索过度集中到它偏好的分支上,预算增大反而放大了这种集中;小预算($K=20$)时先验起「快速定向」的正作用,大预算时其负作用开始显现。这说明「加预算」不是万能药——先验、价值网络与预算三者此消彼长,而非简单叠加。
与 UCT 的对比. UCT 的 bonus 形如 $\sqrt{\ln N/N_a}$(对先验无感),PUCT 的 bonus 形如 $P_a\sqrt{N}/(1+N_a)$(对先验敏感)。前者在臂数少时更稳,后者在臂数多且先验可信时更强。
14.2.6 UCT 的”奇怪之处”:元层推理(Metalevel Reasoning)
严格定义. 讲义第 26 页提出的问题:“Why is this slightly strange? Hint: why were upper confidence bounds a good idea for exploration/exploitation? Is there an exploration/explotation problem during simulated episodes?” 答案是:UCB 之所以重要,是因为在真实环境中每次拉臂都有机会成本(真实后悔),且回报分布未知。而在模拟回合中:(i) 回报由已知模型 $(\hat M,\pi)$ 生成,可以无限次重采样;(ii) 每次”拉臂”的真实成本是计算时间,不是环境后悔。因此这里被最小化的”regret”是一个内部代理量——讲义脚注把它归入元层推理(metalevel reasoning),并引 Hay, Russell, Tolpin & Shimony (2012)《Selecting Computations: Theory and Applications》。
直观解释. 在真实世界里,探索很贵(可能亏钱);在树搜索里,探索只是选择”接下来把算力花在哪里”。所以 UCT 实际回答的是一个算力分配问题:”下一步模拟应当去探索哪条分支,才能让根节点的最终决策最准?”这是一个纯粹的内部问题,与外部环境的探索/利用权衡只在形式上相似。
具体示例. 这解释了 14.4.2 中 6×6 环境根节点的实测现象:当 $c=0$(贪婪,完全不探索内部)时,一旦早期采样噪声把某条次优臂推高,后续 481/500 次模拟全部浪费在那条臂上(数据出自 6×6 环境,见 14.4.2),”内部探索”不足直接导致外部决策错误——内部探索不足会外化为外部表现变差,尽管二者的目标函数并不相同。
与前序讲次的对比. L9–L11 中的探索是为了在真实环境中收集信息以优化策略;UCT 的探索是为了在模拟环境中收集信息以优化当前这一步的决策。前者改变参数,后者不改变参数。
14.2.7 价值对齐的第四种解读:对齐到道德(Aligning to Morality)
严格定义(讲义第 5 页). 前三种解读把”what we really want”的”we”理解成用户:对齐到用户的意图(intention)、偏好(preference)、或利益(interest)。第四种解读把这个”we”扩展为所有人:“AI agent is value-aligned if it does what is morally right.” 判据从”用户满意”变成”道德上正确”。
直观解释. 讲义第 4 页用一整页只写了三个词回答”上一讲漏了什么”:PEOPLE OTHER THAN THE USER! 用户的意图、偏好甚至利益,都可能对他人有害;对齐到用户并不蕴含对齐到道德。讲义第 5 页的例证是 Paperclip AI:它之所以错,不是因为它没满足工厂主的意图,而是因为”it’s bad for everyone if the world is destroyed”。
具体示例(讲义第 7 页的智能体购票场景). 假设你有一个个人 AI 智能体,替你以最优价格买演唱会门票:它监控市场、议价、自动下单。讨论题:当所有人都用同样目标的智能体时会发生什么?讲义给出的答案是——个体层面完全对齐的行为,会汇聚成集体层面的不良后果:智能体之间的竞速更快、价格尖峰(price spikes)、用户之间优势不平等。这里没有任何单个智能体”违背”了它的用户;问题出在均衡(equilibrium)而非个体。
与监督学习/前序讲次的对比. L8–L10 的 RLHF 与偏好学习优化的是”用户的打分”,本小节的判据是不能被用户打分充分表达的道德约束。这个落差正是讲义第 6 页强调的:”The user still matters……Even though we want to align to morality, we also want to align to what the user wants when what the user wants is morally acceptable.”——用户视角没有被抛弃,而是被放进了一个更大的伦理框架里。
14.3 算法伪代码与完整推导
14.3.1 算法一:UCT 搜索(含完整选择公式与收敛论证)
算法 UCT-Search(root_state s_root, 模拟次数 K, 探索常数 c, 模拟策略 π_sim, 模型 M̂)
────────────────────────────────────────────────────────────────────
输入:根状态 s_root;预算 K;常数 c > 0;模拟策略 π_sim;模型 M̂
输出:根节点动作统计 {N(s_root,a), Q(s_root,a)},取 â = argmax_a N(s_root,a)
初始化:树 T ← 仅含根节点 s_root;对所有节点 i 与动作 a:N(i,a) ← 0, W(i,a) ← 0
for k = 1, 2, ..., K do
i ← s_root # ① 选择(Selection)
路径 path ← [ ]
while i 不是叶节点(已在树中且有子节点) do
a ← argmax_a [ Q(i,a) + c*sqrt( ln N(i) / N(i,a) ) ] # 未访问臂优先
path.append((i, a))
i ← M̂.Child(i, a) # 沿树下行;对手方由 π_sim 采样
end while
a ← argmax_a [ Q(i,a) + c*sqrt( ln N(i) / N(i,a) ) ] # ② 扩展(Expansion)
path.append((i, a))
s' ← M̂.Sample(i, a) # 采样后继(滑倒/对手随机性)
在 T 中新建节点 s',初值 N(s',·)=0, W(s',·)=0
③ 评估(Evaluation)
if s' 是终止状态 then v ← R(s') # 终局奖励(+1 / -1)
else v ← V̂(s') # 价值网络/rollout 估计
end if
④ 备份(Backup,折扣传播)
back ← v
for (i, a) in reverse(path) do
N(i, a) ← N(i, a) + 1
W(i, a) ← W(i, a) + back # 等价于累加 γ^d · v
back ← γ · back
end for
end for
return argmax_a N(s_root, a)
算法逻辑解说.
- 为什么备份要带折扣? 这是本讲代码调试中真实踩到的坑。AlphaZero 用 $\gamma=1$ 且中间奖励恒为 0,所以”把叶子价值原样加给所有祖先”是对的。但本讲实验用 $\gamma=0.95$(或 4×4 版的 $0.9$),若不给路径上的边乘 $\gamma^d$,深度 $d$ 的叶子价值会被高估 $\gamma^{-d}$ 倍,根节点 $Q$ 甚至会出现大于 1 的假值(本讲开发中实测到过 $Q=+0.950$ 的异常)。修正后 $Q$ 全部落在合法区间(如 $c=0$ 时根节点”上”臂 $Q=+0.437$)。
- 未访问臂优先:$\ln N(i)/0$ 发散,实现上必须先返回任一 $N(i,a)=0$ 的臂。这保证了每个动作至少被采样一次(”乐观初始化”的树版本,呼应 L11)。
- 终止节点不展开:叶子是终止态时直接取 $R$,不再调用价值网络,否则会污染价值头标签。
数学推导:从 Hoeffding 不等式到 $\sqrt{\ln N/N_a}$. 设某节点 $i$ 的动作 $a$ 的真实期望回报为 $\mu_a$,$N_a$ 次采样回报独立同分布且落在 $[0,1]$(价值归一化后),样本均值 $\bar\mu_a=\frac{1}{N_a}\sum_k G_k$。Hoeffding 不等式给出
\[\Pr\bigl(\bigl\vert \bar\mu_a-\mu_a\bigr\vert \ \ge\ \epsilon\bigr)\ \le\ 2\exp\!\bigl(-2N_a\epsilon^2\bigr).\]令右端 $=\delta$ 并解出 $\epsilon$,得到以 $1-\delta$ 概率成立的置信区间
\[\bigl\vert \bar\mu_a-\mu_a\bigr\vert \ \le\ \sqrt{\frac{\ln(2/\delta)}{2N_a}}.\]关键一步有两层:先对节点上的 $\vert \mathcal A(i)\vert $ 条臂取联合界(union bound),再取时变的 $\delta_a=N(i)^{-4}$。
第一步(联合界):上面那个区间只保证单条臂以 $1-\delta$ 成立。但 UCT 要做 $\arg\max$,只要任意一条臂越界就可能选错,因此必须让所有臂同时成立。对 $\vert \mathcal A(i)\vert $ 条臂取并集:
\[\Pr\Big(\exists a:\ \vert \bar\mu_a-\mu_a\vert \ge\epsilon\Big)\ \le\ \sum_{a\in\mathcal A(i)}\Pr\Big(\vert \bar\mu_a-\mu_a\vert \ge\epsilon\Big)\ \le\ \vert \mathcal A(i)\vert \cdot 2e^{-2N_a\epsilon^2}.\]要让整体失败概率不超过 $\delta$,每条臂只能用 $\delta_{\text{per-arm}}=\delta/\vert \mathcal A(i)\vert $。
第二步(时变 $\delta$):UCB1 取 $\delta_{\text{per-arm}}=N(i)^{-4}$(随该节点总访问数增大而收紧),代入得
\[\epsilon_a=\sqrt{\frac{\ln\bigl(2\vert \mathcal A(i)\vert N(i)^4\bigr)}{2N_a}}=\sqrt{\frac{4\ln N(i)+\ln\bigl(2\vert \mathcal A(i)\vert \bigr)}{2N_a}}\ \approx\ c\sqrt{\frac{\ln N(i)}{N_a}},\]其中 $c=\sqrt{\tfrac{4+\ln(2\vert \mathcal A(i)\vert )/\ln N(i)}{2}}\to\sqrt2$(当 $\ln N(i)\gg\ln\vert \mathcal A(i)\vert $)。注意联合界的唯一影响是把 $\ln 2$ 换成 $\ln(2\vert \mathcal A(i)\vert )$——$c$ 的极限值仍是 $\sqrt2$,但少了联合界这一步,置信度就只对单条臂成立、对 $\arg\max$ 无效。因此 bonus 不是启发式凑出来的,而是”让每条臂的置信区间随访问次数收窄”这一统计要求的直接后果:$N_a$ 越小,区间越宽,上界越高,越值得一试;$N(i)$ 越大,我们对该节点的整体了解越多,就越是敢于收紧所有臂的置信度、把预算压向看起来最好的那条。
与理论的对应. UCB1 在 $K$ 臂静态 bandit 上的期望 regret 为 $O(\sqrt{KA\ln K})$ 量级(L9 已推)。UCT 把这一保证逐层套用:Kocsis & Szepesvári (2006) 证明 UCT 在有限深度 $H$ 的树上,根节点选择的失败概率随模拟数 $K$ 以多项式速度衰减。但必须诚实指出三个弱化条件(这也是讲义第 26 页”略微奇怪”的深层来源):
- UCT 的”臂”分布非平稳——随着搜索推进,”更深层的回报估计”本身在变化(L13 已指出”the policy used to simulate episodes can change across each episode”);
- 对手方引入 min-max 而非单纯 max(讲义第 11 页:”the tree is mimicking a min-max tree”),因此每层不是独立 bandit;
- 要把根节点选对,$H$ 层都要同时选对,失败概率对深度有不利依赖。
14.3.2 算法二:AlphaZero 自我对弈训练闭环
算法 AlphaZero-SelfPlay-Training(f_θ 初始化, 迭代轮数 T, 每轮对局数 G, 模拟数 K)
────────────────────────────────────────────────────────────────────
输入:随机初始化的网络 f_θ(s) = (p_θ(·|s), v_θ(s));超参 T, G, K
输出:训练好的 f_θ
初始化:回放缓冲区 D ← ∅
for t = 1, 2, ..., T do
── 阶段 1:数据生成(用当前网络驱动 MCTS 自我对弈) ──
for g = 1, 2, ..., G do
s₀ ← 随机初始状态(非终止)
traj ← [ ]
for step = 1, 2, ..., H do
if s 是终止状态 then break
(p, v) ← f_θ(s)
运行 MCTS(root = s, 预算 K, 先验 = p, 叶子价值 = v)
π_MCTS ← normalize( N(s,·) ) # 策略标签
traj.append( (s, π_MCTS) )
a ← Sample(π_MCTS) 或 argmax N # 按根策略落子
s ← M̂.Sample(s, a)
end for
z ← +1 if 该局获胜 else -1 # 价值标签(终局结果)
for (s, π_MCTS) in traj do
D ← D ∪ { (s, π_MCTS, z) } # 同一局所有状态共享 z
end for
end for
── 阶段 2:从缓冲区采样,联合更新两个头 ──
for each mini-batch { (s, π_MCTS, z) } ⊂ D do
计算 L(θ) = (z - v_θ(s))² - π_MCTSᵀ log p_θ(·|s) + c_reg‖θ‖²
θ ← θ - α ∇_θ L(θ) # 价值项 + 策略项一起反传
end for
── 阶段 3(可选):门控评估,只有新网络胜率 > 阈值才接受,防退化 ──
end for
return f_θ
算法逻辑解说 / 一轮数据的完整生命周期. 讲义第 12 页的”Self Play a Game”和第 15 页的”Train Neural Network to Predict Policies and Values”之间缺的就是这段流水线。逐步拆:
- 每个真实落子都是一次完整搜索(讲义第 6–11 页的五张图):从根开始 → 反复扩展 → 用网络预测动作概率作为先验 → 到叶子时插入网络的价值预测 → 沿祖先更新 → 重复到叶子的多次循环 → 最后按 $\pi(s)\propto N(s,a)^{1/\tau}$ 得到根策略。注意讲义第 11 页的细节:“inside the network alternating whether opponent or agent is ‘maximizing’ its value. Therefore tree is mimicking a min-max tree.”——同一棵树上交替最大化/最小化,价值符号需要沿博弈方翻转。
- 落子后保留这条记录 $(s,\boldsymbol{\pi}_{\text{MCTS}})$。关键:标签是搜索的访问分布,不是价值网络的原始输出。搜索比网络强,所以这是”蒸馏”一个更强的老师。
- 一局结束后才拿到 $z$。同一局的所有状态共享同一个 $z$(因为 AlphaZero 只使用终局奖励,且用 $\gamma=1$),于是价值头学到的是”从这个局面出发、由自我对弈双方继续走下去的胜率”。
- 两个头一起反传,共享骨干(讲义第 15 页”Train Neural Network to Predict Policies and Values”的图像即 Silver et al. 2017 Fig. 1:网络同时输出 $(\mathbf p, v)$)。
数学推导:为什么 MCTS 目标比网络原始输出更好? 记网络策略为 $\mathbf p_\theta$,MCTS 策略为 $\boldsymbol{\pi}$。由 L13 的策略改进定理,$\boldsymbol{\pi}$ 是在先验 $\mathbf p_\theta$ 引导下对更深层的利用,其期望回报不低于 $\mathbf p_\theta$;再次用策略改进定理,若网络能精确拟合 $\boldsymbol{\pi}$(即 $\mathbf p_{\theta^{\prime}}=\boldsymbol{\pi}$),则下一轮搜索的起点更强,是一个单调改进的迭代。现实中拟合是近似的——本讲 14.4.3 实测的交叉熵 $CE(\boldsymbol{\pi}{\text{MCTS}}\vert \mathbf p\theta)$ 从第 1 轮的 1.3863($=\ln 4$,即完全均匀、毫无信息)单调降到第 8 轮的 0.7238,始终没有降到 0,量化了”线性容量网络装不下搜索分布”这一压缩瓶颈。这恰好是讲义第 17 页评价问题”What is the influence of architecture?”的微观版本:架构容量决定了闭环能以多快速度把搜索成果沉淀进参数。
与 14.2.2 的对应. 伪代码的三阶段与 14.2.2 严格定义中的”数据生成 / 标签构造 / 参数更新”逐条对应;与 L8 的 DPO/RLHF 相比,这里不需要奖励模型,因为胜负本身就是奖励(L8 的”verifiable reward”特例)。
14.3.3 AlphaGo 与 AlphaZero 的差异(讲义第 16–21 页)
讲义第 16 页并列了二者的共同特征(Self Play / Strategic Computation / Highly selective best-first search / Power of Averaging / Local Computation / Learn and Update Heuristics),第 17 页列出三个评价问题:架构的影响、MCTS 的影响、与人类对局的比较(这三问的实证图在 L13 讲义第 28–31 页,由 L13 笔记负责,本讲不重复)。第 21 页还专门问”Need for Human Data?”。把差异整理如下(讲义正文 + Silver et al. 2017):
| 维度 | AlphaGo (2016) | AlphaZero / AlphaGo Zero (2017) |
|---|---|---|
| 人类数据 | 先用 KGS 约 16 万局做行为克隆(监督)初始化 | 完全不用,从随机权重起步 |
| 策略改进方式 | REINFORCE 策略梯度自我对弈 | MCTS 访问分布充当策略目标(本讲 14.3.2) |
| 网络结构 | 策略网络与价值网络参数独立 | 单一网络 $f_\theta=(p,v)$,共享残差骨干双头输出 |
| 叶子评估 | $\frac12 v(s)+\frac12 z_{\text{rollout}}$(价值网络 + 快速 rollout) | 主要依赖 $v_\theta(s)$,rollout 被弃用 |
| 对手建模 | 对手动作从策略网络采样 | 同 |
| 选择规则 | 启发式 UCT 变体 | PUCT(14.2.5) |
| 泛化 | 仅围棋 | 围棋/国际象棋/将棋同一套超参 |
延伸(讲义第 22 页):”These ideas are useful beyond Go. For chess, shogi, other games… For discovering faster matrix multiplication (AlphaTensor)、For discovering faster sorting algorithms (AlphaDev). Beautiful insight: using RL to vastly speed up problems can represent as (extremely large) search problems.”——把”算法发现”重新表述为搜索问题,是这个范式最有价值的迁移。从 AlphaZero 到 MuZero(讲义未展开,SPEC 列为 L14 参考阅读):MuZero 连规则都不给,学习三组函数——表示函数 $h$(观测 → 隐状态)、动力学函数 $g$(隐状态 + 动作 → 下一隐状态 + 即时奖励)、预测函数 $f$(隐状态 → 策略 + 价值),并在隐空间里跑同一套 MCTS;因此它不需要 $M̂$,是”无模型(model-free)外观 + 有模型(model-based)搜索”的混合体。MCTS 在 LLM 推理中的应用(如树搜索 + 过程奖励模型)在 Winter 2026 的 lecture14 中并未出现,本讲按要求略去,只在 14.6 给出前向指引。
14.3.4 伦理客座的论证结构(讲义 ethics_society_234_2.pdf)
伦理部分不是算法,但有清晰的论证骨架,值得以伪代码的形式还原其”决策流程”:
论证框架 对齐到道德:两条路线 + 一个补充
────────────────────────────────────────────────────────────────────
起点(第 2 页回顾):价值对齐 = 设计"做我们真正想要之事"的 AI
├─ 三种旧解读:用户真正 意图 / 偏好 / 利益
└─ 上一讲的案例:谄媚(sycophancy)、智能体式 AI(Agentic AI)
第 1 步(第 3–6 页):补上被遗漏的维度
└─ PEOPLE OTHER THAN THE USER
→ 第四种解读:AI 价值对齐 ⟺ 它做道德上正确的事
→ 但用户仍然重要:当用户所欲在道德上可接受时,仍要对齐到用户
第 2 步(第 7–13 页):自上而下(Top-Down)——显式写下道德原则
├─ 手段:奖赏函数、后处理、硬约束、全局目标
├─ 哲学困难:正确的道德原则是什么?这是道德理论的开放问题
│ · 功利主义:最大化总净幸福 —— 但幸福的分布呢?权利呢?
│ · 常识多元论:多原则并存 —— 冲突时怎么办?例外怎么办?
├─ 工程风险:道德"奖励黑客"(moral reward hacking)
│ —— 错误指定的原则会推荐令人意外的坏行为
└─ 局限:规则集难以覆盖所有情境 / 边界与例外 / 规则互相冲突 /
过度简化 / 难以刻画个体细微差异
第 3 步(第 14–19 页):自下而上(Bottom-Up)——从示例中学习道德
├─ 手段:逆强化学习(IRL)、模仿学习、RLHF
├─ 哲学困难:道德分歧(moral disagreement)—— 谁的示例?
│ · "该不该生成先知穆罕默德的形象?该不该给规避执法的小贴士?"
│ —— 取决于你问谁
│ · 有些分歧来自问题本身太难
├─ 技术困难:罕见/未预见情形
│ · 在真实人类驾驶数据上训练的自驾车,可能从未见过刹车失灵致死场景
│ · 若 AI 错误外推,就出现道德"理解"的鸿沟
├─ 规范困难:代表性(representation)
│ · 个体与文化间的道德分歧;用谁的示例?
│ · 多数派行为可能压倒少数派价值
└─ 局限:反馈分布不均 —— 多数群体更易被代表,
少数/边缘群体被低代表,学到的价值会复制既有社会偏见
第 4 步(第 16–17 页):补充方案——参与式 AI(Participatory AI)
├─ 把"从人类学习"扩展为:多方利益相关者 + 受影响的非用户
│ + 持续输入(而非一次性训练)
└─ 把价值视为:情境化的(contextual)、可争议的(contestable)、
随时间可修订的(revisable)
实践形态:社区顾问委员会、持续用户反馈渠道、部署前公众咨询
关键伦理考量:承认价值会冲突;愿意长期修订系统
第 5 步(第 20 页):结论
├─ 没有银弹能保证完全道德的行为
├─ 但对齐可以更好或更坏;要更好:
│ · 从(几乎)所有人都同意的简单事项开始:不要杀人、通常不要撒谎
│ · 然后尽力捕捉复杂性:
│ 自上而下 —— 认真思考原则、冲突、例外
│ 自下而上 —— 发挥创造力,尽可能训练更多罕见/边界案例
逻辑解说. 这个框架的锋利之处在于两条路线的困难是对偶的:自上而下败于”原则无法穷尽情境”,自下而上败于”示例无法覆盖分布”。前者是规格(specification)问题,后者是数据(distribution)问题。讲义并没有给出统一解,而是把重心放在”承认困难“——第 16 页把价值定义为”可争议、可修订”的,本身就是对”对齐是一次性技术任务”这一假设的否定。这与 RL 的常规直觉形成有生产性的张力:RL 把目标函数当作给定前提,伦理客座恰恰在追问这个前提。
与第一部分(L10 客座)的衔接. 讲义 lecture10post.txt 第 17 页起是 Wanheng Hu 的价值对齐第一部分:Paperclip AI 思想实验(Bostrom 2014)、”从船到路/从娱乐到治疗”的现实案例、以及把问题精确化为”意图 vs 指令 + 背景假设难以形式化”(”Humans work with many background assumptions that are (1) hard to formalize and (2) easy to take for granted”)。本讲只作引用;详细展开留给第 16 讲。
14.4 代码实现与实验分析
本讲共运行 4 个脚本(均只用 numpy / matplotlib / 标准库,自写 GridWorld,无 gym/scipy/torch):
| 脚本 | 内容 | 实测运行时间 |
|---|---|---|
cs234/code/L14_snippet1.py | 代码块一:搜索预算 × 先验质量(4×4) | 约 0.9 s |
cs234/code/L14_snippet2.py | 代码块二:UCT 常数 $c$ 校准(4×4) | 约 1.8 s |
cs234/code/L14_mcts_uct.py | 完整实验:搜索 × 先验、价值网络 × 搜索、两因素分解、$c$ 校准 | 36.8 s |
cs234/code/L14_alphazero_loop.py | AlphaZero 式自我对弈闭环(MCTS 作为策略改进算子) | 12.2 s |
14.4.1 代码块一:搜索预算 × 策略先验质量
"""L14 笔记代码块 1(可独立运行):搜索预算 × 策略先验质量。
只用 numpy + 标准库;4x4 GridWorld;约 1 s。
关键结论:先验越好,搜索起点越高;先验越差,搜索需要更多预算才能补救。
"""
import numpy as np
np.random.seed(0)
G, NS, NA = 4, 16, 4
PITS, GOAL, GAMMA, SLIP = {(1, 1), (2, 2)}, (3, 3), 0.9, 0.1
DIRS = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def rc(s):
return divmod(s, G)
def nxt(s, a):
r, c = rc(s)
dr, dc = DIRS[a]
return max(0, min(G - 1, r + dr)) * G + max(0, min(G - 1, c + dc))
def term(s):
"""返回 (终止奖励, 是否终止)。"""
r, c = rc(s)
if (r, c) == GOAL:
return 1.0, True
if (r, c) in PITS:
return -1.0, True
return 0.0, False
def sample(s, a):
"""滑倒模型:以 SLIP 概率均匀随机走。"""
if np.random.rand() < SLIP:
a = np.random.randint(NA)
return nxt(s, a)
def bellman(s, a, V):
"""Q(s,a) = (1-slip)*后继值 + slip*四方向平均后继值;后继终止则用其奖励。"""
def nv(s2):
tr, t = term(s2)
return tr if t else GAMMA * V[s2]
return (1.0 - SLIP) * nv(nxt(s, a)) + sum(SLIP / NA * nv(nxt(s, b)) for b in range(NA))
# ---- 真值迭代求 V* 与 Q* ----
V = np.zeros(NS)
for _ in range(2000):
Vn = V.copy()
for s in range(NS):
tr, t = term(s)
Vn[s] = tr if t else max(bellman(s, a, V) for a in range(NA))
if np.max(np.abs(Vn - V)) < 1e-13:
V = Vn
break
V = Vn
Q = np.array([[term(s)[0] if term(s)[1] else bellman(s, a, V) for a in range(NA)]
for s in range(NS)])
FREE = [s for s in range(NS) if not term(s)[1]]
def prior(kind, tau=1.0):
"""策略先验:uniform(均匀)/ good(指向目标)/ bad(系统性指错)。"""
P = np.full((NS, NA), 1.0 / NA)
for s in FREE:
d = np.array([abs(rc(nxt(s, a))[0] - GOAL[0]) + abs(rc(nxt(s, a))[1] - GOAL[1])
for a in range(NA)], float)
if kind == "uniform":
z = np.zeros(NA)
elif kind == "good":
z = -d / tau
else:
z = d / tau
e = np.exp(z - z.max())
P[s] = e / e.sum()
return P
class Node:
__slots__ = ("s", "t", "ch", "N", "W", "P")
def __init__(self, s, P):
self.s, self.t = s, term(s)[1]
self.ch, self.N, self.W, self.P = [None] * NA, [0.0] * NA, [0.0] * NA, P
def select(nd, c, mode="puct"):
"""PUCT: argmax_a Q + c*P(s,a)*sqrt(1+sum N)/(1+N(s,a))
UCB1: argmax_a Q + c*sqrt(ln(1+sum N)/N(s,a)) —— 完全忽略先验"""
if mode == "ucb":
for a in range(NA):
if nd.N[a] == 0.0:
return a
tot, ba, bv = sum(nd.N), 0, -1e18
for a in range(NA):
v = nd.W[a] / nd.N[a] + c * np.sqrt(np.log(tot + 1.0) / nd.N[a])
if v > bv:
bv, ba = v, a
return ba
sq, ba, bv = np.sqrt(sum(nd.N) + 1.0), 0, -1e18
for a in range(NA):
n = nd.N[a]
v = (nd.W[a] / n if n else 0.0) + c * nd.P[a] * sq / (1.0 + n)
if v > bv:
bv, ba = v, a
return ba
def mcts(s0, budget, Pt, c=1.5, mode="puct"):
"""一次完整搜索:选择 -> 扩展 -> 叶子评估 -> 折扣备份。"""
root = Node(s0, Pt[s0])
for _ in range(budget):
nd, path = root, []
while not nd.t: # 选择直到未扩展的叶子
a = select(nd, c, mode)
path.append((nd, a))
if nd.ch[a] is None:
s2 = sample(nd.s, a)
nd.ch[a] = Node(s2, Pt[s2]) # 扩展一个新节点
nd = nd.ch[a]
break
nd = nd.ch[a]
back = term(nd.s)[0] if nd.t else V[nd.s] # 叶子评估(用 V* 当完美价值网络)
for n2, a in reversed(path): # 折扣备份(中间奖励为 0)
n2.N[a] += 1.0
n2.W[a] += back
back *= GAMMA
return root
def acc(budget, Pt, mode="puct"):
"""根节点访问最多(AlphaZero 用 argmax N)是否属于 Q* 的最优动作集合。"""
hit = 0
for s in FREE:
a = int(np.argmax(mcts(s, budget, Pt, mode=mode).N))
hit += int(Q[s, a] >= np.max(Q[s]) - 1e-9) # 并列最优也算命中
return hit / len(FREE)
budgets = [1, 5, 20, 100, 500]
print("状态数=%d, 自由状态=%d, V*(s=0)=%.4f, V*(s=%d 目标左侧)=%.4f"
% (NS, len(FREE), V[0], 3 * G + 2, V[3 * G + 2]))
print("| 先验与选择规则 | " + " | ".join("K=%d" % b for b in budgets) + " |")
print("|---|---|---|---|---|---|")
for k in ["uniform", "good", "bad"]:
Pt = prior(k)
print("| PUCT, %-7s | %s |" % (k, " | ".join("%.3f" % acc(b, Pt) for b in budgets)))
Pt = prior("bad")
print("| UCB1, 忽略先验 | %s |"
% " | ".join("%.3f" % acc(b, Pt, mode="ucb") for b in budgets))
代码做什么. 建立一个 4×4 滑倒型 GridWorld(16 状态、4 动作、2 陷阱、1 目标、$\gamma=0.9$、$\varepsilon=0.1$);先用真值迭代算出 $V^$ 与 $Q^$ 作为”标准答案”与”完美价值网络”;再实现三种策略先验(均匀 / 指向目标 / 系统性指错)与一个包含 PUCT/UCB1 两种选择规则的 MCTS;最后对 13 个自由状态各建一棵树,检查”根节点访问次数最多的动作”是否落在 $Q^*$ 的最优动作集合里。
RL 机制透视. 这段代码把 14.2.4 的三个量都做成了可调旋钮:prior(kind) 控制先验质量 $\Delta_{\mathbf p}$,budget 控制模拟次数 $K$,select(mode) 控制”先验是否参与决策”。UCB1 那一行是整个实验的对照组——它完全忽略先验,因此”PUCT+bad 先验”与”UCB1+同一张表”的差距,就是错误先验造成的纯损失。另外 acc 用”属于最优动作集合”而非”等于 argmax“,因为这个环境里根节点”下”与”右”严格并列($Q^*$ 都是 0.4898),用 argmax 会把正确决策误判为错误——这是一个小而真实的实现陷阱。
实验观察(真实输出).
状态数=16, 自由状态=13, V*(s=0)=0.4898, V*(s=14 目标左侧)=0.9399
| 先验与选择规则 | K=1 | K=5 | K=20 | K=100 | K=500 |
|---|---|---|---|---|---|
| PUCT, uniform | 0.000 | 0.077 | 0.769 | 0.692 | 0.769 |
| PUCT, good | 0.769 | 1.000 | 1.000 | 1.000 | 0.846 |
| PUCT, bad | 0.000 | 0.000 | 0.000 | 0.077 | 0.154 |
| UCB1, 忽略先验 | 0.000 | 1.000 | 0.692 | 0.769 | 0.923 |
读法:(1) 先验越好,起点越高——$K=1$ 时 good 先验已达 0.769,而 uniform/bad 都是 0.000,说明”$K=1$ 的搜索几乎等价于直接执行先验”,这与”$\pi\propto N^{1/\tau}$ 且只访问了一个动作”完全一致。(2) 搜索放大先验——good 先验从 0.769 抬到 1.000($K=5,20,100$)。(3) 错误先验需要极大预算才能补救——bad 先验在 $K=100$ 才勉强到 0.077,因为 PUCT 的 bonus 与先验相乘,”先验说不要走的路”几乎拿不到探索机会。(4) 最强证据是最后一行:完全忽略先验的 UCB1,在 $K=5$ 就达到 1.000,在 $K=500$ 达到 0.923——当先验不可信时,关掉先验比留着一个坏先验更好。注意 $K=1,5$ 行数值有噪声(单次随机种子),趋势比个别数值更可靠。
14.4.2 代码块二:UCT 探索常数 $c$ 的经验校准
"""L14 笔记代码块 2(可独立运行):UCT 探索常数 c 的经验校准。
只用 numpy + 标准库;4x4 GridWorld;约 2 s。
展示三件事:
(1) c=0 退化为贪心 -> 锁定到次优动作("过早利用");
(2) c 太大 -> bonus 淹没 Q,访问分布趋于均匀("退化为均匀采样");
(3) bonus 的量纲:U = c*sqrt(ln N / N_a) 必须与 Q 的取值范围同阶,
否则 (2) 或 (1) 必然发生。
"""
import numpy as np
np.random.seed(0)
G, NS, NA = 4, 16, 4
PITS, GOAL, GAMMA, SLIP = {(1, 1), (2, 2)}, (3, 3), 0.9, 0.1
DIRS = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def rc(s):
return divmod(s, G)
def nxt(s, a):
r, c = rc(s)
dr, dc = DIRS[a]
return max(0, min(G - 1, r + dr)) * G + max(0, min(G - 1, c + dc))
def term(s):
r, c = rc(s)
if (r, c) == GOAL:
return 1.0, True
if (r, c) in PITS:
return -1.0, True
return 0.0, False
def sample(s, a):
if np.random.rand() < SLIP:
a = np.random.randint(NA)
return nxt(s, a)
def bellman(s, a, V):
def nv(s2):
tr, t = term(s2)
return tr if t else GAMMA * V[s2]
return (1.0 - SLIP) * nv(nxt(s, a)) + sum(SLIP / NA * nv(nxt(s, b)) for b in range(NA))
V = np.zeros(NS)
for _ in range(2000):
Vn = V.copy()
for s in range(NS):
tr, t = term(s)
Vn[s] = tr if t else max(bellman(s, a, V) for a in range(NA))
if np.max(np.abs(Vn - V)) < 1e-13:
V = Vn
break
V = Vn
Q = np.array([[term(s)[0] if term(s)[1] else bellman(s, a, V) for a in range(NA)]
for s in range(NS)])
FREE = [s for s in range(NS) if not term(s)[1]]
class Node:
__slots__ = ("s", "t", "ch", "N", "W")
def __init__(self, s):
self.s, self.t = s, term(s)[1]
self.ch, self.N, self.W = [None] * NA, [0.0] * NA, [0.0] * NA
def ucb1(nd, c):
"""UCT 选择:未访问动作优先;否则 argmax Q + c*sqrt(ln(1+ΣN)/N_a)。"""
for a in range(NA):
if nd.N[a] == 0.0:
return a
tot, ba, bv = sum(nd.N), 0, -1e18
for a in range(NA):
v = nd.W[a] / nd.N[a] + c * np.sqrt(np.log(tot + 1.0) / nd.N[a])
if v > bv:
bv, ba = v, a
return ba
def mcts(s0, budget, c):
"""均匀先验的 UCT(完全不用策略网络,只靠 UCB1 + 价值网络)。"""
root = Node(s0)
for _ in range(budget):
nd, path = root, []
while not nd.t:
a = ucb1(nd, c)
path.append((nd, a))
if nd.ch[a] is None:
s2 = sample(nd.s, a)
nd.ch[a] = Node(s2)
nd = nd.ch[a]
break
nd = nd.ch[a]
back = term(nd.s)[0] if nd.t else V[nd.s]
for n2, a in reversed(path):
n2.N[a] += 1.0
n2.W[a] += back
back *= GAMMA
return root
def acc(budget, c):
hit = 0
for s in FREE:
a = int(np.argmax(mcts(s, budget, c).N))
hit += int(Q[s, a] >= np.max(Q[s]) - 1e-9) # 并列最优也算命中
return hit / len(FREE)
cs = [0.0, 0.25, 0.5, 1.0, 1.414, 3.0, 8.0]
budgets = [20, 100, 500]
print("=== UCT 常数 c 校准(4x4 GridWorld, 13 个自由状态, 完美价值网络)===")
print("Q* 取值范围 = [%.3f, %.3f],故 bonus 应与该量纲同阶" % (Q.min(), Q.max()))
print("")
print("| c | " + " | ".join("K=%d" % b for b in budgets) + " |")
print("|---|---|---|---|")
for c in cs:
print("| %.3f | %s |" % (c, " | ".join("%.3f" % acc(b, c) for b in budgets)))
print("")
print("根节点 s=0(Q* 下/右并列最优)预算=500 的访问分布与 bonus 分解:")
for c in [0.0, 0.25, 1.414, 8.0]:
r = mcts(0, 500, c)
tot = sum(r.N)
out = []
for a in range(NA):
q = r.W[a] / r.N[a] if r.N[a] else 0.0
u = c * np.sqrt(np.log(tot + 1.0) / r.N[a]) if r.N[a] else float("inf")
out.append("a%d: N=%3d Q=%+.3f U=%.3f" % (a, r.N[a], q, u))
print(" c=%-5.3f | %s" % (c, " | ".join(out)))
print("")
print("注:根节点 s=0 处 Q*[下]=Q*[右]=0.4898 并列最优(朝 (3,3) 目标);")
print(" c=0 会因早期采样噪声锁定次优臂(上或左),c 太大则访问趋于均匀。")
代码做什么. 去掉策略先验,只留 UCB1 bonus(即”纯 UCT”),在 $c\in\{0,0.25,0.5,1,1.414,3,8\}$、预算 $K\in\{20,100,500\}$ 的网格上测决策精度;并在根节点上把每条边的 $\mathrm{UCT}=Q+U$ 两项分别打印,直观展示 bonus 的绝对量级如何随 $c$ 变化。
RL 机制透视. 这段代码是 14.2.1 与 14.2.6 的数值化。$c=0$ 时 $\mathrm{UCT}=Q$,退化成对 $Q$ 估计的贪婪——而 $Q$ 是极少数样本的均值,方差极大,一旦早期噪声抬高某条次优臂,探索项为零就再也无法纠正。$c$ 很大时 bonus 主导,$U$ 从 $0.03$ 量级涨到 $1.7\sim2.0$ 量级,超过 $Q$ 的整个取值范围 $[-1,1]$,选择变得与 $Q$ 无关、近似均匀轮转。有效 $c$ 的存在区间由”$U$ 与 $Q$ 同阶”这一量纲条件决定——这正是 Hoeffding 推导中 $c$ 只是一个常数倍数的原因,它不该被赋予”越大越探索”的独立含义。
实验观察(真实输出).
=== UCT 常数 c 校准(4x4 GridWorld, 13 个自由状态, 完美价值网络)===
Q* 取值范围 = [-1.000, 1.000],故 bonus 应与该量纲同阶
| c | K=20 | K=100 | K=500 |
|---|---|---|---|
| 0.000 | 0.462 | 0.538 | 0.462 |
| 0.250 | 0.846 | 0.538 | 0.692 |
| 0.500 | 0.692 | 0.538 | 0.923 |
| 1.000 | 0.615 | 0.769 | 0.846 |
| 1.414 | 0.538 | 0.385 | 0.923 |
| 3.000 | 0.538 | 0.615 | 0.538 |
| 8.000 | 0.462 | 0.538 | 0.538 |
根节点 s=0(Q* 下/右并列最优)预算=500 的访问分布与 bonus 分解:
c=0.000 | a0: N= 11 Q=+0.232 U=0.000 | a1: N= 2 Q=-0.176 U=0.000 | a2: N=484 Q=+0.279 U=0.000 | a3: N= 3 Q=+0.046 U=0.000
c=0.250 | a0: N= 22 Q=+0.207 U=0.133 | a1: N= 33 Q=+0.239 U=0.109 | a2: N= 34 Q=+0.243 U=0.107 | a3: N=411 Q=+0.329 U=0.031
c=1.414 | a0: N=127 Q=+0.300 U=0.313 | a1: N=131 Q=+0.299 U=0.308 | a2: N=123 Q=+0.296 U=0.318 | a3: N=119 Q=+0.289 U=0.323
c=8.000 | a0: N=139 Q=+0.189 U=1.692 | a1: N=123 Q=+0.089 U=1.799 | a2: N=140 Q=+0.194 U=1.686 | a3: N= 98 Q=-0.128 U=2.015
读法:(1) 精度表呈倒 U 型——$c=0$ 与 $c=8$ 最差(0.462/0.538),中间区间($c=0.25\sim1.414$)明显更好,这是 14.2.1 预测的两难。(2) bonus 分解是最有说服力的一栏:$c=0$ 时 $N=[11,2,484,3]$——484 次模拟投入 a2(”左”,次优方向)而最优的 a1/a3 只有 2/3 次,纯贪婪被早期噪声欺骗;$c=0.25$ 时 a3(”右”,最优之一)获 411 次;$c=8$ 时四条臂的 $U$ 都在 $1.7\sim2.0$,访问退化为近似均匀 $[139,123,140,98]$。(3) 单点数值仍有噪声($K=100$ 列不单调),这本身就是提醒:$c$ 的”最佳值”不是稳定常数,而依赖 $Q$ 的尺度与预算——工程上通常取 $c\approx1\sim2$ 并把 $Q$ 归一化到 $[0,1]$。
14.4.3 实验三:AlphaZero 式自我对弈闭环(MCTS 作为策略改进算子)
脚本 L14_alphazero_loop.py 在 6×6 GridWorld 上跑 8 轮闭环,函数逼近器刻意做得容量有限(策略头 10 维线性 softmax、价值头 6 维线性回归),并在每轮先测量再训练,因此测得的交叉熵是”上一轮的网络”对”本轮新产生的搜索分布”的拟合误差。
实验观察(真实输出).
| 迭代 | 训练样本 | CE(π_MCTS‖π_θ) | 原始策略胜率 | MCTS(40)胜率 | MCTS(200)胜率 |
|---|---|---|---|---|---|
| 1 | 128 | 1.3863 | 0.000 | 0.452 | 0.452 |
| 2 | 87 | 1.3793 | 0.065 | 0.484 | — |
| 3 | 52 | 1.2747 | 0.129 | 0.968 | — |
| 4 | 47 | 1.1125 | 0.581 | 0.935 | 0.871 |
| 5 | 43 | 0.9468 | 0.742 | 1.000 | — |
| 6 | 43 | 0.8453 | 0.677 | 0.903 | — |
| 7 | 33 | 0.8008 | 0.710 | 0.968 | — |
| 8 | 41 | 0.7238 | 0.806 | 0.968 | 0.968 |
根节点 s=0(最优动作 = 右)的分布对比(末轮训练后的网络)
π_θ(prior) = [0.11 0.286 0.004 0.6 ]
π_MCTS(N/ΣN) = [0.022 0.051 0. 0.926 ]
消融:策略头置零(均匀先验)+ 价值头置零,仅靠 MCTS 搜索
均匀先验原始策略(不搜索)胜率 = 0.000
均匀先验 + 零价值 + MCTS(200) 胜率 = 0.581
均匀先验 + 零价值 + MCTS(1000) 胜率 = 0.774
对照:AlphaZero 式学到的网络 + 不同搜索预算
MCTS(1 ) 胜率 = 0.806
MCTS(40 ) 胜率 = 0.839
MCTS(200 ) 胜率 = 0.903
三段评注:代码做什么——实现 14.3.2 的完整三阶段流水线(自我对弈生成 $(\mathbf{p},v)$ 标签 → 联合反传 → 再对弈),并额外测三个量:原始策略胜率、$K=40$ 的 MCTS 胜率、搜索目标与网络的交叉熵。RL 机制透视——这张表把”搜索即策略改进算子”从口号变成曲线:原始策略胜率 $0.000\to0.806$(8 轮)说明搜索成果确实沉淀进了参数;每轮的 MCTS 胜率都高于同轮原始策略(第 5 轮 $1.000$ vs $0.742$,第 8 轮 $0.968$ vs $0.806$),说明搜索始终比它所蒸馏出的学生强,这正是闭环能持续改进的前提(若学生反超老师,改进就停止了)。根节点分布对比给出最直观的一幕:网络先验把 0.600 的权重给”右”,而搜索把 0.926 给它——搜索放大了先验的正确倾向。实验观察——(1) 交叉熵从 $1.3863=\ln 4$(均匀)单调降到 0.7238 但永不归零,这是”线性容量是压缩瓶颈”的直接量化,也是讲义第 17 页”架构影响”问题的微观对应;(2) 消融最有力:把两个头全部置零(无先验、无价值)后,同样 $K=200$ 的预算胜率只有 0.581,而学到的网络在 $K=200$ 时达 0.903——同一预算下网络带来 $+0.32$ 的增益;即便把无先验的预算加大 5 倍到 $K=1000$,也只到 0.774,仍低于网络在 $K=200$ 的成绩——加预算救不回缺先验的损失;(3) 对照行还显示”学好的网络 + $K=1$”已有 0.806,说明闭环的成果主要存在参数里,搜索是增量放大器而非唯一来源(与 L13 的影响分析结论方向一致)。
14.4.4 实验二补充:价值网络质量 × 搜索预算的两因素分解
脚本 L14_mcts_uct.py 用一个 6×6 GridWorld(31 个自由状态、4 陷阱、$\gamma=0.95$、$\varepsilon=0.1$,$V^(s_0)=0.5225$)把”架构”与”搜索”两个因子交叉。价值网络质量用四档模拟:zero(不用价值网络,即 AlphaGo Zero 消融)、weak(压缩 + 偏置 + 强噪声,MSE $0.3892$/corr $0.537$)、medium(MSE $0.0672$/corr $0.902$)、exact($=$ $V^$,MSE $0.0000$/corr $1.000$)。对随机实现取 5 个种子平均:
| 价值网络 | K=1 | K=5 | K=20 | K=100 | K=500 | $\Delta$acc(500−1) |
|---|---|---|---|---|---|---|
zero(无) | 0.000 | 0.129 | 0.394 | 0.503 | 0.645 | +0.645 |
weak(弱) | 0.000 | 0.258 | 0.381 | 0.387 | 0.465 | +0.465 |
medium(中) | 0.000 | 0.174 | 0.381 | 0.497 | 0.497 | +0.497 |
exact(精确) | 0.000 | 0.097 | 0.594 | 0.587 | 0.645 | +0.645 |
两因素分解(预算固定 $K=100$,5 种子平均)与”坏先验能否被 $c$ 补救”:
| 先验 / 价值网络 | $K=100$ 精度 | 坏先验 + 增大 $c$ | 精度 | 后悔 | |
|---|---|---|---|---|---|
uniform / zero | 0.548 | $c=1.5$ | 0.129 | 0.1177 | |
uniform / weak | 0.490 | $c=4.0$ | 0.097 | 0.1155 | |
uniform / exact | 0.568 | $c=8.0$ | 0.032 | 0.1378 | |
good / zero | 0.871 | $c=16.0$ | 0.000 | 0.1307 | |
good / weak | 0.800 | PUCT good+exact $K=100$ | 0.806 | 0.0574 | |
good / exact | 0.871 | PUCT good+exact $K=20$ | 0.871 | 0.0039 |
实验观察. (1) 先验的质量远比价值网络的质量重要:同一预算下,先验从 uniform 换到 good 带来 $0.548\to0.871$(+0.32),而价值网络从 zero 换到 exact 只带来 $0.548\to0.568$(+0.02)。这与 PUCT 的结构一致——先验直接进入选择规则,而价值网络只影响叶子评估。(2) 搜索与网络高度可替代但有上限:zero(完全没有价值网络)在 $K=500$ 时达到 0.645,与 exact 的 0.645 相同;但 weak 在 $K=500$ 只有 0.465,反而低于 zero(0.645)——一个”半对半错”的价值网络比没有价值网络更糟,因为它的系统性偏差会持续误导备份,而 zero 至少是中性无偏的。这是”架构影响”最反直觉的一条实证。(3) 错误先验无法靠增大 $c$ 补救:$c$ 从 1.5 增到 16.0,精度从 0.129 单调降到 0.000,后悔从 0.1177 升到 0.1307。原因是 PUCT 的 bonus 与 $P_\theta$ 相乘,调大 $c$ 会让”先验推荐的路”获得更多访问,等于更用力地朝错误方向探索。(4) PUCT 的预算效应并不单调:$K=20$ 时「PUCT+good+exact」精度 $0.871$、后悔 $0.0039$;但 $K=100$ 时精度回落到 $0.806$、后悔升到 $0.0574$;$K=500$ 时精度仍为 $0.806$、后悔回到 $0.0064$。即盲目增大预算并不能拯救被先验带偏的搜索——$K=100$ 的 PUCT($0.806$)反而输给同预算的 good+exact($0.871$)。AlphaZero 的真正配方不是「更多模拟」,而是先验、价值网络与预算三者的匹配:先验负责定向、价值网络负责精修、预算负责覆盖长尾,任一环节不匹配都会让另外两者的收益被吃掉。
14.4.5 讲义的 Check Your Understanding 全部答案(讲义第 24–30 页)
题 1(第 24–25 页):MCTS 适用于哪些 MDP? 官方答案 F F T。逐条:
- “短时域 + 少量状态与动作” → False。这种情形下直接用真值迭代/策略迭代精确求解整个 MDP 更划算;MCTS 只需为当前状态做局部计算,其价值恰恰在于状态多到无法枚举。
- “长时域 + 大动作空间 + 小状态空间” → False。状态空间小意味着可以表格化精确规划;此时 MCTS 要在每个节点上从巨大的 $\mathcal A$ 里挑臂,采样效率反而低。
- “长时域 + 大状态空间 + 小动作空间” → True。这正是 MCTS 的甜蜜点:用采样打破状态维度的维数灾难,而分支因子小到可以在每个节点上做可信的 bandit 估计。
诚实的补充:围棋是大状态空间且大动作空间(361),按上述判据本不该适合 MCTS——AlphaGo 之所以能行,靠的正是 PUCT 的先验门控(14.2.5),把大 $\mathcal A$ 收窄成”网络看好的少数分支”。也就是说,判断题考的是”纯 UCT”的适用性,而 AlphaZero 的成功属于”UCT + 强先验”的扩展。
题 2(第 26–28 页):UCT 为什么”略微奇怪”? 答案见 14.2.6:UCB 在真实环境中用于应对”探索有机会成本 + 分布未知”;在模拟回合中回报来自已知模型、可无限重采样,真正被分配的资源是算力而非环境奖励,因此这里的 regret 最小化是元层推理(metalevel reasoning),与外部探索/利用只在形式上同源。
题 3(第 27–28 页):关于 UCT 的两个陈述。 官方答案 T, T。
- “This may be useful since it will prioritize actions that lead to later good rewards” → True(bonus 让有潜力的分支获得更多模拟,从而被更准确地估计)。
- “UCB minimizes regret. UCT is minimizing regret within rollouts of the tree.” → True,但讲义特意追问”if this is true, think about if this a good idea?”——这是一个好问题而非好消息:被最小化的 regret 是内部量,它与外部表现的关系并不由 UCB 理论保证。
题 4(第 29–30 页):Refresh Your Understanding。
- “上置信界用于平衡探索与利用已有信息以获得高回报” → True。
- “这些算法可用于 bandit 与 MDP” → True(L9–L13 已分别建立)。
- “若奖励模型已知,使用上置信界算法就没有收益” → Depends on setting。讲义原文答案:”In bandits, no additional gain. In RL, if the dynamics model is not known, there will be a gain.”——即奖励已知 ≠ 动力学已知:bandit 里”已知奖励”就等于问题已解,但 MDP 里转移未知时仍需探索。
14.5 评估指标与理论保证
评估指标. MCTS/AlphaZero 类系统的评估是多层级的,本讲实验覆盖了前三层:
| 层级 | 指标 | 本讲实测(来源) | 说明 |
|---|---|---|---|
| 单步决策 | 根节点精度、Q* 后悔 $\max_a Q^(s,a)-Q^(s,\hat a)$ | 0.000→0.903 精度 / 0.279→0.003 后悔(14.4.1、14.4.4) | 最小粒度,可直接对照 $Q^*$ |
| 整局表现 | 抵达目标频率(本讲)/ Elo 或胜率(围棋) | 0.000→0.968(§A 整局到达率表) | 受随机性影响大,需配对起点降方差 |
| 训练闭环 | $CE(\pi_{\text{MCTS}}\vert \pi_\theta)$、自我对弈迭代曲线 | 1.3863→0.7238(14.4.3) | 衡量”搜索成果能否沉淀进参数” |
| 对抗强度 | Elo(L13 影响分析负责) | — | 需要外部对手池,成本高 |
计算复杂度. 单次模拟的代价:选择阶段 $O(H\cdot A)$($H$ 为树深,$A$ 为分支因子),扩展 $O(1)$,叶子评估 $O(C_{\text{net}})$(一次前向传播),备份 $O(H)$。故 $K$ 次模拟总计 $O\bigl(K(H A + C_{\text{net}})\bigr)$。关键对比:完全 expectimax 树的规模是
\[\bigl(\vert \mathcal S\vert \vert \mathcal A\vert \bigr)^{H}\quad\text{(L13 讲义第 9 页)}\ \longrightarrow\ \text{MCTS 用 } O(KH)\ \text{个节点替代},\]这是”用采样打破维数灾难”的精确含义:代价从指数变为线性于 $K$,代价是放弃最优性保证、只求渐进最优。
理论保证(必须写明形式).
- UCB1(单层,L9):$K$ 臂、回报有界时,期望 regret $R_K=\mu^*K-\sum_k\mu_{a_k}=O\bigl(\sqrt{KA\ln K}\bigr)$。这是 UCT bonus 的理论来源(14.3.1 的 Hoeffding 推导)。
- UCT(树上,Kocsis & Szepesvári 2006):在有限深度 $H$ 的树中,根节点选择的失败概率随模拟数 $K$ 以多项式速率衰减;但对深度 $H$ 有不利依赖(需 $H$ 层同时正确),且由于对手使问题变为 min-max,逐层 bandit 的独立性假设被破坏。
- 策略改进(L13 + 本讲 14.4.3):若 $Q$ 无偏,$\pi^{\prime}(s)=\arg\max_a Q^\pi(s,a)$ 满足 $V^{\pi^{\prime}}(s)\ge V^\pi(s)$;AlphaZero 的闭环在此基础上追加一步”近似蒸馏”,近似误差由网络容量决定(实测 CE 不归零)。
条件依赖分析(何时上述保证失效).
- 探索常数:如 14.4.2 所示,$c$ 偏离 $Q$ 的量纲区间即失效;$c$ 与回报尺度、预算耦合。
- 先验质量:14.4.1 显示坏先验使 $K=100$ 的精度仅 0.077;14.4.4 显示调大 $c$ 不能补救,反而更糟。
- 价值估计偏差:14.4.4 显示
weak网络在 $K=500$ 时(0.465)反而低于完全不用价值网络的zero(0.645)——系统性偏差比无信息更有害。 - 模型正确性:本讲环境是给定模型($P$ 已知);若用学到的模型(MuZero 路线),模型误差会像 L13 的”black-box model”讨论那样传导至搜索。
- 在线/离线:MCTS 是在线的(为当前状态现算);AlphaZero 的参数训练依赖离线重放缓冲区,缓冲区陈旧会导致分布漂移。
- 伦理层面的”条件依赖”:即便以上全部满足,系统也只保证”优化了被写下的目标”,不保证目标写对了(14.3.4 与 14.8 的伦理讨论)。
14.6 与其他讲次的关联
向后(本讲在用什么).
- L2:真值迭代/策略迭代给出 $V^,Q^$,是本讲所有实验的”标准答案”,也是”小状态空间下不该用 MCTS”(14.4.5 判断题 1)的依据。
- L9–L11:UCB1、乐观初始化、regret 界。UCT 的 bonus 是 UCB1 在树上的逐节点套用;”未访问臂优先”是乐观初始化的树版本。
- L13(强关联):本讲的直接前置。L13 提供 MCTS 四阶段(选择/扩展/评估/备份)、expectimax 的 $(\vert \mathcal S\vert \vert \mathcal A\vert )^H$ 规模、”1 步策略改进”、self-play 优势、以及 AlphaGo/AlphaZero 影响分析(架构影响 / MCTS 影响 / 总体表现 / 人类数据需求)的实证图。本讲不重复影响分析,而是补上 L13 未展开的两块:(i) self-play 数据如何变成训练信号的完整回路(14.3.2);(ii) UCT 的 Hoeffding 论证与 $c$ 校准(14.2.1、14.3.1、14.4.2)。
- L10 客座(价值对齐第一部分):Paperclip AI 思想实验、”从船到路/从娱乐到治疗”、意图 vs 指令。本讲仅引用,详细内容归 L16。
- L5–L8:策略梯度/RF/DPO/RFHF 提供了回报建模与偏好学习工具,是伦理部分”自下而上”路线(IRL、模仿学习、RLHF)的技术底座。
向前(本讲被谁用).
- L15(Shane Gu, World of World Modeling):世界模型正是 MuZero 式”学习隐式动力学”的一般化;本讲 14.3.3 的 MuZero 小节点到为止。
- L16(Wanheng Hu 客座 + 讨论):本讲伦理部分的完整版,包含奖励黑客、偏好聚合(
L16_preference_aggregation.png)、奖励黑客实验(L16_reward_hacking.png)等技术化展开。 - 课程项目:AlphaZero 范式是”搜索 + 学习”类项目的标准模板;14.4.3 的容量瓶颈实验可直接作为”架构消融”的报告素材。
- Quiz(W9 周三 Mar 4)与 Poster Session(W10 周三 Mar 11):本讲第 24–30 页的 CYU 就是 Quiz 复习材料。
14.7 关键要点
- 搜索是策略改进算子,不是策略本身。 $\pi_{\text{MCTS}}(a\vert s)\propto N(s,a)^{1/\tau}$ 只在当前状态上改进策略,参数不动;把它蒸馏进网络才形成可持续的闭环(14.3.2、14.4.3)。
- 自我对弈的闭环 = 老师(搜索)教学生(网络),学生反哺老师。 老师比学生强是闭环持续的前提(实测每轮 MCTS 胜率都高于同轮原始策略);学生受容量限制永远追不上老师(实测 CE 从 1.3863 只降到 0.7238)。
- 搜索放大先验:好先验用极少预算就能见效,坏先验可能永远救不回来。 $K=1$ 时 good 先验精度 0.769、bad 先验 0.000;$K=100$ 时 bad 仅 0.077。先验质量比价值网络质量重要得多(+0.32 vs +0.02,14.4.4)。
- UCT 的 bonus 有严格来源:$\sqrt{\ln N/N_a}$ 是 Hoeffding 置信区间先对 $\vert \mathcal A\vert $ 条臂取联合界、再令 $\delta=N^{-4}$ 后的展开。 $c$ 只是常数倍数,必须与 $Q$ 的量纲同阶;$c\to0$ 退化为贪婪并锁定次优臂,$c\to\infty$ 退化为均匀采样(14.3.1、14.4.2)。
- “UCT 最小化的是内部 regret”,这是元层推理。 模拟中探索的成本是算力而非环境后悔,因此 UCB 的外部最优性保证不能直接搬到树上(14.2.6、14.4.5 题 3)。
- 对齐的”我们”不等于”用户”。 个人层面完全对齐的行为可以在集体层面制造价格尖峰与不平等(讲义第 7 页购票场景);自上而下与自下而上各有对偶的困难——前者败于规格无法穷尽,后者败于数据分布不均(14.3.4)。
- 没有银弹。 讲义结论:从几乎所有人同意的简单原则起步(不杀人、通常不撒谎),再尽力捕捉复杂性——自上而下认真思考冲突与例外,自下而上尽可能覆盖罕见/边界案例。
14.8 常见误区与注意事项
误区 1:以为”搜索次数越多一定越好”。 错。6×6 主实验(14.2.4 表)中 uniform 先验的精度在 $K=100$ 是 0.613、$K=500$ 反降到 0.548;14.4.4 中 weak 价值网络在 $K=500$ 是 0.465,低于 zero 的 0.645。正确认识:搜索是放大器,它放大先验与价值估计中的信息,也放大其中的偏差;可用预算必须与”先验质量、价值偏差、$c$ 的量纲”一起调整,不存在单调的”多算必胜”。
误区 2:以为 UCT 的探索常数 $c$ 就是”探索强度旋钮”,越大越爱探索、越保险。 错。14.4.4 实测:坏先验下 $c$ 从 1.5 增到 16.0,精度从 0.129 单调降到 0.000。因为 PUCT 的 bonus 与 $P_\theta$ 相乘,调大 $c$ 等于更用力地朝先验指的方向探索。正确认识:$c$ 由 Hoeffding 推导决定,其作用是”让置信区间宽度与 $Q$ 同阶”;调参前应先归一化 $Q$ 的取值范围(工程惯例 $c\approx1\sim2$、$Q\in[0,1]$),并且先修先验,再调 $c$。
误区 3:把 UCT 的”UCB 保证”直接当作 MCTS 的最优性保证。 错。讲义第 27–28 页的 CYU 答案是 True(UCT 确实在最小化 rollout 内的 regret),但紧接着追问”think about if this is a good idea?”。正确认识:UCT 逐层套用 bandit,但 (i) 各层的回报分布非平稳、(ii) 对手使结构变为 min-max、(iii) 要在 $H$ 层同时正确才能选对根动作,因此其保证弱于单层 UCB1,只在 $K\to\infty$ 时收敛到 minimax 最优。它是一个元层推理规则(14.2.6),不是外部最优性定理。
误区 4:认为”奖励模型/动力学模型已知时,就不需要上置信界了”。 不完整。讲义第 30 页的官方答案是”Depends on setting:In bandits, no additional gain. In RL, if the dynamics model is not known, there will be a gain.” 正确认识:要把”奖励已知”和”动力学已知”分开看——reward model 已知而 transition 未知时,探索仍然必要(这正是 L11–L12 乐观初始化/RMax 的立足点)。
误区 5:用 argmax 判定”决策是否正确”,忽略并列最优。 这是本讲开发中真实踩到的实现陷阱。4×4 环境根节点处 $Q^[\text{下}]=Q^[\text{右}]=0.4898$ 严格并列,若用 int(argmax(Q[s])) == a 判定,任何正确选择”右”的搜索都会被记为错误,导致精度被系统性低估。正确认识:评估树搜索时要用最优动作集合判定(本讲代码用 Q[s,a] >= max(Q[s]) - 1e-9),否则得到的曲线会掺入纯粹由并列打破规则造成的噪声。
误区 6:在折扣环境里备份时忘记沿路径折扣。 错。AlphaZero 用 $\gamma=1$ 且只有终局奖励,所以”叶子价值原样加到所有祖先”是对的;但若像本讲实验那样取 $\gamma=0.95$,必须按路径深度乘 $\gamma^d$,否则深度 $d$ 的叶子价值被高估 $\gamma^{-d}$ 倍——开发中曾实测到根节点 $Q=+0.950$ 这种越界假值。正确认识:备份公式是 $W(s,a)\mathrel{+}=\gamma^{d}v$,$d$ 为该边到叶子的步数;这条 bug 会让搜索偏好”看起来深的假高价值”分支,且不会报错,只会静默降低性能。
误区 7:把 AlphaZero 的”不用人类数据”理解为”模仿学习没用”。 错。讲义第 21 页专门问”Need for Human Data?”。正确认识:在围棋这种规则完备、模拟成本极低的领域,人类先验反而可能限制搜索(AlphaGo Zero 击败原版 100–0)。但在探索昂贵或危险的领域(例如手术机器人),从人类示范初始化仍然不可替代——”是否用人类数据”取决于能否安全地大量试错,而不是取决于范式的新旧。
误区 8:把”价值对齐”等同于”让用户满意”。 错。讲义第 4–6 页的全部要点是补上”PEOPLE OTHER THAN THE USER”:用户的意图、偏好、利益都可能对他人有害;Paperclip AI 的失败不是没满足工厂主,而是”对所有人都坏”。正确认识:对齐到用户是必要条件而非充分条件——在用户所欲道德可接受时仍应对齐到用户,但判据必须放进更大的伦理框架。进一步地,讲义第 7 页的智能体购票场景说明:即使每个智能体都完美对齐了各自的用户,均衡结果仍可能是坏的(价格尖峰、不平等)——这是集体行动问题,不是个体对齐问题。
误区 9:以为伦理问题可以留给”更强的技术”在未来解决。 与讲义立场不符。讲义第 20 页的结论是”No silver bullet“,并把价值定义为”可争议的、随时间可修订的”(第 16 页),第 17 页要求”Willingness to revise systems over time”。正确认识:对齐不是一个有终点的技术任务,而是一个需要持续制度安排(社区顾问委员会、持续反馈渠道、部署前公众咨询)的过程;把它当作一次性工程问题本身就是讲义要纠正的假设。
14.9 思考题(带答案)
思考题 1(技术计算题):用 Hoeffding 不等式推导 UCT 的 bonus,并检验 $c$ 的量纲
题目. 某 MCTS 节点 $i$ 上,动作 $a$ 的真实期望回报 $\mu_a\in[0,1]$,已采样 $N_a$ 次的样本均值记为 $\bar\mu_a$。 (a) 用 Hoeffding 不等式写出 $\vert \bar\mu_a-\mu_a\vert \le\epsilon$ 以概率 $1-\delta$ 成立所需的 $\epsilon$; (b) 取 $\delta=N(i)^{-4}$($N(i)$ 为该节点总访问数),证明 bonus 形如 $c\sqrt{\ln N(i)/N_a}$,并给出 $c$ 的表达式; (c) 若价值被归一化到 $[-1,1]$ 而非 $[0,1]$,$c$ 应如何调整?用本讲 14.4.2 的实测数据说明”不调整会怎样”; (d) 取 $N(i)=500$、$N_a=1$、$c=1.414$,算出 bonus 值;再用 14.4.2 输出中 $c=1.414$ 那一行的实际 $U$ 值核对量级。
答案. (a) Hoeffding:$\Pr(\vert \bar\mu_a-\mu_a\vert \ge\epsilon)\le 2e^{-2N_a\epsilon^2}$。令 $2e^{-2N_a\epsilon^2}=\delta$,解得 \(\epsilon=\sqrt{\frac{\ln(2/\delta)}{2N_a}}.\)
(b) 先做联合界:区间式只对单条臂成立,而 $\arg\max$ 要求所有 $\vert \mathcal A(i)\vert $ 条臂同时可信,故每条臂的允许失败概率须收紧为 $\delta_{\text{per-arm}}=\delta/\vert \mathcal A(i)\vert $。代入 $\delta=N(i)^{-4}$: \(\epsilon=\sqrt{\frac{\ln\bigl(2\vert \mathcal A(i)\vert N(i)^{4}\bigr)}{2N_a}}=\sqrt{\frac{4\ln N(i)+\ln\bigl(2\vert \mathcal A(i)\vert \bigr)}{2N_a}}=\underbrace{\sqrt{\frac{4+\ln\bigl(2\vert \mathcal A(i)\vert \bigr)/\ln N(i)}{2}}}_{\text{随 }N(i)\text{ 缓变}}\cdot\sqrt{\frac{\ln N(i)}{N_a}}\ \approx\ c\sqrt{\frac{\ln N(i)}{N_a}},\) 即 $c\to\sqrt{2}$(当 $\ln N(i)\gg\ln\vert \mathcal A(i)\vert $ 时)。联合界只把 $\ln 2$ 换成 $\ln(2\vert \mathcal A(i)\vert )$,不改变 $c$ 的极限值——这也解释了工程惯例 $c\approx1.414$。
(c) $[-1,1]$ 的回报极差是 $[0,1]$ 的 2 倍。Hoeffding 需要把回报平移缩放到 $[0,1]$:令 $\tilde G=(G+1)/2\in[0,1]$,则对 $G$ 的误差是 $\tilde G$ 误差的 2 倍,故 $c$ 应放大到约 $2\sqrt2\approx2.83$。本讲 14.4.2 的数据正好是反例:环境里 $Q^*\in[-1,1]$,但代码仍用 $c=1.414$,结果该行的 bonus 只有 $U\approx0.31$,与 $Q\approx0.30$ 恰好同阶——碰巧可用;而 $c=0.25$ 时 $U\approx0.03\sim0.13$ 远小于 $Q$,探索不足,$c=8$ 时 $U\approx1.7\sim2.0$ 超过整个 $Q$ 值域,探索过剩。可见 $c$ 的”正确值”取决于 $Q$ 的尺度,不能照搬。
(d) $\sqrt{\ln 501/1}=\sqrt{6.2166}=2.4933$,$U=1.414\times2.4933=\mathbf{3.53}$。但实测 $c=1.414$ 行的 $U$ 只有 $0.308\sim0.323$。差异的原因是:$N_a$ 在根节点不是 1(实测各臂 $N_a\approx119\sim131$),代 $N_a=128$:$\sqrt{\ln 501/128}=\sqrt{0.04857}=0.2204$,$U=1.414\times0.2204=\mathbf{0.312}$,与实测 0.31 吻合。这个核对本身就是一条教训:bonus 值必须用该臂的实际访问次数算,不能用”$N_a=1$”的直觉估计。
思考题 2(技术计算题):为什么”坏先验 + 大预算”救不回来?
题目. 本讲 14.4.1 实测:6×6 环境下 bad 先验(系统性指错方向)在 $K=1,5,20$ 的精度全部为 0.000,$K=100$ 才 0.161、$K=500$ 仅 0.258;而”完全忽略先验的 UCB1”在 $K=5$ 就到 1.000。请用 PUCT 选择公式解释这个不对称,并回答:把 $c_{\text{puct}}$ 从 1.5 调到 8.0 或 16.0 能否补救?用 14.4.4 的实测数据支持你的结论。
答案. PUCT 的选择分数为 \(\mathrm{score}(a)=Q(s,a)+c_{\text{puct}}\,P_\theta(a\vert s)\,\frac{\sqrt{\textstyle\sum_{a^{\prime}}N(s,a^{\prime})}}{1+N(s,a)}.\) 关键在 bonus 是乘性的:它正比于 $P_\theta(a\vert s)$。若先验把某个次优动作 $a_{\text{bad}}$ 的概率推到很高、把最优动作 $a^$ 的概率压到很低,那么 (i) $a_{\text{bad}}$ 一开始就被反复访问,其 $Q$ 估计很快收敛到”该动作真实价值”——这个值确实低;(ii) 但因为先验已把 $a^$ 的 bonus 压得很小,$a^$ 几乎拿不到访问机会,其 $Q$ 永远停留在初始值 0(或极少样本的噪声值)。于是 $Q(a^){\text{估计}}\approx0<Q(a{\text{bad}})_{\text{真实}}$,搜索无法”发现”自己的错误——先验的错误被 Q 的缺失固化下来。这正是实测 bad 先验在 $K=20$ 仍为 0.000 的机制。
增大 $c_{\text{puct}}$ 不能补救,反而更糟。因为 bonus 仍然乘着 $P_\theta$,调大 $c$ 只会让”先验推荐的路”获得更多访问,等于更用力地朝错误方向探索。14.4.4 的实测证实这一点:坏先验下 $c=1.5$ 精度 0.129,$c=4.0$ 降到 0.097,$c=8.0$ 降到 0.032,$c=16.0$ 降到 0.000,后悔相应从 0.1177 升到 0.1307(单调恶化)。
正确的补救方向有三条:(1) 用不乘先验的选择规则——实测同环境同预算下纯 UCB1 在 $K=5$ 达 1.000,说明”先验不可信时关掉先验”是有效的;(2) 给先验做温度平滑或加均匀混合下限(如 $P\leftarrow(1-\alpha)P+\alpha/A$),保证每个动作都有基础探索概率;(3) 从源头修先验(更多训练/更好架构)——这与 14.4.4 的结论一致:先验质量带来的增益(+0.32)远大于价值网络质量(+0.02)。
思考题 3(概念与工程题):自我对弈闭环里,一轮数据的标签到底是什么?
题目. 讲义第 12 页”Self Play a Game”与第 15 页”Train Neural Network to Predict Policies and Values”之间,一轮自我对弈产生的数据是如何变成训练信号的?请写出三个标签的来源,并解释 14.4.3 实测的 $CE(\pi_{\text{MCTS}}\vert \pi_\theta)$ 为什么从 1.3863 出发、降到 0.7238 就止步。
答案. 一轮自我对弈产生的是三元组集合 $\{(s_t,\ \boldsymbol{\pi}_t,\ z)\}$,三个分量的来源各不相同:
- 状态 $s_t$:由对局轨迹给出,但落子不是从网络直接采样,而是先在该状态跑完整 MCTS,再按根策略 $\pi_{\text{MCTS}}(a\vert s_t)\propto N(s_t,a)^{1/\tau}$(或直接取 $\arg\max_a N$)落子——即 $\pi(s)\propto N(s,a)^{1/\tau}$(讲义第 11 页)。
- **策略标签 $\boldsymbol{\pi}t$:搜索的归一化访问分布** $N(s_t,\cdot)/\sum_a N(s_t,a)$,不是网络原始输出 $\mathbf p\theta$。这正是”用更强的老师蒸馏学生”:搜索比网络强,故标签优于当前策略。
- 价值标签 $z$:终局结果 $\pm1$,同一局的所有状态共享同一个 $z$(AlphaZero 用 $\gamma=1$ 且中间奖励为 0),因此价值头学的是”从该局面出发、由自我对弈双方继续走下去的胜率”。
交叉熵的起止值都有精确解释。起点 1.3863:$\ln 4=1.3863$,正是 4 个动作上均匀分布的交叉熵;第 1 轮时 $\mathbf p_\theta$ 是随机初始化的(近似均匀),而目标 $\boldsymbol{\pi}_1$ 已有结构,故初始 CE 恰好等于”完全无信息”的值。止步于 0.7238:策略头是 10 维手工特征上的线性 softmax,其可表达的分布族远比”搜索在 4 个动作上产生的、依赖深层树统计的分布”窄;因此存在一个由容量决定的正的下界,无论训练多久都无法消除。实测这个下界在 8 轮后仍为 0.7238,说明拟合还远未饱和但已被容量限制。工程含义:这量化了讲义第 17 页”架构影响”的核心——闭环把搜索成果沉淀进参数的速度由架构容量决定;要更快逼近搜索,就得换更强的函数逼近器(残差网络),这正是 AlphaGo Zero 用 19/39 个残差块的原因。
思考题 4(伦理讨论题):把”对齐”从用户扩展到道德——两条路线的困难是对偶的
题目. 结合 ethics_society_234_2.pdf:讲义第 5 页把价值对齐的第四种解读定为”AI 做道德上正确的事”,随后第 8–19 页分别讨论自上而下与自下而上两条路线。请 (a) 说明两条路线各自的核心困难,并指出它们为何是”对偶”的;(b) 用自己的话解释”道德奖励黑客(moral reward hacking)”与”道德分歧(moral disagreement)”分别是哪条路线的失败模式;(c) 讲义第 7 页的智能体购票场景中,每个智能体都完全对齐了自己的用户,为什么结果仍然可能是坏的?这个案例说明”对齐”缺少了什么维度?(d) 讲义第 20 页给出的建议是”从所有人都同意的简单事项开始,再尽力捕捉复杂性”——这个建议在工程上对应什么做法?请给出一条具体的、可检验的设计主张。
参考论述. (a) 自上而下(第 8–11 页)显式写下道德原则并用奖赏函数/后处理/硬约束实现,其困难在于规格(specification):正确的道德原则本身是道德理论的开放问题——功利主义要最大化总净幸福,但”幸福的分布呢?权利呢?”;常识多元论承认多原则并存,但”原则冲突时怎么办?高度细微的例外怎么办?”;任何规则集都难以”cover all possible situations”、难以处理边界情形、容易过度简化、难以刻画个体差异。自下而上(第 14–19 页)从示例/反馈中学习道德(IRL、模仿学习、RLHF),其困难在于数据分布:罕见或未预见的情形没有样本(”在真实人类驾驶数据上训练的自驾车,可能从未见过刹车失灵致死场景”)、反馈分布不均(”多数群体更易被代表,少数/边缘群体被低代表”,”学到的价值可能复制既有社会偏见”)、以及代表性上的规范困难(”用谁的示例?”)。对偶性:自上而下败于”原则无法穷尽情境”,自下而上败于”示例无法覆盖分布”——前者是规则空间的开集问题,后者是样本空间的开集问题;两者从相反方向遭遇同一个”开放世界”困难,因此不存在只修一条路就能解决的方案。
(b) 道德奖励黑客是自上而下的失败模式:原则被错误指定后,优化器会找到令人意外的坏行为来”满足”字面原则(第 9 页:”Incorrectly specified moral principles can recommend surprising forms of bad behavior”)。这与 L16 将展开的奖励黑客同源,但发生在”道德”这一层规格上——例如一个被要求最大化总净幸福的智能体可能通过压制不幸福者的可见性来”提高”统计量。道德分歧是自下而上的失败模式:从示例学习必须先回答”学谁的”,而不同个体与文化对同一行为给出相反示例(第 14 页的两个例子——”该不该生成先知穆罕默德的形象?该不该给规避执法的小贴士?”——答案”取决于你问谁”),因此聚合方案本身携带规范性选择,而多数派行为会压倒少数派价值。
(c) 购票场景(第 7 页):每个智能体都被完美地对齐到各自用户的偏好(以最优价格买到票),但”Many others also use agents with the same goal”,于是个体层面的对齐行为在集体层面产生 faster competition between agents(智能体竞速)、price spikes(价格尖峰)、unequal advantages across users(用户间优势不平等)。这个案例说明”对齐”缺少的是集体/均衡维度:对齐的判据被定义在”单个智能体 vs 它的用户”这一对关系上,而当所有智能体同时行动时,市场价格是所有人行为的内生结果——没有人违背自己的用户,但所有用户都受损。技术上,这对应”近视的、单体最优”目标在多智能体系统里无法保证全局好结果,与 L12 的多任务/多智能体探索、以及博弈论中的均衡选择问题直接相连;在伦理上,它证明”对齐到用户”(讲义前三种解读)结构性地不足以处理社会后果,必须有第 4–5 页那种”we = 所有人”的判据补充。
(d) 工程上对应分层把关 + 参与式修订。可检验的设计主张(示例):任何部署到多用户环境的对齐系统,必须同时满足两条可审计条件——(i) 存在一层”近乎共识”的硬约束(如不得造成人身伤害、不得欺骗、不得操纵),以不可被奖励优化绕过的形式实现(过滤器/硬约束而非惩罚项),并有单元测试覆盖”试图以伤害换奖励”的对抗用例;(ii) 存在一个持续收集受影响非用户反馈的通道(社区顾问委员会、持续反馈渠道、部署前公众咨询),并公开”价值修订日志”以证明系统愿意随时间修订(呼应第 16–17 页”values as contextual, contestable, revisable”)。 这条主张是可检验的:条件 (i) 可用对抗测试集的通过率度量,条件 (ii) 可用”是否存在非用户反馈通道 + 修订记录”这一二元事实核查。它同时对应讲义第 20 页的两句建议——先用大家都同意的简单事项兜底,再用制度化的持续过程去”尽力捕捉复杂性”。
附:本讲实验产物
| 文件 | 说明 |
|---|---|
cs234/code/L14_mcts_uct.py | 完整实验:搜索 × 先验、价值网络 × 搜索、两因素分解、$c$ 校准(36.8 s) |
cs234/code/L14_alphazero_loop.py | AlphaZero 式自我对弈闭环,MCTS 作为策略改进算子(12.2 s) |
cs234/code/L14_snippet1.py | 代码块一(4×4 搜索预算 × 先验,约 0.9 s) |
cs234/code/L14_snippet2.py | 代码块二(4×4 UCT 常数 $c$ 校准,约 1.8 s) |
cs234/code/L14_uct_search.png | 三联图:搜索预算 × 先验 / 搜索预算 × 价值网络 / 探索常数 $c$ |
cs234/code/L14_alphazero_loop.png | 双联图:自我对弈闭环曲线 / 容量压缩瓶颈(含 $\ln 4$ 基线) |
cs234/code/L14_mcts_uct.log、L14_alphazero_loop.log、L14_snippet1.log、L14_snippet2.log | 上述四个脚本的原始运行日志 |