概述

RLVR(Reinforcement Learning with Verifiable Rewards) 是一种利用可验证奖励信号来训练大型语言模型(LLM)推理能力的方法。与传统的依赖人类反馈的强化学习(RLHF)不同,RLVR 在具有确定性强验证标准的任务(如数学推理、代码生成)中特别有效。1

RLVR 近期在大语言模型推理能力提升方面取得了显著成功,被广泛应用于数学求解、编程任务等领域。代表方法包括 GRPO、DAPO 等变体。然而,2025 年 NeurIPS Best Paper Runner-Up 研究表明,RLVR 可能并未真正提升模型的推理容量上限,而仅仅是提高了采样效率。2


1. RLVR 基础

1.1 什么是可验证奖励

可验证奖励(Verifiable Rewards)是 RLVR 的核心概念,其定义为:

能够客观判定模型输出正确性的奖励信号,通常是二元值(正确/错误)或数值评分。

可验证奖励的特征

特征说明
确定性奖励函数 对相同输入总是返回相同结果
可计算性奖励可由程序自动计算,无需人工标注
稀疏性通常仅在序列末端(terminal)给出奖励

典型应用场景

  • 数学推理:答案正确性可精确验证(如 GSM8K、MATH 数据集)
  • 代码生成:通过执行代码并对比输出验证正确性
  • 形式化证明:证明验证器可自动检查证明有效性

1.2 奖励类型

RLVR 中的奖励可分为两类:

终态奖励(Terminal Reward)

仅在完整响应生成后给出奖励:

其中 为输入问题, 为模型生成的答案。

过程奖励(Process Reward)

对推理过程中的每个中间步骤给予奖励:

这种奖励方式能提供更细粒度的学习信号,但需要可靠的步骤验证器。

1.3 RLVR 的优势

┌─────────────────────────────────────────────────────────────────┐
│                      RLVR 优势                                   │
│                                                                  │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐            │
│  │  数据效率高  │   │   无奖励 hack │   │   可扩展性强 │            │
│  │  单样本即可 │   │  客观验证    │   │  自动化训练  │            │
│  └─────────────┘   └─────────────┘   └─────────────┘            │
│                                                                  │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐            │
│  │  激励推理   │   │  多样性保持 │   │   训练稳定  │            │
│  │  探索解题路径│   │  减少模式崩塌│   │  梯度可控  │            │
│  └─────────────┘   └─────────────┘   └─────────────┘            │
└─────────────────────────────────────────────────────────────────┘

核心优势详解

  1. 样本效率:One-Shot RLVR 研究表明,仅使用一个训练样本即可有效提升推理能力3
  2. 无偏奖励信号:可验证奖励避免了人类主观偏好带来的偏差
  3. 可扩展自动化:无需人工标注,可大规模生成训练数据

2. One-Shot RLVR 机制分析

2.1 核心思想

One-Shot RLVR 证明:使用单一精心挑选的训练样本,即可有效激励模型的数学推理能力。3

直觉解释

  • 单一正确样本提供了解题路径的”锚点”
  • 模型通过对比自己生成的多个响应,学习区分正确与错误的推理路径
  • 即使只有一个正例,采样多样性也能产生有效的学习信号

2.2 采样策略

One-Shot RLVR 的关键在于选择高质量的单一训练样本。论文提出使用响应方差作为评估标准:

def select_best_sample(prompt, model, n_candidates=32):
    """
    选择最具多样性的训练样本
    
    策略:选择生成响应与参考响应差异最大的样本
    这类样本往往包含更丰富的推理信息
    """
    responses = [model.generate(prompt) for _ in range(n_candidates)]
    
    # 计算响应间的互信息或熵
    diversity_scores = []
    for i, resp in enumerate(responses):
        # 与其他响应的平均编辑距离
        avg_dist = sum(edit_distance(resp, r) for j, r in enumerate(responses) if j != i) / (n_candidates - 1)
        diversity_scores.append(avg_dist)
    
    # 选择多样性最高的样本
    best_idx = np.argmax(diversity_scores)
    return responses[best_idx]

2.3 为什么 One-Shot RLVR 有效

理论分析

