Hexo

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

NLP——LLM对齐微调-RL-Collapse-Training-Inference-Mismatch(Sequence-level-MIS)

注:本文包含 AI 辅助创作

  • 参考链接:
    • 原始博客:(Sequence-level MIS)When speed kills stability: Demystifying RL collapse from the training-inference mismatch, 20250927, ByteDance
      • 博客最早发表于 20250927,目前还在持续更新,最近一次更新为 20251013
    • 其他相关 arXiv 论文:Trust Region Masking for Long-Horizon LLM Reinforcement Learning, 20251228-20260227, Fudan & CUHK
    • 引用了本文的博客

Blog Summary

  • 作者从 RL Collapse 现象入口,定位到是训推不一致问题导致的,进而详细讨论了如何解决训推不一致的问题
  • 本文整体有较强的理论意义,核心是证明了:LLM RL 的重要性采样最优是 Sequence-level 的,而 Token-level 重要性采样只有在特定情况下能够替代 Sequence-level 重要性采样,更精确的推导见 NLP——LLM对齐微调-MiniRL
  • 本文证明了:只有当 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 保持在 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\) 的信任域内时,即当 \(d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }\approx d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 且 \(A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }\approx A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 时,\(J(\theta)\) 才能被 \(g_\text{tok}(\theta)\) 优化
  • 特别说明:本文中所说的 Token-level 和 Sequence-level 都是针对重要性采样权重而言的,不是针对 RL 目标本身,本文会直接使用到类似 RL 目标的表达,容易让读者误解是 RL 建模目标本身的建模方式(Token-level or Sequence-level)
  • 本文工作已经被诸多框架引入,比如 VeRL 和 Slime 等,同时还被 Qwen 团队的 MiniRL 工作(详情见 NLP——LLM对齐微调-MiniRL)引用
    • 各种框架的使用详情见 原始博客 When speed kills stability: Demystifying RL collapse from the training-inference mismatch, 20250927, ByteDance
  • 理想中最合适的 Principled 修正方案:
    • Sequence-level IS 是数学上无偏的修正方法
      • 不是 TIS,也不是 MIS,即没有截断也没有 Mask
      • 实际使用时,特别大的比值一般是异常的,所以使用 TIS 做截断或使用 MIS 做 Mask
    • Sequence-level MIS,即对 IS 比率超过阈值 \(C\) 的序列的策略损失进行 Mask:
      $$ \rho(y|x) \gets \rho(y|x) \mathbb{I}\{\rho(y|x) \le C\} $$
      • 注意:MIS 对阈值内的部分是保留了梯度的,和 VeRL 中 RS 的实现不同
    • Token-level 的修正,如 Token-level TIS 等都是有偏的,但是方差更小,所以也常用
    • Sequence-level 的 TIS 数学上不是无偏的:
      • MIS Mask 掉超大的值,理论上将这些样本判定是异常的,如果截断,反而修改了原始 IS,引入一些误差
      • 理解:超过阈值的序列我们认为是异常的,Mask 掉更好,不影响原来的分布,但实际 截断应该也还行,毕竟 Mask 也不是随机丢弃样本,是有倾向性的丢弃,如果这部分样本不是异常呢?分布就变得有偏了!

整体介绍

TLDR

  • 对更快推理速度的不懈追求造成了一种危险的“训练-推理不一致性”,它可能悄然破坏 LLM 的强化学习
  • 作者的研究揭示了一个在现代推理和智能体 RL 中尤为严重的恶性循环:
    • OOD 上下文导致低概率采样: 智能体工作流将模型暴露于外部输入和动态环境中,迫使其频繁生成 低概率 token
      • 这些 token 对于新颖的推理、工具调用和自适应 Response 至关重要
      • 理解:这里是在说模型与外界环境交互过程中可能会遇到一些 OOD 的场景,从而生成一些原本 低概率的 Token?
        • 这里的低概率应该不是指低概率但是因为高温被采样
      • 详情见:3.4 OOD Tool Responses Amplifies the Mismatch 章节
    • 低概率 Token 放大训练崩溃: 这些 token 成为最薄弱的环节
      • 训练-推理不一致性对它们最为严重,导致灾难性的大梯度,从而引发性能悄然下降和突然的训练失败
      • 详情见本文 3.3 确凿证据:低概率 Token 陷阱 章节
    • 硬件差异使问题复杂化:
      • 不同的 GPU 架构会以不可预测的方式加剧不一致性,这意味着相同的智能体训练设置在一台机器上可能成功,而在另一台上可能灾难性地失败
      • 详情见:3.5 环境因素:硬件的关键作用 章节
    • Sequence-level 修正是 Principled 解决方案:
      • Sequence-level IS 修正 是数学上无偏的修复方法
      • 详情见:4.2.1 一个 Principled 解决方案:分布修正

Deeper Analysis:

  • 为了对这个问题进行严格的理论分解,作者发表了三篇系列博客:
    • Part 1: Why Off-Policy Breaks RL — An SGA Analysis Framework
      • 第 1 部分包含主要内容:为何 Off-Policy 会破坏 RL——SGA 分析框架
      • 已知 (TRPO 理论):
        • 替代目标 \(L_\mu(\pi)\) 是 RL 目标 \(J(\pi)\) 的一阶泰勒近似
        • TRPO 下界 \(J(\pi) \ge L_\mu(\pi) - C \cdot T^2 \cdot D_{TV}^{\max}\) 表明近似误差随 \(T^2\) 增长,需要信任域按 \(\delta \propto 1/T^2\) 缩小
      • 作者的主要 Insight:
        • Token-level IS (PPO/GRPO) 计算的是 \(\nabla L_\mu\),而不是 \(\nabla J\)
        • Token-level IS 修正了 token 分布,但没有修正状态分布的不匹配 (\(d_\mu \ne d_\pi\)),导致 \(O(T^2 D_{TV}^{\max})\) 的偏差
      • 作者通过 SGA 引理形式化了两种失败模式 :
        • 偏差 (Bias) (由 \(D_{TV}\) 衡量)
        • 方差 (Variance) (由 \(\chi^2\) 散度衡量)
        • 作者认为这两个指标不可互换
    • Part 2: Applying the SGA Framework — Token v.s. Sequence-level Correction
      • 第 2 部分主要内容:讨论 Token-level 与 Sequence-level 修正的对比(讨论 Part 1 中 SGA 框架的应用)
      • 作者的分析:
        • Token-level IS (PPO/GRPO) 由于替代目标的一阶近似误差而产生 \(O(T^2 D_{TV}^{\max})\) 的偏差
        • Sequence-level IS 是无偏的,但具有指数级方差 \(O((1+\bar{\chi}^2_{\max})^T)\)
      • 作者的解决方案:
        • Seq-TIS 通过截断 \(\rho(y) \to \min(\rho(y), C)\) 实现了可控的偏差-方差权衡
        • 关键结论: 当 不可忽略时 ,这种偏差是一个需要 Sequence-level 解决方案的 Sequence-level 问题
    • Part 3: Trust Region Optimization via Sequence Masking
      • 第 3 部分内容:讨论通过序列掩码实现信任域优化
      • 已知 (TRPO 理论):
        • 信任域约束确保替代目标仍然是一个有效的近似
      • 作者的解决方案:
        • (1) Seq-MIS :通过拒绝 \(\mathbb{I}(\rho \le C) \cdot \rho \cdot f\) 来强制执行硬信任域 (Hard Trust Region),完全排除 OOD 样本
        • (2) Geo-RS :使用几何均值 \(\rho_{\text{geo} }=\rho^{1/T}\) 来实现一个 长度不变的 Per-Token 信任域 (length-invariant Per-Token Trust Region)
          • 这是 TRPO 硬信任域在 LLM 中的一种实用实现,避免了系统性地拒绝长序列

第 1 节:The Mystery of the Sudden Collapse

  • 在快速发展的用于大型语言模型的强化学习 (LLM-RL) 领域,一种令人沮丧的突然训练崩溃模式正在浮现
  • 无论是在复杂的 Reasoning RL 还是多轮 Agentic RL 中,许多人都观察到训练过程在一段稳定学习后,会灾难性地失败
  • 本文作者最近在 Qwen3 模型上进行 多轮工具集成推理 (multi-turn tool-integrated-reasoning,TIR) 的智能体 RL 实验时,亲身遇到了这个问题
    • 这发生在 L20 GPU 集群上 GRPO 算法的 on-policy 和 off-policy 变体上
    • 图 1 显示了作者在 Qwen3-14B-Base 上四次崩溃实验的奖励和梯度范数动态
    • 随着训练的进行,梯度范数突然爆炸,导致模型崩溃
  • 图 1
    • 在 Qwen3-14B-Base 上进行的四次失败的 GRPO TIR 实验的奖励 (左) 和梯度范数 (右)
    • 所有实验在每个训练步采样 1024 条轨迹 (64 个 Prompt × 16 个 Response ),并使用 1e-6 的学习率
    • 对于 on-policy 和 off-policy 实验,ppo_mini_batch_size 分别设置为 1024 和 256
  • 最初,作者的初步解决思路集中在常见的疑点上:
    • 作者检查了代码,确认作者的智能体循环遵循 token-in-token-out 过程
    • 作者调整了 Adam 优化器中的超参数 beta1 和 beta2
    • 作者还对优势函数应用了批归一化以平衡更新
    • …
  • 但这些标准的修复方法都不起作用
    • 因为即使是更简单的 on-policy 实验也失败了,作者怀疑问题不在于 RL 算法本身,而在于训练栈中更基础的部分
    • 这引导作者开始考虑现代 LLM-RL 中一个关键且日益普遍的挑战:高度优化的推理引擎与可靠的训练框架之间不可避免的 Gap

A Fundamental Conflict: The Growing Gap Between Inference and Training

  • 根本性冲突是推理与训练之间日益扩大的鸿沟
  • Rollout 速度是 LLM-RL 的核心瓶颈
    • 为了实现所需的海量吞吐量,现代推理引擎(例如,vLLM、SGLang、TensorRT-LLM)采用了激进的优化策略
      • 如推测解码、低精度计算 (INT8/FP8) 以及专门的、batch-variant CUDA 内核
      • 在保持采样保真度的同时,现代推理引擎的主要目标是最大化吞吐量 ,通常以每秒 token 数来衡量
    • 训练框架(例如,FSDP、DeepSpeed、Megatron-LM)必须寻求不同的平衡点,优先考虑梯度计算的数值稳定性和精度
      • 通常对主要权重和优化器状态使用 FP32 等更高精度的格式
    • 这种优化优先级和约束上的分歧造成了不可避免的训练-推理不一致性 ,而对更快 rollout 的不懈追求正使这一差距变得更大
    • 虽然有人可能提议强制实施相同的计算(例如,使用“batch invariant kernels”),但这些解决方案会带来严重的性能损失,违背了使用高速推理引擎的初衷
    • 这种速度与一致性之间的权衡是问题的核心,使其成为一个持续存在的挑战,而非简单的工程修复
  • 在作者的技术栈中,这种不匹配体现在作者的 vLLM 推理采样器和 FSDP 训练器之间
    • 实际的参数更新是:
      $$
      \mathbb{E}_{x\sim \mathcal{D} }\mathbb{E}_{y\sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }\left( \cdot |x \right)}\left[ R\left( x,y \right) \nabla_{\theta}\log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\left( y|x \right) \right]
      $$
    • 而理论上的参数更新应该是:
      $$
      \mathbb{E}_{x\sim \mathcal{D} }\mathbb{E}_{y\sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\left( \cdot |x \right)}\left[ R\left( x,y \right) \nabla_{\theta}\log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\left( y|x \right) \right].
      $$
      • \(x\) 是从分布 \(\mathcal{D}\) 中采样的 Prompt
      • \(y\) 是 Response
      • \(R\) 是奖励函数
      • \(\theta\) 是 LLM 的参数
      • \(\color{red}{\pi^\text{vllm}_\theta}\) 和 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 分别是 vLLM 引擎和 FSDP 引擎中实现的策略
        • 注:接下来,为了讨论这一点,作者找了一种方法来衡量它

Anatomy(剖析)of the Training Collapse

3.0 Experiments Setup

  • 除非另有说明,第 3 节 和 第 4 节 中展示的实验是在 TIR Setting 下的 VeRL 框架上进行的,使用 vLLM v1 采样器 (AsyncvLLMServer)、Qwen3-14B-Base 模型和 GRPO 算法,全部在 L20 GPU 集群上运行

Measuring the Mismatch: The vllm-kl Metric

  • 一个衡量训练-推理不一致性的非常直接的指标是 vllm-kl :
    $$
    \small{\mathbb{E}_{s\sim d_{\color{red}{\pi^\text{vllm}_\theta} } }\left[\text{KL}\left(\color{red}{\pi^\text{vllm}_\theta}\left(\cdot|s\right),\color{blue}{\pi^\text{fsdp}_\theta}\left(\cdot|s\right)\right)\right] = \mathbb{E}_{s\sim d_{\color{red}{\pi^\text{vllm}_\theta} },a\sim {\color{red}{\pi^\text{vllm}_\theta}\left(\cdot|s\right)} } \left[\log\left(\frac{\color{red}{\pi^\text{vllm}_\theta}(a|s)}{\color{blue}{\pi^\text{fsdp}_\theta}(a|s)}\right)\right],}
    $$
    • \(d_\pi\) 是策略 \(\pi\) 的状态占用 (state-occupancy)
    • \(s\) 是上下文前缀(状态)
    • \(a\) 是 token(动作)
    • 注:作者的实验涉及工具调用,这意味着 Response \(y\) 可能包含工具 Response
      • 问题:这个公式中似乎没有看到任何 \(y\) 的表达式啊
      • 理解:这里应该是强调除了用户输入的 Query(Prompt)后,用户得到的 Reponse 部分会包含工具调用的返回结果(比如调用 Python 执行数学计算)
        • 注:TIR 中,模型 Reasoning 过程中会和工具交互,得到工具调用的结果,然后基于工具调用结果继续 Reasoning(一次 Response 可能包含多次工具调用),并最终整合后返回给用户
    • 注:本文中定义的 vllm-kl 指标只考虑模型自身生成的 token
      • 理解:这样才是合适的,因为工具调用的结果不是模型输出的,对模型来说只是环境信息(类似 Query),不需要模型关注,模型也无法修改
  • 以下代码提供了在 VeRL 中使用 K3 估计器 计算 vllm-kl 指标的实现,假设推理引擎的 token 概率已经是可访问的:
    1
    2
    3
    4
    5
    6
    rollout_log_probs = batch.batch["rollout_log_probs"] # pi_vllm
    actor_old_log_probs = batch.batch["old_log_probs"] # pi_fsdp
    response_mask = batch.batch["response_mask"]
    log_ratio = actor_old_log_probs - rollout_log_probs
    vllm_k3_kl_matrix = torch.exp(log_ratio) - log_ratio - 1
    vllm_k3_kl = masked_mean(vllm_k3_kl_matrix,response_mask)

The Warning Signs: Correlated Instability

  • 作者的第一条线索是,高 vllm-kl 值并非孤立事件
    • 它们与其他不稳定迹象密切相关
Fluctuations in FSDP Entropy and Rewards
  • 在许多实验中都可以观察到 vllm-kl 的异常尖峰(Spike)通常会同时触发 FSDP 策略 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 的熵和奖励的异常波动
  • 图 2 所示的实验结果是一个直观的例子
    • 如图 2 所示,熵尖峰出现的位置与 vllm-kl 尖峰的位置几乎完美对应
    • 虽然在奖励中没有观察到同样明显的相关性,但可以看到在步骤 250 左右出现了一个巨大的 vllm-kl 尖峰,它触发了低质量批次的生成,并在此处也导致了奖励的明显下降
    • 这意味着当不一致性较大时,vLLM 策略 \(\color{red}{\pi^\text{vllm}_\theta}\) 和 FSDP 策略 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 都进入了一个不稳定区域
