ToT 的 BFS/DFS 有个致命缺口:蒙特卡洛树搜索(MCTS)用「随机试错+统计」让大模型想得更深,小模型 + 它竟超过 GPT-4
前面三篇我们走了一条清晰的线:CoT(链)→ ToT(树,能试错回头)→ GoT(图,能拼碎片)。你以为到图就到头了?
今天聊 MCTS(蒙特卡洛树搜索)------它和 ToT 跑在同一棵 thought 树上,但换了一套更聪明的搜索策略。
先抛一个反直觉结论:
一个更小的开源模型(LLaMA-33B)+ MCTS,在规划任务上超过了大得多的 GPT-4 + 普通 CoT。
这不是模型变大了,是「怎么用模型去想」变了。AlphaGo 靠 MCTS 战胜李世石,现在它也被用来让 LLM「想得更深」。
〇、ToT 的盲区:确定性剪枝会误杀好分支
回想 ToT 的剪枝逻辑:评估器说某状态 impossible,就永远丢掉。
这有个致命前提------评估器必须永远判对。但前面讲过,评估器就是那个 LLM 自己,它会看走眼:
- 把本该保留的好分支 误判为
impossible→ 永久误杀(这解永远丢了); - 把死路 误判为
likely→ 一直占着预算。
人类下棋不是这样想的。我们不会「一条路判死就永不回头」,也不会「每条路平均用力」。我们会在看起来有戏、但又没完全验证过的几步上多想几次 ,用多次试错后的统计结果来相信哪边更靠谱。
MCTS 正是把这种「用随机试错 + 统计对冲不确定性」形式化的算法。 它不是靠一次评估定生死,而是:多次随机推演(rollout)→ 统计哪条路赢的次数多 → 把搜索预算自动引向有希望的分支。
一句话定位:ToT 的 BFS/DFS 是「外部代码用穷举+贪心剪枝来搜树」;MCTS 是「外部代码用随机采样+价值统计来搜同一棵树」。树还在,搜索策略换了。
一、MCTS 是什么:在谱系里的位置
Monte Carlo Tree Search(蒙特卡洛树搜索) 是一类用于决策 / 规划问题 的启发式搜索算法。它在「可能动作空间极大、无法穷举」的场景里(围棋约 10^170 种局面、数学推理有无限多条证明路径),通过反复随机模拟来逼近最优解,而不必搜索整棵树。
它是所有现代围棋程序(AlphaGo / AlphaZero)的核心搜索算法。
回顾前面三篇的归属关系:
| 范式 | 结构 | 搜索策略 | 谁在管结构 |
|---|---|---|---|
| CoT | 链(线性) | 无(一次生成) | 模型内部 |
| ToT | 树 | BFS / DFS | 外部框架 |
| GoT | 图 | BFS / DFS + 聚合细化 | 外部框架 |
| MCTS | 树 | UCT(UCB 选择)+ 随机 rollout | 外部框架 |
关键认知 :MCTS 和 ToT 是同一层(外部编排)的两种搜索策略,不是递进关系 。MCTS 可以替换 ToT 里的 BFS/DFS,仍跑在同一棵 thought 树上;它和 GoT 也不冲突------图结构上同样能套 MCTS 选择。
澄清「不是什么」:
- ❌ 不是模型内部能力(不像 o1 的 hidden thinking),模型只是被反复调用的子程序。
- ❌ 不是一句 prompt 能触发的,是一段算法代码(选择/扩展/模拟/回溯四步循环)。
- ❌ 不是穷举,它有意不搜完整棵树,靠采样 + 统计把预算花在刀刃上。
- ✅ 是一种「在树结构上做有偏采样的搜索算法」,核心是 UCB 选择公式。
二、核心机制:四步循环
MCTS 把「搜索」建模成在树上反复跑同一个四步循环,直到预算(迭代次数)耗尽,再从统计结果里挑最优路径。
2.1 三个基本量
- 状态(State):当前局面(如棋盘)。LLM 推理里 = 当前的部分推理轨迹 / 剩余数字集合。
- 动作(Action):从某状态能走的合法一步。LLM 推理里 = 模型生成的「下一个 thought / 下一步运算」。
- 奖励(Reward):走到终局后的结果信号(赢/输,或「是否凑出 24」)。
每个树节点维护两个统计量:n(被访问次数)、w(累计价值,如获胜次数)。节点的「平均价值」= w / n。
2.2 四步详解
- Selection(选择) :从根出发,按 UCB1 公式递归选子节点,一路向下直到某个未完全展开的节点。UCB1 自动平衡「利用高价值节点」和「探索少访问节点」。
- Expansion(扩展) :到达叶节点后,生成它的一个或多个子节点(尝试几个候选动作),挑一个作为新节点
C。 - Simulation / Rollout(模拟 / 推演) :从
C出发,用随机(或默认)策略一直走到终局 ,得到结果。这一步不记录进搜索树 ,只是一次"快速试完"来估计C的价值。 - Backpropagation(回溯更新) :把模拟结果沿
C → 根反向传回,更新路上每个节点的n(+1) 和w(+本次结果)。让"好路径"的统计价值慢慢累积。
四步跑完 = 一次迭代。重复成千上万次后,根节点各子树统计趋于稳定,选
w/n最高的分支即为答案。
2.3 UCB1 公式(MCTS 的灵魂)
选择子节点 i 时:
UCB1(i) = w_i / n_i + c · √(ln N / n_i)
└─利用项─┘ └───探索项───┘
w_i / n_i(利用项):该节点目前的平均胜率,越大越值得走。√(ln N / n_i)(探索项):父节点总访问N越大、本节点访问n_i越小,该项越大,越"值得去试探"。c(探索常数):理论上取√2,实践常凭经验调(1~2),越大越爱探索冷门分支。
直觉 :一个"赢了很多次但试得也多"的节点,和一个"只试了一次但赢了"的节点------UCB1 会让后者也有机会被选中,避免算法过早认定某路"最好"而错过其他潜力分支。这就是探索-利用权衡的数学实现。
2.4 伪代码
python
def mcts(root, budget):
for _ in range(budget): # 迭代预算
node = selection(root) # ① UCB1 选到叶
child = expansion(node) # ② 扩展出新节点
reward = simulation(child) # ③ 随机 rollout 到终局
backpropagation(child, reward) # ④ 沿路径更新 n, w
return best_child(root) # 选 w/n 最高分支
三、统一案例:Game of 24 的 MCTS 走查
题目和 ToT 篇一致:用 4、9、10、13 凑 24。
- 状态 = 剩余数字集合,如
{4,9,10,13}。 - 动作 = 选两数做一次运算,如
13-9=4,新状态{4,4,10}。 - 奖励 = 走到只剩一个数时,若 =24 则 reward=1,否则 0。
- rollout = 从某状态随机选两数随机运算,一路算到剩一个数,看是否=24。
一次迭代的明细(带数字) :初始根 {4,9,10,13},假设已有统计。本次迭代:
- Selection :根下有两个候选
A{4,4,10}(n=5, w=3 → 均值0.6)和B{6,9,13}(n=2, w=1 → 均值0.5)。算 UCB1(设 N=7, c=1.4):- A:
0.6 + 1.4·√(ln7/5) ≈ 0.6 + 0.61 = 1.21 - B:
0.5 + 1.4·√(ln7/2) ≈ 0.5 + 1.21 = 1.71→ B 被选中(虽均值略低,但访问少,探索项更高)
- A:
- Expansion :在 B 下生成子节点
B1{6,4,13}作为新节点 C。 - Simulation:从 C 随机 rollout 到终局,假设这次没凑出 24 → reward=0。
- Backpropagation :路径
C→B→根的n各 +1,w不变。B 的均值略降。
注意:这次 B 被"探索"了一次,即便结果不好,下次它的探索项会变小,算法自然回归到更稳的 A。这正是 UCB 的奥妙------不靠一次评估定生死,而靠多次统计收敛。
对比 ToT(BFS) :ToT 会让 LLM 评估 B「impossible 就剪掉」。若 LLM 误判,B 里其实藏着的解就永远丢了。MCTS 不剪,只是"少去" ,靠 rollout 统计自然降权------对评估噪声更鲁棒。
四、MCTS 在 LLM 推理中的适配(RAP)
MCTS 原本为博弈设计(终局胜负明确)。用到 LLM 推理,关键是怎么定义「状态/动作/奖励」。代表工作是 RAP(Reasoning via Planning,Hao et al., 2023)。
4.1 把推理建模成 MDP(马尔可夫决策过程)
| MCTS 通用概念 | LLM 推理中的对应(RAP) |
|---|---|
| 状态 State | 部分推理轨迹(已生成的 thought 序列) |
| 动作 Action | LLM 生成的下一个推理步骤 |
| 奖励 Reward | **世界模型(也是 LLM)**给的信号:「这步多大可能导向正确解」 |
| 终局 | 得到最终答案 / 达到目标状态 |
4.2 RAP 的核心创新:LLM 当「双角色」
RAP 把同一个 LLM 复用成两个角色:
- Agent(策略):给定当前状态,生成候选「下一步推理动作」。
- World Model(世界模型):给定「状态+动作」,预测「执行后的下一个状态」,并给该状态打分("这有多可能通向正确答案")。
这解决了 LLM 推理的一大短板:没有内部世界模型去预判"这一步走了会怎样",只能自回归一路写下去、撞了南墙不回头。RAP 让模型在脑子里"先模拟几步再决定"。
4.3 真实实验结果(LLaMA-33B 设置下)
| 任务 | 基线(CoT) | RAP(MCTS) | 说明 |
|---|---|---|---|
| Blocksworld(6 步规划) | 近乎 0% | 42%(20 轮迭代) | 四步内难题平均 64% ;LLaMA-33B+RAP 比 GPT-4+CoT 相对 +33% |
| GSM8K(数学) | 29.4% | 48.8%(RAP-Aggregate ≈51.8%) | 同一 LLaMA-33B,远超 CoT |
| PrOntoQA(逻辑证明) | 证明准确率 64.8% | 78.8%(预测准确率 94.2%) | 显著超越 CoT 与 Least-to-Most |
最关键的一条 :一个更小的开源模型(LLaMA-33B)+ RAP ,能在规划任务上超过大得多的 GPT-4 + 普通 CoT 。这印证了全系列反复强调的主题------"怎么用模型的推理能力"和"模型本身多大"同样重要。
五、MCTS vs BFS/DFS(ToT)vs 其他搜索
MCTS 和 ToT 跑在同一棵树上,差别只在搜索策略:
| 维度 | ToT-BFS | ToT-DFS | MCTS |
|---|---|---|---|
| 遍历方式 | 逐层、每层留 top-b | 一条路深探、死就回溯 | UCB1 有偏采样 |
| 是否穷举 | 近似穷举(受 b 限) | 单链深探 | 有意不穷举 |
| 剪枝依据 | 评估器打分 | 同左 | rollout 统计价值 |
| 是否需要价值估计 | 是(一次性) | 是 | 是(多次累积) |
| 对评估器噪声 | 敏感(误判即误剪) | 敏感 | 更鲁棒(统计对冲) |
| 预算分配 | 平均/固定宽度 | 单链 | 自动集中于有希望分支 |
| 参数 | b, max_depth | max_depth | 迭代次数, c(探索常数) |
MCTS 的三大相对优势:
- 预算自动分配:不用手设 b,UCB 自己把算力引向高价值区。
- 从早期错误恢复:rollout 统计让"曾被冷落的好分支"仍有机会被翻出。
- 对噪声鲁棒:不依赖单次评估定生死。
代价:每次 rollout 都要把轨迹"跑完",LLM 调用数可能比 BFS 还多;且 rollout 质量依赖 World Model / 评估器------评估器烂,统计再多边也是"在烂信号上收敛"。
后续变体(图谱)
- LATS(Zhou et al., 2023):MCTS 统一到「推理+行动+规划」,用环境反馈引导,HumanEval 达 92.7% Pass@1。
- LLM-MCTS(Zhao et al., 2023):LLM 当常识世界模型 + 启发式策略。
- MCTSr / rStar(2024):小模型靠 MCTS 自 refine / 策略-价值互增强。
- AlphaLLM / AlphaGeometry:MCTS + 自对弈训练,搜出来的树同时当训练信号(类 AlphaZero)。
六、局限性(必读)
MCTS 完整继承了 ToT「外部框架、多次调用」的代价,还多了自己的坑:
- 必须有可模拟 / 可评估的奖励信号 。围棋有胜负,24 点有"是否=24"。但开放式生成(写文章、闲聊)没有清晰终局奖励,rollout 无从谈起------这类任务 MCTS 用不上。
- 评估器 / World Model 不可靠 = 系统性偏差。rollout 和奖励都靠 LLM 自评。若模型对"哪步对"的判断本身错,MCTS 只是在错误信号上越收敛越自信。连回 ToT 第 6 章"评估器致命弱点"。
- 计算成本高。每次迭代含 expansion(调 LLM)+ rollout(再调 LLM 跑完)+ 评估,调用数比 ToT-BFS 只多不少。
- 探索不足会陷局部。c 太小或预算不够,可能过早锁定非最优分支。
- 实现复杂度高于 BFS/DFS。需维护 n/w 统计、UCB 计算、rollout 策略。
适用边界一句话 :只在「有清晰终局奖励、状态可模拟、且需要规划/试错」的任务上才值------数学谜题、规划、逻辑推理、代码生成(编译即免费验证)。其余别上。
七、关键参数怎么选
| 参数 | 含义 | 经验值 | 怎么调 |
|---|---|---|---|
| 迭代次数 (budget) | 跑多少轮四步循环 | 几百~几千 | 越大越准越慢;先小后大找拐点 |
| c(探索常数) | UCB 探索项权重 | 理论 √2,实践 1~2 | 噪声大→调大;评估准→调小 |
| rollout 策略 | 模拟时随机还是有引导 | 随机最省,引导更准 | 有 cheap verifier 就用确定性 rollout |
| 奖励设计 | reward 怎么给 | 终局对错 / World Model 置信度 | 最影响成败,优先用确定性 verifier |
| 状态/动作定义 | thought 粒度 | 同 ToT:一步运算 / 一个子问题 | 太粗搜不动,太细爆炸 |
经验法则:先用确定性奖励(能代码验证就别让 LLM 自评)+ 适中 c(1.4)+ 迭代次数调到准确率不再涨为止。奖励设计比迭代次数更关键。
八、怎么用(实现)
和 ToT 一样,MCTS 是外部框架,需一段代码驱动。
现成库:
- RAP 官方实现 :
https://github.com/maitrix-org/llm-reasoners(含 Blocksworld / GSM8K / PrOntoQA 的 MCTS 配置)。 - LATS :
https://github.com/ZhangYihan1/LATS(MCTS + 环境反馈统一框架)。
最小骨架(教学版,需接你的 LLM API):
python
# 教学骨架:MCTS 四步循环(call_llm / world_model 需接你的 LLM)
def mcts(root_state, budget=500, c=1.4):
root = Node(root_state)
for _ in range(budget):
node = root
while node.children and not node.to_expand():
node = max(node.children, key=lambda n: ucb(n, c)) # ① Selection
if not node.is_terminal():
thought = call_llm(f"从状态 {node.state} 给出下一步推理:")
child = Node(thought); node.children.append(child); node = child # ② Expansion
reward = rollout(node.state) # ③ Simulation(最好用确定性 verifier)
while node: # ④ Backpropagation
node.n += 1; node.w += reward; node = node.parent
return best_leaf(root)
def ucb(node, c):
if node.n == 0:
return float('inf')
return node.w / node.n + c * (log(node.parent.n) / node.n) ** 0.5
要点:①
ucb()即 UCB1 公式;②rollout最好用确定性 verifier(如 24 点直接算剩余数是否=24),避免 LLM 自评噪声;③④ 回传即 Backpropagation。
九、为什么这条线值得你串起来
「LLM 推理搜索谱系」四篇到这就闭环了:
CoT(链,模型内部一次生成)→ SC(多链投票)→ ToT(树,BFS/DFS 外部编排)→ GoT(图,聚合/细化)→ MCTS(树,UCB 有偏采样)。
一条越来越清晰的规律浮现:
模型「想得对」的上限,不只在模型多大,更在「你用什么结构去组织它的思考」。 链 → 树 → 图 → 带统计的树,本质上是让模型从「一根筋写答案」进化到「会试错、会回头、会拼碎片、会用概率对冲不确定性」。
MCTS 是这条线上把「不确定性」处理得最优雅的一环------它不假装评估器永远对,而是用多次试错 + 统计把噪声对冲掉。