为待训练的策略模型, 为参考(基座)模型。对于单一训练样本 ,RLVR 的目标是:

是确定性终态奖励时:

这意味着策略需要最大化生成正确答案的概率,同时保持与基座模型的相似性。

关键洞察

现象解释
采样多样性即使单一正例,通过多次采样可探索不同推理路径
奖励对比正确响应获得 ,错误响应 ,形成对比学习效果
KL 约束防止模型过拟合到单一模式,保持泛化能力

3. RLVR vs GRPO/DAPO/PPO 对比

3.1 算法概述

当前主流的 LLM 推理训练算法可分为三类:

PPO(Proximal Policy Optimization)

原始的策略优化算法,需要额外训练价值网络(Value Network):

其中 是概率比, 是优势函数估计。

GRPO(Group Relative Policy Optimization)

DeepSeek 提出的 PPO 简化版本,无需价值网络:

其中 ,使用组内归一化的奖励作为优势估计。

DAPO(Decoupled Clip and Dynamic sAmpling Policy Optimization)

基于 GRPO 的改进,提出四个关键技术4

  1. Clip-Higher:提高剪裁上限,允许更大的策略更新
  2. Dynamic Sampling:过滤掉始终正确或始终错误的样本
  3. Token-Level Policy Gradient Loss:在 token 级别计算损失,而非序列级别
  4. Overlong Reward Shaping:对过长响应进行惩罚

3.2 算法对比表

维度PPOGRPODAPO
价值网络需要不需要不需要
计算复杂度
奖励归一化需外部处理组内归一化组内归一化
Token 级损失序列级序列级✅ 支持
过拟合控制KL 惩罚KL 惩罚Clip-Higher
代表性工作GPT-4, ClaudeDeepSeek-MathByteDance

3.3 关键差异分析

PPO vs GRPO vs DAPO 流程对比
═══════════════════════════════════════════════════════════════════════

PPO:
┌────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────┐
│ Sampling│ →  │ Value Update│ →  │ Advantage  │ →  │ Policy  │
│  G responses│  │ Network     │    │ Estimation │    │ Update  │
└────────┘    └─────────────┘    └─────────────┘    └─────────┘
                    ↑                                      │
                    └──────────────────────────────────────┘

GRPO:
┌────────┐    ┌─────────────────────────┐    ┌─────────┐
│ Sampling│ →  │ Relative Reward Normalize│ →  │ Policy  │
│  G responses│  │ (μ=0, σ=1 per group)    │    │ Update  │
└────────┘    └─────────────────────────┘    └─────────┘
                     ↑                             │
                     └─────────────────────────────┘

DAPO:
┌────────┐    ┌──────────────┐    ┌──────────────┐    ┌─────────┐
│ Sampling│ →  │Dynamic Filter│ →  │Token-Level   │ →  │Policy   │
│  G responses│  │(remove trivial)│   │Loss + Clip-Hi│   │Update   │
└────────┘    └──────────────┘    └──────────────┘    └─────────┘

3.4 DAPO 四项关键技术详解

1. Clip-Higher

原始 PPO/GRPO 使用对称剪裁 ,DAPO 发现对于 LLM 推理场景,应使用非对称剪裁:

这允许策略更多地增加高奖励轨迹的概率。

2. Dynamic Sampling

在训练过程中,动态过滤掉无效样本:

3. Token-Level Policy Gradient Loss

将序列级损失分解为 token 级:

仅在成功轨迹中对 token 级概率进行优化。

4. Overlong Reward Shaping

对超过长度阈值 的响应施加额外惩罚:


4. RLVR 的局限性:pass@k vs 推理容量

4.1 核心发现

2025 年 NeurIPS Best Paper Runner-Up 研究系统地揭示了 RLVR 的根本性局限。2

核心结论

RLVR 并未真正提升 LLM 的推理容量(Reasoning Capacity),而仅仅是提高了采样效率

4.2 Pass@K 指标分析

Pass@K 定义:从 个采样中至少有一个正确的概率。

其中 是第 次采样正确的概率。

关键观察

指标RLVR 模型基座模型
Pass@1更高较低
Pass@10/100较低更高
推理覆盖范围较窄较广
Pass@K 曲线对比
═══════════════════════════════════════════════════════════════════