Rising FSDP PPL and Gradient Norm Leading to Policy Collapse,上升的 FSDP PPL 和梯度范数导致策略崩溃
  • 作者观察到 vllm-kl 的尖峰同时触发了 fsdp-ppl 指标和梯度范数的爆炸
    • 在作者的实验中, Response \(y\) 的 fsdp-ppl 指标计算如下:
      $$
      \text{fsdp-ppl}: \exp\left(\frac{-1}{\left| \mathcal{T}_{\mathcal{M} }\left( y \right) \right|}\sum_{t\in \mathcal{T}_{\mathcal{M} }\left( y \right)}{\log \color{blue}{\pi_{\theta}^{\text{fsdp} } }\left( y_t|y_{ < t} \right)}\right)
      $$
      • \(\mathcal{T}_{\mathcal{M} }\left( y \right)\) 是 Response \(y\) 中由模型自身生成的 token 的索引集合
      • 最终的 fsdp-ppl 指标是批次中所有 Response 的 fsdp-ppl 指标的平均值
  • 图 3 展示了 GRPO 的 on-policy 版本和 off-policy 版本的实验结果
    • 在两个实验中,vllm-kl 的尖峰几乎精确地触发了 fsdp-ppl 和梯度范数的相应爆炸
    • 还可以观察到,在训练奖励崩溃之前,vllm-kl 指标有显著的上升
  • 在本文的实验中,模型自身生成的序列至少包含数百个 token
    • 原本的期望:在训练的后期阶段,ppl 指标保持在 1 左右更为合理
      • 理解:
        • 因为后期熵基本收敛了,大部分 Generated Token 的概率都是 1.0 左右,此时对应的对数概率接近 0,整体 Token 粒度的对数概率均值也接近 0,从而得到的 PPL 则接近 1
        • 实际上, Token 概率是微小于 1 的,对数概率微小于 0,取 -1 得到的值微大于 0,得到的指数(PPL)微大于 1
      • 问题:Off-policy(对应 Bottom)下的 PPL 应该接近于 1 才对,目前看起来是接近于 0 的,不太符合预期
        • 回答:这里的图是对的,因为这个图的单位是 1e32,所以看起来似乎在 0 左右
    • 观察到的现象:在训练-推理不一致性显著的批次中(即 vllm-kl 非常高时),作者观察到 fsdp-ppl 指标发生爆炸 这表明 FSDP 引擎为推理策略采样的 token 分配了灾难性的低概率,导致梯度爆炸
    • 这一观察帮助进一步定位了不一致性更可能发生的地方
      • 当这些 FSDP 概率极低的 token 被采样时,它们在 vLLM 引擎中的概率并非同样低
        • 补充说明:在本人的实际训练过程中,也观察到许多类似的现象,这种在当前策略低概率的 Token 会引发 KL 散度 k3 估计的爆炸(因为 Old 策略对应的 Token 概率不一定同样低)
      • 这个问题也是导致 KL 散度差异较大的其中一个原因

The Smoking Gun: The Low-Probability Token Pitfall,低概率 Token 陷阱的确凿证据

  • 核心 Insight:不一致性并非均匀分布
  • 通过分析具有不同 vllm-kl 水平的批次,作者发现了一个鲜明的模式:
    • 对于 vLLM 推理引擎认为概率较低 (low probability) 的 token,这种差异最为严重
    • 当一个 token 的推理概率趋近于零时,其训练概率可能会小几个数量级,从而导致无限的 PPL 和梯度
  • 为了确保结论尽可能具有普适性,作者选取了 在训练崩溃前、不同训练步数 从各种实验中采样的批次
    • 所有这些批次都表现出相对较高的 vllm-kl 值,使作者能够在显著条件下研究不一致性模式
    • Rollout 批次在以下三个 vllm-kl 范围内收集,每组五个批次(约 5M token):
      • Group 1 (low): 每个 rollout batch 的 vllm-kl 不大于 1e-3,并且批次是使用 H20 GPU 采样的
      • Group 2 (medium): 每个 rollout batch 的 vllm-kl 属于 [1e-3, 2e-2],并且批次是使用 L20 GPU 采样的
      • Group 3 (high): 每个 rollout batch 的 vllm-kl 属于 [2e-2, 1e-1],并且批次是使用 L20 GPU 采样的
  • 下面的图 4 (a)(b)(c) 展示了在不同 vllm-kl 量级下,vLLM 引擎的输出概率
    • 即 \(\color{red}{\pi^\text{vllm}_\theta}(a|s)\) 与不一致性之间的关系,这里的不一致性由 \(\log\left(\color{blue}{\pi^\text{fsdp}_\theta}(a|s)\right)-\log\left(\color{red}{\pi^\text{vllm}_\theta}(a|s)\right)\) 衡量:
  • 从上图中,我们可以清晰地观察到:
    • 当 vLLM 概率 \(\color{red}{\pi^\text{vllm}_\theta}\) 趋近于零时,不一致程度往往更为显著
      • 并且 \(\log\left(\color{blue}{\pi^\text{fsdp}_\theta}\right)-\log\left(\color{red}{\pi^\text{vllm}_\theta}\right)\) 的极端值更可能在这些条件下出现
    • 在 L20 GPU 上收集的批次,即组 2 和组 3 中的批次,表现出一种训练-推理不一致性
      • 主要表现为 FSDP 概率 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 显著小于 vLLM 概率 \(\color{red}{\pi^\text{vllm}_\theta}\)

OOD Tool Responses Amplifies the Mismatch,OOD 工具 Response 放大了不一致性

The Mismatch Is More Severe in Non-First-Round Outputs,不一致性在非首轮输出中更为严重
  • 第 3 节的发现解释了为什么这个问题在作者的多轮 TIR 实验中如此尖锐,特别是在非首轮模型输出 (non-first-round model outputs) 中
  • 该过程如下:
    • 1)Agent 接收一个工具 Response ,这通常是结构化文本(例如,包含在 <python_output> 和 </python_output> 标签中的上下文),相对于其预训练和 SFT 数据而言是 OOD 的
      • 注意:这是工具的 Response
    • 2)面对这种不熟悉的 OOD 上下文,智能体的策略 变得更加不确定,使其更有可能在其后续轮次中采样低概率 token(这在 SimpleTIR 中也有观察到)
    • 3)正如作者刚刚确定的,这些低概率 token 是发生严重不一致性的主要场所,为 fsdp-ppl 和梯度的爆炸创造了条件
  • 作者绘制了三组批次(每组约 5k 条轨迹)中的不一致性,突出了首轮模型输出和非首轮模型输出之间的差异,作者考虑以下两种方法来可视化不一致性:
    • Log-ppl scatter plot(散点图) :
      • x 轴:由 vLLM 策略 \(\color{red}{\pi^\text{vllm}_\theta}\) 计算的 ppl 指标的对数,记为 vllm-log-ppl
      • y 轴:由 FSDP 策略 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 计算的 ppl 指标的对数,记为 fsdp-log-ppl
    • Probability scatter plot :
      • x 轴:vLLM 策略 \(\color{red}{\pi^\text{vllm}_\theta}\) 的 token 概率
      • y 轴:FSDP 策略 \(\color{blue}{\pi^\text{fsdp}_\theta}\) 的 token 概率
  • 三组不一致性的可视化结果
  • 从可视化结果中,作者可以观察到:
    • 1)非首轮输出的 vllm-log-ppl 通常大于首轮输出,这意味着在面对不熟悉的 OOD 上下文时,会采样到更多的低概率 token
      • 横向比较 log-ppl 可以看出,非首轮的横轴和纵轴范围均较大(注:从图中可以看出,首轮的 log-ppl 集中在左下角,非首轮的覆盖面积则更广)
      • 理解:相当于熵变高了(即 PPL 变大了),此时 Token 的概率都不高,输出的不确定性增高
    • 2)不一致性主要发生在非首轮模型输出中(第二列为非首轮)
      • 表现为 FSDP 策略与 vLLM 策略之间的 log-ppl 和 token 概率的平均绝对差更大,皮尔逊相关系数更低
    • 3)随着 vllm-kl 值的增加,训练-推理不一致性主要在非首轮输出中恶化
    • 4)不一致性始终显示 fsdp-log-ppl 大于 vllm-log-ppl,表明 FSDP 引擎产生了更极端的低概率 token
      • 问题:为什么 fsdp-log-ppl 相对 vllm-log-ppl 会严格偏大呢?甚至一个小于的点都看不到?
More Tool Calls, More Training Instability,工具调用越多,训练不稳定性越大
  • 本节的实验表明,OOD 工具 Response 加剧了训练-推理不一致性和训练不稳定性
  • 在 H20 GPU 上使用 Qwen3-14B-Base 作为基础模型,进行了 off-policy GRPO 实验,设置 clip higher=0.28 和 4 个 mini-batches
  • 将单条轨迹中最大工具调用次数(超参数 max_tool_turn)分别设置为 20 和 100
  • 实验结果如图 5 和图 6 所示,可以观察到:
    • 随着工具调用次数的增加,训练崩溃发生的时间更早(轮次越多,爆炸越快)
    • 崩溃时,在所有情况下都观察到了梯度爆炸和 vllm-kl 的爆炸

The Environmental Factor: The Critical Role of Hardware

  • 作者还发现物理硬件是一个关键变量
    • 完全相同的代码和模型在不同的 GPU 硬件上产生了截然不同的不一致性水平
  • 为了评估不同硬件上的不一致性程度,作者在相同的代码环境和超参数下运行 on-policy 算法,仅在推理和训练时切换不同的 GPU
  • 图 7 分别展示了在 L20、H20 和 A100 上的训练动态
  • 从图中可以观察到
    • 实验中 vllm-kl 的量级基本遵循:H20 < L20 < A100
      • H20 的 vllm-kl 通常在 5e-4 到 1e-3 的量级
      • L20 大约在 1e-3 到 1e-2
      • A100 主要在 1e-2 到 1 之间
    • 由于 A100 上严重的训练-推理不一致性,正常训练变得不可行,导致奖励曲线高度不稳定
  • 在作者的 A100 GPU 上运行 的实验中,禁用 vLLM 引擎中的级联注意力 (cascade attention) 特别有助于减少不一致性
    • 作者在 第 4.2.4 节(在 vLLM 中禁用级联注意力) 中展示了这些结果
  • 最有力的证据来自于作者将一个失败的 L20 实验从其 checkpoint 开始在 H20 GPU 上恢复训练(见图 8)
    • 训练立即稳定并恢复,证明了硬件对该问题的 First-order 影响

The Mismatch is Not Static: A Vicious Cycle Driven by Optimization

  • 这种不一致性并非静态的,而是由优化驱动的恶性循环
  • 有人可能认为训练-推理不一致性是硬件和软件栈的静态属性
    • 但作者接下来的“Batch-filter”实验证明,除了与硬件和软件栈有关,不一致性还与训练动态和模型状态有关,即 不一致性与训练动态和模型状态是耦合的
  • 作者在 “Batch-filter” 实验中设置了以下策略更新方式:
    • 对于每个训练步,如果收集到的批次产生的 vllm-kl 指标大于阈值
      • 则跳过在该批次上更新模型参数 (因为此类更新带着噪音的,容易导致训练崩溃)
      • 此时直接进入下一步,继续收集数据,直到获得 vllm-kl 值低于阈值的批次,此时才更新模型
  • 这个实验背后的逻辑是,如果不一致性的程度完全独立于模型的输出分布和训练动态,那么 vllm-kl 的量级在不同的训练步应呈现相同的分布
  • 但图 9 所示的实验结果表明,一旦模型进入某种状态,它就开始持续生成高不一致性的批次 ,从而发生持续过滤,几乎停止了训练(右图橙黄色背景部分)
  • 这一点,连同在其他运行中观察到的 vllm-kl 和 fsdp-ppl 螺旋式上升(图 10),指向了一个危险的反馈循环
  • 作者推测这是由于以下两阶段的失败级联 (two-stage failure cascade) 造成的:
    • 1)阶段 1:数值敏感性增加
      • RL 优化器将模型权重推入 bfloat16 数据类型具有较低相对精度的数值范围(例如,非常小或非常大的值)
    • 2)阶段 2:内核驱动的误差放大
      • 这些初始的、微小的 bfloat16 量化误差随后被输入到 vLLM 和 FSDP 的不同内核实现中
      • 不同的计算顺序充当非线性放大器,导致微小的初始偏差滚雪球般地变成最终 logits 的巨大差异
    • 这就形成了一个恶性反馈循环 :
      • 不一致性导致有偏且嘈杂的梯度,这可能进一步将参数推入数值敏感区域 ,这反过来又会使下一次迭代的不一致性恶化,直到系统崩溃
    • 另一个个人理解:
      • 如果参数超错误的未知噪音方向更新,那么更新后的模型采样得到的结果可能是奇怪的,即一些原本低概率的 Token 会更容易被采样出来(推测熵可能会异常的增大),这样的 Token 更容易导致更大的 vllm-kl

Attempts to Alleviate Training-Inference Mismatch,介绍缓解训练-推理不一致性的一些尝试

  • 接下来将列出作者尝试过的缓解训练-推理不一致性的方法
    • 其中一些方法有帮助,而另一些则没有

Ineffective Attempts,无效尝试

Use FP32 LM Head
  • Inspired by the Minimax-M1 technical report and the blog post《Your Efficient RL Framework Secretly Brings You Off-Policy RL Training》
    • 作者修补了 vLLM,将 lm_head 转换为 fp32 精度
    • 理解:作者的基本思路是,让 vLLM 的参数精度更贴近 FSDP 的精度,从而一定程度上缓解训推不一致问题
  • 但在作者的实验中,修补后不一致性问题仍然存在,模型崩溃无法避免
    • 图 11 显示了在 L20 GPU 上使用 vLLM 引擎中 bf16 lm_head 的一个失败的 on-policy 实验,以及一个从崩溃实验的第 200 个训练步后开始在 vLLM 引擎上使用 fp32 lm_head 的实验
    • 可以观察到,两个实验最终都崩溃了,并且使用 fp32 lm_head 的实验仍然表现出 vllm-kl 的爆炸
    • 注意:以上实验不是从一开始就是用 FP32 的,而是 bf16 训练至出现问题后从 200 Step 恢复,此时使用 FP32 替换 bf16
  • 作者还尝试从第 4.1.1 节中使用 bf16 lm_head 的失败实验的第 200 个训练步开始恢复 RL 训练,禁用分块预填充 (chunked prefill),以观察这是否能解决崩溃问题
    • 实验结果(如图 12 所示)表明,这种方法并未解决崩溃问题
    • 问题:分块预填充 会导致精度问题吗?
      • 理解:似乎没有发现,但是这个应该会导致一些计算顺序的不确定,导致输出不确定的问题
Enable enforce_eager and free_cache_engine
  • VeRL 的 DAPO 官方指南 提到,启用 CUDA 图 (enforce_eager=False) 可能导致模型 Performance 下降
    • 理解:这里的 Performance 下降应该主要是指训练得到的模型下游指标(测试性能)变差
  • 为了探究它是否影响训练-推理不一致性,作者进行了一项消融研究,以考察 vLLM 引擎超参数 enforce_eager 的影响,同时考虑另一个超参数 free_cache_engine
  • 作者在 Reasoning RL 上进行了实验
    • 在 H100 GPU 上使用 Qwen3-4B-Base 作为基础模型,进行了 on-policy GRPO 实验,共运行四种实验设置:
      • 超参数 enforce_eager 和 free_cache_engine 的穷举组合,每个设置为 True 或 False
    • 性能在 AIME24 基准上进行了评估
  • 实验结果如图 13 所示
    • 从图中可以看出,调整 enforce_eager 和 free_cache_engine 的值对训练-推理不一致性和测试性能(下游指标)没有显著影响

Effective Attempts,有效尝试

4.2.1 A Principled Solution: Distribution Correction
  • 训练-推理不一致性将原本的 on-policy RL 问题变成了一个 off-policy 问题
    • 其中用于生成 rollout 的策略(行为策略 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\))与正在训练的策略(目标策略,\(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\))不同
    • 在理论上修正这种分布偏移的一种合理方法是 重要性采样 (IS)
    • 但对于保持梯度无偏和实现稳定训练而言,IS 的具体形式至关重要
  • 受 off-policy-rl (2025) 的发现启发
    • off-policy-rl (2025) 首次强调了这种由训练-推理不一致性导致的隐式 off-policy 问题
    • 作者分析了两种主要的 IS 形式:理论上合理的 Sequence-level IS 和常见但有偏的 Token-level IS 近似
