推理时扩展深度解析:Test-Time Scaling 的理论与实践
5620 字
28 分钟
推理时扩展深度解析:Test-Time Scaling 的理论与实践
1. 引言:训练的局限与推理的潜力
1.1 预训练 Scaling 的瓶颈
传统的 LLM 能力提升依赖预训练阶段的 scaling laws:
预训练 Scaling Laws:
能力 ∝ 模型参数量 × 训练tokens × 计算量
历史数据: ┌─────────────────────────────────────────────────────────┐ │ GPT-2 (1.5B) 训练 tokens ~ 10^9 │ │ GPT-3 (175B) 训练 tokens ~ 10^11 │ │ PaLM (540B) 训练 tokens ~ 10^12 │ │ GPT-4 (估计) 训练 tokens ~ 10^13+ │ └─────────────────────────────────────────────────────────┘
问题: → 高质量数据日益稀缺 → 训练成本指数增长 → 边际收益递减 → 模型能力在某些任务上仍有上限1.2 推理时扩展的崛起
Test-Time Scaling(推理时扩展)提供了一条新路径:
┌─────────────────────────────────────────────────────────────┐│ 推理时扩展的核心思想 │├─────────────────────────────────────────────────────────────┤│ ││ 传统观点: ││ "模型能力由训练决定,推理只是执行" ││ ││ 新观点: ││ "推理时也可以投入计算来提升答案质量" ││ ││ 类比: ││ → 训练 = 写代码时编译一次 ││ → 推理 = 运行时可以多次迭代优化 ││ ││ 核心公式: ││ ││ 能力 = f(训练计算量, 推理计算量) ││ ││ 关键洞察: ││ → 增加推理时的计算量可以弥补训练时的不足 ││ → 复杂问题需要更多推理时计算 ││ → 简单问题可以跳过复杂推理 ││ │└─────────────────────────────────────────────────────────────┘1.3 本系列文章关联
| 文章 | 关联 |
|---|---|
| PEFT/LoRA 深度解析 | 高效微调方法 |
| 后训练深度解析 | SFT/RLHF 对齐训练 |
| 模型量化深度解析 | 推理优化 |
2. Chain-of-Thought:推理的起点
2.1 CoT 的核心思想
Chain-of-Thought(CoT,Wei et al., 2022)让模型显式输出推理步骤:
class ChainOfThought: """ Chain-of-Thought 提示
核心:将答案的推导过程显式表达出来 """
def standard_prompt(self): """ 标准提示 """ return """ Q: 小明有3个苹果,小红给了他2个,他又吃了1个,还剩几个? A: 4个 """
def cot_prompt(self): """ CoT 提示 """ return """ Q: 小明有3个苹果,小红给了他2个,他又吃了1个,还剩几个? A: 让我们逐步思考。
1. 小明开始有3个苹果 2. 小红给了他2个,所以是 3 + 2 = 5 个 3. 他又吃了1个,所以是 5 - 1 = 4 个
所以还剩 4 个苹果。 """
def math_prompt(self): """ 数学问题 CoT """ return """ Q: 计算 15 × 17
A: 让我们逐步计算。
1. 15 × 17 = 15 × (20 - 3) 2. = 15 × 20 - 15 × 3 3. = 300 - 45 4. = 255
答案是 255。 """2.2 CoT 为什么有效?
class CoTAnalysis: """ CoT 有效性分析 """
def why_works(self): """ CoT 有效的可能原因 """ return { "intermediate_tokens": "中间 token 作为工作记忆", "sequential_computation": "强制模型逐步计算而非直接记忆", "error_localization": "错误更容易定位", "attention_distribution": "注意力更均匀分布", "program_synthesis": "隐式合成计算程序", }
def ablation(self): """ 消融实验结论 """ return { "math_tasks": "CoT 提升最显著 (~40% 提升)", "commonsense": "中度提升 (~15%)", "factual_recall": "提升有限", "key_factors": [ "模型规模 >= 100B 参数", "使用数学/代码类任务", "显式提示 'let's think step by step'", ], }2.3 CoT 的实现细节
class CoTImplementation: """ CoT 实现 """
def few_shot_cot(self): """ Few-shot CoT
提供多个 CoT 示例 """ return """ Q: 小明有5个球,丢了2个,又买了3个,现在有几个? A: 让我们逐步思考。 1. 开始有5个球 2. 丢了2个: 5 - 2 = 3 3. 又买了3个: 3 + 3 = 6 答案: 6个
--- Q: 书店有80本书,第一天卖了15本,第二天卖了20本,还剩多少? A: 让我们逐步思考。 1. 开始有80本 2. 第一天卖了15本: 80 - 15 = 65 3. 第二天卖了20本: 65 - 20 = 45 答案: 45本
--- Q: [新问题] """
def zero_shot_cot(self): """ Zero-shot CoT
简单指令触发 """ return """ 问题: [用户问题]
让我们逐步思考: """
def api_usage(self): """ API 使用示例 """ return ''' from openai import OpenAI
response = client.chat.completions.create( model="gpt-4", messages=[ { "role": "user", "content": "问题: 小明有3个苹果,小红给了他2个,他又吃了1个,还剩几个?\\n\\n让我们逐步思考:" } ], max_tokens=500, temperature=0.7, )
print(response.choices[0].message.content) '''3. Self-Consistency:多数投票
3.1 Self-Consistency 原理
Self-Consistency(Wang et al., 2023)通过采样多条推理路径,选择最一致的答案:
class SelfConsistency: """ Self-Consistency
核心思想: 1. 多次采样不同的推理路径 2. 统计每个答案出现的次数 3. 选择出现最多的答案 """
def __init__(self, model, num_samples=40): self.model = model self.num_samples = num_samples
def generate_paths(self, question): """ 生成多条推理路径 """ responses = []
for _ in range(self.num_samples): response = self.model.generate( prompt=f"{question}\n\n让我们逐步思考:", temperature=0.8, # 高温度增加多样性 max_tokens=500, ) responses.append(response)
return responses
def extract_answer(self, response): """ 从响应中提取答案 """ # 简单实现:提取最后一行数字 lines = response.strip().split("\n") for line in reversed(lines): # 尝试提取数字 import re numbers = re.findall(r'-?\d+', line) if numbers: return numbers[-1] # 取最后一个数字
return None
def majority_vote(self, answers): """ 多数投票 """ from collections import Counter
counter = Counter(answers) most_common = counter.most_common(1)[0]
return { "answer": most_common[0], "count": most_common[1], "total": len(answers), "confidence": most_common[1] / len(answers), "all_votes": counter, }
def solve(self, question): """ 完整流程 """ # Step 1: 生成多条路径 responses = self.generate_paths(question)
# Step 2: 提取答案 answers = [self.extract_answer(r) for r in responses] answers = [a for a in answers if a is not None]
# Step 3: 多数投票 result = self.majority_vote(answers)
return result3.2 Self-Consistency 的效果
Self-Consistency 效果(GSM8K 数据集):
基线 (Greedy): → LLM 准确率: 46.9%
Self-Consistency (40 samples): → 准确率提升到: 74.4% → 相对提升: +27.5%
关键发现: → 复杂问题提升更显著 → 多数投票能过滤错误推理 → 计算量换质量的有效方式
成本分析: → 40x 推理成本 → 但比训练大模型便宜得多3.3 温度与采样策略
class SamplingStrategy: """ 采样策略优化 """
def temperature_analysis(self): """ 温度分析 """ return { "temperature_0.0": { "description": "Greedy 解码", "diversity": "最低", "适合": "简单问题", }, "temperature_0.3": { "description": "低温度", "diversity": "低", "适合": "需要一定多样性的推理", }, "temperature_0.6": { "description": "中等温度", "diversity": "中等", "适合": "大多数推理任务", }, "temperature_0.8": { "description": "高温度", "diversity": "高", "适合": "Self-Consistency", }, }
def top_p_analysis(self): """ Top-p 核采样分析 """ return { "top_p_0.9": "截断尾部 10%,保持较高质量", "top_p_0.95": "更宽松的截断,更多样性", "top_p_0.99": "几乎不做截断,最大多样性", "recommendation": "top_p=0.95, temperature=0.7 是好的起点", }4. Best-of-N:加权采样
4.1 Best-of-N 基础
class BestOfN: """ Best-of-N 采样
核心思想: 1. 生成 N 个候选答案 2. 用奖励模型对每个答案打分 3. 选择得分最高的答案 """
def __init__(self, reward_model, n=100): self.reward_model = reward_model self.n = n
def generate_candidates(self, question): """ 生成 N 个候选 """ candidates = []
for _ in range(self.n): response = self.llm.generate( prompt=f"{question}\n\n让我们逐步思考:", temperature=0.8, ) candidates.append(response)
return candidates
def score_candidates(self, question, candidates): """ 对候选打分 """ scores = []
for candidate in candidates: # 使用奖励模型打分 score = self.reward_model.score(question, candidate) scores.append(score)
return scores
def select_best(self, candidates, scores): """ 选择最佳 """ best_idx = scores.index(max(scores)) return { "answer": candidates[best_idx], "score": scores[best_idx], }4.2 加权 Best-of-N
class WeightedBestOfN: """ 加权 Best-of-N
不仅选择最佳,还考虑概率 """
def select_with_probability(self, candidates, log_probs, scores): """ 基于概率加权的选择 """ import numpy as np
# 计算概率 probs = np.exp(log_probs)
# 归一化分数 normalized_scores = (scores - np.mean(scores)) / (np.std(scores) + 1e-8)
# 加权概率 weights = probs * np.exp(normalized_scores) weights = weights / weights.sum()
# 加权采样 selected_idx = np.random.choice(len(candidates), p=weights)
return candidates[selected_idx]4.3 Best-of-N vs Self-Consistency
class Comparison: """ Best-of-N vs Self-Consistency """
def compare(self): """ 对比 """ return { "self_consistency": { "需要": "CoT 提示", "评判方式": "多数投票", "优点": "无需额外奖励模型", "缺点": "需要一致的答案格式", "适用": "数学、代码等有明确答案的任务", }, "best_of_n": { "需要": "奖励模型", "评判方式": "奖励打分", "优点": "可应用于开放式任务", "缺点": "需要训练奖励模型", "适用": "对话、写作等开放式任务", }, }5. Process Reward Model:过程奖励
5.1 结果奖励 vs 过程奖励
class RewardModels: """ 结果奖励 vs 过程奖励 """
def outcome_reward_model(self): """ 结果奖励模型 (ORM)
只在最终答案处打分 """ return """ 问题: 2x + 5 = 15, 求 x
解答: 步骤1: 2x = 15 - 5 = 10 步骤2: x = 10 / 2 = 5 步骤3: x = 5
最终答案: x = 5
ORM 奖励: ✓ (最终答案正确) """
def process_reward_model(self): """ 过程奖励模型 (PRM)
对每个推理步骤打分 """ return """ 问题: 2x + 5 = 15, 求 x
解答: 步骤1: 2x = 15 - 5 = 10 → PRM: 0.9 ✓ 步骤2: x = 10 / 2 = 5 → PRM: 0.85 ✓ 步骤3: x = 5 → PRM: 0.8 ✓
最终答案: x = 5 → ORM: 1.0 ✓
关键优势: → 能识别错误步骤 → 提供更细粒度的反馈 → 更好地指导搜索 """5.2 PRM 的实现
class ProcessRewardModel: """ PRM 实现 """
def __init__(self, base_model): self.model = base_model
def score_step(self, question, reasoning_steps): """ 对推理步骤打分
输入: [步骤1, 步骤2, ..., 步骤N, 最终答案] 输出: [奖励1, 奖励2, ..., 奖励N] """ step_rewards = []
accumulated_context = question
for i, step in enumerate(reasoning_steps): # 构建上下文 context = accumulated_context + "\n" + step
# 使用模型预测该步骤是否正确 # 方式1: 二分类 (正确/错误) correctness = self.model.predict_step_correctness(context)
# 方式2: 打分 (0-1) score = self.model.score_step_quality(context)
step_rewards.append(score) accumulated_context += "\n" + step
return step_rewards
def lookahead_reward(self, current_step, future_steps): """ 前看奖励
评估从当前状态可能达到的奖励 """ total_reward = 0
for future_step in future_steps: # 模拟未来的奖励 future_reward = self.model.score_step_quality(future_step) total_reward += future_reward * self.discount_factor
return total_reward5.3 PRM 的训练
class PRMTraining: """ PRM 训练 """
def training_data(self): """ 训练数据构建 """ return """ 数据来源: 1. 人工标注 - 收集多条推理路径 - 标注每个步骤是否正确
2. 合成数据 - 使用 LLM 生成推理路径 - 自动标记正确/错误的步骤
3. 过程监督 - 在 RLHF 中加入过程奖励 - 使用 Process-Directed RL
数据格式: { "question": "...", "steps": [ {"text": "步骤1", "label": 1}, {"text": "步骤2", "label": 1}, {"text": "错误步骤", "label": 0}, {"text": "步骤4", "label": 1}, ], } """
def training_objective(self): """ 训练目标 """ return """ PRM 训练目标:
L = -∑ log P(r_i | s_1, ..., s_i) × r_i
其中: - r_i 是步骤 i 的奖励 (0 或 1) - P 是模型预测的步骤正确概率
也可以使用回归目标: L = MSE(P(s_i is correct), r_i) """6. Tree of Thoughts:搜索式推理
6.1 ToT 的核心思想
Tree of Thoughts(Yao et al., 2023)将推理建模为树搜索:
class TreeOfThoughts: """ Tree of Thoughts
核心思想: 1. 将问题分解为多个思考节点 2. 探索多条思考路径 3. 使用启发式评估选择最佳路径 """
def __init__(self, model, max_depth=5, num_branches=3): self.model = model self.max_depth = max_depth self.num_branches = num_branches self.tree = None
def generate_thoughts(self, state): """ 从当前状态生成多个思考 """ prompt = f""" 当前状态: {state}
请提出 {self.num_branches} 个不同的思考方向或行动: """
response = self.model.generate(prompt, temperature=0.8)
# 解析多个思考 thoughts = response.split("\n")[:self.num_branches]
return thoughts
def evaluate_state(self, state, goal): """ 评估当前状态
返回: (score, reason) """ prompt = f""" 目标: {goal} 当前状态: {state}
评估这个状态对目标的贡献程度 (0-10),并说明理由: """
response = self.model.generate(prompt)
# 解析分数 score = self.extract_score(response)
return score, response
def search(self, initial_state, goal): """ 树搜索 """ from collections import deque
# BFS 或 DFS queue = deque([(initial_state, [], 0)]) # (state, path, depth) best_state = None best_score = -float('inf')
while queue: state, path, depth = queue.popleft()
# 评估当前状态 score, _ = self.evaluate_state(state, goal)
if score > best_score: best_score = score best_state = state
# 如果还没到最大深度,继续扩展 if depth < self.max_depth: thoughts = self.generate_thoughts(state)
for thought in thoughts: new_state = state + "\n" + thought new_path = path + [thought] queue.append((new_state, new_path, depth + 1))
return best_state, best_score6.2 ToT vs CoT 对比
class ToTvsCoT: """ Tree of Thoughts vs Chain of Thoughts """
def compare(self): """ 对比 """ return { "CoT": { "structure": "链式,一条路径", "branching": "无", "exploration": "无", "backtracking": "无", "适合任务": "简单推理、事实问答", }, "ToT": { "structure": "树状,多条路径", "branching": "有", "exploration": "有(广度搜索)", "backtracking": "无(但可扩展为图)", "适合任务": "复杂规划、创意写作", }, }
def example_task(self, task_type): """ 任务适用性 """ return { "24_game": { "task": "使用 4 个数字和基本运算得到 24", "recommended": "ToT", "reason": "需要探索多种运算组合", }, "writing": { "task": "写一篇结构清晰的文章", "recommended": "ToT", "reason": "需要规划文章结构和内容", }, "math_proof": { "task": "证明数学定理", "recommended": "CoT + PRM", "reason": "步骤连续性很重要", }, "qa": { "task": "回答事实性问题", "recommended": "CoT", "reason": "简单推理即可", }, }7. Beam Search 在推理中的应用
7.1 传统 Beam Search
class BeamSearch: """ Beam Search 用于推理 """
def __init__(self, model, beam_width=5): self.model = model self.beam_width = beam_width
def decode(self, prompt, max_length=200): """ Beam Search 解码 """ # 初始化 beams = [ {"tokens": [], "score": 0.0, "log_probs": []} ] completed = []
for step in range(max_length): all_candidates = []
for beam in beams: if beam.get("finished"): # 已完成的 beam completed.append(beam) continue
# 扩展当前 beam logits = self.model.get_logits(beam["tokens"]) top_k = self.model.top_k(logits, k=self.beam_width * 2)
for token, log_prob in top_k: new_tokens = beam["tokens"] + [token] new_score = beam["score"] + log_prob new_log_probs = beam["log_probs"] + [log_prob]
all_candidates.append({ "tokens": new_tokens, "score": new_score, "log_probs": new_log_probs, "finished": self.model.is_eos(token), })
# 选择 top-k beams all_candidates.sort(key=lambda x: x["score"], reverse=True) beams = all_candidates[:self.beam_width]
# 检查是否全部完成 if all(b["finished"] for b in beams): break
# 合并完成的和未完成的 all_seqs = completed + beams all_seqs.sort(key=lambda x: x["score"] / len(x["tokens"]), reverse=True)
return all_seqs[0]["tokens"]
def with_reasoning(self, prompt): """ 带推理的 Beam Search """ # 第一阶段:生成推理路径 reasoning_beams = self.generate_reasoning_beams(prompt)
# 第二阶段:基于答案一致性选择 answer_votes = self.vote_on_answers(reasoning_beams)
# 返回最一致的答案 return answer_votes[0]7.2 推理时 Beam Search
class InferenceTimeBeamSearch: """ 推理时 Beam Search 优化 """
def diverse_beams(self): """ 多样性 Beam Search """ return """ 标准 Beam Search 只保留概率最高的路径 可能导致路径同质化
多样性 Beam Search 惩罚相似的候选:
score_i = log P(token_i) + λ × diversity_penalty
diversity_penalty = max_j exp((similarity(token_i, token_j)) / τ)
其中 λ 控制多样性权重,τ 是温度参数 """
def lookahead_beams(self): """ 前看 Beam Search """ return """ 评估当前 token 时考虑未来的潜力:
score(token_t) = log P(token_t) + γ × V(state_{t+1})
其中 V 是价值函数,评估从当前状态能达到好结果的可能性
这需要训练一个价值网络来预测未来奖励 """8. STaR:自推理引导
8.1 STaR 原理
STaR(Self-Taught Reasoner,Zelikman et al., 2022)让模型自己生成推理:
class STaR: """ STaR: Self-Taught Reasoner
核心思想: 1. 让模型尝试解决难题 2. 成功解决时,记录成功的推理过程 3. 失败时,使用"rationale generation"生成推理 4. 用这些数据微调模型 5. 重复迭代 """
def __init__(self, model, iterations=5): self.model = model self.iterations = iterations
def attempt_solve(self, question, correct_answer): """ 尝试解决问题 """ # 生成解答(带 CoT) response = self.model.generate( f"问题: {question}\n让我们逐步思考:", temperature=0.5, )
extracted_answer = self.extract_answer(response)
if extracted_answer == correct_answer: # 成功:记录推理过程 return { "success": True, "rationale": response, "answer": extracted_answer, } else: # 失败:尝试生成正确推理 return {"success": False, "rationale": None, "answer": extracted_answer}
def rationale_generation(self, question, correct_answer): """ 理由生成
提示模型"假设你最终会得到正确答案" """ prompt = f""" 问题: {question} 正确答案: {correct_answer}
请推理出正确的答案,假设你是对的。 让我们逐步思考,最后给出正确答案。 """
response = self.model.generate(prompt, temperature=0.5)
# 验证生成的推理是否正确 extracted = self.extract_answer(response) if extracted == correct_answer: return response else: return None
def iterative_training(self, dataset): """ 迭代训练 """ for iteration in range(self.iterations): print(f"迭代 {iteration + 1}/{self.iterations}")
training_examples = []
for item in dataset: question = item["question"] answer = item["answer"]
# 尝试解决 result = self.attempt_solve(question, answer)
if result["success"]: # 成功案例 training_examples.append({ "prompt": question, "response": result["rationale"], }) else: # 失败案例:生成正确推理 rationale = self.rationale_generation(question, answer) if rationale: training_examples.append({ "prompt": question, "response": rationale, })
# 用收集的数据微调模型 if training_examples: self.model.fine_tune(training_examples)
# 评估 accuracy = self.evaluate(dataset) print(f" 准确率: {accuracy:.2%}")
if accuracy > 0.9: break
return self.model8.2 STaR 的效果
STaR 效果(StrategyQA 数据集):
基线(无推理): → 准确率: 53.0%
CoT(few-shot): → 准确率: 59.7%
STaR(自迭代): → 准确率: 73.2% → 提升: +13.5%
关键洞察: → 模型可以"教会自己"推理 → 成功的推理例子比失败更重要 → 迭代可以不断提升能力9. 测试时计算 Scaling Laws
9.1 理论框架
class TestTimeScaling: """ 测试时计算 Scaling Laws """
def power_law(self, compute_budget, task_difficulty): """ 性能与计算量的幂律关系
P(C) = a × C^b + c
其中: - C 是推理计算量 - a, b, c 是拟合参数 - b 通常在 0.1-0.3 之间 """ import numpy as np
a, b, c = 0.3, 0.2, 0.5 performance = a * (compute_budget ** b) + c
return min(performance, 1.0) # 上限 1.0
def compute_optimal(self, task_difficulty, model_cost, compute_cost): """ 计算最优策略
给定任务难度和成本,选择: - 使用更大的模型 - 还是在推理时投入更多计算 """ return { "easy_task": "使用小模型 + 少量推理计算", "medium_task": "使用中等模型 + 适量推理计算", "hard_task": "使用大模型 + 充足推理计算", "very_hard_task": "使用最大模型 + 最大推理计算", }
def compute_allocation(self, total_compute): """ 计算量分配
在模型规模和推理计算之间如何分配 """ return """ 论文 "Test-Time Compute" 的发现:
对于简单问题: → 增加推理计算的效果有限 → 应该用更大的模型
对于复杂问题: → 增加推理计算效果显著 → 可以弥补模型规模不足
最佳策略: → 根据问题难度自适应分配计算 → 简单问题用少量计算 → 复杂问题用更多计算 """9.2 前沿研究
class FrontierResearch: """ 前沿研究 """
def chain_of_verification(self): """ Chain of Verification
生成答案后,验证每个步骤 """ return """ 流程: 1. 生成初始答案 2. 列出答案中的关键声明 3. 对每个声明独立验证 4. 根据验证结果修正答案
效果:显著减少幻觉 """
def chain_of_draft(self): """ Chain of Draft
快速草稿 → 逐步精化 """ return """ 流程: 1. 草稿 1:快速但不精确 2. 草稿 2:基于反馈修正 3. 草稿 N:持续精化直到满意
优势:比直接生成更高效 """
def prompt_optimization(self): """ 推理时提示优化 """ return """ 在推理时优化提示:
1. APE: 自动提示优化 - 采样多个提示 - 选择效果最好的
2. APO: 自动提示精化 - 分析失败案例 - 自动改进提示
3. Self-Generated Critiques - 让模型评估自己的回答 - 根据评估修正 """10. 实战指南
10.1 方法选择
class MethodSelection: """ 方法选择指南 """
def select(self, task_type, compute_budget): """ 根据任务和计算量选择方法 """ recommendations = { "math_proof": { "low_compute": "CoT + few-shot", "medium_compute": "Self-Consistency (20 samples)", "high_compute": "Self-Consistency (40) + PRM lookahead", "recommended": "CoT + Self-Consistency", }, "code_generation": { "low_compute": "CoT", "medium_compute": "Self-Consistency + execution feedback", "high_compute": "ToT + test execution", "recommended": "Self-Consistency + execution", }, "creative_writing": { "low_compute": "CoT", "medium_compute": "Best-of-N + reward model", "high_compute": "Evolutionary generation", "recommended": "Best-of-N", }, "fact_qa": { "low_compute": "Direct answer", "medium_compute": "CoT", "high_compute": "CoT + verification", "recommended": "CoT + verification", }, }
return recommendations.get(task_type, recommendations["fact_qa"])10.2 实现模板
class ImplementationTemplate: """ 实现模板 """
def self_consistency_template(self): """ Self-Consistency 模板 """ return ''' from collections import Counter import re
def self_consistency_solve(question, model, n_samples=20): """Self-Consistency 实现"""
# 生成多个解答 responses = [] for _ in range(n_samples): response = model.generate( f"{question}\\n\\n让我们逐步思考:", temperature=0.7, max_tokens=500, ) responses.append(response)
# 提取答案 answers = [] for response in responses: # 提取最后一个数字或关键词 answer = extract_answer(response) if answer: answers.append(answer)
# 多数投票 if answers: counter = Counter(answers) return counter.most_common(1)[0][0]
return None
def extract_answer(text): """从 CoT 响应中提取答案""" # 尝试提取数字 numbers = re.findall(r'-?\\d+\\.?\\d*', text) if numbers: return numbers[-1] # 尝试提取关键词 if "答案是" in text: return text.split("答案是")[-1].strip() return None '''
def best_of_n_template(self): """ Best-of-N 模板 """ return ''' def best_of_n_solve(question, model, reward_model, n_samples=50): """Best-of-N 实现"""
# 生成候选 candidates = [] for _ in range(n_samples): response = model.generate(question, temperature=0.8) candidates.append(response)
# 评分 scored = [] for candidate in candidates: score = reward_model.score(question, candidate) scored.append((candidate, score))
# 返回最佳 scored.sort(key=lambda x: x[1], reverse=True) return scored[0][0] '''10.3 成本优化
class CostOptimization: """ 成本优化 """
def adaptive_computation(self): """ 自适应计算
简单问题用少计算,复杂问题用多计算 """ return """ 策略: 1. 先用简单方法尝试 2. 如果置信度低,升级到更复杂方法 3. 如果还是低,继续升级
实现: def solve_with_adaptive(question): # Level 0: 直接回答 answer = direct_answer(question) if confidence(answer) > 0.9: return answer
# Level 1: CoT answer = cot_answer(question) if confidence(answer) > 0.85: return answer
# Level 2: Self-Consistency answer = self_consistency(question, n=10) if confidence(answer) > 0.8: return answer
# Level 3: Full Self-Consistency return self_consistency(question, n=40) """
def batch_optimization(self): """ 批处理优化 """ return """ 多个问题一起处理:
1. 按难度分组 - 简单问题:批量处理 - 复杂问题:单独处理
2. 共享计算 - 对相似问题复用推理路径
3. 缓存 - 缓存常见问题的解答 """11. 核心公式汇总
11.1 Self-Consistency
其中 是第 次采样的答案。
11.2 Best-of-N 加权
其中 是奖励模型对答案 的打分, 是温度参数。
11.3 测试时 Scaling
其中 是推理计算量, 是任务相关的拟合参数。
12. 总结
12.1 方法对比
┌─────────────────────────────────────────────────────────────┐│ 推理时扩展方法对比 │├─────────────────────────────────────────────────────────────┤│ ││ 方法 计算量 精度 适用场景 ││ ───────────────────────────────────────────────────────── ││ CoT 低 中 通用推理 ││ Self-Consistency 中 高 有明确答案的任务 ││ Best-of-N 中 高 开放式任务 ││ PRM 高 很高 需要精细控制的任务 ││ ToT 高 很高 复杂规划 ││ STaR 迭代 很高 可自提升的任务 ││ ───────────────────────────────────────────────────────── ││ ││ 核心原则:计算量换质量 ││ │└─────────────────────────────────────────────────────────────┘12.2 最佳实践
推理时扩展最佳实践:
1. 从简单开始 → 先尝试 CoT,再升级到更复杂方法
2. 自适应计算 → 简单问题少计算,复杂问题多计算
3. 选择合适的方法 → 数学/代码:Self-Consistency → 开放式:Best-of-N → 复杂规划:ToT
4. 成本控制 → 设置计算预算 → 使用 early stopping
5. 持续迭代 → 用 STaR 自我提升 → 收集成功的推理案例12.3 未来方向
推理时扩展的未来:
1. 更智能的搜索 → 结合蒙特卡洛树搜索 → 学习何时停止搜索
2. 更好的奖励模型 → Process Reward Model 的进步 → 更准确的步骤评估
3. 训练与推理协同 → 用推理数据训练更好的模型 → 循环自我提升
4. 硬件优化 → 专为推理时计算设计的芯片 → 更高效的并行推理
5. 理论完善 → 更精确的 scaling laws → 最优计算分配策略推荐阅读
- Chain-of-Thought(Wei et al., 2022)—— CoT 原论文
- Self-Consistency(Wang et al., 2023)—— 多数投票方法
- Tree of Thoughts(Yao et al., 2023)—— 搜索式推理
- STaR(Zelikman et al., 2022)—— 自推理引导
- Process Reward Models(Lightman et al., 2023)—— 过程奖励
参考资料
- Wei, J., et al. (2022). “Chain-of-Thought Prompting Elicits Reasoning in Large Language Models.” NeurIPS.
- Wang, X., et al. (2023). “Self-Consistency Improves Chain of Thought Reasoning in Language Models.” ICLR.
- Yao, S., et al. (2023). “Tree of Thoughts: Deliberate Problem Solving with Large Language Models.” NeurIPS.
- Zelikman, E., et al. (2022). “STaR: Self-Taught Reasoner Bootstrapping Reasoning with Reasoning.” NeurIPS.
- Lightman, H., et al. (2023). “Let’s Verify Step by Step.” arXiv.
- Brown, B., et al. (2024). “Language Model Testing-Time Compute.” OpenAI Blog.
- Snell, C., et al. (2024). “Scaling LLM Test-Time Compute Optimally.” arXiv.
- Jones, A., et al. (2024). “Inference-Time Scaling: A Case Study.” arXiv.
- Tian, Y., et al. (2024). “Self-Correction is All You Need.” arXiv.
- Qu, S., et al. (2024). “Deliberation after Learning: A New Paradigm.” arXiv.
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
推理时扩展深度解析:Test-Time Scaling 的理论与实践
https://aiattnstudio.link/posts/test-time-scaling/