Pass@K
  ↑
1.0├                                              ━━ 基座模型
   │                                           ╱
   │                                        ╱
0.8│                                     ╱
   │                                  ╱
   │                               ╱
0.6│                            ╱
   │                         ╱
   │                      ╱
0.4│                   ╱━━━━━━  RLVR模型
   │               ╱
   │            ╱
0.2│         ╱
   │      ╱
   │   ╱
   │╱
   └──────────────────────────────────────────→ K
      1    2    5   10   20   50  100

4.3 推理容量(Reasoning Capacity)

定义:模型在大量采样下()能够解决问题的最大比例。

研究发现

  1. RLVR 缩小了推理覆盖范围:RLVR 训练后,模型在更多问题上的一致性降低
  2. 基座模型在极限采样下更强:当允许大量采样时,基座模型能解决更多问题
  3. RL 降低熵:训练过程使模型分布更加”尖锐”,减少了探索空间

4.4 为什么 RLVR 不能提升推理容量

理论解释

为基座模型策略, 为 RLVR 训练后的策略。

RLVR 优化目标可写为:

这等价于在基座模型的邻域内寻找最优策略。关键洞察

任何新发现的解题路径都必须通过 KL 约束,这意味着 RLVR 不能发现基座模型能力范围之外的新解法

4.5 采样效率 vs 推理容量

维度RLVR大量采样基座模型
目标提高 Pass@1提高 Pass@K
适用场景推理成本受限允许多次尝试
推理容量可能下降保持最大
最优选择实际应用理论研究

5. 数学公式推导:RLVR 目标函数

5.1 马尔可夫决策过程(MDP) formulation

LLM 推理可建模为有限时域马尔可夫决策过程:

其中:

  • :状态空间(包含输入 prompt 和已生成的 tokens)
  • :动作空间(词汇表)
  • :转移概率函数(确定性:给定状态和动作,下一状态确定)
  • :奖励函数
  • :折扣因子(通常 用于终态任务)
  • :最大步数

5.2 终态奖励设置

对于纯推理任务,奖励仅在终端状态给出:

其中 是完整生成的响应, 是终态奖励函数(如答案匹配检测器)。

5.3 PPO 目标函数

原始 PPO 的 clipped 目标函数:

优势函数 由价值网络 估计:

其中 是时序差分(TD)误差。

5.4 GRPO 目标函数推导

GRPO 通过简化消除了价值网络的需求。对于同一输入 采样 个响应

  1. 组内奖励归一化

  2. KL 正则化的对比损失形式:论文证明 GRPO 可以写成 KL 正则ized 的对比损失5

    其中 是正样本(), 是负样本(), 是序列的对数概率和。

5.5 RLVR 的信息论解释

从信息论角度,RLVR 的目标是最大化奖励相关的互信息

其中:

  • 是奖励分布的熵(固定,由数据集决定)
  • 是在给定策略 下奖励的剩余熵

直观理解:RLVR 降低了对给定策略的奖励不确定性,即让策略更”确定”地产生高奖励响应。但这同时也可能减少了分布的熵,限制了模型探索不同解题路径的能力。


6. 实践指南:何时使用 RLVR

6.1 适用场景

RLVR 效果好的场景

场景原因示例
强验证标准可精确判定答案正确性数学题、代码执行
任务边界清晰输出格式可解析LeetCode、GSM8K
计算资源有限Pass@1 提升显著实时推理服务
已有基座模型推理能力足够,只需微调Qwen Math、DeepSeek

6.2 不适用场景

RLVR 效果差或不适用的场景

场景原因替代方案
开放式生成无明确验证标准RLHF、DPO
需要创新解法RL 难以发现新路径SFT + CoT prompting
长程规划稀疏奖励难以学习Process Reward、HER
安全关键任务reward hacking 风险Human-in-the-loop

6.3 训练配置建议