The Principled Estimator: Sequence-Level IS
  • 正确、无偏的策略梯度估计器对整个生成的序列(轨迹)\(y\) 应用一个单一的重要性比率
  • 这正确地将其期望从行为策略重新加权到目标策略,从而产生目标函数 \(J(\theta)\) 的真实梯度
  • 下面一步步推导 Sequence-level IS 估计器 \(g_{\mathrm{seq} }(\theta)\)
    • Step 1:目标是最大化在目标 FSDP 策略 下的期望奖励:
      $$
      J(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|x)}[R(x,y)]
      $$
    • Step 2:因此,真实的策略梯度为:
      $$
      g(\theta) = \nabla_{\theta} J(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|x)}\left[R(x,y) \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x)\right]
      $$
    • Step 3:由于作者只能从 vLLM 策略 中采样,作者使用重要性采样来改变策略梯度的期望的分布:
      $$
      g_{\mathrm{seq} }(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)}\left[ \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x)}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(y|x)} \cdot R(x,y) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x) \right]
      $$
      • 这本质上是 off-policy REINFORCE 算法
  • 这个估计器在数学上等价于策略梯度的标准优势形式
    • 因为重要性采样比率精确地修正了期望(数学上等价)
补充详细推导:以上策略梯度的 On-policy 形式
  • 步骤 1:将期望转换为其 On-Policy 形式
    • IS 估计器取其关于行为策略 \(\color{red}{\pi^{\mathrm{vllm} } }\) 的期望
    • 通过将期望的定义写为积分,行为策略密度 \(\color{red}{p_{\theta}^{\mathrm{vllm} } }(y|x)\) 被抵消:
      $$
      \begin{align}
      g_{\mathrm{seq} }(\theta) &= \int \left( \frac{\pi_{\color{blue}{\theta} }^{\mathrm{fsdp} }(y|x)}{\pi_{\color{red}{\theta} }^{\mathrm{vllm} }(y|x)} \cdot R(x,y) \cdot \nabla_{\theta} \log \pi_{\color{blue}{\theta} }^{\mathrm{fsdp} }(y|x) \right) \pi_{\color{red}{\theta} }^{\mathrm{vllm} }(y|x) dy \\
      &= \int \left( R(x,y) \cdot \nabla_{\theta} \log \pi_{\color{blue}{\theta} }^{\mathrm{fsdp} }(y|x) \right) \pi_{\color{blue}{\theta} }^{\mathrm{fsdp} }(y|x) dy
      \end{align}
      $$
      • 这是真实的 on-policy 梯度,因为期望是对目标策略 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\) 而言的
    • 这证明了 \(g_{\mathrm{seq} }(\theta)\) 是真实策略梯度的无偏估计量
      $$
      g_{\mathrm{seq} }(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|x)}\left[R(x,y) \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x)\right] = g(\theta)
      $$
      • 理解:其实这个不需要证明,IS 对原始的 真实策略梯度 进行精确修正,得到的本就是数学上完全等价的形式
      • 注:真实的策略梯度 见前一小节的推导结果:
        $$
        g(\theta) = \nabla_{\theta} J(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|x)}\left[R(x,y) \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x)\right]
        $$
  • 步骤 2:分解为时间步并应用因果关系 (仅考虑当前时间步之后的 Reward \(G_t\))
    • 现在处理更简单的 on-policy 表达式,展开轨迹级别的项并应用 因果关系 (causality) 原理(在步骤 \(t\) 的动作仅影响未来的奖励)
    • 这允许我们将总奖励 \(R(x,y)\) 替换为 未来回报 (return-to-go) \(G_t = \sum_{k=t}^{|y|-1} r(s_k, a_k)\)
      $$
      g(\theta) = \mathbb{E}_{y \sim \color{blue}{\pi_{\theta} } } \left[ \sum_{t=0}^{|y|-1} G_t \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a_t|s_t) \right]
      $$
  • 步骤 3:引入优势函数 (减去一个 Baseline 得到 \(A^{\color{blue}{\pi_{\theta} } }(s_t, a_t) = G_t - V^{\color{blue}{\pi_{\theta} } }(s_t)\))
    • 为了减少方差,减去一个依赖于状态的 Baseline ,即价值函数 \(V^{\color{blue}{\pi_{\theta} } }(s_t)\)
    • 这将未来回报转换为 优势函数 (Advantage Function) ,\(A^{\color{blue}{\pi_{\theta} } }(s_t, a_t) = G_t - V^{\color{blue}{\pi_{\theta} } }(s_t)\)
      $$
      g(\theta) = \mathbb{E}_{y \sim \color{blue}{\pi_{\theta} } } \left[ \sum_{t=0}^{|y|-1} A^{\color{blue}{\pi_{\theta} } }(s_t, a_t) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a_t|s_t) \right]
      $$
  • 步骤 4:从 Trajectory-level 期望转换为 State-level 期望
    • 最后一步将对轨迹的期望重新表述为对由目标策略引起的状态访问分布 \(d_{\color{blue}{\pi_{\theta} } }\) 的等价期望
    • 从步骤 3 到步骤 4 的详细数学推导
      • 步骤 A:从轨迹级期望开始
        $$
        g(\theta) = \mathbb{E}_{y \sim \color{blue}{\pi_{\theta} } } \left[ \sum_{t=0}^{|y|-1} A^{\color{blue}{\pi_{\theta} } }(s_t, a_t) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a_t|s_t) \right]
        $$
      • 步骤 B:应用期望的线性性质
        • 交换期望和求和运算符
        • 可以将求和扩展到无穷大,因为对于超出轨迹有限长度 \(|y|\) 的时间步 \(t\) 的任何项都是零,所以只是加了零
          $$
          g(\theta) = \sum_{t=0}^{\infty} \mathbb{E}_{y \sim \color{blue}{\pi_{\theta} } } \left[ A^{\color{blue}{\pi_{\theta} } }(s_t, a_t) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a_t|s_t) \right]
          $$
      • 步骤 C:将期望展开为显式求和
        • 通过对每个可能的状态 \(s\) 和动作 \(a\) 求和,并用它们的联合概率 \(P(s_t=s, a_t=a) = P(s_t=s) \cdot \color{blue}{\pi_{\theta} }(a|s)\) 加权,来重写内部期望
          $$
          g(\theta) = \sum_{t=0}^{\infty} \sum_{s \in \mathcal{S} } \sum_{a \in \mathcal{A} } P(s_t=s) \cdot \color{blue}{\pi_{\theta} }(a|s) \cdot A^{\color{blue}{\pi_{\theta} } }(s, a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a|s)
          $$
      • 步骤 D:引入状态占用度量 (通过交换求和顺序来引入)
        • 重新排列求和项,将与状态 \(s\) 相关的所有项分组
          $$
          g(\theta) = \sum_{s \in \mathcal{S} } \left( \sum_{t=0}^{\infty} P(s_t=s) \right) \cdot \left( \sum_{a \in \mathcal{A} } \color{blue}{\pi_{\theta} }(a|s) \cdot A^{\color{blue}{\pi_{\theta} } }(s, a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a|s) \right)
          $$
          • 第一项,\(\sum_{t=0}^{\infty} P(s_t=s)\),是 状态占用度量 (state occupancy measure) 的定义,\(d_{\color{blue}{\pi_{\theta} } }(s)\)
          • 第二项是对动作的期望的定义,\(\mathbb{E}_{a \sim \color{blue}{\pi_{\theta} }(\cdot|s)}[\dots]\)
            $$
            g(\theta) = \sum_{s \in \mathcal{S} } d_{\color{blue}{\pi_{\theta} } }(s) \cdot \mathbb{E}_{a \sim \color{blue}{\pi_{\theta} }(\cdot|s)} \left[ A^{\color{blue}{\pi_{\theta} } }(s, a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a|s) \right]
            $$
      • 步骤 E:得到最终形式
        • 对所有状态按其状态占用度量加权求和,根据定义,是对状态分布 \(d_{\color{blue}{\pi_{\theta} } }\) 的期望
          $$
          g(\theta) = \mathbb{E}_{s \sim d_{\color{blue}{\pi_{\theta} } } } \left[ \mathbb{E}_{a \sim \color{blue}{\pi_{\theta} }(\cdot|s)} \left[ A^{\color{blue}{\pi_{\theta} } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta} }(a|s) \right] \right]
          $$
  • 这个推导过程得到策略梯度的最终优势形式:
    $$
    \color{red}{g_{\mathrm{seq} }(\theta)} = \mathbb{E}_{s \sim d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } } } \mathbb{E}_{a \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|s)} \left[ A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \right]
    $$
    • \(s=(x,y_{ < t})\) 是状态(前缀)
    • \(a=y_t\) 是动作(token)
    • \(d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 是目标 FSDP 策略下的状态占用度量
      • 它形式化地定义为遵循策略 \(\pi\) 时状态 \(s\) 被访问的期望次数:
        $$
        \color{blue}{d_{\pi}(s) := \mathbb{E}_{x’ \sim \mathcal{D}, y’ \sim \pi(\cdot|x’)} \left[ \sum_{t’=0}^{|y’|-1} \mathbb{I}\{ (x’, y’_{<t’}) = s \} \right] = P(x) \cdot \prod_{k=0}^{t-1} \pi(y_k|x,y_{<k})}
        $$
  • 因为这个策略梯度估计器 \(g_{\mathrm{seq} }(\theta)\) 是 无偏的 ,意味着
    $$\color{red}{g_{\mathrm{seq} }(\theta)} = g(\theta)$$
    • 为了数值稳定性,使用了 截断重要性采样 (Truncated Importance Sampling, TIS)
    • TIS 将 Sequence-level 比率 \(\rho(y|x)\) 截断在一个常数 \(C\)
A Common Biased Estimator: Token-Level IS,常见的有偏估计器
  • 一个常见的启发式方法,通常受到 PPO 等算法的启发,并在 off-policy-rl (2025) 中使用,是对每个 token 应用重要性比率
  • 虽然这通常具有比 Sequence-level 比率更低的方差,但它是一个 有偏估计器 ,对于自回归模型在理论上是不合理的
    • 更低的方差来源是指 Sequence-level 时对数比率是多个 Token-level 的对数比率连乘计算得到的(详情见下两个公式),这样的话得到的结果波动自然比单个 Token 的对数比率大
  • 推导 Token-level IS 梯度估计器 \(g_{\mathrm{tok} }(\theta)\)
    • 第一步:这个公式开始于错误地在时间步求和内部应用重要性采样比率:即,\(g_{\mathrm{tok} }(\theta)\) 被定义为:
      $$
      g_{\mathrm{tok} }(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)}\left[ R(x,y) \cdot \sum_{t=0}^{|y|-1} \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t})}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(y_t|x,y_{ < t})} \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t}) \right]
      $$
      • 作为对照,这里我们同步贴一下 Sequence-level 的梯度估计器:
        $$
        g_{\mathrm{seq} }(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)}\left[ \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x)}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(y|x)} \cdot R(x,y) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y|x) \right]
        $$
        • 这里的 \(R(x,y)\) 是从 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 采样的完整轨迹的经验回报(因为 \(y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)\)),它是状态-动作值 \(Q^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a)\) 的蒙特卡洛估计
    • 第二步:同上一小节中的详细推导过程,我们可以类似地将对轨迹的期望重写为对在 vLLM 策略 下访问的状态的期望:
      $$
      g_{\mathrm{tok} }(\theta) = \mathbb{E}_{s \sim d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } } } \mathbb{E}_{a \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|s)} \left[ \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s)}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s)} \cdot A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \right]
      $$
      • 引入基线并改变对动作的期望,得到最终形式:
        $$
        g_{\mathrm{tok} }(\theta) = \mathbb{E}_{s \sim d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } } } \mathbb{E}_{a \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|s)} \left[ A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \right]
        $$
        • 这个最终表达式清楚地揭示了 Token-level IS 的梯度偏差
      • 补充:第二步的详细证明详情见附录
        • 注:推导过程中与 Sequence-level 表达式推导过程中的主要区别在于 Token-level 相加的校准形式无法被 Sequence-level 的期望直接消去,从而导致最终表达式的期望中仍然遗留了 vLLM 的策略信息
      • 特别注意:
        • 这里的 \(A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a)\) 表示我们的 Advantage 是基于 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 采样和估计的
    • 现在对比真实策略梯度的无偏估计 \(\color{red}{g_{\mathrm{seq} }(\theta)} \):
      $$
      \color{red}{g_{\mathrm{seq} }(\theta)} = \mathbb{E}_{s \sim d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } } } \mathbb{E}_{a \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|s)} \left[ A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \right]
      $$
    • 可以清楚地看到,只有当 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 保持在 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\) 的信任域内时,即当 \(d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }\approx d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 且 \(A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }\approx A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 时,\(J(\theta)\) 才能被 \(g_\text{tok}(\theta)\) 优化
Token-level IS 中偏差的来源 (The Source of Bias in Token-Level IS)
  • 比较 \(g_{\mathrm{tok} }(\theta)\) 与真实梯度 \(g_{\mathrm{seq} }(\theta)\) 揭示了两个截然不同且显著的误差,这些误差使得 Token-level 估计器有偏
  • 来源 1:状态占用不匹配
    • 一个合理的 off-policy 修正必须考虑两种分布偏移:
      • 动作概率:Token-level 方法修正了动作概率
      • 状态访问概率:Token-level 方法没有修正状态访问概率
        • 真实梯度 (\(g_{\mathrm{seq} }\)):
          • 期望是对在 正确的目标 fsdp 分布 下访问的状态,\(\mathbb{E}_{s \sim d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } } }\)
        • 有缺陷的梯度 (\(g_{\mathrm{tok} }\)):
          • 期望是对在 错误的行为 vLLM 分布 下访问的状态,\(\mathbb{E}_{s \sim d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } } }\)
    • 这隐含地假设状态占用比率为 1,即 \({d_{\color{blue}{\pi^{\mathrm{fsdp} } } }(s)} /{d_{\color{red}{\pi^{\mathrm{vllm} } } }(s)} = 1\)
    • 这个假设在自回归模型中被灾难性地违反了
      • 由于 LLM 中的 MDP 是确定性的转移,一个不同的 token 选择就能保证状态轨迹完全分歧
        • 理解:这里的状态轨迹分歧会直接导致状态占用 \(d_\pi(s)\) 发生较大变化,而且越长的状态轨迹,发生偏移的概率越大
      • 因为忽略这一点,\(g_{\mathrm{tok} }(\theta)\) 引入了一个大的、不受控的偏差
  • 来源 2:奖励信号不匹配
    • 第二个关键错误是, Token-level 梯度使用来自 错误策略 的奖励信号对更新进行加权
      • 真实梯度 (\(g_{\mathrm{seq} }\)):
        • 更新由 目标 fsdp 策略 的优势函数 \(A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\) 缩放,表示在该策略下的期望未来奖励
      • 有缺陷的梯度 (\(g_{\mathrm{tok} }\)):
        • 更新由 行为 vLLM 策略 的优势函数 \(A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }\) 缩放
      • 即目标策略的梯度正被一个属于行为策略的奖励信号所缩放(本该是目标策略的奖励信号来缩放)
  • 由于状态分布和奖励信号从根本上是不匹配的, Token-level 梯度是一个有偏且理论上不合理的估计器
    • 这些理论表明:
      • 尽管 Token-level 方法可能具有更低的方差,但梯度偏差仍然存在,可能导致训练不稳定性
        • 本文的实验证实了这一预测
      • 作者还提供了关于 Token-level 和 Sequence-level 方法的详细偏差和方差分析 (第 1 部分 & 第 2 部分)
Experimental Validation
  • 总结来看,本文的理论分析预测,有偏的 Token-level IS 将不稳定并最终失败,而无偏的 Sequence-level IS 将是稳健的
  • 本文给出实验也证实了这一点
实验一:IS Prevents Gradient Explosion, but Token-Level Still Fails(Token-level TIS 防止了梯度爆炸,但是仍然失败了)
  • 作者在 L20 GPU 上从第 200 个训练步开始,使用 Token-level TIS 和 Sequence-level TIS (\(C=2\)) 恢复了一个崩溃的实验
  • 如图 14 所示
    • 虽然两者最初都防止了原始实验中看到的梯度爆炸,但使用 Token-level TIS 的运行后来仍然崩溃了
    • 使用 Sequence-level TIS 的运行保持稳定,验证了作者的理论,即来自 Token-level 方法的有偏梯度最终会导致失败
