06 - 最新研究进展 (2024-2025)¶
学习时间: 5-6小时 重要性: ⭐⭐⭐⭐⭐ 了解强化学习前沿动态 前置知识: Transformer、离线RL、PPO基础
🎯 学习目标¶
完成本章后,你将能够: - 了解2024-2025年强化学习的最新进展 - 掌握Decision Transformer的核心思想 - 理解序列建模在RL中的应用 - 了解多模态强化学习方法 - 掌握RL for Reasoning的核心方法(GRPO、STaR、PRM) - 理解从o1到DeepSeek-R1的推理增强范式 - 了解RL for Code Generation的前沿进展(CodeRL、RLEF)
1. 2024年强化学习领域重大事件¶
1.1 图灵奖授予强化学习先驱¶
2025年3月:ACM宣布将图灵奖授予 Andrew Barto 和 Richard Sutton,以表彰他们在强化学习领域的奠基性贡献。
意义: - 强化学习成为AI核心领域获得最高荣誉 - 标志着RL从学术研究走向主流应用 - 激励更多研究者投入RL领域
1.2 主要研究趋势¶
2024-2025研究趋势:
├── 序列建模方法
│ ├── Decision Transformer
│ └── Online Decision Transformer
├── 多模态强化学习
│ └── Gato-like通用智能体
├── 大模型+RL
│ └── RLHF → DPO → GRPO演进
├── ⭐ RL for Reasoning(最热门)
│ ├── DeepSeek-R1 / OpenAI o1
│ ├── GRPO / STaR / PRM
│ └── 蒸馏与RL结合
├── RL for Code Generation
│ ├── CodeRL / RLEF
│ └── 代码Agent训练
├── 样本效率提升
│ └── 更好的离线RL方法
└── 世界模型
└── 更稳定的模型学习方法
2. Decision Transformer¶
2.1 核心思想¶
将RL视为序列建模问题: - 不学习价值函数或策略 - 直接建模轨迹序列 - 使用Transformer架构
关键洞察:
轨迹 = (回报, 状态, 动作) 的序列
2.2 与传统RL的区别¶
| 特性 | 传统RL | Decision Transformer |
|---|---|---|
| 核心 | 学习价值函数/策略 | 序列建模 |
| 训练 | 时序差分/Bellman方程 | 监督学习 |
| 架构 | DQN/PPO等 | Transformer |
| 样本 | 需要在线交互 | 离线数据即可 |
2.3 算法流程¶
输入: 轨迹 τ = (R_0, s_0, a_0, R_1, s_1, a_1, ...)
1. 将轨迹转换为序列:
[R_0, s_0, a_0, R_1, s_1, a_1, ...]
2. 使用Transformer建模条件分布:
P(a_t | R_t, s_t, R_{t-1}, s_{t-1}, a_{t-1}, ...)
3. 训练目标: 最大化动作预测准确率
4. 推理时: 给定目标回报,生成动作序列
2.4 代码实现¶
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
class DecisionTransformer(nn.Module): # 继承nn.Module定义网络层
"""Decision Transformer模型"""
def __init__(self, state_dim, action_dim, hidden_dim=128,
n_layers=3, n_heads=4, max_len=100):
super(DecisionTransformer, self).__init__()
self.state_dim = state_dim
self.action_dim = action_dim
self.hidden_dim = hidden_dim
self.max_len = max_len
# 嵌入层
self.embed_return = nn.Linear(1, hidden_dim)
self.embed_state = nn.Linear(state_dim, hidden_dim)
self.embed_action = nn.Linear(action_dim, hidden_dim)
# 位置编码
self.pos_embed = nn.Parameter(torch.randn(1, max_len, hidden_dim))
# Transformer
encoder_layer = nn.TransformerEncoderLayer(
d_model=hidden_dim,
nhead=n_heads,
dim_feedforward=hidden_dim * 4,
batch_first=True
)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=n_layers)
# 预测头
self.predict_action = nn.Sequential(
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, action_dim),
nn.Tanh()
)
self.predict_return = nn.Linear(hidden_dim, 1)
self.predict_state = nn.Linear(hidden_dim, state_dim)
def forward(self, returns, states, actions, timesteps):
"""
前向传播
参数:
returns: (batch, seq_len, 1)
states: (batch, seq_len, state_dim)
actions: (batch, seq_len, action_dim)
timesteps: (batch, seq_len)
返回:
预测的动作、状态、回报
"""
batch_size, seq_len = states.shape[0], states.shape[1]
# 嵌入
return_embeddings = self.embed_return(returns)
state_embeddings = self.embed_state(states)
action_embeddings = self.embed_action(actions)
# 交错排列: [r_1, s_1, a_1, r_2, s_2, a_2, ...]
stacked_inputs = torch.stack( # torch.stack沿新维度拼接张量
[return_embeddings, state_embeddings, action_embeddings], dim=2
).reshape(batch_size, 3 * seq_len, self.hidden_dim) # 重塑张量形状
# 添加位置编码
pos_embeddings = self.pos_embed[:, :3 * seq_len, :]
stacked_inputs = stacked_inputs + pos_embeddings
# Transformer
transformer_out = self.transformer(stacked_inputs)
# 提取动作预测(每隔3个token)
action_preds = self.predict_action(transformer_out[:, 2::3])
return action_preds
def get_action(self, returns, states, actions, timesteps):
"""获取动作预测"""
action_preds = self.forward(returns, states, actions, timesteps)
return action_preds[:, -1, :] # 返回最后一个动作
class DTTrainer:
"""Decision Transformer训练器"""
def __init__(self, state_dim, action_dim, lr=1e-4):
self.model = DecisionTransformer(state_dim, action_dim)
self.optimizer = optim.Adam(self.model.parameters(), lr=lr)
self.loss_fn = nn.MSELoss()
def train_step(self, trajectories):
"""
训练一步
参数:
trajectories: 轨迹批次
- returns: (batch, seq_len, 1)
- states: (batch, seq_len, state_dim)
- actions: (batch, seq_len, action_dim)
"""
returns = trajectories['returns']
states = trajectories['states']
actions = trajectories['actions']
# 前向传播
action_preds = self.model(returns, states, actions, None)
# 计算损失(只计算动作预测)
loss = self.loss_fn(action_preds, actions)
# 反向传播
self.optimizer.zero_grad() # 清零梯度
loss.backward() # 反向传播计算梯度
torch.nn.utils.clip_grad_norm_(self.model.parameters(), 0.25)
self.optimizer.step() # 更新参数
return loss.item() # 将单元素张量转为Python数值
2.5 优势与局限¶
优势: - 无需Bellman更新,训练稳定 - 天然支持离线学习 - 可以利用大规模预训练 - 可扩展到多任务
局限: - 需要大量离线数据 - 对长序列建模能力有限 - 难以处理稀疏奖励
3. Online Decision Transformer (ODT)¶
3.1 动机¶
问题:原始DT只能离线学习
解决方案:ODT结合在线探索和离线预训练
3.2 核心思想¶
3.3 代码框架¶
class OnlineDecisionTransformer:
"""Online Decision Transformer"""
def __init__(self, state_dim, action_dim):
self.dt_model = DecisionTransformer(state_dim, action_dim)
self.exploration_bonus = 0.1 # 探索奖励系数
def select_action(self, state, target_return):
"""选择动作(带探索)"""
# 使用DT模型预测动作
with torch.no_grad(): # 禁用梯度计算,节省内存
action = self.dt_model.get_action(
target_return, state, prev_actions, timesteps
)
# 添加探索噪声
action = action + np.random.normal(0, self.exploration_bonus, size=action.shape)
return action
def online_update(self, new_trajectory):
"""在线更新"""
# 将新轨迹加入缓冲区
self.replay_buffer.add(new_trajectory)
# 从缓冲区采样训练
batch = self.replay_buffer.sample()
loss = self.dt_model.train_step(batch)
return loss
4. 多模态强化学习¶
4.1 Gato回顾¶
DeepMind的Gato(2022): - 单一Transformer处理多种任务 - 文本、图像、控制任务统一建模 - 展示了通用智能体的可能性
4.2 2024年进展¶
主要方向: 1. 视觉-语言-动作模型(VLA) 2. 机器人基础模型 3. 多模态世界模型
4.3 视觉-语言-动作模型¶
class VLAModel(nn.Module):
"""视觉-语言-动作模型"""
def __init__(self, vocab_size, image_size, action_dim):
super(VLAModel, self).__init__()
# 视觉编码器
self.vision_encoder = VisionEncoder(image_size)
# 语言编码器
self.language_encoder = LanguageEncoder(vocab_size)
# 多模态融合
self.fusion = MultiModalFusion()
# 动作解码器
self.action_decoder = ActionDecoder(action_dim)
def forward(self, image, text, previous_actions):
"""
前向传播
参数:
image: 视觉输入
text: 语言指令
previous_actions: 历史动作
"""
# 编码
visual_features = self.vision_encoder(image)
language_features = self.language_encoder(text)
# 融合
fused_features = self.fusion(visual_features, language_features, previous_actions)
# 解码动作
action = self.action_decoder(fused_features)
return action
5. 大模型时代的强化学习¶
📌 交叉引用:RLHF的完整技术讲解请参考 LLM学习/03-系统与工程/04-对齐技术.md,本节侧重RLHF的最新研究进展与演进趋势。
5.1 RLHF的演进¶
从InstructGPT到GPT-4: - 奖励模型规模增大 - 多轮RL优化 - Constitutional AI(宪法AI)
2024年新方向: - DPO (Direct Preference Optimization):无需奖励模型 - KTO (Kahneman-Tversky Optimization):基于人类心理 - RLAIF:用AI反馈替代人类反馈
5.2 DPO简介¶
核心思想:直接优化策略满足人类偏好
目标函数: $\(L_{DPO} = -\mathbb{E}_{(x, y_w, y_l) \sim D} \left[ \log \sigma \left( \beta \log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)} \right) \right]\)$
优势: - 无需训练奖励模型 - 训练更稳定 - 计算效率更高
6. 未来展望¶
6.1 研究趋势¶
未来5年趋势:
├── 通用智能体
│ └── 单一模型处理多种任务
├── 样本效率
│ └── 从更少数据学习
├── 可解释性
│ └── 理解RL决策过程
├── 安全对齐
│ └── 确保RL系统安全
└── 跨领域应用
└── 科学发现、医疗、教育
6.2 挑战与机遇¶
挑战: - 奖励设计困难 - 样本效率仍需提升 - 泛化能力有限 - 安全对齐问题
机遇: - 大模型结合RL - 多模态学习 - 世界模型 - 具身智能
7. RL for Reasoning — 推理增强(2024-2025 最热门方向)¶
📌 核心洞察:2024-2025年,强化学习最具突破性的应用方向是推理增强(RL for Reasoning)。从OpenAI o1到DeepSeek-R1,RL被证明能显著提升大语言模型的推理能力,开启了"后RLHF时代"的新范式。
7.1 背景:从 o1 到 DeepSeek-R1 的范式革命¶
时间线:
RL for Reasoning 里程碑:
├── 2024.05 DeepSeek-V2 —— 高效MoE架构
├── 2024.09 OpenAI o1 —— 首个推理增强模型(闭源)
├── 2024.11 QwQ-32B-Preview —— 阿里开源推理模型探索
├── 2025.01 DeepSeek-R1 —— 首个完全开源的RL推理模型
├── 2025.02 DeepSeek-R1蒸馏系列 —— 多尺寸开源
├── 2025.03 Kimi k1.5 / Claude 3.7 Sonnet —— 推理模型持续涌现
└── 2025.Q2 开源社区复现浪潮 —— Open-R1, SimpleRL等
为什么重要?
传统RLHF(Reinforcement Learning from Human Feedback)主要解决的是模型对齐(alignment)问题——让模型输出更符合人类偏好。而RL for Reasoning的目标是提升模型的推理能力本身,让模型学会"慢思考"(slow thinking),在数学、编程、逻辑推理等任务上实现质的飞跃。
这种新范式也被称为 RLVR(Reinforcement Learning with Verifiable Rewards)——用可验证的奖励(如数学答案正确性、代码通过测试)替代人类偏好作为训练信号,是 DeepSeek-R1-Zero 等推理模型的核心训练方法。
| 维度 | 传统RLHF | RL for Reasoning (RLVR) |
|---|---|---|
| 目标 | 对齐人类偏好 | 提升推理能力 |
| 奖励来源 | 人类标注 / 偏好数据 | 可验证的正确性(数学答案、代码执行) |
| 训练信号 | 主观偏好 | 客观对错(可自动验证) |
| 典型方法 | PPO + 奖励模型 | GRPO / STaR / PRM |
| 代表系统 | InstructGPT, ChatGPT | o1, DeepSeek-R1, DeepSeek-R1-Zero |
7.2 RLHF / RLAIF 回顾与局限¶
📌 交叉引用:RLHF完整技术细节请参考 LLM学习/03-系统与工程/04-对齐技术.md
RLHF经典流程:
RLHF三阶段:
┌─ Stage 1: SFT ──────────────────────────┐
│ 在高质量指令数据上微调基座模型 │
└──────────────────────────────────────────┘
↓
┌─ Stage 2: Reward Model ─────────────────┐
│ 训练奖励模型学习人类偏好排序 │
│ 输入(x, y) → 输出标量得分 r(x, y) │
└──────────────────────────────────────────┘
↓
┌─ Stage 3: RL Fine-tuning ───────────────┐
│ 使用PPO优化策略模型,最大化奖励 │
│ 同时加入KL散度约束防止偏离太远 │
└──────────────────────────────────────────┘
RLHF/RLAIF的局限:
- 奖励模型的天花板:奖励模型本身不完美,存在reward hacking风险
- 标注成本高昂:高质量人类偏好标注成本极高,RLAIF虽缓解但引入AI偏见
- PPO训练不稳定:超参数敏感,需要Critic网络(额外的显存开销)
- 对推理能力提升有限:RLHF主要改善风格和安全性,对数学/编码推理提升有限
- 奖励信号模糊:人类偏好是主观的,不适合评判推理正确性
7.3 GRPO:DeepSeek-R1 的核心训练方法¶
GRPO(Group Relative Policy Optimization) 是DeepSeek-R1的核心RL训练算法,也是2025年最受关注的RL算法之一。
7.3.1 核心原理¶
关键创新:不需要额外的Critic(价值)网络,通过组内相对奖励来估计基线(baseline)。
传统PPO的问题:
其中优势函数 \(\hat{A}_t\) 需要一个Critic网络来估计,这意味着: - 额外的模型参数(Critic通常与Policy同等规模) - 额外的显存占用 - Critic的训练误差会传播到Policy更新
GRPO的解决方案:
对于每个问题 \(q\),采样一组(Group)回答 \(\{o_1, o_2, \ldots, o_G\}\),然后用组内相对奖励代替Critic:
GRPO目标函数:
7.3.2 与PPO的详细对比¶
| 维度 | PPO (RLHF) | GRPO (DeepSeek-R1) |
|---|---|---|
| Critic网络 | ✅ 需要(与Policy同等规模) | ❌ 不需要 |
| 显存占用 | 4个模型(Policy/Ref/Reward/Critic) | 3个模型(Policy/Ref/Reward) |
| 优势估计 | GAE (Generalized Advantage Estimation) | 组内标准化奖励 |
| 采样方式 | 逐条采样 | 批量采样一组 |
| 计算效率 | 较低(Critic前向传播) | 较高(省去Critic计算) |
| 训练稳定性 | 受Critic误差影响 | 更稳定(直接使用奖励) |
| 奖励信号 | 学习到的奖励模型 | 可验证的规则奖励(如数学正确性) |
| 适用场景 | 通用对齐 | 有明确对错的推理任务 |
7.3.3 训练流程详解¶
import torch
import torch.nn.functional as F
class GRPOTrainer:
"""
GRPO训练器(简化版)
核心思想:
1. 对每个问题,用当前策略采样G个回答
2. 用规则/奖励模型对每个回答打分
3. 在组内做标准化得到相对优势
4. 用PPO-clip目标更新策略
"""
def __init__(self, policy_model, ref_model, reward_fn,
group_size=8, clip_eps=0.2, kl_coeff=0.01, lr=1e-6):
self.policy = policy_model # 策略模型 π_θ
self.ref_model = ref_model # 参考模型 π_ref(冻结)
self.reward_fn = reward_fn # 奖励函数 r(q, o)
self.group_size = group_size # 每个问题采样数 G
self.clip_eps = clip_eps # PPO裁剪参数 ε
self.kl_coeff = kl_coeff # KL散度系数 β
self.optimizer = torch.optim.Adam(self.policy.parameters(), lr=lr)
def compute_group_advantages(self, rewards):
"""
计算组内相对优势(GRPO核心)
参数:
rewards: shape (batch_size, group_size) -- 每组G个回答的奖励
返回:
advantages: shape (batch_size, group_size) -- 标准化后的优势
"""
# 组内均值和标准差
mean_r = rewards.mean(dim=-1, keepdim=True) # (batch, 1)
std_r = rewards.std(dim=-1, keepdim=True) + 1e-8 # (batch, 1)
# 标准化
advantages = (rewards - mean_r) / std_r # (batch, G)
return advantages
def compute_kl_divergence(self, log_probs_policy, log_probs_ref):
"""计算策略与参考模型的KL散度"""
kl = (log_probs_policy - log_probs_ref).mean()
return kl
def train_step(self, questions):
"""
GRPO训练一步
参数:
questions: 一批问题 [q_1, q_2, ..., q_B]
"""
all_losses = []
for question in questions:
# ===== Step 1: 采样一组回答 =====
with torch.no_grad():
outputs = []
for _ in range(self.group_size):
output = self.policy.generate(question, temperature=0.7)
outputs.append(output)
# ===== Step 2: 计算奖励 =====
rewards = torch.tensor([
self.reward_fn(question, output) for output in outputs
]) # shape: (G,)
# ===== Step 3: 计算组内相对优势 =====
advantages = self.compute_group_advantages(rewards.unsqueeze(0)).squeeze(0) # unsqueeze增加一个维度 # squeeze压缩维度
# ===== Step 4: 计算策略比率和损失 =====
for i, output in enumerate(outputs): # enumerate同时获取索引和元素
# 当前策略的对数概率
log_prob = self.policy.log_prob(question, output)
# 旧策略的对数概率(采样时的)
with torch.no_grad():
log_prob_old = self.policy.log_prob(question, output)
log_prob_ref = self.ref_model.log_prob(question, output)
# 策略比率
ratio = torch.exp(log_prob - log_prob_old)
# PPO-Clip损失
surr1 = ratio * advantages[i]
surr2 = torch.clamp(ratio, 1 - self.clip_eps, 1 + self.clip_eps) * advantages[i]
policy_loss = -torch.min(surr1, surr2)
# KL惩罚
kl_penalty = self.kl_coeff * self.compute_kl_divergence(log_prob, log_prob_ref)
loss = policy_loss + kl_penalty
all_losses.append(loss)
# ===== Step 5: 反向传播 =====
total_loss = torch.stack(all_losses).mean()
self.optimizer.zero_grad()
total_loss.backward()
torch.nn.utils.clip_grad_norm_(self.policy.parameters(), max_norm=1.0)
self.optimizer.step()
return total_loss.item()
def math_reward_function(question, answer):
"""
数学推理奖励函数示例
DeepSeek-R1使用的奖励信号:
- 准确性奖励:答案是否正确(0/1)
- 格式奖励:是否按要求格式输出(如\\boxed{})
"""
# 提取模型输出的最终答案
predicted = extract_answer(answer)
# 获取标准答案
ground_truth = get_ground_truth(question)
# 准确性奖励
accuracy_reward = 1.0 if predicted == ground_truth else 0.0
# 格式奖励(鼓励使用思维链和规范格式)
format_reward = 0.0
if "<think>" in answer and "</think>" in answer:
format_reward += 0.1
if "\\boxed{" in answer:
format_reward += 0.1
return accuracy_reward + format_reward
7.3.4 DeepSeek-R1 训练Pipeline¶
DeepSeek-R1的完整训练分为多个阶段:
DeepSeek-R1 训练流程:
┌─ Stage 0: 基座模型 ─────────────────────────────┐
│ DeepSeek-V3 Base(671B MoE) │
└──────────────────────────────────────────────────┘
↓
┌─ Stage 1: 冷启动SFT ────────────────────────────┐
│ 少量高质量CoT数据微调 │
│ 目的:教会模型产生<think>...</think>格式 │
│ 数据量:数千条精选推理轨迹 │
└──────────────────────────────────────────────────┘
↓
┌─ Stage 2: RL训练(GRPO)─────────────────────────┐
│ 使用GRPO在数学/编程/逻辑推理任务上训练 │
│ 奖励信号:可验证的正确性 + 格式规范 │
│ 关键发现:模型自发涌现"aha moment"、自我反思 │
└──────────────────────────────────────────────────┘
↓
┌─ Stage 3: 拒绝采样 + SFT ───────────────────────┐
│ 从Stage 2模型采样大量CoT数据 │
│ 过滤出高质量推理轨迹 │
│ 在全领域数据(含通用对话)上SFT │
└──────────────────────────────────────────────────┘
↓
┌─ Stage 4: 第二轮RL ─────────────────────────────┐
│ 在全领域上进行RL微调 │
│ 包括有用性+安全性+推理能力的综合奖励 │
│ 最终得到DeepSeek-R1 │
└──────────────────────────────────────────────────┘
关键发现——"aha moment":
在Stage 2的纯RL训练中,DeepSeek团队观察到模型自发涌现了以下推理行为: - 自我验证:"Wait, let me check this again..." - 回溯修正:"Hmm, that doesn't seem right. Let me reconsider..." - 分步推理:将复杂问题分解为子步骤 - 探索多条路径:尝试不同解题方法
这些行为并非通过数据教授,而是RL训练过程中自然涌现的。
7.4 STaR:自我改进推理¶
STaR(Self-Taught Reasoner) 是一种让模型通过自我生成推理过程来迭代改进的方法。
7.4.1 算法流程¶
STaR算法:
┌─ Step 1: 初始推理 ──────────────────────────────┐
│ 对每个问题(q, a*),让模型生成推理过程 │
│ (q) → 模型生成 → rationale + answer │
└──────────────────────────────────────────────────┘
↓
┌─ Step 2: 过滤 ──────────────────────────────────┐
│ 保留 answer == a* 的样本 → 正确推理集 │
│ 丢弃 answer ≠ a* 的样本 │
└──────────────────────────────────────────────────┘
↓
┌─ Step 3: Rationalization(合理化)──────────────┐
│ 对失败的问题:将正确答案a*作为提示 │
│ 让模型生成能推导出a*的推理过程 │
│ → "反向合理化" │
└──────────────────────────────────────────────────┘
↓
┌─ Step 4: 微调 ──────────────────────────────────┐
│ 在正确推理 + 合理化推理的数据上微调模型 │
│ 重复Step 1-4,迭代改进 │
└──────────────────────────────────────────────────┘
7.4.2 代码示例¶
class STaRTrainer:
"""STaR (Self-Taught Reasoner) 训练器"""
def __init__(self, model, tokenizer, num_iterations=5):
self.model = model
self.tokenizer = tokenizer
self.num_iterations = num_iterations
def generate_rationale(self, question, hint=None):
"""生成推理过程"""
if hint:
prompt = f"Question: {question}\nHint: The answer is {hint}\nLet's think step by step:"
else:
prompt = f"Question: {question}\nLet's think step by step:"
output = self.model.generate(prompt, max_length=512, temperature=0.7)
rationale, answer = self.parse_output(output)
return rationale, answer
def star_iteration(self, dataset):
"""STaR一轮迭代"""
training_data = []
for question, ground_truth in dataset:
# Step 1: 直接推理
rationale, predicted = self.generate_rationale(question)
if predicted == ground_truth:
# Step 2: 正确 → 保留
training_data.append({
'question': question,
'rationale': rationale,
'answer': predicted
})
else:
# Step 3: 错误 → 合理化(提供答案作为hint)
rationale_hint, predicted_hint = self.generate_rationale(
question, hint=ground_truth
)
if predicted_hint == ground_truth:
training_data.append({
'question': question,
'rationale': rationale_hint,
'answer': predicted_hint
})
# Step 4: 微调
self.finetune(training_data)
return len(training_data)
def train(self, dataset):
"""完整STaR训练"""
for i in range(self.num_iterations):
n_samples = self.star_iteration(dataset)
accuracy = self.evaluate(dataset)
print(f"Iteration {i+1}: {n_samples} samples, accuracy={accuracy:.2%}")
Quiet-STaR(2024):STaR的进阶版本,让模型在生成每个token时都进行内部推理("quiet thinking"),无需显式标注推理数据。
7.5 过程奖励模型 (PRM) vs 结果奖励模型 (ORM)¶
奖励建模是RL for Reasoning的关键环节。
7.5.1 两种范式对比¶
ORM(Outcome Reward Model):
输入:问题q + 完整回答o
输出:单一标量奖励 r(q, o) ∈ [0, 1]
判断:最终答案对不对?
PRM(Process Reward Model):
输入:问题q + 推理过程的每一步 s_1, s_2, ..., s_n
输出:每步的奖励 r(q, s_1), r(q, s_1, s_2), ...
判断:每一步推理是否正确?
| 维度 | ORM | PRM |
|---|---|---|
| 奖励粒度 | 整体结果 | 逐步骤 |
| 标注成本 | 低(只需最终答案) | 高(需标注每一步) |
| 信用分配 | 差(稀疏奖励) | 好(密集奖励) |
| 对错误检测 | 只知道最终错了 | 能定位哪一步出错 |
| 训练效率 | 低 | 高 |
| 代表工作 | 基础RLHF | OpenAI PRM800K, Math-Shepherd |
7.5.2 PRM的训练与使用¶
class ProcessRewardModel:
"""过程奖励模型(PRM)"""
def __init__(self, base_model, step_separator="\\n\\n"):
self.model = base_model
self.step_separator = step_separator
self.reward_head = torch.nn.Linear(base_model.hidden_size, 1)
def score_steps(self, question, reasoning_steps):
"""
对推理过程的每一步打分
参数:
question: 问题
reasoning_steps: ["Step 1: ...", "Step 2: ...", ...]
返回:
step_scores: 每步的得分 [0.9, 0.85, 0.3, ...]
"""
step_scores = []
context = f"Question: {question}\n"
for step in reasoning_steps:
context += step + self.step_separator
# 编码到当前步骤的上下文
hidden = self.model.encode(context)
# 取最后一个token的隐藏状态
score = torch.sigmoid(self.reward_head(hidden[:, -1, :]))
step_scores.append(score.item())
return step_scores
def best_of_n_with_prm(self, question, candidates, aggregation="min"):
"""
使用PRM进行Best-of-N选择
aggregation:
- "min": 取所有步骤得分的最小值(保守策略)
- "last": 取最后一步的得分
- "prod": 取所有步骤得分的乘积
"""
best_score = -float('inf')
best_candidate = None
for candidate in candidates:
steps = candidate.split(self.step_separator)
scores = self.score_steps(question, steps)
if aggregation == "min":
final_score = min(scores)
elif aggregation == "last":
final_score = scores[-1] # [-1]负索引取最后元素
elif aggregation == "prod":
final_score = 1.0
for s in scores:
final_score *= s
if final_score > best_score:
best_score = final_score
best_candidate = candidate
return best_candidate, best_score
2025关键进展: - Math-Shepherd:自动化PRM标注,用Monte Carlo Tree Search估计每步的正确概率 - 自动PRM:无需人工标注,通过多次采样自动判断每步正确性 - 隐式PRM:不显式训练PRM,而是通过RL训练过程隐式学习过程奖励
7.6 思维链 (CoT) 作为 RL 动作空间¶
核心思想:将思维链推理视为RL中的"动作序列",每一步推理是一个动作。
7.6.1 形式化定义¶
将推理问题建模为MDP:
状态 s_t:问题 + 已生成的推理步骤 (s_0, s_1, ..., s_{t-1})
动作 a_t:生成下一个推理步骤 s_t
转移 T:确定性转移(拼接新步骤到上下文)
奖励 r:
- 中间奖励:PRM对每步的评分(可选)
- 最终奖励:答案是否正确
策略 π(a_t | s_t):语言模型的条件生成概率
7.6.2 搜索策略¶
不同的搜索策略决定了如何在推理空间中探索:
class ReasoningSearch:
"""推理搜索策略"""
@staticmethod # @staticmethod不需要实例即可调用
def best_of_n(model, question, n=64, reward_model=None):
"""
Best-of-N采样
最简单的方法:生成N个答案,选最好的
"""
candidates = []
for _ in range(n):
response = model.generate(question, temperature=0.7)
score = reward_model.score(question, response)
candidates.append((response, score))
return max(candidates, key=lambda x: x[1]) # lambda匿名函数
@staticmethod
def beam_search_with_prm(model, question, beam_width=5, max_steps=10, prm=None):
"""
带PRM引导的Beam Search
在推理步骤层面进行搜索
"""
# 初始beam
beams = [{"steps": [], "score": 0.0, "context": f"Q: {question}\n"}]
for step_idx in range(max_steps):
all_candidates = []
for beam in beams:
# 对每个beam,生成多个候选下一步
for _ in range(beam_width):
next_step = model.generate_step(beam["context"], temperature=0.8)
# PRM打分
step_score = prm.score_step(question, beam["steps"] + [next_step])
all_candidates.append({
"steps": beam["steps"] + [next_step],
"score": beam["score"] + step_score,
"context": beam["context"] + next_step + "\n"
})
# 保留top-k
beams = sorted(all_candidates, key=lambda x: x["score"], reverse=True)[:beam_width]
# 检查是否有beam已完成
for beam in beams:
if is_answer_complete(beam["steps"][-1]):
return beam
return beams[0]
@staticmethod
def monte_carlo_tree_search(model, question, num_simulations=100, prm=None):
"""
蒙特卡洛树搜索(MCTS)用于推理
在step级别构建搜索树
"""
root = MCTSNode(state=question, parent=None)
for _ in range(num_simulations):
# Selection:选择最有前途的节点
node = root.select(exploration_weight=1.4)
# Expansion:生成新的推理步骤
next_step = model.generate_step(node.state, temperature=1.0)
child = node.expand(next_step)
# Simulation:完成剩余推理并评估
full_solution = model.complete_reasoning(child.state)
reward = evaluate_solution(question, full_solution)
# Backpropagation:更新统计
child.backpropagate(reward)
# 返回最佳路径
return root.best_path()
7.7 RL for Code / Agent¶
7.7.1 代码Agent的RL训练¶
SWE-Agent / Devin等代码Agent正在使用RL进行训练优化:
代码Agent的RL训练框架:
┌─ 环境 ──────────────────────────────────────────┐
│ 代码仓库 + 终端 + 测试套件 + Issue描述 │
└──────────────────────────────────────────────────┘
↓
┌─ 状态空间 ──────────────────────────────────────┐
│ 当前代码文件、终端输出、已执行的操作历史 │
└──────────────────────────────────────────────────┘
↓
┌─ 动作空间 ──────────────────────────────────────┐
│ 编辑文件、执行命令、搜索代码、提交修复 │
│ create_file / edit_file / run_test / search │
└──────────────────────────────────────────────────┘
↓
┌─ 奖励 ──────────────────────────────────────────┐
│ 测试通过率、代码质量、步骤效率 │
│ r = test_pass_rate + λ_1·quality - λ_2·steps │
└──────────────────────────────────────────────────┘
class CodeAgentRewardFunction:
"""代码Agent的奖励函数设计"""
def __init__(self, test_weight=1.0, quality_weight=0.1, efficiency_weight=0.05):
self.test_weight = test_weight
self.quality_weight = quality_weight
self.efficiency_weight = efficiency_weight
def compute_reward(self, trajectory):
"""
计算代码修复轨迹的奖励
trajectory包含:
- issue_description: Bug描述
- actions: Agent执行的操作序列
- final_patch: 最终提交的代码补丁
- test_results: 测试运行结果
"""
# 1. 测试通过奖励(核心)
test_reward = self.compute_test_reward(trajectory['test_results'])
# 2. 代码质量奖励
quality_reward = self.compute_quality_reward(trajectory['final_patch'])
# 3. 效率惩罚(步骤越少越好)
efficiency_penalty = len(trajectory['actions']) * self.efficiency_weight
total_reward = (
self.test_weight * test_reward +
self.quality_weight * quality_reward -
efficiency_penalty
)
return total_reward
def compute_test_reward(self, test_results):
"""基于测试结果的奖励"""
if test_results['all_passed']:
return 1.0
else:
# 部分奖励:通过的测试比例
return test_results['passed'] / test_results['total'] * 0.5
def compute_quality_reward(self, patch):
"""基于代码质量的奖励"""
score = 0.0
# 修改行数适当
if len(patch.split('\n')) < 50:
score += 0.3
# 无语法错误
if not has_syntax_errors(patch):
score += 0.5
# 包含注释
if has_comments(patch):
score += 0.2
return score
7.7.2 工具使用 (Tool-Use) 中的RL¶
RL在训练LLM使用外部工具(API调用、搜索、计算器等)方面也取得了重要进展:
Tool-Use RL训练:
┌─ 工具定义 ────────────────────────────────────────┐
│ search(query) → results │
│ calculator(expr) → number │
│ code_exec(code) → output │
│ api_call(endpoint, params) → response │
└────────────────────────────────────────────────────┘
↓
┌─ 训练信号 ────────────────────────────────────────┐
│ 工具调用是否正确(语法/参数) │
│ 工具返回结果是否被有效利用 │
│ 最终回答是否因工具使用而更准确 │
└────────────────────────────────────────────────────┘
关键方法: - Toolformer:自监督学习工具使用时机和方式 - RL from Execution Feedback:通过执行结果作为奖励训练工具调用 - ReAct + RL:在Reason-Act框架上叠加RL优化
7.8 蒸馏与RL的结合¶
DeepSeek-R1蒸馏系列是2025年最具影响力的开源成果之一:将大模型的推理能力蒸馏到小模型中。
7.8.1 蒸馏流程¶
R1蒸馏流程:
┌─ 教师模型 ──────────────────────────────────────┐
│ DeepSeek-R1 (671B MoE) │
│ 生成大量高质量推理轨迹 │
│ 800K条包含<think>...</think>的完整推理数据 │
└──────────────────────────────────────────────────┘
↓ 蒸馏数据
┌─ 学生模型 ──────────────────────────────────────┐
│ Qwen-2.5系列: 1.5B / 7B / 14B / 32B │
│ Llama-3系列: 8B / 70B │
│ 在蒸馏数据上进行SFT微调 │
└──────────────────────────────────────────────────┘
↓
┌─ 结果 ──────────────────────────────────────────┐
│ DeepSeek-R1-Distill-Qwen-32B: │
│ AIME 2024: 72.6% (超越OpenAI o1-mini) │
│ MATH-500: 94.3% │
│ 仅通过SFT蒸馏,无需RL训练! │
└──────────────────────────────────────────────────┘
7.8.2 蒸馏 vs RL vs 蒸馏+RL¶
| 训练方式 | 性能 | 成本 | 适用场景 |
|---|---|---|---|
| 纯SFT蒸馏 | ★★★★ | 低 | 资源受限,追求性价比 |
| 纯RL训练 | ★★★★★ | 极高 | 旗舰模型,算力充足 |
| 蒸馏 → RL | ★★★★★+ | 中高 | 用蒸馏数据冷启动后再RL |
DeepSeek的关键发现: - 纯蒸馏(无RL)的小模型在benchmark上已经很强 - 但蒸馏模型缺乏泛化能力——在未见过的推理模式上表现差 - RL训练让模型真正"学会推理",而非仅仅模仿推理格式 - 最佳实践:先蒸馏冷启动,再进行RL训练
7.8.3 开源社区复现¶
2025年Q1-Q2的主要复现工作:
| 项目 | 方法 | 基座模型 | 特点 |
|---|---|---|---|
| Open-R1 (HuggingFace) | GRPO复现 | 多种 | 社区协作,完整pipeline |
| SimpleRL | 简化GRPO | Qwen-2.5 | 最简化的R1复现 |
| TinyZero | GRPO | 小模型 | 验证RL在小模型上的涌现 |
| Logic-RL | GRPO变体 | Qwen-2.5 | 逻辑推理专项 |
| STILL-2 | 蒸馏+RL | Qwen-2.5 | 蒸馏后RL的完整流程 |
7.9 2025-2026 展望¶
7.9.1 端到端推理RL¶
趋势:跳过SFT冷启动阶段,直接从基座模型开始RL训练。
DeepSeek-R1-Zero实验已证明这是可能的(虽然训练不稳定),未来随着算法改进,端到端推理RL有望成为主流。
7.9.2 多模态推理RL¶
数学/几何推理:模型需要"看图"推理(几何证明、图表分析)
视觉编程:通过观察UI界面生成代码
科学推理:理解实验图表、分子结构等
7.9.3 可预期的突破方向¶
2025-2026展望:
├── 算法改进
│ ├── 更高效的RL算法(GRPO变体/改进)
│ ├── 更好的过程奖励建模(自动PRM)
│ └── 更稳定的端到端训练策略
├── 应用拓展
│ ├── RL for Agent(工具使用/代码修复/自动化)
│ ├── RL for 多模态推理(视觉/语音/视频)
│ └── RL for 科学发现(数学定理证明/化学合成)
├── 开源生态
│ ├── 完整开源训练框架
│ ├── 高质量推理数据集
│ └── 标准化评估基准
└── 理论理解
├── 为什么RL能涌现推理能力?
├── 推理能力的scaling law
└── RL vs 蒸馏的本质区别
8. RL for Code Generation — 代码生成强化学习¶
📌 代码生成是RL for Reasoning的重要分支,因为代码具有可自动验证的天然优势(编译通过、测试通过 = 正确)。
8.1 CodeRL / PPOCoder¶
CodeRL(2022) 是最早将RL系统性地应用于代码生成的工作之一。
8.1.1 核心思想¶
CodeRL框架:
┌─ 代码生成模型 (Actor) ───────────────────────────┐
│ 基于CodeT5/StarCoder等代码LM │
│ 输入:问题描述/函数签名 │
│ 输出:候选代码 │
└──────────────────────────────────────────────────┘
↓
┌─ Critic模型 ─────────────────────────────────────┐
│ 预测代码在不同测试用例上的通过概率 │
│ 提供细粒度反馈(不只是对/错) │
│ 分类:compile error / runtime error / │
│ wrong answer / correct │
└──────────────────────────────────────────────────┘
↓
┌─ RL优化 ─────────────────────────────────────────┐
│ 使用Critic信号作为奖励 │
│ PPO优化代码生成策略 │
└──────────────────────────────────────────────────┘
PPOCoder(2023)进一步改进,引入: - 基于代码结构的奖励(AST相似度) - 执行反馈的多阶奖励设计 - 更好的探索策略
8.2 代码执行反馈作为奖励信号¶
代码生成的天然优势:奖励信号可以通过自动执行获得!
class CodeExecutionReward:
"""基于代码执行的奖励计算"""
def __init__(self, timeout=10):
self.timeout = timeout
def compute_reward(self, generated_code, test_cases):
"""
执行代码并计算奖励
test_cases: [
{"input": "...", "expected_output": "..."},
...
]
"""
reward = 0.0
# Level 1: 语法检查
if not self.syntax_check(generated_code):
return -0.5 # 语法错误
# Level 2: 编译/解析检查
if not self.compile_check(generated_code):
return -0.3 # 编译错误
# Level 3: 执行测试用例
passed = 0
for test in test_cases:
try: # try/except捕获异常
result = self.execute(generated_code, test['input'], timeout=self.timeout)
if result == test['expected_output']:
passed += 1
except TimeoutError:
reward -= 0.1 # 超时惩罚
except RuntimeError:
reward -= 0.1 # 运行时错误
# 通过率奖励
pass_rate = passed / len(test_cases)
reward += pass_rate # [0, 1]
return reward
def multi_level_reward(self, generated_code, test_cases):
"""
多层级奖励(更细粒度)
返回:
dict: 各维度的得分
"""
return {
'syntax': self.syntax_score(generated_code), # 语法正确性
'compilable': self.compile_score(generated_code), # 可编译性
'functional': self.functional_score(generated_code, test_cases), # 功能正确
'efficiency': self.efficiency_score(generated_code, test_cases), # 运行效率
'style': self.style_score(generated_code) # 代码风格
}
8.3 RLEF:从执行反馈中强化学习¶
RLEF(Reinforcement Learning from Execution Feedback) 是2024-2025年代码生成RL的主流方法。
8.3.1 与RLHF的区别¶
| 维度 | RLHF (代码) | RLEF |
|---|---|---|
| 反馈来源 | 人类评判代码质量 | 自动执行测试用例 |
| 反馈成本 | 高(需要人类标注) | 极低(自动运行) |
| 反馈准确性 | 主观(代码风格偏好) | 客观(通过/不通过) |
| 反馈规模 | 受限于标注预算 | 几乎无限 |
| 奖励设计 | 学习奖励模型 | 直接用执行结果 |
8.3.2 RLEF训练流程¶
RLEF训练循环:
┌────────────────────────────────────────────────┐
│ 1. 从题目库采样编程问题 q │
│ 2. 用策略模型生成N个候选代码 {c_1, ..., c_N} │
│ 3. 在沙箱中执行每个代码,运行测试用例 │
│ 4. 根据测试结果计算奖励 r_i │
│ 5. 使用GRPO/PPO更新策略 │
│ 6. 重复 │
└────────────────────────────────────────────────┘
安全执行环境:
- Docker容器隔离
- 资源限制(CPU/内存/时间)
- 网络隔离(禁止外部访问)
- 文件系统只读挂载
2025关键应用: - Competitive Programming:AlphaCode 2、CodeForces级别的RL代码Agent - 自动Bug修复:SWE-bench上的RL训练Agent(通过率从20%→50%+) - 代码翻译:跨语言代码转换的RL优化(Python→Rust、Java→Go等) - 测试生成:RL训练模型自动生成高覆盖率测试用例
9. 本章总结¶
2024-2025关键进展¶
最新研究:
├── Decision Transformer
│ └── RL作为序列建模
├── Online DT
│ └── 离线+在线结合
├── 多模态RL
│ └── 视觉-语言-动作
├── RLHF演进
│ └── DPO、RLAIF、KTO
├── RL for Reasoning ⭐⭐⭐(最热门)
│ ├── GRPO(DeepSeek-R1核心算法)
│ ├── STaR / Quiet-STaR(自我改进)
│ ├── PRM vs ORM(过程奖励建模)
│ ├── CoT作为RL动作空间
│ ├── 蒸馏与RL结合
│ └── 开源社区复现浪潮
├── RL for Code Generation
│ ├── CodeRL / PPOCoder
│ ├── RLEF(执行反馈强化学习)
│ └── 代码Agent训练
└── 通用智能体
└── Gato-like模型
学习建议¶
- 关注顶会论文:NeurIPS、ICML、ICLR
- 跟踪开源项目:GitHub trending,特别是Open-R1、SimpleRL等复现项目
- 参与社区讨论:Reddit r/reinforcementlearning、r/LocalLLaMA
- 实践新算法:复现GRPO,在小模型上验证推理RL的效果
- 阅读技术报告:DeepSeek-R1、OpenAI o1等系统技术报告
✅ 自测问题¶
-
Decision Transformer与传统RL的主要区别是什么?
-
为什么2024年图灵奖授予Barto和Sutton?
-
DPO相比PPO+RLHF有什么优势?
-
多模态强化学习的主要挑战是什么?
-
GRPO与PPO的核心区别是什么?为什么GRPO更适合推理任务的RL训练?
-
PRM(过程奖励模型)相比ORM(结果奖励模型)有哪些优势?在实际训练中如何权衡?
-
DeepSeek-R1的训练分为哪几个阶段?每个阶段的目的是什么?
-
STaR算法中的"Rationalization"步骤解决了什么问题?
-
RLEF相比RLHF在代码生成场景中有什么优势?
-
蒸馏和RL训练在推理能力获取上的本质区别是什么?
📚 延伸阅读¶
- Chen et al. (2021) - Decision Transformer: Reinforcement Learning via Sequence Modeling
- Zheng et al. (2022) - Online Decision Transformer
- Rafailov et al. (2023) - Direct Preference Optimization
- Reed et al. (2022) - A Generalist Agent (Gato)
- DeepSeek-AI (2025) - DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning
- Shao et al. (2024) - DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models (GRPO原始论文)
- Zelikman et al. (2022) - STaR: Bootstrapping Reasoning With Reasoning
- Zelikman et al. (2024) - Quiet-STaR: Language Models Can Teach Themselves to Think Before Speaking
- Lightman et al. (2023) - Let's Verify Step by Step (OpenAI PRM)
- Wang et al. (2024) - Math-Shepherd: Verify and Reinforce LLMs Step-by-step without Human Annotations
- Le et al. (2022) - CodeRL: Mastering Code Generation through Pretrained Models and Deep Reinforcement Learning
- Shojaee et al. (2023) - PPOCoder: Execution-Based Code Generation using Deep Reinforcement Learning
恭喜完成所有前沿主题学习!
→ 回到:06-前沿主题README