# RLVR 训练配置示例
config = {
    # 算法选择
    "algorithm": "GRPO",  # 推荐:GRPO 或 DAPO
    
    # 采样参数
    "num_generations": 16,      # 每批采样数(影响组内归一化)
    "max_tokens": 2048,         # 最大生成长度
    "temperature": 1.0,          # 采样温度
    
    # 优化参数
    "learning_rate": 1e-6,      # 学习率(通常较小)
    "beta": 0.01,                # KL 惩罚系数
    "epsilon": 0.2,              # PPO 剪裁参数
    
    # 奖励设置
    "reward_type": "terminal",  # terminal 或 process
    "reward_norm": "group",     # 组内归一化
    
    # DAPO 特有
    "clip_high": 0.4,           # Clip-Higher 参数
    "dynamic_sampling": True,   # 动态采样
    "token_level_loss": True,   # Token 级损失
    "length_penalty": 0.001,   # 长度惩罚系数
}

6.4 算法选择流程

开始
  │
  ▼
问题是否有明确的验证标准?
  │
  ├─ 否 → 不适合 RLVR,考虑 RLHF/DPO
  │
  └─ 是 → 是否需要 Token 级信用分配?
           │
           ├─ 否 → GRPO(简单高效)
           │
           └─ 是 → 考虑 DAPO 或 Process Reward
                     │
                     ▼
              是否对响应长度敏感?
               │
               ├─ 是 → DAPO(带 Overlong Shaping)
               │
               └─ 否 → 基础 GRPO + 长度过滤

7. PyTorch 代码示例

7.1 GRPO 训练循环

import torch
import torch.nn.functional as F
from torch.distributions.categorical import Categorical
 
def grpo_loss(
    log_probs: torch.Tensor,      # Shape: (batch_size, num_generations, seq_len)
    rewards: torch.Tensor,         # Shape: (batch_size, num_generations)
    ref_log_probs: torch.Tensor,   # Shape: (batch_size, num_generations, seq_len)
    beta: float = 0.01,
    epsilon: float = 0.2,
) -> torch.Tensor:
    """
    GRPO Loss 计算
    
    Args:
        log_probs: 当前策略的 token 级对数概率
        rewards: 每条序列的终态奖励
        ref_log_probs: 参考策略的对数概率
        beta: KL 惩罚系数
        epsilon: PPO 剪裁参数
    
    Returns:
        GRPO 损失
    """
    batch_size, num_generations, seq_len = log_probs.shape
    
    # 组内奖励归一化(计算优势)
    rewards_mean = rewards.mean(dim=1, keepdim=True)
    rewards_std = rewards.std(dim=1, keepdim=True) + 1e-8
    advantages = (rewards - rewards_mean) / rewards_std  # (B, G)
    
    # 序列级对数概率
    seq_log_probs = log_probs.sum(dim=-1)  # (B, G)
    seq_ref_log_probs = ref_log_probs.sum(dim=-1)  # (B, G)
    
    # 概率比率 r(θ)
    ratio = torch.exp(seq_log_probs - seq_ref_log_probs)  # (B, G)
    
    # Clipped 目标
    clipped_ratio = torch.clamp(ratio, 1 - epsilon, 1 + epsilon)
    
    # PPO-style 损失
    policy_loss = -torch.min(
        ratio * advantages.unsqueeze(-1),
        clipped_ratio * advantages.unsqueeze(-1)
    ).mean()
    
    # KL 惩罚
    kl_penalty = F.kl_div(
        seq_log_probs,
        seq_ref_log_probs,
        reduction='batchmean',
        log_target=True
    )
    
    return policy_loss + beta * kl_penalty
 
 