实验二:Token-Level TIS in Reasoning RL(Token-Level TIS 在更简单的 RL 中能防止梯度崩溃,但训练仍然不稳定且没有达到更好的最终性能)
  • Token-level TIS 在复杂的 TIR 实验中失败,但它可以在更简单的推理 RL 中帮助防止崩溃
    • 因为那里的不一致性较小
  • 在 on-policy GRPO 和 RLOO 实验中(图 15)
    • Token-level TIS 防止了梯度爆炸,但训练仍然不稳定,并且没有达到更好的最终性能
    • 这可能是由于其潜在的梯度偏差
实验三:TIS Prolongs Training But Can Suffer from Instability,TIS 延长训练但可能遭受不稳定性,测试性能无法超过其他实验崩溃前的峰值
  • 作者在 L20 GPU 上从头开始使用 Sequence-level TIS (\(C=2\)) 进行了一个 on-policy TIR 实验
  • 如图 16 所示
    • 虽然该方法阻止了完全崩溃,但奖励曲线在达到平台期后表现出持续波动,并且其测试性能未超过原始实验在崩溃前达到的峰值
实验四:Masked Importance Sampling, MIS, Sequence-level MIS 可以超过原始基线的最高峰值
  • 为了改进 TIS,作者提出了 掩码重要性采样 (Masked Importance Sampling, MIS) (注:这里是 Sequence-level MIS)
    • 注:其实类似思想(Token-level MIS)是在 (IcePop)Small Leak Can Sink a Great Ship—Boost RL Training on MoE with IcePop!, 20250919, AntGroup,但未明确命名为 MIS 而已
      • 相关 PR:【PR to TRL】[GRPO] Sequence-level TIS + MIS(20251106)
      • 注:在 IcePop 中,更多强调的是 Token-level MIS
  • 对 IS 比率超过阈值 \(C\) 的序列的策略损失进行掩码:
    $$ \rho(y|x) \gets \rho(y|x) \mathbb{I}\{\rho(y|x) \le C\} $$
    • 理解:超出 \(C\) 的 \(\rho(y|x)\) 会被置为 0
    • 问题:为什么是单向的?
      • 因为本文的观察可以看到,这个比值过大时容易出现不稳定(RL Collapse)
        • 上文的观察中有个结论是当 vLLM 概率 \(\color{red}{\pi^\text{vllm}_\theta}\) 趋近于零时,不一致程度往往更为显著
      • 当这个比值过小时理论没有问题,因为更新权重相当于被降低了(其实屏蔽可能也行,只是说会降低 Token 效率)
  • 如图 17 所示:MIS 不仅稳定了训练,而且超过了原始实验和 TIS 实验的峰值训练奖励和测试准确率
    • 问题:怎么感觉在下游测试指标(图 17 右图)继续训练 TIS 可能也能拿到不错的收益?因为性能还在持续增长
实验五:Token-Level MIS vs. Sequence-Level MIS,Token-level 的 MIS 不太够用,初期能防止梯度爆炸,后期还是会崩溃
  • 最后,作者比较了 Token-level MIS 和 Sequence-level MIS
  • 正如预期,图 18 显示:
    • 两者都能防止初始梯度爆炸,但 Token-level MIS 实验仍然崩溃了
    • 这强化了作者的结论:对于复杂的、长视距的自回归任务,只有理论上合理的 Sequence-level 修正才是可靠的
4.2.2 Top-p Sampling
  • 如上所述,作者观察到 vLLM 策略的低概率 token 更容易出现严重的训练-推理不一致性问题,导致 FSDP 策略的概率极低
  • 为了进一步证实这一点,作者进行了 top-p 消融研究
    • 在 L20 GPU 上运行 on-policy GRPO 实验,并将 vLLM 采样策略的 top-p 超参数分别设置为 0.98、0.99 和 0.999(注意这里没有应用重要性采样进行梯度修正)
    • 通过设置较小的 top-p 值,作者的目标是降低推理阶段出现极低 vLLM 概率 token 的频率 ,从而减轻训练-推理不一致性
  • 作者的消融结果如图 19 所示
    • 正如预期,vllm-kl 指标表明,较小的 top-p 减少了 vllm-kl 尖峰的出现
    • 但较小的 top-p 也增加了 vLLM 策略 \(\color{red}{\pi^{\text{vllm} }_\theta}\) 和 FSDP 策略 \(\color{blue}{\pi^{\text{fsdp} }_\theta}\) 之间的分布差异
      • 理解: top-p 变小影响了 vLLM 策略采样的分布,而 FSDP 中是没有类似 top-p 影响的(是所有分布同时训练),所以 vLLM 采样时的 top-p 越小,vLLM 和 FSDP 策略之间的差异越大 (再次强调:此时没有应用 IS 修正)
    • 因此,在不应用 TIS 的情况下,梯度偏差变得更大,导致随着 top-p 的减小,奖励提升变慢
4.2.3 Use other GPU series
  • 在发现 H20 GPU 上运行的实验的训练-推理不一致性显著小于 L20 GPU 后,作者将所有 TIR 实验切换到了 H20 GPU ,这大大减少了训练崩溃的发生
  • 图 20 显示了在 L20 和 H20 GPU 上,分别在相同配置下从头开始训练的两个 on-policy GRPO 实验的结果
  • 可以观察到,在 H20 GPU 上运行的 on-policy 实验显著延长了稳定训练时长 ,并取得了更好的性能
4.2.4 Disable Cascade Attention in vLLM, 在 vLLM 中禁用级联注意力
  • 根据这个 GitHub issue,作者在初始化 vLLM 引擎时设置了 disable_cascade_attn=True,并发现它在 A100 GPU 上进行的实验中显著有助于减少训练-推理不一致性
  • 作者在 A100 GPU 上使用 Qwen3-14B-Base 作为基础模型,进行了两个 on-policy GRPO 实验,disable_cascade_attn 分别设置为 True 和 False
  • 结果如图 21 所示
    • 禁用级联注意力后, vllm-kl 指标从 5e-2 到 1e-1 的范围下降到大约 1e-3,表明训练-推理不一致性显著减少
    • 同时可以观察到,训练集上的奖励也适当地增加了

Conclusion & Key Takeaways for Practitioners

  • 训练-推理不一致性不是一个细枝末节的 bug,而是一个贯穿现代 Reasoning and Agentic RL 的根本性且日益严峻的挑战,它是由对性能的必要追求所驱动的
  • 不一致性是不可避免的权衡: 接受高速推理总是会与训练计算产生分歧这一事实
    • 这是一个核心的权衡,而非暂时性的缺陷
  • 监控训练健康状况: vllm-kl 指标是一个重要的早期预警系统
    • 将其与困惑度 (PPL) 和梯度范数一起跟踪,以预测和诊断不稳定性,防止其导致崩溃
  • 识别真正的凶手: 问题不是随机的
    • 它是由 低概率 token (low-probability tokens) 系统性地触发的,这些 token 在模型处理分布外 (OOD) 输入时更频繁地生成
      • 这在工具使用和多轮应用中很常见
  • 硬件是一阶变量: 相同的代码可能在一种 GPU 架构上崩溃,在另一种上完美训练
    • 始终在自己的目标硬件上验证 Setting,因为结果可能无法完全移植
  • 使用理论合理的修正: 虽然更换硬件或调整采样器会有所帮助,但最稳健、最 Principled 解决方案是算法层面的
    • 理论上存在偏差的 Token-level 修正是不够的,在实验中仍然可能失败
    • Sequence-level 方法,如截断重要性采样 (Seq-TIS) 和掩码重要性采样 (Seq-MIS) ,通过修正完整的状态轨迹直接解决梯度偏差问题
    • 这些方法对于维持稳定性至关重要,应被视为任何 Serious LLM-RL 训练栈的默认选项
  • 其他:作者推测这个训推不一致性问题在 MoE 模型上可能会更加的严重

附录:Token-level IS 下的 策略梯度期望 表达式推导

  • 本节负责详细推导 Token-Level IS 梯度估计器 \( g_{\mathrm{tok} }(\theta) \) 的表达式
  • 这个推导的目标是:从一个基于轨迹的定义出发,通过一系列变换,将其表达为对“状态-动作”对的期望形式
    • 最终目标:展示 \( g_{\mathrm{tok} }(\theta) \) 与真实梯度 \( g_{\mathrm{seq} }(\theta) \) 的偏差来源

第 1 步:从 Token-Level IS 的轨迹级定义出发

  • 根据 4.2.1 节中的定义,Token-Level IS 的梯度估计器是基于轨迹的,它错误地将重要性比率应用在了对每个时间步的求和内部:
    $$
    g_{\mathrm{tok} }(\theta) = \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)}\left[ R(x,y) \cdot \sum_{t=0}^{|y|-1} \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t})}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(y_t|x,y_{ < t})} \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t}) \right] \tag{1}
    $$
  • 这里的核心思想是:
    • 虽然想要优化目标策略 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\),但由于只能从行为策略 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 采样得到的轨迹 \(y\) 中进行学习,我们就在 每个 token 上 使用一个重要性权重来修正策略偏差(这个修正本身就是有偏的/错误的)

第 2 步:将轨迹期望分解为“状态-动作”对的期望

  • 这一步是将对完整轨迹 \(y\) 的期望,转化为对所有可能访问到的“状态-动作”对 \((s, a)\) 的期望
    • 这里的“状态” \(s\) 是生成动作 \(a\) 时的上下文(即 \(s = (x, y_{ < t})\))
  • 对于一条长度为 \(|y|\) 的轨迹,它的贡献是其中每个 token 的贡献之和
    • 利用期望的线性性质,可以将求和与期望进行交换
    • 将期望写成对所有可能的轨迹进行积分(或求和),可以得到:
      $$
      \begin{aligned}
      g_{\mathrm{tok} }(\theta) &= \sum_{t=0}^{\infty} \mathbb{E}_{x \sim \mathcal{D}, y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)} \left[ R(x,y) \cdot \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t})}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(y_t|x,y_{ < t})} \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(y_t|x,y_{ < t}) \right] \\
      &= \sum_{t=0}^{\infty} \sum_{s \in \mathcal{S} } \sum_{a \in \mathcal{A} } P_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s_t = s, a_t = a) \cdot \mathbb{E}_{y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)} \left[ R(x,y) | s_t=s, a_t=a \right] \cdot \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s)}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s)} \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s)
      \end{aligned}
      $$
  • 理解:这个看起来很复杂的表达式其实在做一件简单的事:
    • 遍历所有可能的时间步 \(t\),所有可能的状态 \(s\),以及所有可能的动作 \(a\)
    • 对于每一种可能性
      • 计算其发生的概率
        $$P_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s_t=s, a_t=a)$$
      • 然后乘上在该 \((s,a)\) 之后获得的期望回报
        $$\mathbb{E}[R(x,y)|s_t=s, a_t=a]$$
      • 最后再乘上 token-level 的 IS 权重和梯度项

第 3 步:引入状态-动作价值函数 \(Q\) 和状态占用度量 \(d\)

  • 接下来这里做两个关键的代换:
    • 1)条件期望回报 \( \mathbb{E}_{y \sim \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(\cdot|x)} \left[ R(x,y) | s_t=s, a_t=a \right] \) 正是 行为策略下的状态-动作价值函数 \( Q^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s, a) \) 的定义
      • 它衡量了在状态 \(s\) 采取动作 \(a\) 后,遵循策略 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 所能获得的期望累积奖励
    • 2)联合概率 \( P_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s_t=s, a_t=a) \) 可以分解为 \( P_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s_t=s) \cdot \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s) \)
      • 而 \(\sum_{t=0}^{\infty} P_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s_t=s) \) 正是 行为策略下的状态占用度量 (State Occupancy Measure) ,记为 \( d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s) \)
      • 它衡量了在整个交互过程中,状态 \(s\) 被访问的期望次数
  • 将这两个定义代入,上述双重求和(\(\sum_{t} \sum_{s}\))就可以巧妙地合并成一个对状态 \(s\) 的加权求和,权重正是状态占用度量 \(d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s)\):
    $$
    \begin{aligned}
    g_{\mathrm{tok} }(\theta) &= \sum_{s \in \mathcal{S} } d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s) \sum_{a \in \mathcal{A} } \color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s) \cdot Q^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s, a) \cdot \frac{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s)}{\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s)} \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s)
    \end{aligned}
    $$
  • 可以看到,分母中的 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s)\) 和分子中的 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }(a|s)\) 可以直接约掉!约简后,作者得到一个非常简洁的形式:
    $$
    g_{\mathrm{tok} }(\theta) = \sum_{s \in \mathcal{S} } d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s) \sum_{a \in \mathcal{A} } \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \cdot Q^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s, a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \tag{2}
    $$

第 4 步:引入基线函数以降低方差

  • 在策略梯度方法中,直接使用 \(Q\) 函数会导致较高的方差
    • 通常我们会引入一个与动作无关的基线 \(V(s)\) 来降低方差,而不改变期望值
    • 最常用的基线是状态价值函数 \(V^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s)\)
      $$
      Q^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s, a) = V^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s) + A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s, a)
      $$
      • 其中 \(A\) 是优势函数
    • 将 \(Q\) 替换为 \(V + A\) 后,代入式 (2):
      $$
      \begin{aligned}
      g_{\mathrm{tok} }(\theta) &= \sum_{s} d_{\color{red}{\pi} }(s) \sum_{a} \color{blue}{\pi}(a|s) \cdot \left( V^{\color{red}{\pi} }(s) + A^{\color{red}{\pi} }(s, a) \right) \cdot \nabla_{\theta} \log \color{blue}{\pi}(a|s) \\
      &= \underbrace{ \sum_{s} d_{\color{red}{\pi} }(s) V^{\color{red}{\pi} }(s) \sum_{a} \color{blue}{\pi}(a|s) \nabla_{\theta} \log \color{blue}{\pi}(a|s) }_{\text{ = 0} } + \sum_{s} d_{\color{red}{\pi} }(s) \sum_{a} \color{blue}{\pi}(a|s) A^{\color{red}{\pi} }(s, a) \nabla_{\theta} \log \color{blue}{\pi}(a|s)
      \end{aligned}
      $$
      • 注:为了简洁考虑,上式中:
        • 用 \(\color{red}{\pi}\) 表示 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\)
        • 用 \(\color{blue}{\pi}\) 表示 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\)
  • 问题:为什么第一项等于 0?
    • 因为:
      $$\sum_{a} \color{blue}{\pi}(a|s) \nabla_{\theta} \log \color{blue}{\pi}(a|s) = \mathbb{E}_{a \sim \color{blue}{\pi}(\cdot|s)}[\nabla_{\theta} \log \color{blue}{\pi}(a|s)] = 0$$
      • 这是一个对数似然梯度的恒等式,其期望值为零(得分函数 \(\nabla_{\theta} \log \color{blue}{\pi}(a|s)\) 期望为 0)
      • 因此,包含基线 \(V(s)\) 的项就自然消失了
    • 理解:为什么第二项不等于 0?
      • 第一项可以为 0 是因为第一项的 \(V^{\color{red}{\pi} }(s) \) 与动作 \(a\) 无关,不会随着动作 \(a\) 的变化而变化,可以单独从期望中提出来
      • 第二项不为 0 是因为第二项的 \(A^{\color{red}{\pi} }(s, a)\) 与动作 \(a\) 有关,不能单独从期望中提出来
        • 虽然 \(A^{\color{red}{\pi} }(s, a)\) 包含的是 \(\color{red}{\pi}\),但还包含了 \(a\),这导致了 \(A^{\color{red}{\pi} }(s, a)\) 与动作分布 \(\color{blue}{\pi}(a|s)\) 有关(主要是与动作有关)

第 5 步:得到最终形式

  • 消去为零的项后,我们得到了 Token-Level IS 估计器的最终形式:
    $$
    g_{\mathrm{tok} }(\theta) = \mathbb{E}_{s \sim d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } } } \mathbb{E}_{a \sim \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(\cdot|s)} \left[ A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a) \cdot \nabla_{\theta} \log \color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }(a|s) \right]
    $$

第 6 步:Token-Level IS 为什么是有偏的?

  • 通过上面这个推导,我们可以清晰地看到问题的根源:
    • 1)状态分布错误 :期望 \(\mathbb{E}_{s \sim d_{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } } }\) 是在行为策略 \(\color{red}{\pi_{\theta}^{\mathrm{vllm} } }\) 的访问状态上求的,而我们真正想要的,应该是目标策略 \(\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } }\) 的访问状态 \(d_{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }\)
    • 2)奖励信号错误 :用来衡量“好与坏”的标准是行为策略的优势函数 \(A^{\color{red}{\pi_{\theta}^{\mathrm{vllm} } } }(s,a)\),而非目标策略的优势函数 \(A^{\color{blue}{\pi_{\theta}^{\mathrm{fsdp} } } }(s,a)\)
  • 因此,尽管 Token-Level IS 看起来在每个 token 上进行了修正,但它修正的是错误的分布,使用的是错误的评价标准
    • 只有当两个策略几乎一样时(即 \(d_{\color{red}{\pi} } \approx d_{\color{blue}{\pi} }\) 且 \(A^{\color{red}{\pi} } \approx A^{\color{blue}{\pi} }\)),它才近似正确,否则其梯度是有偏的,这也就是原文实验里它仍然会导致训练崩溃的根本原因

附录:RL 中校准训推不一致的三种数学上准确方式

  • 本节内容参考自:verl 的 rollout_corr.md 文件:github.com/verl-project/verl/blob/main/docs/algo/rollout_corr.md
  • 三种方法整体说明
    方法 策略数量 核心数学校正 关键约束
    Decoupled Mode 3 \( \rho_t \cdot \min(r_t(\theta), \text{clip}(r_t(\theta))) \) 需额外前向传播
    Bypass Mode 2 \( \min(r_t(\theta), \text{clip}(r_t(\theta))) \) \(\rho_t=1\),无批次不变性
    Bypass + Policy Gradient Mode 2 \( \operatorname{sg}\left(\prod \frac{\pi_\theta}{\pi_{\text{rollout} } }\right) \sum \log\pi_\theta \hat{A} \) 必须使用 stop-gradient
  • 注:虽然 Bypass Mode 和 Bypass + Policy Gradient Mode 在策略上都不需要重新计算 \(\pi_{\text{old} }\),但是 这样的话就会导致无法上报 训推不一致相关的指标
    • 在同一个轨迹包含多个采样策略的异步训练 Setting 下,训推不一致的指标本身就比较难上报
  • 截止当前(202608 重新更新)不同框架的用法大致说明:
    • AReaL 使用的就是 Decoupled Mode ,且 Proximal Policy 使用的是当前批次的策略
    • Slime 使用的是 类似 Bypass Mode ,然后加了双向的 TIS,详情见 SAO 论文
    • VeRL 中,在面对异步模式时,一般似乎是建议使用 Bypass Mode 了
      • separate_async 模式,强制使用 Bypass Mode
      • fully_async 模式,即 Streaming 完全解耦模式下,默认使用的是 Bypass Mode (可选非 Bypass Mode)
      • one_step_off 模式,可选 Bypass Mode 或重算

Decoupled Mode,共三个策略

  • 引入中间近端策略 \(\pi_{\text{old} }\),将分布偏移分解为两步校正:
  • 校正数据分布漂移 (从行为策略 \(\pi_{\text{rollout} }\) 到近端策略 \(\pi_{\text{old} }\))
    • 从 NLP——LLM对齐微调-RL-Collapse-Training-Inference-Mismatch(Sequence-level-MIS) 中可以知道,理论上无偏的校准应该是 Sequence-Level 的 MIS
  • 校正策略学习漂移 (从近端策略 \(\pi_{\text{old} }\) 到当前策略 \(\pi_{\theta}\)):
    • 使用 PPO 裁剪比率
      $$
      r_t(\theta) = \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{old} }(a_t \mid s_t)}
      $$
  • 综合损失函数为(将 IS 校正作用于 PPO 目标):
    $$
    \mathcal{L}_{\text{Decoupled} }(\theta)
    = -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } }
    \left[
    \rho_t \cdot
    \min\Big(
    r_t(\theta) \hat{A}_t,
    \operatorname{clip}\big(r_t(\theta), 1-\epsilon, 1+\epsilon\big) \hat{A}_t
    \Big)
    \right]
    $$
  • 理解:该模式因引入 \(\rho_t\) 重加权,理论上可实现 批次大小不变性 (Batch Size Invariance),但需要额外前向传播计算 \(\pi_{\text{old} }\)
    • 这里的 “批次大小不变性”,是指 Decoupled PPO 方法的一个关键特性
    • Batch Size Invariance 的定义:如果一个算法在 Batch Size 发生改变时,可以通过修改其他超参数(如 LR 等)来近似恢复原始 Batch Size 的训练行为,则称这个算法满足 Batch Size Invariance
    • 标准 PPO 通过比值 \(\frac{\pi_\theta}{\pi_{\text{old} } }\) 控制策略更新大小,其中 \(\pi_{\text{old} }\) 被假定同时是近端策略 和 行为策略
      • 这种耦合使得近端策略一直随着行为策略在变化,无法实现 Batch Size Invariance
        • 因为当 Rollout Batch Size 发生变化时,近端策略更新的频率也在发生变化,这个是无法恢复的
    • Decoupled PPO(Hilton,2021) 通过 解耦两个角色 解决了 PPO 对批次大小的敏感性:
      • 1)Proximal policy \(\pi_{\text{prox} }\):PPO 裁剪的锚点策略(控制策略更新大小)
      • 2)Behavior policy \(\mu\):收集数据的策略(用于通过重要性采样进行 off-policy 校正)
      • 具体来说:Decoupled PPO 论文通过 COM(Center of Mass)来调节 Proximal policy 策略回看的步数(Batch Size 变小,则提升回看步数,几乎保证 Off-policy 幅度差不多)

Bypass Mode,两策略 + PPO

  • 该模式强制令近端策略等同于行为策略,即 \(\pi_{\text{old} } = \pi_{\text{rollout} }\),因此校正权重退化为:
    $$
    \rho_t = 1
    $$
  • 此时 PPO 比率直接度量当前策略与行为策略的概率比:
    $$
    r_t(\theta) = \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{rollout} }(a_t \mid s_t)}
    $$
  • 损失函数退化为标准 PPO 形式(但数据来自行为策略 \(\pi_{\text{rollout} }\)):
    $$
    \mathcal{L}_{\text{Bypass} }(\theta)
    = -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } }
    \left[
    \min\Big(
    r_t(\theta) \hat{A}_t,
    \operatorname{clip}\big(r_t(\theta), 1-\epsilon, 1+\epsilon\big) \hat{A}_t
    \Big)
    \right]
    $$
  • 理解:此模式计算效率高,但失去了批次大小不变性,且近端策略与行为策略耦合

Bypass + Policy Gradient Mode,两策略 + REINFORCE

  • 该模式同样使用两策略(\(\pi_{\text{rollout} }\) 与 \(\pi_{\theta}\)),但放弃 PPO 裁剪 ,改用序列级别的显式重要性采样校正(轨迹概率比):
  • 定义序列级权重:
    $$
    w_{\text{seq} }(\theta) = \prod_{t=1}^{T} \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{rollout} }(a_t \mid s_t)}
    $$
  • 其策略梯度损失函数为:
    $$
    \begin{align}
    \mathcal{L}_{\text{PG} }(\theta)
    &= -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } }
    \left[
    \operatorname{sg}\big( w_{\text{seq} }(\theta) \big)
    \cdot
    \sum_{t=1}^{T} \log \pi_{\theta}(a_t \mid s_t) \cdot \hat{A}_t
    \right] \\
    &= -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } }
    \left[
    \operatorname{sg}\big( w_{\text{seq} }(\theta) \big)
    \cdot
    \sum_{t=1}^{T} \left ( \log \pi_{\theta}(a_t \mid s_t) \cdot \hat{A}_t \right )
    \right]
    \end{align}
    $$
    • 这里 \(\cdot \hat{A}_t\) 不能放到前面来,因为 \(\hat{A}_t\) 是 Token 粒度的,不是 Sequence 粒度的,重要性采样系数是 Sequence 粒度的
    • 其中 \(\operatorname{sg}(\cdot)\) 表示 stop-gradient(即 \( \text{sg}[x] = x \) 但反向传播时视作常数)
      • 这是重要性采样理论的关键要求:
        • 若省略该 stop-gradient,梯度计算将错误地优化权重本身,而非目标策略 ,导致目标函数被错误优化
    • 注:这里也不是标准的 REINFORCE 方法(REINFORCE 方法应该是使用 \(G_t\) 而不是 \(A_t\)),只是说类似 REINFORCE 方法的格式(普通的 PG 方法)
  • 理解:此模式计算速度最快(仅需一次前向传播),但缺少 PPO 的信任域约束,更新风险相对较大
  • 理解:其实本质上,Pure On-policy PPO 的梯度和 REINFORCE 的梯度完全一样(两者形式不同,但最终梯度是完全一样的,本质是一样的)
    • 这里 Pure On-policy PPO 的梯度和 REINFORCE 的梯度 的理解详情可参考:RL——PPO及其训练技巧 中的关于 Pure On-policy PPO 的讨论
  • 理解:这里针对 Reinforce 使用了序列粒度的比值,但是实际上也可以使用 Token 粒度的比值,此时:Pure On-policy PPO 的梯度和 REINFORCE 的梯度完全一致
  • 问题:为什么 这里要将 Bypass Mode + PPO-clip 模式 和 带 IS 的 REINFORCE 模式 分开写?
    • 因为两者在 VeRL 中需要的配置不同
      • Bypass Mode + PPO-clip 模式配置 rollout_is=null
      • 带 IS 的 REINFORCE 模式配置 rollout_is=sequence/token
    • PPO-clip 中天然就有 IS 和 Clip 了,可以通过 PPO 的 IS(\(r_t\theta\)) 直接校准两种不同
      $$
      r_t(\theta) = \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{rollout} }(a_t \mid s_t)}
      $$
    • 带 IS 的 REINFORCE 中将 IS 视为了 Rollout 修正 的这个角色的比值(\(\rho_t\theta\)),所以需要设置 rollout_is=sequence/token(打开 rollout_correction)
      • 若为 Token 粒度
        $$
        \rho_t(\theta) = \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{rollout} }(a_t \mid s_t)}
        $$
      • 若为 Sequence 粒度
        $$
        w_{\text{seq} }(\theta) = \rho(\theta) = \frac{\pi_{\theta}(y \mid x)}{\pi_{\text{rollout} }(y \mid x)} = \prod_{t=1}^{T} \frac{\pi_{\theta}(a_t \mid s_t)}{\pi_{\text{rollout} }(a_t \mid s_t)}
        $$

NLP——LLM对齐微调-VeRL-rollout_corr_math解读

注:本文包含 AI 辅助创作

  • 参考链接:
    • (Mathematical Formulations of Rollout Correction Methods in verl)github.com/verl-project/verl/blob/main/docs/algo/rollout_corr_math.md
    • 其他相关文件:github.com/verl-project/verl/blob/main/docs/algo/rollout_corr.md
    • 系列博客:
      • Main blog post: https://richardli.xyz/rl-collapse
      • Part 1: Why Mismatch Breaks LLM-RL (analytical framework using TV distance for bias and χ²-divergence for variance)
      • Part 2: The Gradient Estimator Trials (token-level vs sequence-level correction bias-variance tradeoff)
      • Part 3: When Math Meets Reality—Toxic Tails and Length Traps (why rejection over clipping, and geometric-level RS)
      • Latest Paper: https://arxiv.org/abs/2512.23075
    • 实现参考
      • Rollout 校正使用指南 - 实际配置和故障排除
      • 配置: verl/trainer/config/algorithm.py
      • IS/RS 辅助: verl/trainer/ppo/rollout_corr_helper.py
      • PPO 损失: verl/trainer/ppo/core_algos.py
      • 测试: tests/trainer/ppo/test_rollout_corr.py

整体总结

  • 算法:从 REINFORCE 到 PPO 再到 Decoupled PPO
  • Rollout 校正提供了一个统一框架,用于处理 RL 训练中的 一般性 off-policy 问题
  • 任何数据收集分布与训练分布不同的场景,适用场景包括:
    • Policy mismatch :不同精度(FP8 vs FP16 vs BF16 vs FP32),不同后端(vLLM vs SGLang vs FSDP vs Megatron)
    • Temporal lag :模型陈旧性,异步 Rollout 工作节点
    • Replay buffers :使用来自更早策略版本的轨迹进行训练
    • Off-policy 算法 :行为克隆,DAPO,专家演示
    • Data filtering :重加权,偏好学习(preference learning),课程学习
    • 补充理解:一些随机算子、前向操作误差等导致的不一致也可以在这里被修正

理论基础:从 REINFORCE 到 Decoupled PPO

REINFORCE:策略梯度基线

  • REINFORCE 算法(1992)是策略梯度方法的基础
  • 原始 REINFORCE(On-Policy)
    • 对于从当前策略 \(\pi_\theta\) 采样的轨迹 \(\tau = (s_0, a_0, s_1, a_1, \ldots, s_T, a_T)\),策略梯度为:
      $$
      \nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \left[ \sum_{t=0}^T \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot A_t \right]
      $$
      • \(A_t\) 是时间步 \(t\) 的优势函数
  • Off-Policy REINFORCE
    • 当轨迹从不同的行为策略 \(\mu\) 采样时,作者对 联合轨迹分布 应用重要性采样:
      $$
      \nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \mu} \left[ \frac{P_{\pi_\theta}(\tau)}{P_\mu(\tau)} \sum_{t=0}^T \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot A_t \right]
      $$
    • 其中轨迹级重要性权重为:
      $$
      \frac{P_{\pi_\theta}(\tau)}{P_\mu(\tau)} = \frac{p(s_0) \prod_{t=0}^T \pi_\theta(a_t|s_t) p(s_{t+1}|s_t, a_t)}{p(s_0) \prod_{t=0}^T \mu(a_t|s_t) p(s_{t+1}|s_t, a_t)} = \prod_{t=0}^T \frac{\pi_\theta(a_t|s_t)}{\mu(a_t|s_t)}
      $$
      • 转移动态 \(p(s_{t+1}|s_t, a_t)\) 和初始状态 \(p(s_0)\) 相互抵消,只留下每步动作概率比值的乘积
  • REINFORCE 的特点
    • 支持 Off-policy :可以通过重要性采样从任何行为策略学习
    • 无 Trust region :策略更新不受约束
  • PS:verl 中的实现: bypass_pg_is 预设实现了带截断重要性采样的 Off-policy REINFORCE

PPO:加入信任域控制

  • 近端策略优化(2017)增加了裁剪的替代目标:
    $$
    L_{\text{PPO} }(\theta) = -\mathbb{E}_{(s,a) \sim \mu} \left[ \min\left( r_t(\theta) A_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right]
    $$
    • \(r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\mu(a_t|s_t)}\),\(\epsilon\) 是裁剪范围(通常为 0.2)
  • PPO 的特点:
    • 两个策略 :\(\mu\)(用于裁剪的参考)和 \(\pi_\theta\)(被更新的策略)
    • 通过裁剪实现信任域 :通过比值 \(r_t(\theta) = \frac{\pi_\theta}{\mu}\) 限制策略更新幅度