def training_step(
    model,
    ref_model,
    prompts: list[str],
    tokenizer,
    reward_fn,
    optimizer,
    num_generations: int = 16,
    **config
):
    """
    单步 GRPO 训练
    """
    device = next(model.parameters()).device
    
    # 1. 对每个 prompt 采样多个响应
    all_responses = []
    all_log_probs = []
    
    for prompt in prompts:
        input_ids = tokenizer(prompt, return_tensors='pt')['input_ids'].to(device)
        
        # 多次采样
        batch_responses = []
        batch_log_probs = []
        
        for _ in range(num_generations):
            with torch.no_grad():
                outputs = model.generate(
                    input_ids,
                    max_new_tokens=config.get('max_tokens', 512),
                    do_sample=True,
                    temperature=config.get('temperature', 1.0),
                )
            
            response_ids = outputs[0, input_ids.shape[1]:]
            batch_responses.append(response_ids)
            
            # 计算 log_prob(需要用训练模式重新计算)
            outputs_train = model(outputs)
            log_probs = F.log_softmax(outputs_train.logits, dim=-1)
            
            # token 级 log prob
            token_log_probs = log_probs[0, :-1].gather(1, outputs[0, 1:].unsqueeze(-1)).squeeze(-1)
            batch_log_probs.append(token_log_probs)
        
        all_responses.append(torch.stack(batch_responses))
        all_log_probs.append(torch.stack(batch_log_probs))
    
    # 2. 计算奖励
    responses_text = [tokenizer.decode(r) for r in torch.cat(all_responses, dim=0)]
    prompts_repeated = [p for p in prompts for _ in range(num_generations)]
    rewards = torch.tensor([
        reward_fn(p, r) for p, r in zip(prompts_repeated, responses_text)
    ], device=device).view(len(prompts), num_generations)
    
    # 3. 参考模型 log prob
    with torch.no_grad():
        ref_log_probs_all = []
        for resp_ids in torch.cat(all_responses, dim=0).split(1, 0):
            ref_outputs = ref_model(resp_ids.squeeze(0).unsqueeze(0))
            ref_log_probs = F.log_softmax(ref_outputs.logits, dim=-1)
            ref_token_log_probs = ref_log_probs[0, :-1].gather(
                1, resp_ids.squeeze(0)[1:].unsqueeze(-1)
            ).squeeze(-1)
            ref_log_probs_all.append(ref_token_log_probs)
        ref_log_probs = torch.stack(ref_log_probs_all).view(len(prompts), num_generations, -1)
    
    # 4. 计算损失并更新
    log_probs = torch.stack(all_log_probs).to(device)
    
    loss = grpo_loss(
        log_probs=log_probs,
        rewards=rewards,
        ref_log_probs=ref_log_probs,
        beta=config.get('beta', 0.01),
        epsilon=config.get('epsilon', 0.2),
    )
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    return loss.item(), rewards.mean().item()

7.2 DAPO 扩展

def dapo_extensions(log_probs, rewards, seq_lens, config):
    """
    DAPO 特有扩展
    """
    # 1. Dynamic Sampling - 过滤无效样本
    valid_mask = (rewards > 0) & (rewards < 1)  # 去除全对/全错的样本组
    
    # 2. Token-Level Policy Gradient Loss
    # 仅在成功轨迹中计算 token 级损失
    success_mask = (rewards == 1).unsqueeze(-1)  # (B, G, 1)
    masked_log_probs = log_probs * success_mask.float()
    token_loss = -masked_log_probs.mean()
    
    # 3. Overlong Reward Shaping
    max_len = config.get('max_len', 2048)
    length_penalty = config.get('length_penalty', 0.001)
    overlong_mask = (seq_lens > max_len).float()
    reward_shaping = -length_penalty * overlong_mask * (seq_lens - max_len).float()
    
    # 4. Clip-Higher 调整
    clip_high = config.get('clip_high', 0.4)
    # 在计算 policy loss 时使用非对称 clip
    
    return token_loss, reward_shaping

8. 相关主题

RLVR 与以下主题密切相关:


9. 参考文献


本文档最后更新于 2026-05-14

Footnotes

  1. RLVR 综述 — Awesome RLVR: Reinforcement Learning with Verifiable Rewards

  2. RLVR 的局限性 — Yue et al. “Does Reinforcement Learning Really Incentivize Reasoning Capacity in LLMs Beyond the Base Model?” NeurIPS 2025 Best Paper Runner-Up. arXiv:2504.13837 | Project Page 2

  3. One-Shot RLVR — Wang et al. “Reinforcement Learning for Reasoning in Large Language Models with One Training Example.” CoRR 2025. arXiv:2504.20571 | GitHub 2

  4. DAPO — “DAPO: An Open-Source LLM Reinforcement Learning System at Scale.” OpenReview 2025. arXiv:2503.14476

  5. GRPO 对比损失形式 — “Reinforcement Learning with Verifiable Rewards: GRPO’s Contrastive Loss Perspective.” arXiv:2503.06639 arXiv:2503.06639