Decoupled PPO :实现批次大小不变性(Batch Size Invariance)

  • 这里的 “批次大小不变性”,是指 Decoupled PPO 方法的一个关键特性
  • Batch Size Invariance 的定义:如果一个算法在 Batch Size 发生改变时,可以通过修改其他超参数(如 LR 等)来近似恢复原始 Batch Size 的训练行为,则称这个算法满足 Batch Size Invariance
  • 标准 PPO 通过比值 \(\frac{\pi_\theta}{\pi_{\text{old} } }\) 控制策略更新大小,其中 \(\pi_{\text{old} }\) 被假定同时是近端策略 和 行为策略
    • 这种耦合使得近端策略一直随着行为策略在变化,无法实现 Batch Size Invariance
      • 因为当 Rollout Batch Size 发生变化时,近端策略更新的频率也在发生变化,这个是无法恢复的
  • Decoupled PPO(Hilton,2021) 通过 Decoupled 两个角色 解决了 PPO 对批次大小的敏感性:
    • 1)Proximal policy \(\pi_{\text{prox} }\):PPO 裁剪的锚点策略(控制策略更新大小)
    • 2)Behavior policy \(\mu\):收集数据的策略(用于通过重要性采样进行 off-policy 校正)
    • 具体来说:Decoupled PPO 论文通过 COM(Center of Mass)来调节 Proximal policy 策略回看的步数(Batch Size 变小,则提升回看步数,几乎保证 Off-policy 幅度差不多)
  • Decoupled 这两个角色,得到 三策略公式 :
    $$
    L_{\text{DecoupledPPO} }(\theta) = -\mathbb{E}_{(s,a) \sim \mu} \left[ w_t \cdot \min\left( r_t(\theta) A_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right]
    $$
    • 其中:
      • \(w_t = \frac{\pi_{\text{prox} }(a_t|s_t)}{\mu(a_t|s_t)}\):重要性采样权重(校正行为策略 \(\mu\))
        • 这里 \(\pi_{\text{prox} }\) 在训练期间是冻结的,因此 \(w_t\) 是常数(不需要 stopgrad 操作符)
      • \(r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\text{prox} }(a_t|s_t)}\):PPO 比值(控制相对于近端策略 \(\pi_{\text{prox} }\) 的策略更新大小)
  • 通过 Decoupled 实现了:
    • 批次大小不变性 :策略更新控制(通过 \(\pi_{\text{prox} }\))独立于数据聚合方式(理解:因为 Decoupled PPO 可以做到更新独立于数据 Batch Size)
    • 灵活的行为策略 :可以使用任意 \(\mu\)(不同工作节点、回放缓冲或陈旧 checkpoint)
    • 陈旧数据利用 :可通过重要性采样校正更早的轨迹
    • 保留裁剪 :针对 \(\pi_{\text{prox} }\) 的裁剪限制了更新幅度

verl 中的实现:三策略框架

  • verl 库使用三种不同的策略实现 Decoupled PPO ,每种策略承担特定角色
  • 符号汇总
    • \(\pi_{\text{rollout} }\):行为策略(数据收集)
    • \(\pi_{\text{old} }\):近端策略(PPO 锚点)
    • \(\pi_{\theta}\):当前策略(被更新的策略)
    • \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\):每 Token 的 IS 比值(校正 Drift 1)
    • \(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{old} }(a_t|s_t)}\):PPO 比值(校正 Drift 2)
    • \(A_t\):Token \(t\) 处的优势
    • \(T\):序列中的有效 Token 集合
    • \(C_{\text{IS} }\):IS 权重的上阈值(例如 2.0)
    • \(C_{\text{RS-upper} }\):RS 掩码的上阈值(例如 2.0)
    • \(C_{\text{RS-lower} }\):RS 掩码的下阈值(通常为 \(1/C_{\text{RS-upper} }\))
    • \(\epsilon\):PPO 裁剪范围(通常为 0.2)

策略角色与符号

  • \(\pi_{\text{rollout} }\)(行为策略 \(\mu\))
    • 在 Rollout/数据收集阶段创建快照行为策略快照,生成用于训练的轨迹
      • 理解:一般在某个 Rollout 批次上的训练期间冻结(异步时则按照一定的时机来冻结)
    • 常见不匹配来源 :
      • 策略不匹配:相同权重,不同实现(精度、后端),补充:还有算子,forward 策略等
      • 时间滞后:来自异步工作节点的陈旧 checkpoint
      • 回放缓冲:来自更早迭代的历史数据
      • Off-policy 算法:专家演示、辅助策略(DAPO)
      • 数据过滤:重加权或过滤后的数据
  • \(\pi_{\text{old} }\)(近端策略 \(\pi_{\text{prox} }\))
    • PPO 裁剪的参考策略(在同一个批次上的所有 PPO 更新轮次中冻结)
      • PPO 裁剪的锚点(控制策略更新大小)
      • 当与 \(\pi_{\text{rollout} }\) 分离时:实现批次大小不变性和陈旧数据的有效利用
      • 理解:LLM 中这里通常是在同一个 Rollout 批次上的所有 PPO 更新轮次中冻结(异步时则是没多个连续的更新步之间冻结)
      • 理解:LLM 中常见的 Proximal Policy 跟原始论文 Decoupled PPO(Hilton,2021) 中的做法不同(原始论文使用了 COM(Center of Mass)的概念来得到 Proximal 策略(一个历史策略加权平均的策略)
    • 创建时机 :
      • Decoupled mode :在训练轮次开始时通过 actor.compute_log_prob() 计算
      • Bypass mode :设置为等于 \(\pi_{\text{rollout} }\)(跳过单独计算)
  • \(\pi_{\theta}\)(当前策略 Current Policy)
    • 在训练期间被优化的策略,每一步梯度更新都会被修改

Operating Modes,运行模式

  • Decoupled mode (三个策略)
    • 在每个训练轮次开始时单独计算 \(\pi_{\text{old} }\)
    • 具有三个策略的完整 Decoupled PPO (数学上正确)
    • 实现批次大小不变性
    • 分别校正 Drift 1(rollout→old)和 Drift 2(old→current)
  • Bypass mode (两个策略)
    • 设置 \(\pi_{\text{old} } = \pi_{\text{rollout} }\)(跳过单独计算)
    • 使用 \(\pi_{\text{rollout} }\) 同时作为行为策略和近端策略(数学上正确)
    • 近端策略等于行为策略,因此两者之间不需要 IS 校正
    • 更快(跳过 actor.compute_log_prob() 调用)
    • 不实现批次大小不变性

两种分布漂移

  • Drift 1: \(\pi_{\text{rollout} } \to \pi_{\text{old} }\)(Off-Policy 差距)
    • 数据收集策略与训练参考策略之间的分布偏移
    • 范围从可忽略(相同 checkpoint,微小差异)到严重(回放缓冲、专家数据)
    • 校正方式 :重要性采样权重 \(w_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\)
    • 当使用 Bypass mode 时可忽略
  • Drift 2: \(\pi_{\text{old} } \to \pi_{\theta}\)(策略更新漂移)
    • 训练期间策略参数更新带来的漂移
    • 随着 \(\pi_\theta\) 通过梯度下降更新而自然发生
    • 校正方式 :对比值 \(r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\text{old} }(a_t|s_t)}\) 进行 PPO 裁剪
    • 适用于 on-policy 和 off-policy 训练

算法组件与组合

  • verl 中的 Rollout 校正框架由 正交组件 构建而成,可以灵活组合:
    • 1)运行模式 :如何计算 \(\pi_{\text{old} }\)( Decoupled vs Bypass )
    • 2)损失函数 :PPO(带裁剪)vs 纯 IS(仅策略梯度)
    • 3)IS/RS 聚合级别 :Token、序列或几何 (Geometric)

运行模式: Decoupled vs Bypass

  • 运行模式决定近端策略 \(\pi_{\text{old} }\) 的计算方式
Decoupled mode (三个策略)
  • 参数:bypass_mode = false
  • 策略设置:
    • \(\pi_{\text{rollout} }\):行为策略(数据收集)
    • \(\pi_{\text{old} }\):近端策略(在训练轮次开始时通过 actor.compute_log_prob() 计算)
    • \(\pi_{\theta}\):当前策略(被更新)
  • IS 比值: \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\)(校正 Drift 1:rollout→old)
  • PPO 比值: \(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{old} }(a_t|s_t)}\)(校正 Drift 2:old→current)
  • 性质:
    • ✅ 实现批次大小不变性
    • ✅ 分别校正两种分布漂移
    • ✅ 高效利用陈旧数据
    • ❌ 需要额外的前向传播(actor.compute_log_prob())
Bypass mode (两个策略)
  • 参数: bypass_mode = true
  • 策略设置:
    • \(\pi_{\text{rollout} }\):行为策略(数据收集)
    • \(\pi_{\text{old} } = \pi_{\text{rollout} }\):近端策略等于行为策略
    • \(\pi_{\theta}\):当前策略(被更新)
  • 比值:
    • 使用 PPO-clip 损失(loss_type = "ppo_clip",默认):
      • PPO 比值 \(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\) 针对 Rollout 策略进行裁剪(IS 由比值处理)
    • 使用 REINFORCE 损失(loss_type = "reinforce"):
      • IS 比值 \(\rho_t = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\) 在损失函数中即时计算
  • 性质:
    • ✅ 跳过 actor.compute_log_prob() 调用(更快)
    • ✅ 通过 IS/RS 处理 off-policy 校正(当使用带 IS/RS 的策略梯度时)
    • ✅ 使用两个策略而非三个( \(\pi_{\text{rollout} }\) = \(\pi_{\text{old} }\) )
    • ⚠️ 不像 Decoupled mode 那样将近端策略与行为策略分离

损失函数:PPO vs 策略梯度

PPO 损失(带裁剪)
  • 参数: loss_type = "ppo_clip"( Bypass mode 默认)
  • 损失函数:
    $$
    L_{\text{PPO} }(\theta) = -\mathbb{E}_t \left[ w_t \cdot \min\left( r_t(\theta) A_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right]
    $$
    • \(w_t\):IS 权重(取决于聚合级别,见第 3.3 节)。在 Decoupled mode 下,\(w_t = \frac{\pi_{\text{old} } }{\pi_{\text{rollout} } }\),且 \(\pi_{\text{old} }\) 被冻结,因此 \(w_t\) 是常数(不需要 stopgrad)。在 Bypass mode 下使用 PPO 损失时,通常不单独计算 IS 权重
    • \(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{old} }(a_t|s_t)}\):PPO 比值
    • \(\epsilon\):裁剪范围(通常为 0.2)
  • 性质:
    • 通过裁剪实现信任域控制
    • 限制策略更新幅度
    • RL 训练中的标准做法
策略梯度损失(带 IS/RS 校正)
  • 参数:loss_type = "reinforce"(需要 bypass_mode = true)

  • 损失函数(以序列级 IS 为例):
    $$
    L_{\text{PG} }(\theta) = -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } } \left[ \text{stopgrad}(w_{\text{seq} }(\theta)) \cdot \sum_{t \in T} \log \pi_{\theta}(a_t|s_t) \cdot A_t \right]
    $$

    • \(w_{\text{seq} }(\theta)\):样本权重(IS 或 RS,详见 §3.3-3.4)
    • 对于 IS:\(w_{\text{seq} }(\theta) = \min\left( \prod_{t \in T} \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}, C_{\text{IS} } \right)\)
    • 对于 RS:\(w_{\text{seq} }(\theta) \in \{0, 1\}\)(二元拒绝掩码)
    • stopgrad 操作符 :权重 \(w_{\text{seq} }(\theta)\) 使用 \(\pi_\theta\) 计算,但在计算 \(\nabla_\theta L\) 时被当作 常数系数
      • 这对于重要性采样的正确性是必需的(理论依据见下文)
  • 有效梯度:
    $$
    \nabla_\theta L_{\text{PG} } = -\mathbb{E}_{(s,a) \sim \pi_{\text{rollout} } } \left[ \text{stopgrad}(w_{\text{seq} }(\theta)) \cdot \sum_{t \in T} \nabla_\theta \log \pi_{\theta}(a_t|s_t) \cdot A_t \right]
    $$

  • stopgrad 的理论依据:

    • stopgrad 操作符是 数学上必需的 ,由重要性采样理论要求,而非实现细节,原因如下:

      • 基本原则 :重要性采样是一种 改变测度 的技术(将样本从一个分布重新加权以估计另一个分布下的期望),而不是优化重加权函数本身

      • 形式推导 :

        • 1)原始目标 :作者要优化 \(J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta}[\sum_t A_t]\)

        • 2)Off-policy 设置 :作者只有来自 \(\pi_{\text{rollout} }\) 的样本,因此使用重要性采样:
          $$
          J(\theta) = \mathbb{E}_{\tau \sim \pi_{\text{rollout} } } \left[ \underbrace{\frac{P_{\pi_\theta}(\tau)}{P_{\pi_{\text{rollout} } }(\tau)} }_{w(\tau;\theta)} \sum_t A_t \right]
          $$

        • 3)计算策略梯度 :正确的梯度使用 重要性采样之前的策略梯度定理 :
          $$
          \begin{aligned}
          \nabla_\theta J(\theta) &= \nabla_\theta \mathbb{E}_{\tau \sim \pi_\theta}\left[\sum_t A_t\right] \\
          &= \mathbb{E}_{\tau \sim \pi_\theta} \left[\sum_t A_t \nabla_\theta \log \pi_\theta(a_t|s_t) \right] \quad \text{(策略梯度定理)} \\
          &= \mathbb{E}_{\tau \sim \pi_{\text{rollout} } } \left[ w(\tau;\theta) \sum_t A_t \nabla_\theta \log \pi_\theta(a_t|s_t) \right] \quad \text{(测度变换)}
          \end{aligned}
          $$

          • 在最后一行中,\(w(\tau;\theta)\) 作为 乘法系数 来自测度变换,而不是被微分的东西
        • 4)没有 stopgrad 会出什么问题 :如果作者在损失中朴素地计算 \(\nabla_\theta \left[w(\theta) \log \pi_\theta \right]\),会得到:
          $$
          \nabla_\theta \left[w(\theta) \log \pi_\theta \right] = \underbrace{\log \pi_\theta \cdot \nabla_\theta w(\theta)}_{\text{错误:偏置项} } + \underbrace{w(\theta) \cdot \nabla_\theta \log \pi_\theta}_{\text{正确:IS 加权梯度} }
          $$

          • 第一项 \(\log \pi_\theta \cdot \nabla_\theta w(\theta)\) 是计算技巧(使用损失乘以 log 概率)的产物,不是真正策略梯度的一部分
          • 它会使梯度估计产生偏差,并优化与 \(J(\theta)\) 不同的目标
        • 5)实现要求 :在 PyTorch 中,为了只计算第二项,作者必须使用:

          1
          loss = -advantages * log_prob * rollout_is_weights.detach()  # 对权重 stopgrad
          • 如果不使用 .detach(),autograd 会同时计算两项,给出错误的梯度
  • 直观理解 :IS 权重 \(w(\theta)\) 告诉我们 “在估计 \(\pi_\theta\) 下的梯度时,这个样本应该被多大程度地信任”

    • 更新 \(\theta\) 以最大化重新加权后的目标,但并不更新 \(\theta\) 以最大化权重本身,因为那将是循环论证(优化校正因子而不是实际目标)
  • 性质:

    • 算法 :带 IS/RS 校正的 Off-policy 策略梯度
    • 损失类型( Bypass mode 下的 loss_type 配置选项):
      • "ppo_clip"(默认):PPO 裁剪目标
        • \(L = -\mathbb{E}[\min(r \cdot A, \text{clip}(r) \cdot A)]\),其中 \(r = \pi_\theta / \pi_{\text{rollout} }\)
        • 注意:不应用 IS 权重(PPO 比值已经处理了它,否则会重复计数)
      • "reinforce":带显式 IS 权重的纯策略梯度,无 PPO 裁剪
        • \(L = -\mathbb{E}[w \cdot \log \pi_\theta(a|s) \cdot A]\),其中 \(w = \pi_\theta / \pi_{\text{rollout} }\)
    • 始终使用 Bypass mode :直接比较 \(\pi_\theta\) 和 \(\pi_{\text{rollout} }\)
    • 快速 :单次前向传播
  • 实现: core_algos.py 中的 compute_policy_loss_bypass_mode() 和 compute_policy_loss_reinforce()

IS/RS 聚合级别

  • 聚合级别决定每 Token 概率比值如何组合成 IS 权重和/或拒绝掩码
  • 这个选择 独立于运行模式 ,可以在 Decoupled mode 或 Bypass mode 下使用任何聚合级别
Token 级聚合
  • IS 权重:
    $$w_t = \min(\rho_t, C_{\text{IS} })$$

    • 其中
      • Decoupled:
        $$\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}$$
      • 或 Bypass /纯 IS
        $$\rho_t = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}$$
  • 参数配置:

    1
    2
    rollout_is = "token"  # IS 权重
    rollout_rs = "token_k1" # 可选:拒绝采样(比值边界)
  • 性质:

    • 每 Token 独立截断
    • 方差低于序列级(每 Token 的比值乘积被分别限定)
    • 偏差-方差权衡 :
      • Token 级校正偏差大,方差小:
        • Token 级矫正的 偏差 为 \(O(T^2 \Delta_{\max})\)
        • 其中 \(T\) 是序列长度,\(\Delta_{\max}\) 是每 Token 最大策略散度
        • 当 Rollout 策略与训练策略显著偏离时,这种偏差会变得显著
      • 序列级校正偏差为0,方差大
        • 数学上来看是无偏的,但方差更高
    • 典型阈值:1.5 - 5.0
    • 可选的批归一化 批归一化-batch-normalization:在所有 Token 权重上归一化,确保 \(\mathbb{E}[\tilde{w}_t] = 1\)(降低方差)
    • 使用时机 :当 Rollout 策略保持在训练策略的信任域内时,Token 级效果良好
      • 当不匹配严重时,偏差变得不可接受,此时应使用序列级校正
  • 损失函数(REINFORCE + Token IS):
    $$
    L_{\text{REINFORCE+TIS} }(\theta) = -\mathbb{E}_t \left[ \text{stopgrad}(w_t) \cdot \log \pi_\theta(a_t|s_t) \cdot A_t \right]
    $$

    • \(w_t = \min(\rho_t, C_{\text{IS} })\) 是截断后的 Token 级 IS 权重
    • stopgrad 操作符确保在计算 \(\nabla_\theta L\) 时,权重被视为常数
    • 此公式也可以通过将 REINFORCE 梯度替换为裁剪的替代目标来与 PPO 裁剪结合
  • 实现:

    • IS 权重:rollout_corr_helper.py 中的 compute_rollout_correction_weights()
    • 损失:core_algos.py 中的 compute_policy_loss()
序列级聚合
  • IS 权重:
    $$ w_{\text{seq} } = \min\left( \prod_{t \in T} \rho_t, C_{\text{IS} } \right) = \min\left( \exp\left(\sum_{t \in T} \log \rho_t\right), C_{\text{IS} } \right)$$

    • 广播到所有 Token
  • 参数配置:

    1
    2
    rollout_is = "sequence"  # IS 权重
    rollout_rs = "seq_sum_k1" # 可选:拒绝采样
  • 性质:

    • 乘法聚合
    • 对异常值比 Token 级更敏感
    • 典型阈值:2.0 - 10.0
    • 可选的批归一化 批归一化-batch-normalization:在序列均值上归一化(每个序列一个权重)
  • 术语说明:

    • Seq-TIS(序列级截断 IS) :将序列比值 \(\rho(\tau)\) 裁剪为 \(\min(\rho(\tau), C)\)
      • 通过从所有样本中提取信号来最大化信息效率
      • 适用于数据干净、不匹配程度适中的情况
    • Seq-MIS(序列级掩码 IS) :拒绝(掩码)\(\rho(\tau) > C\) 的序列,而不是裁剪
      • 相当于一个硬信任域过滤器
      • 适用于严重不匹配,或分布尾部 “有毒(toxic)”(包含垃圾/对抗样本而非信号)的情况
  • 损失函数(REINFORCE + 序列 IS):
    $$
    L_{\text{REINFORCE+SeqIS} }(\theta) = -\mathbb{E}_t \left[ \text{stopgrad}(w_{\text{seq} }) \cdot \log \pi_\theta(a_t|s_t) \cdot A_t \right]
    $$

    • \(w_{\text{seq} }\) 广播到序列中的所有 Token
    • stopgrad 操作符确保正确的 IS 梯度计算
    • 此公式也可以通过将 REINFORCE 梯度替换为裁剪的替代目标来与 PPO 裁剪结合
几何均值聚合 (Geo-RS)
  • 几何均值比值:
    $$ \rho_{\text{geo} } = \exp\left( \frac{1}{|T|} \sum_{t \in T} \log \rho_t \right) = \left(\prod_{t \in T} \rho_t\right)^{1/|T|} $$

    • 广播到所有 Token
  • 参数配置:

    1
    2
    rollout_is = null  # 无 IS 权重,纯拒绝
    rollout_rs = "seq_mean_k1" # 几何均值拒绝采样(比值边界)
  • 性质:

    • 长度不变性(按序列长度归一化)
    • 理想比值 = 1.0(策略匹配)
    • 典型边界:"0.999_1.001"(约 ±0.1%)
    • 仅用于拒绝采样,不用于 IS 加权
      • 理解:因为经过几何平均处理过的 IS 在数学上是不准确的(PS:GSPO 本身在数学上是不准确的)
  • 长度陷阱问题:

    • 标准 IS 估计器存在系统性的 长度偏差 ,会惩罚长序列,重要性比值 \(\rho(y)\) 是乘性的:
      $$
      \rho(y) = \prod_{t=1}^T \frac{\pi(y_t|y_{ < t})}{\mu(y_t|y_{ < t})}
      $$
      • 因为样本是从行为策略 \(\mu\) 中采样的,于是与 KL 散度类似,这个比值往往是小于等于 1 的,对概率比值的连乘(或者实现时更多是对概率比值对数的连加,然后取指数)会导致这个差异逐步累计,最终造成长度越长,得到的结果越极端(一般是接近于 0)
    • 假设新策略 \(\pi\) 与 \(\mu\) 略有不同,平均每 Token 比值约为 1.1(注:这个例子举的不好,每 Token 比值一般是小于 1 的):
      • 短序列(10 Token): \(\rho \approx 1.1^{10} \approx 2.6\) → 在阈值内,保留
      • 长序列(100 Token): \(\rho \approx 1.1^{100} \approx 13,780\) → 超过阈值,拒绝
    • 这会造成 上下文崩塌 (Context Collapse) :模型偏向于学习短而浅的答案,拒绝长推理链(即使每步质量相同)
      • 对于推理模型(CoT)和 Agent,这实际上惩罚了“思考太久”
  • Geo-RS 解决方案:

    • 几何级拒绝按序列长度归一化,将广延量(总概率乘积)转换为强度量(平均每 Token 漂移):
      $$
      \rho_{\text{geo} }(y) = \rho(y)^{1/T}
      $$
    • 现在两个序列具有相同的“信任分数”:
      • 短(10 Token): \((1.1^{10})^{1/10} = 1.1\)
      • 长(100 Token): \((1.1^{100})^{1/100} = 1.1\)
  • 为什么要用紧阈值?

    • 对于 100 个 Token,每个 Token 的对数比值为 0.01:
      • 算术乘积比值:\(e^{100 \times 0.01} \approx 2.7\)
      • 几何比值:\(e^{0.01} \approx 1.010\)
    • 比值边界 "0.999_1.001" 会拒绝平均每 Token 对数偏差超过约 0.1% 的序列
  • 损失函数(REINFORCE + 几何 RS):
    $$
    L_{\text{GeoRS} }(\theta) = -\mathbb{E}_{(s,a) \mid \text{seq} \in \mathcal{A}_{\text{geo} } } \left[ \sum_{t \in T} \log \pi_\theta(a_t|s_t) \cdot A_t \right]
    $$

    • 其中 \(\mathcal{A}_{\text{geo} } = \{ \text{seq} : C_{\text{RS-lower} } \leq \rho_{\text{geo} } \leq C_{\text{RS-upper} } \}\) 是接受集合(拒绝掩码)
    • 不使用 IS 权重,因此不需要 stopgrad
    • 此公式也可以通过将 REINFORCE 梯度替换为裁剪的替代目标来与 PPO 裁剪结合
  • 组合估计器(Geo-RS-Token-TIS):

    • 为获得最佳效果,将 几何过滤器(长度不变的有效性检查)与 Token 级 IS 权重(更低方差)结合:
      $$
      \hat{g}_{\text{geo-rs-token-tis} }(y) = \underbrace{\mathbb{I}\left( C_{\text{low} } \le \rho(y)^{1/T} \le C_{\text{high} } \right)}_{\text{几何过滤器} } \cdot \prod_t \min(\rho_t, C) \cdot f(y)
      $$
    • 参数配置:
      • rollout_rs="seq_mean_k1" and rollout_is="token"
K2 散度聚合
  • 每 Token 统计量:
    $$
    K2_t = \frac{1}{2} \left(\log \rho_t\right)^2
    $$

    • \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\),实现中将 \(\log \rho_t\) 裁剪到 \([-20, 20]\) 以保证数值安全
  • 序列聚合(共享相同的每 Token \(K2_t\)):

    • seq_sum_k2:\(K2_{\text{sum} } = \sum_{t \in T} K2_t\)
    • seq_mean_k2:\(K2_{\text{mean} } = \frac{1}{|T|} \sum_{t \in T} K2_t\)
    • seq_max_k2:\(K2_{\text{max} } = \max_{t \in T} K2_t\)
  • 参数配置:

    1
    2
    3
    rollout_is = null            # 可选:与 Token IS 权重搭配以降低方差
    rollout_rs = "token_k2" # 或 "seq_sum_k2", "seq_mean_k2", "seq_max_k2"
    rollout_rs_threshold = 2.0 # 仅正上界
  • 性质:

    • 在 \(\log \rho_t\) 上的对称二次惩罚;当策略匹配时为零
    • 在小策略漂移下近似 \(\tfrac{1}{2}\operatorname{Var}[\log \rho]\),因此是匹配度的平滑检测器
    • 仅有上阈值:典型范围对于 token_k2 为 1.5-3.0,对于 seq_mean_k2 为 2.0-2.5,对于 seq_sum_k2 为 2.5-4.0
    • seq_max_k2 即使在序列其余部分干净时也能隔离单 Token 尖峰
    • 可与 Token 级 IS 权重(rollout_is="token")共存,在保留有用样本的同时裁剪方差
  • 组合估计器(K2-RS-Token-TIS):

    • 对于组合过滤和加权,令 \(K2_{\text{agg} }\) 表示选定的聚合(token、sum、mean 或 max):
      $$
      \hat{g}_{\text{k2-rs-token-tis} }(y) = \underbrace{\mathbb{I}\left( K2_{\text{agg} }(y) \le C_{\text{k2} } \right)}_{\text{K2 过滤器} } \cdot \prod_t \min(\rho_t, C) \cdot f(y)
      $$
    • 参数配置:rollout_rs="seq_mean_k2"(或其他 k2 模式)配合 rollout_is="token" 实现
K3 散度聚合
  • 序列级 K3 散度:
    $$
    K3_{\text{seq} } = \frac{1}{|T|} \sum_{t \in T} \left( \rho_t - \log \rho_t - 1 \right)
    $$

    • \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\) 是每 Token 比值
  • K3 等于反向 KL: 在期望上,\(K3 = \text{KL}(\pi_{\text{rollout} } | \pi_{\text{old} })\),推导如下:

    • \(\mathbb{E}_{\pi_\text{rollout} }[\rho] = 1\)
    • \(\mathbb{E}_{\pi_\text{rollout} }[\log \rho] = -\text{KL}(\pi_{\text{rollout} } | \pi_{\text{old} })\)
    • 因此:\(K3 = 1 - (-\text{KL}) - 1 = \text{KL}(\pi_{\text{rollout} } | \pi_{\text{old} })\)
  • 参数配置:

    1
    2
    rollout_is = null          # 无 IS 权重,纯拒绝
    rollout_rs = "seq_mean_k3" # K3 拒绝采样
  • 性质:

    • K3 散度每 Token 总是 >= 0(当 \(\rho = 1\) 时等于 0)
    • 比几何比值检查更稳定,因为每个 Token 项都是非负的
    • 仅有上阈值(因为 K3 >= 0,无需下阈值)
    • 典型阈值:0.001 - 0.01
  • 为什么用 K3 而不是几何比值?

    • 几何比值使用平均对数比值;微小的数值偏差可能使符号翻转
    • \(K3 = \mathbb{E}[\rho - log \rho - 1]\) 每 Token 非负,提供更平滑的检测器
    • 两者估计相同的量:KL( \(\pi_{\text{rollout} }\) || \(\pi_{\text{old} }\) )
    • 对于小散度,K3 ≈ 0.5 × Var(log_ratio)
  • 组合估计器(K3-RS-Token-TIS):

    • 为获得最佳效果,将 K3 过滤器与 Token 级 IS 权重结合:
      $$
      \hat{g}_{\text{k3-rs-token-tis} }(y) = \underbrace{\mathbb{I}\left( K3_{\text{seq} } \le C_{\text{k3} } \right)}_{\text{K3 过滤器} } \cdot \prod_t \min(\rho_t, C) \cdot f(y)
      $$
    • 通过组合 rollout_rs="seq_mean_k3" 和 rollout_is="token" 实现

Batch Normalization, 批归一化

  • Batch Normalization 是一种可选的方差缩减技术,将 IS 权重归一化到每个批次内均值为 1.0

  • 参数配置

    1
    rollout_is_batch_normalize = True  # 默认:False
  • 归一化公式(聚合感知):

    • 对于 Token 级 IS :
      $$
      \tilde{w}_t = \frac{w_t}{\frac{1}{\sum_{i,t} m_{i,t} } \sum_{i,t} w_{i,t} \cdot m_{i,t} }
      $$
      • \(w_{i,t}\) 是截断后的 Token IS 权重
      • \(m_{i,t}\) 是 Response 掩码,归一化在 所有 Token 上进行
    • 对于 序列级 IS :
      $$
      \tilde{w}_i = \frac{w_i}{\frac{1}{B}\sum_{j=1}^B \bar{w}_j}
      $$
      • \(\bar{w}_j = \frac{1}{T_j}\sum_{t=1}^{T_j} w_{j,t} \cdot m_{j,t}\) 是每个序列的均值(一个序列中的所有 Token 权重相同),归一化在 序列 上进行
  • 性质:

    • 在截断 之后 应用,以保留截断的语义
    • 确保每个批次内 \(\mathbb{E}[\tilde{w}] = 1\)
    • 聚合感知 :
      • Token 级在 Token 上归一化
      • 序列级在序列上归一化
    • 使用 masked_mean 以尊重填充 Token
    • 通过消除随机的批次级尺度波动来降低梯度量级方差
  • 指标:

    • rollout_is_batch_norm_factor:应用的归一化因子(归一化前的批次均值)

拒绝采样 (RS)

  • 拒绝采样可以添加到 任何 运行模式和聚合级别的组合中,它修改 response_mask 以排除离群的 Token/序列

  • 参数配置示例:

    1
    2
    3
    4
    5
    6
    7
    8
    rollout_rs = "token_k1"    # Token 级比值边界
    rollout_rs_threshold = "0.6_1.6"

    rollout_rs = "seq_sum_k1" # 序列对数比值之和
    rollout_rs_threshold = "0.5_2.0"

    rollout_rs = "seq_mean_k3" # 序列 K3 散度均值
    rollout_rs_threshold = 0.01
  • 接受集合:

    • Token 级 :\(\mathcal{A}_{\text{token} } = \{ t : C_{\text{RS-lower} } \leq \rho_t \leq C_{\text{RS-upper} } \}\)
    • 序列级 :\(\mathcal{A}_{\text{seq} } = \{ \text{seq} : C_{\text{RS-lower} } \leq \prod_{t \in T} \rho_t \leq C_{\text{RS-upper} } \}\)
    • 几何级 :\(\mathcal{A}_{\text{geo} } = \{ \text{seq} : C_{\text{RS-lower} } \leq \rho_{\text{geo} } \leq C_{\text{RS-upper} } \}\)
  • 性质:

    • 与 IS 加权分离(可以只使用 RS 而不使用 IS)
    • 降低有效样本量
    • 过滤极端离群值
  • 代码实现: rollout_corr_helper.py 中的 compute_rollout_rejection_mask()

组合矩阵

  • 关键洞察: 估计器(如何计算 IS/RS)和运行模式( Decoupled PPO vs Bypass PG)是 正交的
  • 任何估计器都可以与任何运行模式组合
估计器 × 运行模式
  • 具体配置实例:
    估计器 配置 兼容模式
    Token-TIS rollout_is="token" Decoupled PPO , Bypass PG
    Seq-TIS rollout_is="sequence" Decoupled PPO , Bypass PG
    Seq-MIS rollout_is="sequence" + rollout_rs="seq_sum_k1" Decoupled PPO , Bypass PG
    Geo-RS rollout_rs="seq_mean_k1"(几何均值) Decoupled PPO , Bypass PG
    Geo-RS-Token-TIS rollout_is="token" + rollout_rs="seq_mean_k1" Decoupled PPO , Bypass PG
    K3-RS rollout_rs="seq_mean_k3" Decoupled PPO , Bypass PG
    K3-RS-Token-TIS rollout_is="token" + rollout_rs="seq_mean_k3" Decoupled PPO , Bypass PG
  • 注意: 在 Bypass mode 下,loss_type 控制损失函数
    • 使用 “ppo_clip”(默认)或 “reinforce”
可用的预设方法
  • 预设方法展示:
    预设方法 估计器 模式 性质
    Decoupled PPO 模式(3 个策略: \(\pi_{\text{rollout} }\) , \(\pi_{\text{old} }\) , \(\pi_{\theta }\))
    decoupled_token_is() Token-TIS Decoupled PPO 每 Token IS 权重
    decoupled_seq_is() Seq-TIS Decoupled PPO 序列级 IS 权重
    decoupled_seq_is_rs() Seq-MIS Decoupled PPO 序列 IS + 序列 RS
    decoupled_geo_rs() Geo-RS Decoupled PPO 几何 RS
    decoupled_geo_rs_token_tis() Geo-RS-Token-TIS Decoupled PPO 几何过滤器 + Token IS
    K3 KL 估计器(对小 KL 值更稳定)
    decoupled_k3_rs() K3-RS Decoupled PPO K3 拒绝,无 IS 权重
    decoupled_k3_rs_token_tis() K3-RS-Token-TIS Decoupled PPO K3 过滤器 + Token 裁剪权重
    Bypass mode (PPO-clip)(比值处理 IS,RS 掩码离群值)
    bypass_ppo_clip() - Bypass (PPO-clip) 仅 PPO-clip
    bypass_ppo_clip_geo_rs() Geo-RS Bypass (PPO-clip) PPO-clip + Geo-RS(比值)
    bypass_ppo_clip_k3_rs() K3-RS Bypass (PPO-clip) PPO-clip + K3-RS
    Bypass mode (REINFORCE)(显式 IS 权重,无 PPO 裁剪)
    bypass_pg_is() Seq-TIS Bypass (REINFORCE) REINFORCE + Seq IS
    bypass_pg_geo_rs() Geo-RS Bypass (REINFORCE) REINFORCE + Geo-RS(比值)
    bypass_pg_geo_rs_token_tis() Geo-RS-Token-TIS Bypass (REINFORCE) REINFORCE + Geo 过滤器 + Token IS
    其他
    disabled() - - 仅指标
  • 注意:Bypass mode 设置 \(\pi_{\text{old} }\) = \(\pi_{\text{rollout} }\) ,并使用 loss_type 选择损失函数
额外支持的组合(手动配置)
  • 这些组合 完全支持 ,但需要手动配置:

    • 1. Token IS + Token RS

      1
      2
      3
      4
      5
      6
      config = RolloutCorrectionConfig(
      rollout_is="token",
      rollout_is_threshold=2.0,
      rollout_rs="token_k1",
      rollout_rs_threshold="0.5_2.0",
      )
      • 性质: Token 级 IS 权重 + Token 级 RS 掩码
    • 2. 纯 Token RS

      1
      2
      3
      4
      5
      config = RolloutCorrectionConfig(
      rollout_is=None,
      rollout_rs="token_k1",
      rollout_rs_threshold="0.5_2.0",
      )
      • 性质: 仅 Token 级 RS 掩码,无 IS 权重
    • 3. 纯序列 RS

      1
      2
      3
      4
      5
      config = RolloutCorrectionConfig(
      rollout_is=None,
      rollout_rs="seq_sum_k1",
      rollout_rs_threshold="0.5_2.0",
      )
      • 性质: 仅序列级 RS 掩码,无 IS 权重
  • 关键性质:

    • 任何 IS 聚合级别(Token/序列)都可以在 Decoupled 或 Bypass mode 下使用
    • 拒绝采样可以添加到任何组合中
    • 几何聚合通常仅用于 RS(不用于 IS 加权)
    • 纯 RS(bypass_pg_rs)使用 Bypass + 几何 RS,搭配 loss_type="reinforce" 用于 REINFORCE(无 IS 权重)
    • 上表中的所有组合都是有效的,并且实现支持

常见实现错误

不正确的 LLM-RL 实现(无 Rollout 校正的 PPO)
  • 理论: 朴素的 LLM-RL 实现错误地应用 PPO,忽略实际 Rollout 策略 ,并假设 \(\pi_{\text{old} } = \pi_{\text{rollout} }\)
  • 注意: 这种错误的实现模式在 When Speed Kills Stability: Demystifying RL Collapse from the Training-Inference Mismatch 中被识别为 LLM-RL 系统训练不稳定的关键原因,从而推动了本 Rollout 校正框架的发展
  • 损失函数:
    $$
    L_{\text{PPO} }(\theta) = -\mathbb{E}_t \left[ \min\left( r_t(\theta) A_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right]
    $$
    • \(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\text{old} }(a_t|s_t)}\)(忽略 \(\pi_{\text{rollout} }\))
  • 为什么这是错误的:
    • 忽略 \(\pi_{\text{rollout} }\) :使用 \(\pi_{\text{old} }\) 作为行为策略,而不是实际的 \(\pi_{\text{rollout} }\)
    • 策略不匹配 :在 LLM-RL 中,Rollout 通常使用与训练不同的精度/后端/checkpoint,即使权重相同,也会导致 \(\pi_{\text{rollout} } \neq \pi_{\text{old} }\)
    • 不是 PPO 的错 :PPO 本身是正确的;问题在于错误的假设
  • 正确的替代方案:
    • 1)Decoupled mode :三个策略,带从 \(\pi_{\text{rollout} }\) 到 \(\pi_{\text{old} }\) 的 IS 校正
    • 2)Bypass mode :两个策略,使用 \(\pi_{\text{rollout} }\) 同时作为行为策略和近端策略
    • 3)Bypass + 策略梯度模式 :两个策略,带 IS/RS 校正,无 PPO 裁剪
  • 实现: core_algos.py 中的 compute_policy_loss()

Off-Policy 诊断指标

  • 这些指标量化 off-policy 漂移的严重程度
  • 符号说明: 指标使用 \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\)
    • 在 Bypass mode 下,\(\pi_{\text{old} } = \pi_{\text{rollout} }\),因此指标使用 \(\rho_t = \frac{\pi_{\theta} }{\pi_{\text{rollout} } }\) 来测量 rollout→current 漂移

KL 散度

  • 直接 KL 估计器:
    $$
    \text{KL}(\pi_{\text{rollout} } | \pi_{\text{old} }) = \mathbb{E}_{t \sim \pi_{\text{rollout} } } \left[ \log \pi_{\text{rollout} }(a_t|s_t) - \log \pi_{\text{old} }(a_t|s_t) \right]
    $$
  • K3 KL 估计器(替代公式):
    $$
    \text{KL}_{\text{K3} } = \mathbb{E}_{t \sim \pi_{\text{rollout} } } \left[ \rho_t - \log \rho_t - 1 \right]
    $$
    • 其中 \(\rho_t = \frac{\pi_{\text{old} }(a_t|s_t)}{\pi_{\text{rollout} }(a_t|s_t)}\)

困惑度 (Perplexity)

  • 旧策略困惑度:
    $$
    \text{PPL}_{\text{old} } = \exp\left( -\frac{1}{|T|} \sum_{t \in T} \log \pi_{\text{old} }(a_t|s_t) \right)
    $$
  • Rollout 策略困惑度:
    $$
    \text{PPL}_{\text{rollout} } = \exp\left( -\frac{1}{|T|} \sum_{t \in T} \log \pi_{\text{rollout} }(a_t|s_t) \right)
    $$
  • PPL 比值(几何均值 IS 权重的倒数):
    $$
    \text{PPL}_{\text{ratio} } = \frac{\text{PPL}_{\text{old} } }{\text{PPL}_{\text{rollout} } } = \exp\left( -\frac{1}{|T|} \sum_{t \in T} \log \rho_t \right) = \left(\prod_{t \in T} \rho_t\right)^{-1/|T|}
    $$
  • 解释: 值 > 1 表示 \(\pi_{\text{old} }\) 对观察到的动作赋予的概率低于 \(\pi_{\text{rollout} }\)(存在分布偏移)

卡方散度

  • 衡量 IS 权重分布的二阶矩
  • Token 级:
    $$
    \chi^2_{\text{token} } = \mathbb{E}_{t \sim \pi_{\text{rollout} } } \left[ \rho_t^2 \right] - 1
    $$
  • 序列级:
    $$
    \chi^2_{\text{seq} } = \mathbb{E}_{\text{seq} \sim \pi_{\text{rollout} } } \left[ \left(\prod_{t \in T} \rho_t\right)^2 \right] - 1
    $$
  • 解释:
    • \(\chi^2 = 0\):策略相同
    • \(\chi^2 > 0\):值越高表示 off-policy 分布偏移越严重
  • 实现: rollout_corr_helper.py 中的 compute_offpolicy_metrics()

总结与决策指南

方法汇总表

  • 整体方法汇总:
    方法 理论 策略数 PPO 裁剪 IS 校正 正确性 速度
    Bypass mode( \(\pi_{\text{old} }\) = \(\pi_{\text{rollout} }\) ,loss_type 选择算法)
    loss_type="ppo_clip"(默认) PPO(比值 = \(\pi_{\theta }\)/ \(\pi_{\text{rollout} }\) ) 2(rollout, \(\theta\)) ✅ 仅 RS 掩码(比值处理 IS) ✅ 正确 快
    loss_type="reinforce" Off-policy REINFORCE 2(rollout, \(\theta\)) ❌ ✅(显式 IS 权重) ✅ 正确 快
    Bypass mode 预设(PPO-clip)
    bypass_ppo_clip 仅 PPO 2(rollout, \(\theta\)) ✅ - ✅ 正确 快
    bypass_ppo_clip_geo_rs PPO + Geo-RS 2(rollout, \(\theta\)) ✅ Geo-RS 掩码(比值) ✅ 正确 快
    Bypass mode 预设(REINFORCE)
    bypass_pg_is REINFORCE + Seq-TIS 2(rollout, \(\theta\)) ❌ ✅ Seq-TIS ✅ 正确 快
    bypass_pg_geo_rs REINFORCE + Geo-RS 2(rollout, \(\theta\)) ❌ 仅 Geo-RS(比值) ✅ 正确 快
    bypass_pg_geo_rs_token_tis REINFORCE + Geo RS + Token IS 2(rollout, \(\theta\)) ❌ ✅ Geo-RS-Token-TIS ✅ 正确 快
    Decoupled PPO 模式(IS 权重 = \(\pi_{\text{old} }\) / \(\pi_{\text{rollout} }\) )
    decoupled_token_is Decoupled PPO 3(rollout, old, \(\theta\)) ✅ ✅ Token-TIS ✅ 正确 标准
    decoupled_seq_is Decoupled PPO 3(rollout, old, \(\theta\)) ✅ ✅ Seq-TIS ✅ 正确 标准
    decoupled_seq_is_rs Decoupled PPO + RS 3(rollout, old, \(\theta\)) ✅ ✅ Seq-MIS ✅ 正确 标准
    decoupled_geo_rs Decoupled PPO + Geo-RS 3(rollout, old, \(\theta\)) ✅ Geo-RS 仅(比值) ✅ 正确 标准
    decoupled_geo_rs_token_tis Decoupled PPO + Geo RS + Token IS 3(rollout, old, \(\theta\)) ✅ ✅ Geo-RS-Token-TIS ✅ 正确 标准
    错误(供参考)
    朴素 LLM-RL 错误的 PPO 使用 2(old, \(\theta\)) ✅ ❌ ⚠️ 错误 标准
  • 注意:
    • Bypass mode 设置 \(\pi_{\text{old} }\) = \(\pi_{\text{rollout} }\) ,并使用 loss_type 选择损失函数:
      • "ppo_clip"(默认):PPO 裁剪比值(IS 由比值 = \(\pi_{\theta }\)/ \(\pi_{\text{rollout} }\) 处理,不显式使用 IS 权重以避免重复计数)
      • "reinforce":显式 IS 权重以 \(w \cdot \log \pi \cdot A\) 的形式应用
    • 两种损失类型都受益于拒绝采样(RS),它可以掩码掉分布外的样本

估计器层级

  • 这些估计器定义 IS 权重和拒绝掩码的计算方式
  • 它们与运行模式( Decoupled PPO vs Bypass 策略梯度)正交,并且可以与任一种组合
    估计器 配置 机制 最适合
    Token-TIS rollout_is="token" 裁剪每 Token 比值 偏差可接受时方差较低的 IS
    Seq-TIS rollout_is="sequence" 裁剪序列比值 \(\rho(\tau) \to \min(\rho(\tau), C)\) 数据干净、不匹配程度适中的情况;无偏
    Seq-MIS rollout_is="sequence" + rollout_rs="seq_sum_k1" 拒绝 \(\rho(\tau) > C\) 的序列 严重不匹配;过滤“有毒尾部”(垃圾数据)
    Geo-RS rollout_rs="seq_mean_k1" 基于几何均值比值 exp(E[log(r)]) 拒绝 长度不变的信任域
    Geo-RS-Token-TIS rollout_is="token" + rollout_rs="seq_mean_k1" 几何过滤器 + Token IS 权重 基于比值的长度归一化 + 低方差 IS
    K3-RS rollout_rs="seq_mean_k3" 基于 K3 KL 散度拒绝 小 KL 值;平滑检测器
    K3-RS-Token-TIS rollout_is="token" + rollout_rs="seq_mean_k3" K3 过滤器 + Token IS 权重 小 KL + 低方差 IS
  • 注意: 每个估计器都可以与以下任一种运行模式结合使用:
    • Decoupled PPO(bypass_mode=false):三个策略,带 PPO 裁剪
    • Bypass mode(bypass_mode=true):两个策略,可配置损失类型
      • loss_type="ppo_clip"(默认):PPO 裁剪目标(IS 通过比值,应用 RS 掩码)
      • loss_type="reinforce":带显式 IS 权重的 REINFORCE

基于场景的方法特点

  • 按 off-policy 严重程度选择估计器:
    • 可忽略(相同 checkpoint,微小差异):无需 IS 校正;使用 Bypass mode 以提高效率
    • 中等(异步工作节点,轻微陈旧):Token-TIS 提供每 Token IS 校正,方差较低
    • 严重(回放缓冲,陈旧数据):Seq-TIS 或 Seq-MIS 提供序列级 IS 校正;当高权重样本可能包含垃圾数据时使用 Seq-MIS
  • 按序列长度选择估计器:
    • 短序列(标准对话):Seq-TIS 最优
    • 长序列(CoT,Agent):K1-RS 或 K1-RS-Token-TIS 以避免长度陷阱
  • 选择运行模式:
    • 需要批次大小不变性 :使用 Decoupled mode (bypass_mode=false)
    • 需要计算效率 :使用 Bypass mode (bypass_mode=true)以跳过 old_log_prob 计算
    • 无需 PPO 裁剪 :使用 Bypass mode 并设置 loss_type="reinforce"

Decoupled mode vs Bypass mode

  • Decoupled mode(单独计算 old_log_prob):
    • 实现完整的 Decoupled PPO ,使用三个策略(数学上正确)
    • 分别测量和校正 Drift 1(rollout→old)和 Drift 2(old→current)
    • 实现批次大小不变性和陈旧数据的高效利用
    • 支持准确的 off-policy 指标监控
  • Bypass mode(设置 \(\pi_{\text{old} } = \pi_{\text{rollout} }\)):
    • 使用 \(\pi_{\text{rollout} }\) 同时作为行为策略和近端策略(数学上正确)
    • 计算效率:跳过单独的 old_log_prob 计算
    • 不实现批次大小不变性(近端策略取决于数据收集方式)
1…343536…352
San Ye

San Ye

Stay Hungry. Stay Foolish.

704 posts
53 tags
© 2026 San Ye
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4