Hexo

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

NLP——LLM-RL训练指标记录

注:本文包含 AI 辅助创作


整体说明

  • 本文汇总 LLM-RL 训练过程中需要关注的各种指标
  • RL 训练指标重要性:
    • 宗旨:能在训练指标上体现的问题,都不该留到下游测试集上再体现
    • Insight:全面的指标监控有助于快速发现各种可能存在的隐藏 Bug 或 找到改进点

训练日志落盘

  • 训练时在每一步都落表下面的内容
    • Prompt
    • Response/Rollout(每个 Prompt 可能多个)
    • 真实 Rewards 打分情况(每个 Response/Rollout 至少一个,若多个 Reward Model/Rule 则有多个)
    • final_rewards 打分情况(包含长度惩罚等后的最终奖励)

KL 散度(当前策略 vs Reference 策略)

  • KL 散度是最常见的观测指标,有助于判断当前策略偏离 Reference 策略多少了
  • KL 散度的监控上报值往往是直接估计值
    • 注:KL 散度完整值需要对全词表积分,除了用于偶尔对齐指标或训推不一致问题排查外,一般不需要使用
    • KL 散度的近似估计方式有 k1,k2,k3 三种,建议监控 k1 和 k3,其中 k1 的值会更稳定些,k3 可能存在较多 spike
  • 经验:
    • 好的 KL 散度曲线应该是缓慢的逐步增长(若设定 Target KL 来动态调整 KL 惩罚系数,会逐步收敛到 Target KL 区间内)
    • 模型的崩溃往往伴随着 KL 散度的突然崩溃
      • 遇到 KL 突然崩溃时,一般其他指标也会随着崩溃,包括熵、Rewards 曲线等
      • 若 KL 突然崩溃,即使训练时的 Rewards 等暂时没有崩溃,大概率也出现问题了
  • 注意:在使用了 Actor Warmup 的场景中,可能看到比较特别的表现:
    • 可能看到第一步大家都是 0,但第二步的 KL 散度是 0,KL_loss 不为 0
      • KL 散度是 Rollout 后立刻算出来的,第一步模型学习率为 0,此刻模型还没更新,所以第二步看到的指标中 KL 散度依然是 0
      • KL_loss 是梯度步更新计算的,一旦学习率不为 0(第二步),有梯度步开始更新以后,KL_loss 散度就不在是 0 了
    • 补充:这个前提是针对 Rollout 步上报机制的,且 Actor Warmup 是根据 Rollout Step 计算的(整个 Rollout 步的多次 梯度步 使用相同学习率),比如 VeRL 就是这样的

Response 长度

  • Response 长度代表着模型对长度偏好的变化,是非常重要的关注指标
  • Response 相关的指标还有 8K 截断率、16K 截断率、32K 截断率等
  • 经验:
    • 回复长度可能会持平、缓慢上涨、缓慢降低,看具体策略而言可能不同

Entropy

  • 当前策略的熵代表当前模型的探索能力(熵越大,不确定性越高,探索能力越强)
  • 经验:
    • 好的熵没有特别固定的形状,但有一些参考:
      • 可能逐步降低然后收敛(收敛过快往往不是好事,说明模型过快丢失探索能力)
      • 可能先降低,再提升,再收敛(观察到有时候提升时往往伴随着长度的增加)

真实奖励 rewards/score(不包含 kl_rewards 等)

  • ORM 场景中,真实奖励仅出现在最后一个 Token,这个奖励可以看做是 Sequence 粒度的真实奖励(必须监控)
    • 注:这个真实奖励有时也叫做 scores 等
  • 若使用了 PRM,也建议使用详细的上报保证可监控(建议分 Step 进行上报和监控)
  • 针对不同领域同时训练的场景,应该分领域上报该值
  • 对于 Rewards 是 0-1 的场景,应该同步上报每个 Prompt 的正确率等,否则需上报 Rewards 的分布情况
  • 经验:
    • 好的 rewards/score 曲线应该是逐步上涨然后逐步收敛的
    • 若训练过程中突然下降,大概率是模型崩溃了(此时往往伴随着 KL 散度崩溃)

loss 类

Actor Loss

  • Actor Loss 本身不太具备特殊含义,比如 REINFORCE 中的目标函数/损失函数更多只是为了凑出梯度来
  • 经验:
    • Actor Loss 这个值可能是波动的,看不到收敛迹象,但不太会逐步提升
    • 若 Actor Loss 先稳定,然后突然提升, 那么大概率是在这里发生模型崩溃了
    • 在 GRPO/PPO 中,actor loss 跟 advantages 的均值呈现反比(绝对值不同,但是趋势相反),因为 大约有如下公式(忽略 clip 等,不同算法略有不同,但基本差不多)
      $$ \text{loss} \approx - \text{advantages} \times \frac{\pi_\theta}{\pi_{\theta_\text{old}}} $$

Critic Loss

  • Critic Loss 代表了 Critic 模型拟合状态价值函数的能力
  • 经验:
    • 这个值在 Pretrain 阶段是大幅下降的,然后逐步收敛,在 Actor 和 Critic 交叉训练过程中保持收敛状态
    • 若在 Actor 和 Critic 交叉训练过程中, Critic Loss 逐步升高或明显高于 Pretrain 阶段的收敛值,说明当前 Critic 学习速度跟不上 Actor,需要 降低 Actor 学习率 or 提升 Critic 学习率 or 增加 Critic 训练步数(一步 Actor 梯度更新对应多步 Critic 梯度更新)

KL Loss

  • 与 kl 散度本质一致,更多是计算 k2 或 k3

Entropy Loss

  • 与 Entropy 指标一致
  • Rewards 曲线一般直接上报样在进行 Advantages 计算前的奖励情况,一般会上报多个相关值

NLL Loss

  • 仅对 reward > 0 的 token 计算 -mean(action_logprobs * nll_loss_mask),再乘以 rewards_mean,相当于仅更新 reward > 0 的 token,且按照 rewards_mean 加权的交叉熵损失(或负对数似然)更新

MTP Loss

  • MTP Loss

PPO PG IS Clip 相关

  • 重要性采样权重 Clip 相关的各种情况和比例

训推不一致监控和修正各种指标

  • 训推不一致的监控指标
    • training_ppl(包括 log_training_ppl)
    • rollout_ppl(包括 log_rollout_ppl)
    • training_rollout_ppl_diff(包括 training_rollout_log_ppl_diff)
      • training_rollout_log_ppl_diff:一般是统计 Sequence 内部 Token 的 log_probs 均值作为 log_ppl
      • 所以 training_rollout_log_ppl_diff 和下面的 training_rollout_kl(k1) 可能完全相同(若 training_rollout_kl 也是先计算,公式上可看出是同一个值)
        • 注:与 training_rollout_kl(k3) 不同,但趋势几乎一致
    • training_rollout_kl(包含 k1,k3 都可以同时上报,这个值在一些论文中也称为类似 vllm_kl 的命名)
      • 经验:training_rollout_kl 指标在不同模型/显卡上表现不同:
        • 在 GPU H200 卡,Dense 20B 左右的小模型上几乎没有 spike(但训练过程中从 1.2e-3 提升到 2.1e-3 水平,说明这个指标除了与硬件、参数量、模型架构、引擎实现有关外,还与模型自身的输出分布有关)
        • 在 NPU 910B 卡,MoE 500B-A30B 左右的大模型上有许多 spike(训练过程中从 1.5e-3 级别会 spike 到 1.5e-2 级别,甚至偶尔到 5e-2 级别,但不会逐步提升,与 Dense 20B 不同)
  • 极端 Token(Rollout 或 Training 引擎上的低概率 Token 比例,一般如 < 1e-3 等)
  • IS(Importance Sampling)修复系数的统计(均值、标准差等)
    • Sequence-level 和 Token-level 的
  • RS(Rejection Sampling)过滤系数的统计(均值、标准差等)
    • 注:被拒绝等价于被 Mask
    • 按照配置上报,也可以同时上报下面三种:
      • Token-level:按照 Sequence-level 作为过滤粒度,Token 粒度的 IS 比例作为判断依据
      • Sequence-level:按照 Sequence-level 作为过滤粒度,序列内所有 Token 系数的乘积(联合概率分布)作为判断依据
      • Geometric(Sequence-level):按照 Sequence-level 作为过滤粒度,序列内所有 Token 系数的集合平均作为判断依据

Advantages

  • Advantages 表示了 Token 的打压 or 鼓励情况,是最关键的指标之一
  • PPO 的 Advantages 分为 Batch Norm 归一化前和归一化后的,要分别监控
  • 经验:
    • Advantages 的上报(比如均值,最大值等)应该完整符合推导结果(比如均值为 0, 最大值不能超过理论上限等)
    • PPO 中未经过归一化的 Advantages 均值也应该几乎贴近于 0,若大于 0 则大概率是 Critic 还没收敛

Gradient Norm

  • 这个指标需要从底层 Infra 去统计并上报
  • 经验:Gradient Norm 一开始会比较大(可能会涨一下),然后逐步下降
  • 若训练崩溃,则 Gradient Norm 会突然变的非常大,所以 Gradient Norm 变大要非常小心

附录:遇到过的各种指标异常现象总结

PPO 训练过程中 \((\pi_\theta - \pi_{old})\) 逐步增大意味着什么?

  • 首先:对于每个 Rollout Step,第一个梯度 Step 的 \((\pi_\theta - \pi_{old})\) 始终为 0
    • 因为在每次 Rollout 结束后,当前策略网络 \(\pi_\theta\) 的权重与用于采样的旧策略网络 \(\pi_{old}\) 完全一致
  • 若观察到随着 Rollout 步数(或训练 Epoch)的增加,第二个梯度 Step 的 \((\pi_\theta - \pi_{old})\) 的方差越来越大,这是一个需要警惕的信号
    • 通常意味着单次梯度更新对策略产生了越来越剧烈且不均匀的扰动
  • 注:此时 PPO 训练是使用了 Advantages Batch Normalization 的
    • 即:无论 Reward Model 给出的分数多么离谱,无论原始的 TD Error 方差有多大,输入到 Loss 函数中的 Advantage 的均值严格为 0,方差严格为 1
可能问题1:优势函数(Advantage)的方差在急剧扩大(若没有进行 Advantages Batch Normalization )
  • 在 PPO 中,策略更新的梯度方向和步长主要由优势函数 \(A(s,a)\) 决定
  • 若没有进行 Advantages Batch Normalization,且 \((\pi_\theta - \pi_{old})\) 的方差变大,说明在同一个 Batch 内,某些 Token 的概率被剧烈推高,而另一些被剧烈压低
  • 问题发生的链路:
    • 随着 Rollout 的进行,策略模型逐渐偏离初始的 SFT 模型,开始探索到奖励模型未曾见过的状态(OOD 数据)
      • 这会导致 RM 输出极端的、充满噪声的奖励(即已经发生了 Reward Hacking)
    • 进一步导致Critic 无法准确拟合这些极端的奖励,导致计算出的 Advantage 出现极大的方差
    • 高方差的 Advantage 直接导致了高方差的梯度更新
  • 可能导致这一点的原因包含:
    • KL Penalty 不足,导致模型偏离 Reference Model 太多,从而进入 RM 的 OOD 区间,打分开始变得激进且误差大
      • 实验验证:完全关闭 KL Penalty 后,Advantages 的方差 和 \((\pi_\theta - \pi_{old})\) 方差
  • 解法:增加 KL Penalty 约束,防止模型发生 Reward Hacking
可能的问题2:Critic 跟不上 Actor 的更新
  • Critic 的任务是预测当前状态的价值 \(V(s)\)
  • 如果 Actor 的策略变化过快,或者 Critic 的学习率/拟合能力不足,Critic 的预测就会产生滞后
  • 不准确的 \(V(s)\) 会导致 Advantage 估计错误
    • 随着 Rollout 步数增加,这种误差会累积,导致 Actor 在第二步更新时接收到极其嘈杂的梯度信号(有偏的,有误差的信号),从而表现为更新幅度的方差增大
  • 解法:提升 Critic 学习率、降低 Actor 学习率,或者让 Critic 多更新几步

GRPO 训练时 Advantage 均值不为 0

  • Advantage 的均值上报逻辑为:经过组内归一化,再按照序列平均(Token 相等,平均前后值不变),最后在 Sequence 间做归一化
    • 理论上,这个值肯定为 0,因为组内均值为 0,多个组均值也应该为 0
  • 发生问题的原因:
    • 当同一个组的 rewards 完全相同且是无理数时,可能因为精度问题导致组内归一化 Bug
      • 自身减去组内均值不为 0,是一个相同的 1e-8 量级的正数或者负数(具体正负和原始 rewards 值有关)
      • 1e-8 量级的数再除以 (std + 1e-8) 得到在 1 左右的 Advantage(且同一组内所有 Token 值相等)
  • 可选的解法(亲测:std 相关的解法本质都是避免针对过小的 std 组做过大的更新,这类解法可以大幅缩小训练过程中的 kl spike):
    • mask std 过小的组
    • 提升 std 的兜底值
    • 不使用 std 作为分母(如 Dr.GRPO)
    • (精确修复)提升归一化计算的精度(默认 torch 使用 float32,可以切换为 float64 计算)

附录:VeRL 框架上报指标汇总(20260423)

  • 本次梳理 commit_id 为:6daa6e0c1626567a90454a9a79076b30d34d4d8b
  • VeRL 所有指标最终通过下面代码统一上报到 wandb/swanlab 等实验跟踪后端
    1
    logger.log(data=metrics, step=self.global_steps)

Actor 相关指标

actor/pg_loss,策略梯度损失
  • 文件:verl/workers/actor/dp_actor.py:477

  • 由compute_policy_loss_* 系列函数计算后返回,以标准 PPO(vanilla)为例:

    1
    2
    3
    4
    5
    # 令 ratio = exp(log_prob - old_log_prob)(当前策略与旧策略的概率比)
    pg_losses1 = -advantages * ratio
    pg_losses2 = -advantages * clip(ratio, 1 - ε_low, 1 + ε_high)
    pg_losses= max(pg_losses1, pg_losses2) #(带 dual-clip 时取 min 与 c·A)
    pg_loss = agg_loss(pg_losses, response_mask, loss_agg_mode)
  • 其中 agg_loss 支持四种聚合模式(由配置决定):

    • token-mean:所有有效 token 的均值
    • seq-mean-token-sum:先对序列内的 token 求和,再对序列取均值
    • seq-mean-token-mean:先对序列内的 token 取均值,再对序列取均值
    • seq-mean-token-sum-norm:先对序列内的 token 求和,再除以最大响应长度(然后对序列取均值)
actor/pg_clipfrac,策略梯度上裁剪比例
  • 文件:verl/workers/actor/dp_actor.py:478

    1
    pg_clipfrac = masked_mean(pg_losses2> pg_losses1, response_mask)
    • 即 ratio > 1 + ε_high 时被裁剪的token 比例(正优势方向被clip 的占比)
actor/pg_clipfrac_lower,策略梯度下裁剪比例(dual-clip)
  • 文件:verl/workers/actor/dp_actor.py:480

    1
    2
    3
    4
    pg_clipfrac_lower = masked_mean(
    (clip_pg_losses1 > pg_losses3) * (advantages< 0).float(), response_mask
    )
    # 其中 pg_losses3 = -advantages * clip_ratio_c(默认 c=3.0)
  • 仅在 advantages < 0(负优势)时,因 dual-clip 机制触发的 token 比例

    • GSPO/GPG/KL-Cov 等方法此项固定为 0
actor/ppo_kl,近似 KL 散度
  • 文件:verl/workers/actor/dp_actor.py:479

    1
    2
    3
    negative_approx_kl = clamp(log_prob - old_log_prob, -20, 20)
    ppo_kl = masked_mean(-negative_approx_kl, response_mask)
    = masked_mean(old_log_prob - log_prob, response_mask)
  • 这是 KL(π_old ‖ π) 的 token 级均值估计(一阶近似)

    • 在 kl_cov 变体中,上报的是绝对值均值 masked_mean(|log_prob - old_log_prob|, response_mask)
actor/entropy,策略熵
  • 文件:verl/trainer/ppo/ray_trainer.py:1189

  • 在 recompute old_log_probs 阶段从 Actor 的 forward 中获取:

    1
    2
    token_entropy = logsumexp(logits) - sum(softmax(logits) * logits) # 得到每个 token 的熵,与熵的原始定义等价
    entropy_agg = agg_loss(entropys, response_mask, loss_agg_mode)
    • token_entropy 是 Token 粒度的熵
    • entropy_agg 是对 token 粒度的熵按指定 loss 聚合模式计算的标量值(这个计算公式和)
    • 理解:
      • 原始的计算公式中,直接对 softmax 结果取 log 在概率接近 0 时会出现 -inf
      • 这里用 logsumexp (内部用 max-shift 技巧稳定计算)和 pd * logits (logits 本身就是有限值)避免了 log(0) 问题
      • 整个计算流仅涉及稳定的算子,适合大规模训练中的低精度/混合精度场景
    • 注:在新版本的 verl.utils.torch_functional.entropy_from_logits 中,定义函数如下:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      def entropy_from_logits(logits: torch.Tensor) -> torch.Tensor:
      """Calculate Shannon entropy from unnormalized logits.

      Computes H(p) = -sum(p * log(p)) using the numerically stable formula:
      entropy = logsumexp(logits) - sum(softmax(logits) * logits)

      Args:
      logits: Unnormalized log-probabilities of shape (..., vocab_size).

      Returns:
      torch.Tensor: Entropy values with shape (...,), one per distribution.
      """
      pd = torch.nn.functional.softmax(logits, dim=-1)
      entropy = torch.logsumexp(logits, dim=-1) - torch.sum(pd * logits, dim=-1)
      return entropy
  • 补充:上述 token_entropy 的公式推导:
    $$
    \begin{align}
    \text{Entropy}
    &= -\sum_i p_i \log p_i \\
    &= -\sum_i p_i \log\left( \frac{e^{z_i}}{\sum_j e^{z_j}} \right) \\
    &= -\sum_i p_i \left( z_i - \log\sum_j e^{z_j} \right) \\
    &= -\sum_i p_i z_i + \log\sum_j e^{z_j} \cdot \sum_i p_i \\
    &= -\sum_i p_i z_i + \log\sum_j e^{z_j} \\
    &= \text{logsumexp}(z) - \sum_i \left( \text{softmax}(z)_i \cdot z_i \right)
    \end{align}
    $$

actor/kl_loss,KL 损失(有条件上报)
  • 文件:verl/workers/actor/dp_actor.py:465

  • 仅当 config.use_kl_loss = True 时上报:

    1
    2
    kld = kl_penalty(log_prob, ref_log_prob, kl_penalty_type)
    kl_loss = agg_loss(kld, response_mask, loss_agg_mode) * loss_scale_factor
    • 其中 kl_penalty_type 支持多种估计方式(详见 KL 惩罚计算)
actor/kl_coef,KL 损失系数(有条件上报)
  • 文件:verl/workers/actor/dp_actor.py:466

    1
    actor/kl_coef = config.kl_loss_coef
    • 仅当 use_kl_loss = True 时上报,为超参数常量
actor/reward_kl_penalty,奖励中的 KL 惩罚均值
  • 文件:verl/trainer/ppo/ray_trainer.py:191

  • 仅当 algorithm.use_kl_in_reward = True 时,在 apply_kl_penalty 函数中计算:

    1
    2
    3
    4
    kld = kl_penalty(old_log_probs, ref_log_prob, kl_penalty_type)# token level
    kld = kld * response_mask
    current_kl = mean(masked_mean(kld, response_mask, axis=-1)) # 先对序列内平均,再对 batch 平均
    actor/reward_kl_penalty = current_kl
  • 最终 token 级奖励 = token_level_scores - beta * kld

actor/reward_kl_penalty_coeff, KL 惩罚自适应系数
  • 文件:verl/trainer/ppo/ray_trainer.py:191

    1
    actor/reward_kl_penalty_coeff = kl_ctrl.value #(beta,自适应调整)
  • 实际实现时是设定一个 kl 目标,若未达到目标,则通过提升或降低 kl_coef 来调整模型朝达到目标的方向走

actor/grad_norm,Actor 梯度范数
  • 文件:verl/workers/actor/dp_actor.py:486

    1
    actor/grad_norm = clip_grad_norm_(actor_module, max_grad_norm).item()
  • 由 _optimizer_step() 在梯度裁剪时返回

actor/lr,Actor 学习率
  • 文件:verl/workers/fsdp_workers.py:727 / verl/workers/megatron_workers.py:610
    1
    actor/lr = actor_lr_scheduler.get_last_lr()[0]
perf/mfu/actor,Actor MFU(模型浮点利用率)
  • 文件:verl/workers/fsdp_workers.py:719
    1
    2
    estimated_flops = flops_counter.estimate_flops(global_num_tokens, delta_time)
    perf/mfu/actor = estimated_flops * ppo_epochs / promised_flops / world_size

Critic 相关指标

critic/vf_loss,价值函数损失
  • 文件:verl/workers/critic/dp_critic.py:254

    1
    2
    3
    4
    5
    vpredclipped = clip(vpreds, values - ε_v, values + ε_v)
    vf_losses1 = (vpreds - returns)**2
    vf_losses2 = (vpredclipped - returns)**2
    clipped_vf_losses = max(vf_losses1, vf_losses2)
    vf_loss = 0.5 * agg_loss(clipped_vf_losses, response_mask, loss_agg_mode) * loss_scale
    • 这个设计比传统 RL 中 PPO 算法的更优,详细分析可参考:NLP——LLM对齐微调-RLHF,简单理解如下:
      • 1)如果模型预期更新幅度大且之前已经改进过模型了(模型已经更贴近当前目标了) ,它会切断梯度(Loss 取 clipped_value_loss),让模型 “稳一点,别急”
      • 2)如果模型更新更新幅度大且之前往反方向更新过模型了(模型已经更远离当前目标了),它保留梯度(Loss 取 value_loss),让模型 “赶紧改错”
      • 3)如果模型在安全范围内更新,它就是普通的 MSE Loss
critic/vf_clipfrac,价值函数裁剪比例
  • 文件:verl/workers/critic/dp_critic.py:255

    1
    vf_clipfrac = masked_mean(vf_losses2 > vf_losses1, response_mask)
  • 即被 clip 的价值预测所占 token 比例

critic/vpred_mean,价值预测均值
  • 文件:verl/workers/critic/dp_critic.py:256

    1
    critic/vpred_mean = masked_mean(vpreds, response_mask)
  • 当前 mini-batch 中,Critic 对 response token 的价值预测均值

critic/grad_norm,Critic 梯度范数
  • 文件:verl/workers/critic/dp_critic.py:263
    1
    critic/grad_norm = clip_grad_norm_(critic_module, max_grad_norm).item()
critic/lr,Critic 学习率
  • 文件:verl/workers/fsdp_workers.py:1307 / verl/workers/roles/critic.py:178
    1
    critic/lr = critic_lr_scheduler.get_last_lr()[0]
perf/mfu/critic,Critic MFU
  • 文件:verl/workers/fsdp_workers.py:1304 / verl/workers/roles/critic.py:176
    1
    perf/mfu/critic = estimated_flops * ppo_epochs / promised_flops / world_size

奖励/优势/回报统计指标(compute_data_metrics)

  • 这些指标在 verl/trainer/ppo/metric_utils.py:compute_data_metrics 中统一计算
得分(Score)指标
  • 具体指标:
    指标 计算方式
    critic/score/mean mean(token_level_scores.sum(-1)[non_aborted]),非中止样本的序列级得分均值,注意是对 Sequence 内部的 Token 做 sum
    critic/score/max max(token_level_scores.sum(-1)[non_aborted])
    critic/score/min min(token_level_scores.sum(-1)[non_aborted])
  • 注:token_level_scores 是 reward function 输出的原始得分(未减去 KL 惩罚)
奖励(Reward)指标
  • 具体指标
    指标 计算方式
    critic/rewards/mean mean(token_level_rewards.sum(-1)[non_aborted]),含KL 惩罚后的实际奖励均值
    critic/rewards/max max(token_level_rewards.sum(-1)[non_aborted])
    critic/rewards/min min(token_level_rewards.sum(-1)[non_aborted])
  • 注:token_level_rewards = token_level_scores - beta * kld(若开启 KL penalty)
优势值(Advantages)指标
  • 具体指标
    指标 计算方式
    critic/advantages/mean mean(advantages[response_mask]),所有有效 response token 的优势值均值
    critic/advantages/max max(advantages[response_mask])
    critic/advantages/min min(advantages[response_mask])
回报(Returns)指标
  • 具体指标:
    指标 计算方式
    critic/returns/mean mean(returns[response_mask]),有效 token 的回报均值(GAE 计算结果)
    critic/returns/max max(returns[response_mask])
    critic/returns/min min(returns[response_mask])
价值预测(Values)指标(仅 use_critic=True 时)
  • 具体指标
    指标 计算方式
    critic/values/mean mean(values[response_mask]),Critic 旧价值预测均值
    critic/values/max max(values[response_mask])
    critic/values/min min(values[response_mask])
    critic/vf_explained_var 1 - var(returns - values) / (var(returns) + 1e-5),Critic 价值函数解释方差,越接近 1 表示价值估计越准确

序列长度相关指标

  • 均在 verl/trainer/ppo/metric_utils.py:compute_data_metrics 中计算
    指标 计算方式
    response_length/mean mean(response_mask.sum(-1).float()),所有样本 response token 数均值
    response_length/max max(response_length) ,response_length=response_mask.sum(-1).float()
    response_length/min min(response_length)
    response_length/clip_ratio mean(response_length == max_response_length),达到最大长度被截断的样本比例
    response_length_non_aborted/mean 仅统计 response_length > 0 的样本的response 长度均值
    response_length_non_aborted/max 同上,取最大值
    response_length_non_aborted/min 同上,取最小值
    response_length_non_aborted/clip_ratio 非中止样本中达到最大长度的比例
    response/aborted_ratio mean(response_length == 0),响应长度为 0(中止/异常)的样本比例
    prompt_length/mean mean(prompt_mask.sum(-1).float()),prompt token 数均值
    prompt_length/max max(prompt_length)
    prompt_length/min min(prompt_length)
    prompt_length/clip_ratio mean(prompt_length == max_prompt_length),prompt被截断的比例

多轮对话相关指标(按条件展示)

  • 当 batch 中存在 __num_turns__ 字段时上报(多轮对话场景):
    指标 计算方式
    num_turns/mean num_turns.mean(),每条样本的对话轮数均值
    num_turns/max num_turns.max()
    num_turns/min num_turns.min()
  • 当 batch 中存在 tool_call_counts 字段时上报(工具调用场景):
    指标 计算方式
    tool_call_counts/mean tool_call_counts.mean()
    tool_call_counts/max tool_call_counts.max()
    tool_call_counts/min tool_call_counts.min()

时序性能指标

  • 在 verl/trainer/ppo/metric_utils.py 的 compute_timing_metrics 和 compute_throughout_metrics 中计算
各阶段耗时(timing_s/*)
  • 具体逻辑:

    1
    timing_s/{stage_name} = 该阶段实际执行时间(秒)
  • 阶段名称包括:

    • gen(生成)
    • ref(参考策略前向)
    • values(价值估计)
    • adv(优势计算)
    • update_critic(Critic 更新)
    • update_actor(Actor 更新)
    • reward(奖励计算)
    • old_log_prob(log prob 重计算)
    • testing(验证)
    • save_checkpoint(保存检查点)
    • step(总步时间)等
每 token 耗时(timing_per_token_ms/*)
  • 具体计算逻辑:

    1
    2
    timing_per_token_ms/gen = timing_s["gen"] * 1000 / num_response_tokens
    timing_per_token_ms/{其他阶段} = timing_s[stage] * 1000 / (num_prompt_tokens + num_response_tokens)
  • 注:gen 阶段只用 response token 数作分母,其他阶段用全序列 token 数

吞吐量与性能指标

  • 吞吐量相关指标:
    指标 计算方式
    perf/total_num_tokens sum(batch.meta_info["global_token_num"]),本step 处理的 token 总数
    perf/time_per_step timing_raw["step"],每个训练步的总耗时(秒)
    perf/throughput total_num_tokens / (time * n_gpus),每 GPU 每秒处理的 token 数
    perf/max_memory_allocated_gb torch.device.max_memory_allocated() / 1024³,GPU峰值显存分配(GB)
    perf/max_memory_reserved_gb torch.device.max_memory_reserved() / 1024³,GPU 峰值显存预留(GB)
    perf/cpu_memory_used_gb psutil.virtual_memory().used / 1024³,CPU 内存占用(GB)

训练状态指标

  • 在 verl/trainer/ppo/ray_trainer.py:1343 处直接赋值:
    指标 计算方式
    training/global_step 当前全局训练步数 self.global_steps
    training/epoch 当前 epoch 编号

批次负载均衡指标(按条件展示)

  • 当 trainer.balance_batch = True 时,在 _balance_batch 方法中调用 log_seqlen_unbalance(verl/utils/seqlen_balancing.py:194):
    指标 计算方式
    global_seqlen/min 各DP rank 的序列长度之和中的最小值(均衡前)
    global_seqlen/max 各 DP rank 的序列长度之和中的最大值(均衡前)
    global_seqlen/minmax_diff max - min(不均衡程度,越小越好)
    global_seqlen/balanced_min 均衡后各 rank 的序列长度最小值
    global_seqlen/balanced_max 均衡后各 rank 的序列长度最大值
    global_seqlen/mean 各 rank 序列长度总和的均值

Debug 调试指标(按照条件展示)

  • 当 batch 中存在 rollout_log_probs 字段时(开启 rollout vs actor prob 对比),在 verl/utils/debug/metrics.py:calculate_debug_metrics 中计算:
    指标 计算方式
    training/rollout_probs_diff_valid 固定为 1,表示输入有效
    training/rollout_probs_diff_max `max(
    training/rollout_probs_diff_mean `mean(
    training/rollout_probs_diff_std `std(
    training/rollout_actor_probs_pearson_corr corrcoef(actor_probs, rollout_probs)[response_mask],Pearson 相关系数,参考 arXiv:2506.13585

验证集指标(按条件展示)

  • 在 _validate() 方法中,通过 process_validation_metrics 函数处理后以多种统计形式上报:

    1
    2
    3
    4
    5
    6
    7
    8
    val-core/{data_source}/{var_name}/mean@N 		# N 个 rollout 的均值
    val-core/{data_source}/{var_name}/std@N # N 个 rollout 的标准差
    val-core/{data_source}/{var_name}/best@N/mean # bootstrap 采样最优值的均值(pass@N变体)
    val-core/{data_source}/{var_name}/best@N/std # bootstrap 采样最优值的标准差
    val-core/{data_source}/{var_name}/worst@N/mean # bootstrap 采样最差值的均值
    val-core/{data_source}/{var_name}/worst@N/std # bootstrap 采样最差值的标准差
    val-core/{data_source}/{var_name}/maj@N/mean # 多数投票结果的均值(如有 pred字段)
    val-core/{data_source}/{var_name}/maj@N/std # 多数投票结果的标准差
  • 其中 N 以 2 的幂次递增(2, 4, 8, …, n_resps),bootstrap 采样 1000 次。val-aux/ 前缀同理,还额外包含:

    • val-aux/num_turns/mean|max|min(多轮验证时)

补充:KL 散度计算方式汇总

  • kl_penalty 函数(core_algos.py:1272)支持多种 KL 估计变体:
    类型 公式
    kl / k1 logprob - ref_logprob(一阶线性近似)
    abs `
    mse / k2 0.5 * (logprob - ref_logprob)²
    low_var_kl / k3 exp(clamp(ref - log, -20, 20)) - (ref - log) -1(低方差估计,来自 Schulman 2020)

VeRL 中的训推不一致相关指标

  • VeRL 中本功能使用说明文档:github.com/verl-project/verl/blob/main/docs/algo/rollout_corr.md
    • 文档中明确指出训推不一致的校准有三种数学上无偏的方式,详情见:NLP——LLM对齐微调-RL-Collapse-Training-Inference-Mismatch(Sequence-level-MIS)
  • VeRL 数学理论文档:(Mathematical Formulations of Rollout Correction Methods in verl)github.com/verl-project/verl/blob/main/docs/algo/rollout_corr_math.md
  • 这里的指标都来自 rollout_corr_helper.py 文件
  • 所有指标最终都通过 compute_rollout_correction_and_add_to_batch 注入训练 batch 并以 rollout_corr/ 前缀上报
    • 注:compute_rollout_corr_metrics_from_logprobs 还可在 actor 端用当前策略 log prob 实时重算 off-policy 子集指标,用于跟踪训练过程中 off-policy gap 的演化
  • VeRL 训推相关指标汇总:
    关注问题 推荐观察指标
    训推分布是否一致(核心) kl、k3_kl、chi2_token、chi2_seq
    训练 vs 采样 PPL 偏移 log_ppl_diff、ppl_ratio、training_ppl/rollout_ppl
    IS 权重稳定性 rollout_is_eff_sample_size、rollout_is_std、rollout_is_seq_max_deviation
    越界样本比例 rollout_is_ratio_fraction_high/low、rollout_is_oob_ratio
    RS 拒绝强度 rollout_rs_masked_fraction、rollout_rs_seq_masked_fraction、各 <opt>_masked_fraction
    哪类散度主导 对比 rollout_rs_<opt>_mean(k1 反映方向,k2/k3 反映幅度)

符号约定

  • 为统一定义公式方便后续表达,这里我先约定以下符号:
    符号 含义 verl 原始对应代码
    \(B\) batch size —
    \(T\) 序列长度 —
    \(M\in\{0,1\}^{B\times T}\) 矩阵,response_mask,valid token 掩码 response_mask
    \(\pi_{\text{tr} }\) 训练策略(如 FSDP FP32) —
    \(\pi_{\text{ro} }\) 采样策略(如 vLLM BF16) —
    \(a_{i,t}=\log\pi_{\text{tr} }(y_t\mid y_{ < t})\) 训练侧 log 概率,部分开发框架可能叫做 action_log_prob old_log_prob
    \(r_{i,t}=\log\pi_{\text{ro} }(y_t\mid y_{ < t})\) 采样侧 log 概率 rollout_log_prob
    \(\ell_{i,t}=a_{i,t}-r_{i,t}=\log\rho_{i,t}\) log 重要性比 log_ratio
    \(\rho_{i,t}=e^{\ell_{i,t} }=\pi_{\text{tr} }/\pi_{\text{ro} }\) 重要性比 raw_rollout_is_weights
    \(\tau_u,\tau_l\) IS 上下/下界阈值 rollout_is_threshold_upper/lower
    \(N_i=\sum_t M_{i,t}\) 第 \(i\) 序列有效 token 数 —
  • 带掩码算子:
    $$
    \begin{align}
    \text{mMean}(x,M)&=\frac{\sum_{i,t}M_{i,t}x_{i,t} }{\sum_{i,t}M_{i,t}+10^{-8} }\\
    \text{mSum}_i(x,M)&=\sum_t M_{i,t}x_{i,t}\\
    \text{mMean}_i(x,M)&=\frac{\text{mSum}_i(x,M)}{N_i+10^{-8} }
    \end{align}
    $$
  • 注意:全部指标最终在 ./verl/trainer/ppo/rollout_corr_helper.compute_rollout_correction_and_rejection_mask 中统一加 rollout_corr/ 前缀
    • 也就是说:所有的训推不一致相关指标都在 rollout_corr/ 这个 前缀下

Off-policy 诊断指标

  • 代码见:./verl/trainer/ppo/rollout_corr_helper.compute_offpolicy_metrics
  • 这一组指标最直接刻画训推不一致 ,无论是否启用 IS/RS 都会计算
  • 假设 Sequence \(i\) 的平均 log 概率:
    $$\bar{a}_i=\text{mMean}_i(a,M),\quad \bar{r}_i=\text{mMean}_i(r,M)$$
训练策略 PPL
  • 序列级训练困惑度定义为:\(PPL_{tr}^{(i)} = \exp(-\bar{a}_i)\)
  • 总体平均指标:
    指标 公式
    training_ppl \(\displaystyle \frac{1}{B}\sum_{i=1}^B \exp(-\bar{a}_i)\)
    training_log_ppl \(\displaystyle \frac{1}{B}\sum_{i=1}^B (-\bar{a}_i)\)
采样策略 PPL
  • 序列级采样困惑度定义为:\(PPL_{ro}^{(i)} = \exp(-\bar{r}_i)\)
  • 总体平均指标:
    指标 公式
    rollout_ppl \(\displaystyle \frac{1}{B}\sum_{i=1}^B \exp(-\bar{r}_i)\)
    rollout_log_ppl \(\displaystyle \frac{1}{B}\sum_{i=1}^B (-\bar{r}_i)\)
KL 散度估计
  • 直接估计量
    $$\texttt{kl}=\text{mMean}(r-a,M)=\mathbb{E}_{\text{token} }\left[\log\frac{\pi_{\text{ro} } }{\pi_{\text{tr} } }\right]\approx\text{KL}(\pi_{\text{ro} }\Vert\pi_{\text{tr} })$$
    • 正值表示采样策略比训练策略”更自信”(即训推不一致,训练侧分配概率偏低)
  • K3 KL 估计量(Schulman k3,小 KL 下更稳定)
    $$\texttt{k3_kl}=\text{mMean}\left(e^{\ell}-\ell-1,M\right)=\mathbb{E}_{\text{token} }[\rho-\log\rho-1]\approx\text{KL}(\pi_{\text{ro} }\Vert\pi_{\text{tr} })$$
序列级 log-PPL 差
  • 定义 Sequence \(i\) 的差值 \(\Delta_i=\bar{r}_i-\bar{a}_i=\log\frac{\text{PPL}_{\text{tr} }^{(i)} }{\text{PPL}_{\text{ro} }^{(i)} }\):
    指标 公式
    log_ppl_diff \(\displaystyle \frac{1}{B}\sum_i \Delta_i=\mathbb{E}\left[\log\frac{\text{PPL}_{\text{tr} } }{\text{PPL}_{\text{ro} } }\right]\)
    log_ppl_abs_diff \(\displaystyle \frac{1}{B}\sum_i \lvert\Delta_i\rvert\)
    log_ppl_diff_max \(\max_i \Delta_i\)
    log_ppl_diff_min \(\min_i \Delta_i\)
PPL 比值
  • 序列级 PPL 比值 定义 ppl_ratio_i
    • 对于第 \(i\) 个序列,定义其 PPL 比值为:
      $$
      \text{ppl_ratio_i} = \exp(\Delta_i) = \frac{PPL_{tr}^{(i)} }{PPL_{ro}^{(i)} }
      = \exp(\bar{r}_i - \bar{a}_i)
      $$
  • 几何重要性采样权重
    • 序列级的几何平均 IS 权重定义为每个 token 重要性比 \(\rho_{i,t} = e^{\ell_{i,t} }\) 的几何平均:
      $$
      \text{geometric_is_i} = \left( \prod_{t:M_{i,t}=1} \rho_{i,t} \right)^{\frac{1}{N_i} }
      = \exp\left( \frac{1}{N_i} \sum_{t} \ell_{i,t} \right)
      = \exp(\bar{a}_i - \bar{r}_i)
      $$
      • 几何平均相对直接连乘最大的优点是方差极小,且方差随着序列长度的增加而减小
  • 倒数关系
    • 由上两式直接得到:
      $$
      \text{ppl_ratio_i} = \frac{1}{\text{geometric_is_i} }
      $$
    • 注:这与原始代码注释 ppl_ratio_i = 1 / geometric_is_i 完全一致
  • PPL 比值 总体平均 ,上报指标为 rollout_corr/ppl_ratio
    • 所有序列的平均 PPL 比值定义为 ppl_ratio:
      $$
      \texttt{ppl_ratio} = \frac{1}{B} \sum_i \text{ppl_ratio_i}
      = \frac{1}{B} \sum_i \exp(\Delta_i)
      = \mathbb{E}\left[\frac{PPL_{tr} }{PPL_{ro} }\right]
      $$
    • 总体 PPL 比值 rollout_corr/ppl_ratio 的物理意义 :
      • 当训推分布一致时,\(\text{geometric_is_i} \approx 1\),故 \(\text{ppl_ratio_i} \approx 1\)
      • 若训练侧平均概率低于采样侧(\(\bar{a}_i < \bar{r}_i\)),则几何 IS 权重小于 1,PPL 比值(rollout_corr/ppl_ratio)大于 1
\(\chi^2\) 散度(衡量 IS 权重方差,越大越 off-policy)
  • token 级 \(\chi^2\) 散度 chi2_token :
    $$\texttt{chi2_token}=\text{mMean}(\rho^2,M)-1=\mathbb{E}_{\text{token} }[\rho^2]-1=\chi^2(\pi_{\text{tr} }\Vert\pi_{\text{ro} })$$
    • 其中:
      $$\rho=e^\ell=\frac{\pi_{\text{tr} }}{\pi_{\text{ro} }}$$
      • 再次注明:\(\ell_{i,t}=a_{i,t}-r_{i,t}=\log\rho_{i,t}\) 是 log 重要性比(log_ratio)
    • 理解:
      • chi2_token 在衡量 Token 粒度的 比值的平方与 1 之间的差异,这个值为 0 时说明没有训推没有任何误差
      • 当 \(\mathbb{E}[\rho] = 1\) 时(一般都满足),\(\texttt{chi2_token}=\text{mMean}(\rho^2,M)-1=\chi^2(\pi_{\text{tr} }\Vert\pi_{\text{ro} })\) 的值总是大于 0
        $$
        \begin{aligned}
        \texttt{chi2_token} &= \mathbb{E}[\rho^2] - 1 \\
        &= \mathbb{E}[\rho^2] - (\mathbb{E}[\rho])^2 \quad \left( \text{因为 } \mathbb{E}[\rho] = \int \frac{\pi_{\text{tr}}}{\pi_{\text{ro}}} \pi_{\text{ro}} dx = \int \pi_{\text{tr}} dx = 1 \right) \\
        &= \text{Var}(\rho) \\
        &= \mathbb{E}[(\rho - 1)^2] \ge 0.
        \end{aligned}
        $$
  • 序列级 \(\chi^2\) 散度 chi2_seq :
    $$\texttt{chi2_seq}=\frac{1}{B}\sum_i \exp\bigl(2\text{mSum}_i(\ell,M)\bigr)-1=\mathbb{E}_{\text{seq} }[(\rho_i^{\text{seq} })^2]-1$$
    • 其中:
      $$ \rho_i^{\text{seq} }=\prod_{t:M_{i,t}=1}\rho_{i,t}=\exp(\text{mSum}_i(\ell,M)) $$
      • 相对 Token 粒度指标 \(\rho=e^\ell=\frac{\pi_{\text{tr} }}{\pi_{\text{ro} }}\) 的差异是 Sequence 粒度指标先对 log_ratio \(\ell\) 求和,然后再取指数
  • 理解;
    • 训推完全一致时 :两者都等于 0(因为 \(\rho=1\),方差为零)
    • 训推不一致时 :
      • chi2_token :随单步偏差小幅增长(反映局部噪音)
      • chi2_seq :因长度累乘效应呈指数级爆炸(远大于 chi2_token),序列越长、微小偏差累积越大,直接反映全局分布已严重漂移

IS 权重指标

  • 代码在 verl/trainer/ppo/rollout_corr_helper.compute_is_metrics 函数中
  • 由 verl/trainer/ppo/rollout_corr_helper.compute_rollout_correction_weights 函数计算的权重 \(w\)(截断/IcePop 后)和原始权重 \(w_{\text{raw} }\):
    • token 级:
      $$w_{\text{raw} }=e^{\text{clamp}(\ell,\pm 20)}$$
    • sequence 级(计算后广播到所有 token):
      $$w_{\text{raw} }=e^{\text{clamp}(\text{mSum}_i(\ell,M),\pm 20)}$$
      • 注:Token 级和序列级上报的参数是同一个,所以选择 Token 级和 序列级后,得到的这个指标会变成对应的粒度的值
    • TIS:
      $$w=\min(w_{\text{raw} },\tau_u)$$
    • IcePop(MIS):
      $$w=w_{\text{raw} }\cdot\mathbb{1}[\tau_l\le w_{\text{raw} }\le\tau_u]$$
  • 记后续的多个值为:
    $$
    \begin{align}
    w^c=\text{clamp}(w,0,\tau_u) \\
    \tilde{w}=\frac{w^c}{\text{mMean}(w^c,M)}
    \end{align}
    $$
    • 注:这里是归一化权重
中心趋势
  • 这个是非常核心的指标,rollout_is_mean 一般需要在 1 附近,如果太小(比如 Sequence 粒度下,经过累加以后得值就很容易很小或者太大(一般是很小),可能导致模型梯度很小或者很大
    指标 公式
    rollout_is_mean \(\text{mMean}(w,M)\)
    rollout_is_max \(\max_{i,t:M=1} w_{i,t}\)
    rollout_is_min \(\min_{i,t:M=1} w_{i,t}\)
    rollout_is_std \(\sqrt{\text{mMean}\bigl((w^c)^2,M\bigr)-\text{mMean}(w^c,M)^2}\)
  • 注意:代码实现中 sequence 级 rollout_is_max/min 用 log 空间计算以避免溢出
越界比例(衡量 off-policy 比例)
  • 记录超过设定阈值的比例,这几个比例,谁高都不行,最好是都比较低
    级别 指标 公式
    token rollout_is_ratio_fraction_high \(\text{mMean}(\mathbb{1}[w_{\text{raw} }>\tau_u],M)\)
    token rollout_is_ratio_fraction_low \(\text{mMean}(\mathbb{1}[w_{\text{raw} }<\tau_l],M)\)
    seq rollout_is_ratio_fraction_high \(\frac{1}{B}\sum_i\mathbb{1}[\text{mSum}_i(\ell,M)>\log\tau_u]\)
    seq rollout_is_ratio_fraction_low \(\frac{1}{B}\sum_i\mathbb{1}[\text{mSum}_i(\ell,M)<\log\tau_l]\)
有效样本量 ESS
  • 记录有效的样本数量 rollout_is_eff_sample_size
    $$\texttt{rollout_is_eff_sample_size}=\frac{1}{\text{mMean}(\tilde{w}^{2},M)}\in(0,1]$$
    • ESS 越接近 \(1\) 说明权重越均匀(训推一致),越小则 IS 方差越大
    • 注意:名字虽然叫做 ESS,但是实现时是标准的 ESS 除以了 N 的,所以得到的是 0-1 之间的值
附录:ESS 的代码及数学证明详情
  • ESS 计算源码

    1
    2
    3
    4
    5
    6
    7
    # Compute Effective Sample Size (ESS) for truncated weights
    weights_for_ess: torch.Tensor = rollout_is_weights.clamp(min=0.0, max=rollout_is_threshold)
    mean_for_ess: torch.Tensor = verl_F.masked_mean(weights_for_ess, response_mask)
    is_weights_normalized: torch.Tensor = weights_for_ess / (mean_for_ess + 1e-8) # Avoid division by zero
    metrics["rollout_is_eff_sample_size"] = (
    1.0 / verl_F.masked_mean(is_weights_normalized.square(), response_mask).item()
    )
  • 公式定义:

    • 原始权重为 \(w_i\)(代码中的 weights_for_ess)
    • 批量大小为 \(N\)(有效 Token 总数)
    • 权重均值为 \(\bar{w} = \frac{1}{N}\sum w_i\)(代码中的 mean_for_ess)
    • 归一化权重为 \(\tilde{w}_i = \frac{w_i}{\bar{w} }\)(代码中的 is_weights_normalized)
  • 代码最终输出的指标为 :
    $$
    \text{ESS}_{\text{code} } = \frac{1}{\frac{1}{N}\sum_i \tilde{w}_i^2}
    $$

  • 代入 \(\tilde{w}_i = w_i / \bar{w}\) 展开 :
    $$
    \begin{aligned}
    \text{ESS}_{\text{code} }
    &= \frac{1}{\frac{1}{N}\sum_i \left(\frac{w_i}{\bar{w} }\right)^2} \\
    &= \frac{1}{\frac{1}{N}\sum_i \frac{w_i^2}{\bar{w}^2} } \\
    &= \frac{1}{\frac{1}{\bar{w}^2} \cdot \frac{1}{N}\sum_i w_i^2} \\
    &= \frac{\bar{w}^2}{\frac{1}{N}\sum_i w_i^2} \\
    &= \frac{(\frac{1}{N}\sum_i w_i)^2}{\frac{1}{N}\sum_i w_i^2} \quad (\text{将 }\bar{w}\text{ 还原为均值}) \\
    &= \frac{(\sum_i w_i)^2}{N \cdot \sum_i w_i^2} \quad (\text{分子分母同乘 } N^2)
    \end{aligned}
    $$

  • 对比标准 ESS 的归一化比例 :

    • 标准的绝对 ESS 为 \(\frac{(\sum w_i)^2}{\sum w_i^2}\),除以总样本数 \(N\) 后就是 \(\text{ESS}_{\text{code} }\):
      $$
      \text{ESS}_{\text{code} } = \frac{(\sum w_i)^2}{N \cdot \sum w_i^2}
      $$
      • 所以代码中的指标在 0-1 之间 :
  • 补充: 关于 标准的绝对 ESS 为 \(\frac{(\sum w_i)^2}{\sum w_i^2}\) 的证明:

    • 本节在证明一个本质:用权重的平方和与总权重的比值,来反推这批加权样本在统计精度上“相当于”多少个纯随机均匀样本
    • 标准绝对 ESS 公式的根源来自于“方差等价”原则
      • 即加权估计量的方差等于多少个体积为 1 的均匀样本的方差
    • 第一步:加权估计量的方差
      • 假设用重要性权重 \(w_i\) 去估计某个统计量(比如均值),其估计量的方差与权重的平方和有关
      • 对于加权估计量 \(\hat{\mu}_w = \frac{\sum w_i x_i}{\sum w_i}\),在大样本下,其渐近方差近似为:
        $$
        \text{Var}(\hat{\mu}_w) \propto \frac{\sum w_i^2}{(\sum w_i)^2} \cdot \sigma^2
        $$
        • 其中 \(\sigma^2\) 是原始分布的方差
    • 第二步:均匀样本的方差
      • 如果有 \(N_{\text{eff} }\) 个理想的无权重均匀样本(即每个样本的权重都为 1),那么其估计量 \(\hat{\mu} = \frac{1}{N_{\text{eff} } } \sum x_i\) 的方差为:
        $$
        \text{Var}(\hat{\mu}) = \frac{1}{N_{\text{eff} } } \cdot \sigma^2
        $$
    • 第三步:令两者相等,解出 \(N_{\text{eff} }\)
      • 让上面两个方差相等(即让加权样本的估计精度“等效”于多少个均匀样本):
        $$
        \frac{\sum w_i^2}{(\sum w_i)^2} \cdot \sigma^2 = \frac{1}{N_{\text{eff} } } \cdot \sigma^2
        $$
      • 消掉共同的 \(\sigma^2\),交叉相乘即得:
        $$
        N_{\text{eff} } = \frac{(\sum w_i)^2}{\sum w_i^2}
        $$
        • 这个值就可以用来估计 ESS
    • 直观理解:
      • 当所有 \(w_i\) 都相等(都为常数 \(c\))时:
        • 分子 \(= (N \cdot c)^2 = N^2 c^2\),分母 \(= N \cdot c^2\)
        • 比值 \(= N\)
        • 权重均匀,100 个样本就是 100 个有效样本
      • 当权重极度不均衡(一个 \(w=100\),其余 99 个 \(w \approx 0\))时:
        • 分子 \(\approx 100^2 = 10000\),分母 \(\approx 100^2 = 10000\)
        • 比值 \(\approx 1\)
        • 虽然采了 100 个样,但真正起作用的其实只相当于 1 个样本
IcePop 越界比例(仅 lower_upper 阈值时存在)
  • rollout_is_oob_ratio 的公式
    $$\texttt{rollout_is_oob_ratio}=\text{mMean}\bigl(\mathbb{1}[w_{\text{raw} }< \tau_l \lor w_{\text{raw} }>\tau_u],M\bigr)$$
  • 物理含义:
    • 超出 IcePop(MIS)的比例
序列级权重统计
  • 提前计算 Sequence \(i\) 的权重为(Token 粒度的均值)
    $$\bar{w}_i=\text{mMean}_i(w,M)$$
  • Sequence 粒度指标上报为(注意不管使用 token 还是 sequence 粒度都会上报):
    指标 公式
    rollout_is_seq_mean \(\frac{1}{B}\sum_i \bar{w}_i\)
    rollout_is_seq_std \(\text{Std}_i(\bar{w}_i)\)
    rollout_is_seq_max \(\max_i \bar{w}_i\)
    rollout_is_seq_min \(\min_i \bar{w}_i\)
    rollout_is_seq_max_deviation \(\max_i \lvert\bar{w}_i-1\rvert\)
    rollout_is_seq_fraction_high \(\frac{1}{B}\sum_i\mathbb{1}[\bar{w}_i>\tau_u]\)
    rollout_is_seq_fraction_low \(\frac{1}{B}\sum_i\mathbb{1}[\bar{w}_i<\tau_l]\)
批归一化因子(仅 rollout_is_batch_normalize=True 时上报)
  • rollout_is_batch_norm_factor 会上报真实用于归一化权重的那个值(最终权重会被除以该因子使均值为 1)
    指标 公式
    rollout_is_batch_norm_factor \(\bar{w}=\text{mMean}(w,M)\)(token 级)或 \(\frac{1}{B^*}\sum_{i:N_i>0}\bar{w}_i\)(sequence 级)
    • 其中 \(B^*\) 为有效序列数

RS 拒绝采样指标

  • 代码在下面两个函数中:
    • verl/trainer/ppo/rollout_corr_helper.compute_rollout_rejection_mask
    • verl/trainer/ppo/rollout_corr_helper.compute_rs_metrics
三种基础 token 级散度
  • 记 \(\ell_s=\text{clamp}(\ell,\pm 20)\):
    选项后缀 公式 理想值 取值范围
    k1 \(k_1=-\ell_s=\log\frac{\pi_{\text{ro} } }{\pi_{\text{tr} } }\) \(0\) \(\mathbb{R}\)(有符号)
    k2 \(k_2=\tfrac{1}{2}\ell_s^2\) \(0\) \(\geq 0\)
    k3 \(k_3=e^{\ell_s}-\ell_s-1=\rho-\log\rho-1\) \(0\) \(\geq 0\)
  • 三者都用于检测训推散度
    • k1 是 log-比本身(理想=0,方向敏感)=
    • k2 是 Pearson \(\chi^2\) 的一半
    • k3 是 Schulman k3 KL 估计量
聚合粒度
  • 对每个 token 级统计量 \(k\in\{k_1,k_2,k_3\}\),可做三种序列级聚合:
    前缀 公式
    token_* 直接用 \(k_{i,t}\)(无聚合)
    seq_sum_* \(K_i^{\text{sum} }=\text{mSum}_i(k,M)\)
    seq_mean_* \(K_i^{\text{mean} }=\text{mMean}_i(k,M)\)
    seq_max_* \(K_i^{\text{max} }=\max_{t:M_{i,t}=1} k_{i,t}\)(仅 k2/k3)
  • 共 11 个支持选项
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SUPPORTED_ROLLOUT_RS_OPTIONS: set[str] = {
    "token_k1",
    "token_k2",
    "token_k3",
    "seq_sum_k1",
    "seq_sum_k2",
    "seq_sum_k3",
    "seq_mean_k1",
    "seq_mean_k2",
    "seq_mean_k3",
    "seq_max_k2",
    "seq_max_k3",
    }
    TOKEN_LEVEL_ROLLOUT_RS_OPTIONS: set[str] = {"token_k1", "token_k2", "token_k3"}
阈值过滤规则
  • k1 类:双向阈值 \(\text{lower}\le k_1\le\text{upper}\)(在 log 空间比较)
  • k2/k3 类:单向上界 \(k\le\text{upper}\)
  • 多选项时各选项 mask 做逻辑 AND 累乘
每选项指标(<opt> 为具体选项名,如 token_k1、seq_sum_k3)
  • 记该选项的统计量为 \(s\)(token 级或序列级),阈值 \(\theta_u,\theta_l\)(k1 类 \(\theta_l\) 为 log 下界,否则 \(\theta_l=0\)),\(s^c=\text{clamp}(s,\theta_l,\theta_u)\):
    指标 公式
    rollout_rs_<opt>_mean \(\text{mMean}(s,M)\)
    rollout_rs_<opt>_max \(\max(s)\)(序列级仅在有效序列上)
    rollout_rs_<opt>_min \(\min(s)\)
    rollout_rs_<opt>_std \(\sqrt{\text{mMean}((s^c)^2,M)-\text{mMean}(s^c,M)^2}\)
    rollout_rs_<opt>_fraction_high 越上界比例(token 用 mMean,seq 用均值)
    rollout_rs_<opt>_fraction_low 越下界比例(仅 k1 类)
    rollout_rs_<opt>_seq_mean \(\frac{1}{B^*}\sum_i s_i\)
    rollout_rs_<opt>_seq_std \(\text{Std}_i(s_i)\)
    rollout_rs_<opt>_seq_max / _seq_min \(\max_i s_i\) / \(\min_i s_i\)
    rollout_rs_<opt>_seq_max_deviation \(\max_i \lvert s_i-0\rvert=\max_i\lvert s_i\rvert\)
    rollout_rs_<opt>_seq_fraction_high \(\frac{1}{B^*}\sum_i\mathbb{1}[s_i>\theta_u]\)
    rollout_rs_<opt>_seq_fraction_low \(\frac{1}{B^*}\sum_i\mathbb{1}[s_i<\theta_l]\)
    rollout_rs_<opt>_masked_fraction 本选项过滤后token 级被 mask 比例 \(\text{mMean}(1-\text{keep},M)\)
    rollout_rs_<opt>_seq_masked_fraction 本选项过滤后序列级被 mask 比例 \(\frac{\sum_i\mathbb{1}[\exists t:\neg\text{keep}_{i,t}\land M_{i,t}]\cdot\mathbb{1}[N_i>0]}{\sum_i\mathbb{1}[N_i>0]}\)
RS 相关的汇总指标
  • 所有选项 AND 合并后会得到 RS 相关的汇总指标
    指标 公式
    rollout_rs_masked_fraction \(\text{mMean}(1-\text{final_keep},M)\),最终 token 级被拒比例
    rollout_rs_seq_masked_fraction \(\frac{1}{B}\sum_i\mathbb{1}[\exists t:\neg\text{final_keep}_{i,t}\land M_{i,t}]\),至少一个 token 被拒的序列占比

RS 和 IcePop 辨析

一些历史
  • 注:最早 IcePop(蚂蚁百灵团队)中介绍的方法 IcePop 本质就是一个 MIS,但没有强调权重被置为 0 的样本是否走 mask 矩阵,即分母上是否还在
    • 详情可参考:NLP——LLM对齐微调-IcePop
  • 在早期 TRL 的 PR 中 [GRPO] Sequence-level TIS + MIS #4493 中,会明确提到,MIS 就是来源于 IcePop 的介绍
  • 在 VeRL 中,Sequence-level 的 MIS 一般可以理解为指的是 Sequence-level IS + Sequence-level RS 一起实现的一种方式(当然 IcePop 的实现也是类似的,但是有是否走 mask 的区别)
    • 注意:单独的 RS 实现不了 MIS,因为 MIS 下,阈值内的 IS 是保留的
    • Sequence-level MIS,即对 IS 比率超过阈值 \(C\) 的序列的策略损失进行 Mask:
      $$ \rho(y|x) \gets \rho(y|x) \mathbb{I}\{\rho(y|x) \le C\} $$
      • 注意:MIS 对阈值内的部分是保留了梯度的,和 VeRL 中 RS 的实现不同(RS 不保留 IS,仅仅 Mask)
      • 注意:由于使用了 RS,所以本质上是走 Mask 矩阵(即分子分母都 Mask 的实现)
    • 详情见:NLP——LLM对齐微调-RL-Collapse-Training-Inference-Mismatch(Sequence-level-MIS)
IcePop 是 RS 的一种特殊实现吗?
  • 答案是不可以,IcePop 属于 IS 家族,不是 RS 的实现 ,两者是代码和理论上都独立的机制
  • 文档 github.com/verl-project/verl/blob/main/docs/algo/rollout_corr.md 明确说明:
    • Separate from rejection sampling (controlled by rollout_rs parameters)
    • Unlike rollout_rs, IcePop does not modify response_mask; it only changes the IS coefficients
  • 在 VeRL 中实现的核心区别对比
    维度 IcePop RS
    理论归属 IS 家族(TIS 的变体) Rejection Sampling
    代码位置 compute_rollout_correction_weights compute_rollout_rejection_mask
    作用对象 IS 权重 \(w\) response_mask \(M\)
    输出类型 连续权重(含 0) 二值 mask
    配置入口 rollout_is_threshold: "0.5_5.0" rollout_rs + rollout_rs_threshold
    • IS 中
      • 当 rollout_is_threshold 只有一个值时默认为 upper,默认生效 TIS
      • 如果有两个值时默认为 lower_upper,且识别到 lower 存在时默认生效 IcePop
  • 机制对比
    • IcePop :
      $$
      w_i=\begin{cases}\rho_i & \text{if }\tau_l\le\rho_i\le\tau_u\\ 0 & \text{otherwise}\end{cases}
      $$
      • 越界样本权重置 0 ,但 token 仍在 batch 中(仍占显存、仍参与序列长度统计)
      • 界内样本保留实际权重值 (连续)
    • RS :
      $$
      M_{i,t}^{\text{new} }=M_{i,t}\cdot\mathbb{1}[\text{stat}_{i,t}\in[\theta_l,\theta_u]]
      $$
      • 直接修改 response_mask,被拒 token 完全从训练中剔除
      • 二值过滤,不保留任何权重信息
VeRL 数学文档中给出的说明
  • 数学文档:github.com/verl-project/verl/blob/main/docs/algo/rollout_corr_math.md
  • 数学文档将两者明确分类:
    • IS :对应连续权重
      $$w_{\text{seq} }(\theta)=\min\bigl(\prod_t\rho_t,C_{\text{IS} }\bigr) $$
    • RS :对应二值拒绝掩码
      $$ w_{\text{seq} }(\theta)\in\{0,1\} $$
  • 也就是说:
    • IcePop 输出的是连续权重(含 0),属于 IS 框架
    • RS 输出二值 mask,是独立机制
总结 RS and IcePop:特别注意
  • IcePop 把越界权重设为 0,效果上类似”软拒绝”(这些样本对梯度无贡献),所以直觉上容易和 RS 混淆,但本质区别是:
    • IcePop 的 0 权重样本仍占用 batch slot ,只是梯度贡献为 0
      • RS 直接从 mask 中删除,会影响有效样本数 \(N\) 的统计
    • IcePop 界内样本用实际 \(\rho\) 值(保留 IS 的方差减少特性)
      • RS 界内样本权重恒为 1(纯过滤,无 IS 校正)
    • 两者可同时启用 : compute_rollout_correction_and_rejection_mask 中 IS 和 RS 是两个独立 step,先算 IS 权重,再算 RS mask,互不干扰
      • 注:IS 和 RS 本来就是可以同时开启使用的
VeRL 中的 Seq-MIS 示例
  • 代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    # https://github.com/verl-project/verl/blob/main/docs/algo/rollout_corr.md 中推荐使用的 MIS 方式
    config = RolloutCorrectionConfig.decoupled_seq_is_rs() # Seq-MIS

    # 函数实现:verl.trainer.config.algorithm.decoupled_seq_is_rs 实现如下
    def decoupled_seq_is_rs(
    cls,
    is_threshold: float = 2.0,
    rs_threshold: Optional[str | float] = "0.5_2.0",
    ) -> "RolloutCorrectionConfig":
    """Decoupled Mode with Sequence-level IS + Rejection Sampling.

    Sequence-level IS with sequence-level rejection sampling in decoupled mode.
    Rejects entire sequences based on sequence-level IS weight.

    Args:
    is_threshold (float): Upper threshold for IS weights. Default: 2.0
    rs_threshold (Optional[Union[str, float]]): Upper threshold for rejection sampling. Default: 0.5_2.0

    Returns:
    RolloutCorrectionConfig configured for decoupled mode with sequence IS + RS
    """
    return cls(
    rollout_is="sequence",
    rollout_is_threshold=is_threshold,
    rollout_rs="seq_sum_k1",
    rollout_rs_threshold=rs_threshold,
    )
  • 解读:

    • VeRL 中推荐的 MIS 实现是通过 RS 来实现(rollout_rs_threshold="0.5_2.0"),而不是 通过 IS(IcePop)来实现(is_threshold=2.0 没有下界,不会触发 IcePop)

附录:Temperature 如何影响 rollout_corr/kl

  • 假设:
    • 其他配置完全相同(同权重、同 batch、top_p=1、rollout_is=token、rollout_is_threshold=2.0、bypass_mode=false),仅修改 actor_rollout_ref.rollout.temperature,观察训练早期(step 0 附近)的 rollout_corr/kl
    • 注:训推 两侧都对 temperature 做了修正 ,verl 会读取 rollout.temperature 给训练侧
  • 回顾:rollout_corr/kl 是 KL 的 k1 估计器:
    $$
    \text{kl} = \frac{1}{|\mathcal{T}|}\sum_{t\in\mathcal{T} }\Big(\log \pi_{\text{rollout} }(a_t)-\log \pi_{\theta}(a_t)\Big)
    \xrightarrow[\ |\mathcal{T}|\to\infty\ ]{} \text{KL}\big(\pi_{\text{rollout} } | \pi_{\theta}\big)
    $$
    • 所以它们的目标分布是同一个
      $$ \pi \propto \exp(z/T) $$
  • 训推的不同计算路径:
    • 训练(Megatron):
      • logits.div_(temp) → vocab-parallel CE,bf16 除法 ,.float() 上转发生在其后
    • Rollout(SGLang)
      • logits.div_(temperatures) → softmax → log,fp32 除法 ,logits 已 .float()
    • 说明: \(\text{kl}\) 不度量真实的 off-policy 程度(当前两者理论上策略完全对齐),只度量两个引擎的数值失配
  • 注意:一般来说若某一侧漏了温度修正,\(T=0.6\) 时 \(\text{kl}=\mathbb{E}[\log p_1-\log p_{0.6}]\) 会是 \(10^{-1}\sim 10^{0}\) 量级
核心推导:\(\text{kl}\) 是 logit 误差的二阶量,且被 \(1/T^2\) 放大
  • 设 raw logit 为 \(z\),推理引擎的 logit 为 \(z+\varepsilon\)(\(\varepsilon\) 来自 kernel/并行布局/精度差异)
  • 两侧分布:
    $$
    \begin{align}
    \pi_\theta(a)=\frac{e^{z_a/T} }{\sum_b e^{z_b/T} } \\
    \pi_{\text{rollout} }(a)=\frac{e^{(z_a+\varepsilon_a)/T} }{\sum_b e^{(z_b+\varepsilon_b)/T} }
    \end{align}
    $$
  • 记:
    $$ u_a=\frac{\varepsilon_a}{T} $$
  • 则:
    $$ \log\pi_{\text{rollout} }(a)-\log\pi_\theta(a)=u_a-\log\mathbb{E}_{\pi_\theta}[e^{u}]$$
    • 证明:
      $$
      \begin{align}
      \log\pi_{\text{rollout}}(a)-\log\pi_\theta(a)
      &= \left[\frac{z_a+\varepsilon_a}{T} - \log\sum_b e^{(z_b+\varepsilon_b)/T}\right] - \left[\frac{z_a}{T} - \log\sum_b e^{z_b/T}\right] \\
      &= \frac{\varepsilon_a}{T} - \left[\log\sum_b e^{(z_b+\varepsilon_b)/T} - \log\sum_b e^{z_b/T}\right] \\
      &= u_a - \log\left(\frac{\sum_b e^{(z_b+\varepsilon_b)/T}}{\sum_b e^{z_b/T}}\right) \\
      &= u_a - \log\left(\sum_b \frac{e^{z_b/T}}{\sum_c e^{z_c/T}} \cdot e^{\varepsilon_b/T}\right) \\
      &= u_a - \log\left(\sum_b \pi_\theta(b) \cdot e^{u_b}\right) \\
      &= u_a - \log\mathbb{E}_{\pi_\theta}\left[e^{u}\right]
      \end{align}
      $$
  • 代入 KL 定义根据泰勒展开(\(m=\mathbb{E}_\pi[u]\),\(s^2=\text{Var}_\pi(u)\))有:
    $$
    \begin{align}
    \mathbb{E}_{\pi_{\text{rollout} } }[u] &\approx m+s^2 \\
    \log\mathbb{E}_{\pi_\theta}[e^{u}] &\approx m+\tfrac12 s^2 \\
    \text{KL}\big(\pi_{\text{rollout} }|\pi_\theta\big) &\approx\tfrac12 \text{Var}_\pi(u)=\frac{\text{Var}_\pi(\varepsilon)}{2T^{2} }
    \end{align}
    $$
    • 证明:
      • 第 1 步:把 KL 拆成“原始期望”减“归一化 log”
        • 由之前的恒等式:
          $$
          \log\pi_{\text{rollout} }(a)-\log\pi_\theta(a)=u_a-\log\mathbb{E}_{\pi_\theta}[e^{u}]
          $$
        • 两边对 \(\pi_{\text{rollout} }\) 求期望:
          $$
          \begin{align}
          \text{KL}\big(\pi_{\text{rollout} }|\pi_\theta\big)
          &= \mathbb{E}_{\pi_{\text{rollout} } }[u] - \mathbb{E}_{\pi_{\text{rollout} } }\big[\log\mathbb{E}_{\pi_\theta}[e^{u}]\big] \\
          &= \mathbb{E}_{\pi_{\text{rollout} } }[u] - \log\mathbb{E}_{\pi_\theta}[e^{u}]
          \end{align}
          $$
          • 注:第二项中 \(\log\mathbb{E}[e^u]\) 是一个标量常数 ,与变量 \(a\) 无关,所以对它求期望等于它本身
      • 第 2 步:引入归一化常数 \(Z\),把 \(\pi_{\text{rollout} }\) 改写成关于 \(\pi_\theta\) 的形式
        • 令
          $$
          Z = \mathbb{E}_{\pi_\theta}[e^{u}] = \sum_b \pi_\theta(b) e^{u_b}
          $$
        • 则:
          $$
          \pi_{\text{rollout} }(a)=\frac{\pi_\theta(a)e^{u_a} }{Z}
          $$
        • 那么:
          $$
          \mathbb{E}_{\pi_{\text{rollout} } }[u] = \sum_a \frac{\pi_\theta(a)e^{u_a} }{Z} \cdot u_a = \frac{\mathbb{E}_{\pi_\theta}[u e^{u}]}{Z}
          $$
      • 第 3 步:对 \(e^u\) 做二阶泰勒展开(假设 \(u\) 是小量)
        • 定义:
          $$
          m = \mathbb{E}_{\pi_\theta}[u], \quad s^2 = \text{Var}_{\pi_\theta}(u)=\mathbb{E}_{\pi_\theta}[u^2]-m^2
          $$
        • 泰勒展开保留到二阶(\(\mathbb{E}[u^3]\) 及更高阶忽略):
          • 1)展开分子 \(\mathbb{E}_{\pi_\theta}[u e^{u}]\):
            $$
            \begin{align}
            \mathbb{E}[u e^{u}] &\approx \mathbb{E}\big[u(1+u+\frac{u^2}{2})\big] \\
            &= \mathbb{E}[u] + \mathbb{E}[u^2] + o(\frac12\mathbb{E}[u^3]) \\
            &= m + (s^2 + m^2) = m + s^2 + m^2
            \end{align}
            $$
          • 2)展开分母 \(Z = \mathbb{E}_{\pi_\theta}[e^{u}]\):
            $$
            Z \approx \mathbb{E}\big[1+u+\frac{u^2}{2}\big] = 1 + m + \frac12 (s^2 + m^2)
            $$
          • 3)**展开 \(\frac{1}{Z}\)**(利用 \((1+x)^{-1}\approx 1-x\),保留到二阶):
            $$
            \frac{1}{Z} \approx 1 - m - \frac12 s^2 - \frac12 m^2 + m^2 = 1 - m - \frac12 s^2 + \frac12 m^2
            $$
            • 注意这里做了二阶精度下的化简,交叉项被忽略
          • 4)相乘得到
            $$ \mathbb{E}_{\pi_{\text{rollout} } }[u] \approx \frac{m + s^2 + m^2}{Z} $$
            • 保留到二阶:
              $$
              \frac{m + s^2 + m^2}{1 + m + \frac12(s^2+m^2)} \approx (m + s^2 + m^2)(1 - m) = m + s^2 + o(m^2 - m^2) = m + s^2
              $$
            • 即:
              $$
              \color{red}{\mathbb{E}_{\pi_{\text{rollout} } }[u] \approx m + s^2}
              $$
      • 第 4 步:展开 \(\log Z\)
        $$
        \log Z = \log\mathbb{E}_{\pi_\theta}[e^{u}] \approx \log\big(1 + m + \frac12(s^2+m^2)\big)
        $$
        • 利用 \(\log(1+x)\approx x - \frac{x^2}{2}\),取 \(x = m + \frac12(s^2+m^2)\):
          $$
          \log Z \approx \big(m + \frac12 s^2 + \frac12 m^2\big) - \frac12 m^2 = m + \frac12 s^2
          $$
        • 即:
          $$
          \color{red}{\log\mathbb{E}_{\pi_\theta}[e^{u}] \approx m + \frac12 s^2}
          $$
      • 第 5 步:两者相减得到最终的 KL 近似
        $$
        \text{KL} = \mathbb{E}_{\pi_{\text{rollout} } }[u] - \log Z \approx (m + s^2) - (m + \frac12 s^2) = \frac12 s^2
        $$
        • 代回 \(u_a = \varepsilon_a / T\),因为方差的性质 \(\text{Var}(\varepsilon/T) = \text{Var}(\varepsilon)/T^2\),最终得到:
          $$
          \color{red}{\text{KL}\big(\pi_{\text{rollout} }|\pi_\theta\big) \approx \frac12 \text{Var}_{\pi_\theta}(u) = \frac{\text{Var}_{\pi_\theta}(\varepsilon)}{2T^2} }
          $$
直观理解
  • 一阶项 \(m\) 被完美抵消 :它在 \(\mathbb{E}_{\pi_{\text{rollout} } }[u]\) 和 \(\log Z\) 中都出现,相减后消失
    • 这解释了为什么 KL 对噪声的方向(正负)不敏感,只取决于噪声的散布程度
  • KL 是纯二阶量 :
    • 所以理论上它恒为正 ,且完全由方差决定
  • 三个直接推论:
    • 1)一阶项完全抵消 ,\(\text{kl}\) 是严格二阶量 \(\Rightarrow\) 恒为正,且对噪声方向不敏感
    • 2)温度在 softmax 之前作用 ,同一份 \(\varepsilon\) 在 log-prob 空间被放大 \(1/T\),KL 被放大 \(1/T^2\)
    • 3)同阶下 \(\text{KL}(p|q)\approx \text{KL}(q|p)\approx\tfrac12 s^2\),所以 kl 与 k3_kl 应当近似相等
      • 在这是”失配确实很小、展开有效”的自检项
  • 反解 logit 空间的失配幅度(跨 \(T\) 可比的量):
    $$
    \text{std}(\varepsilon)\approx T\sqrt{2 \text{kl} },
    \qquad
    \text{kl}\cdot T^{2}=\tfrac12\text{Var}_\pi(\varepsilon)=\text{const(理想情况)}
    $$
  • Temperature 为 0.6 和 Temperature 为 1.0 时的 KL 散度差异
    • temperature=1.0 时,\(1.00\times\)
    • temperature=0.6 时,\(2.78\times\)
    • 一般来说 temperature 1.0 时的 rollout/kl 更小,但现实中不一定小 2.78 倍
      • 实测中低于理论 \(2.78\times\):原因是概率质量集中效应 :
        • 低温下 \(\pi\) 更尖锐,有效支撑集变窄,\(\text{Var}_\pi(\varepsilon)\) 随之下降,部分抵消 \(1/T^2\)
      • PS:一般似乎差不多两倍左右
不同 Temperature 的可能带来的其他误差
  • 除了上述推导的放大效应,\(T \ne 1\) 还会包含一些其他计算精度误差:
    • 比如 训练侧的除法在 bf16 上原地完成,把每个 \(z_a/T\) 重新舍入到 bf16 网格,而 SGLang 在 fp32 完成同一步
    • 在 temperature=1.0 时一般不会引入误差, 但在 0.6 时则更容易引入误差

附录:Temperature 对 grad-norm 的影响

  • 一般来说,理论上:
    • 由于梯度系数中包含温度项 \(\frac{1}{T}\),所以在提升温度时,grad-norm 大概率是会降低的,且降低幅度和温度上升幅度差不多
  • 但是现实场景中
    • 如果温度降低导致 GRPO 等出现 Advantage 差异过小等问题,则会因为温度降低而丢失部分样本的差异性,所以观察到的 grad-norm 降低幅度不一定跟温度对齐
  • 但是实测下来:
    • 大部分情况下,温度从 1.0 降低到 0.6 后,grad-norm 都是提升的
  • 补充:训练过程中,似乎发现温度更低的,grad-nrom 下降更快
    • 理解:低温下,策略更尖锐,grad-norm 更大,可能导致更新幅度更大,下降更快
  • 补充:低温下,看到的熵是更小的

NLP——技术报告解读-Qwen3

注:本文包含 AI 辅助创作

  • 参考链接:
    • 原始论文:Qwen3 Technical Report, Qwen, 20250514
    • Qwen3技术报告解读-包包算法笔记
    • Qwen3技术报告解读-刘聪NLP
    • Github 链接:github.com/QwenLM/Qwen3
      • github.com/QwenLM/Qwen3/tree/main/examples/llama-factory 文件夹下有 Qwen3 在 Llama-factory 框架下微调的方法

Paper Summary

  • 整体说明:
    • Qwen3 包含一系列 LLM,包括 Dense 和 MoE 模型,参数规模从 0.6B 到 235B 不等(这个模型 Size 的丰富度,可以称为地表最强开源模型了)
    • Qwen3 的一项关键创新是将思考模式(thinking mode,用于复杂的多步推理)和非思考模式(non-thinking mode,用于快速的上下文驱动响应)集成到一个统一框架中
    • Qwen3 引入了思考预算(thinking budget)机制,允许用户在推理过程中自适应地分配计算资源,从而根据任务复杂度平衡延迟和性能
    • 该模型基于包含 36 万亿 token 的大规模数据集进行预训练,能够理解和生成 119 种语言和方言的文本
    • Qwen3 在预训练和训练后模型的标准基准测试中均表现出色,涵盖代码生成、数学、推理和 Agent 相关任务
  • 利用旗舰模型的知识(蒸馏小模型),显著减少了构建小规模模型所需的计算资源,同时确保其具备高度竞争力
  • Qwen3 在多样化基准测试中取得了 SOTA 结果,包括代码生成、数学推理、智能体任务等,与更大的 MoE 模型和专有模型相比具有竞争力
  • 与上一代 Qwen2.5 相比,Qwen3 将多语言支持从 29 种扩展到 119 种语言和方言

Introduction and Discussion

  • 人类的目标:人工通用智能(Artificial General Intelligence, AGI)或人工超级智能(Artificial Super Intelligence, ASI)
  • 这项工作介绍了基础模型家族 Qwen 的最新系列 Qwen3
    • Qwen3 是一组开源 LLM ,在广泛的任务和领域中实现了 SOTA 性能
    • 发布了 Dense 和 MoE 模型,参数数量从 0.6B 到 235B 不等,以满足不同下游应用的需求
    • 旗舰模型 Qwen3-235B-A22B 是一个 MoE 模型,总参数为 235B,每个 token 激活的参数为 22B
      • 这种设计确保了高性能和高效的推理
  • Qwen3 引入了多项关键技术进步以增强其功能和可用性
    • 首先,它将两种不同的操作模式(思考模式和非思考模式)集成到单一模型中
      • 这使得用户无需在不同模型之间切换(例如从 Qwen2.5 切换到 QwQ (2024))即可切换模式
      • 这种灵活性确保开发者和用户可以高效地根据特定任务调整模型行为
    • 此外,Qwen3 引入了思考预算,使用户能够精细控制模型在执行任务时应用的推理努力水平
      • 这一能力对于优化计算资源和性能至关重要,能够根据实际应用中的复杂度调整模型的思考行为
    • 此外,Qwen3 在涵盖 119 种语言和方言的 36 万亿 token 上进行了预训练,有效增强了其多语言能力
      • 这种广泛的语言支持扩大了其在全球用例和国际应用中的部署潜力
    • 这些进步共同使 Qwen3 成为 SOTA 开源大语言模型家族,能够有效解决跨领域和跨语言的复杂任务
  • Qwen3 的预训练过程使用了约 36 万亿 token 的大规模数据集,经过精心筛选以确保语言和领域的多样性
    • 为了高效扩展训练数据,作者采用了多模态方法:Qwen2.5-VL (2025) 被微调以从大量 PDF 文档中提取文本
    • 作者还使用领域特定模型生成合成数据:Qwen2.5-Math (2024) 用于数学内容,Qwen2.5-Coder (2024) 用于代码相关数据
  • 预训练过程采用三阶段策略:
    • 1)通用阶段(S1) :所有 Qwen3 模型在 4,096 token 的序列长度上训练超过 30 万亿 token
      • 在此阶段,模型在语言能力和通用世界知识上完成了全面预训练,训练数据涵盖 119 种语言和方言
    • 2)推理阶段(S2) :为了进一步提升推理能力,作者优化了本阶段的预训练语料库,增加了 STEM、编码、推理和合成数据的比例
      • 模型在 4,096 token 的序列长度上进一步训练约 5 万亿高质量 token
      • 在此阶段,作者加速了学习率衰减
    • 3)长上下文阶段(S3) :在最后的预训练阶段,作者收集高质量的长上下文语料以扩展 Qwen3 模型的上下文长度
      • 所有模型在 32,768 token 的序列长度上训练了数千亿 token
      • 长上下文语料库包含 75% 长度在 16,384 到 32,768 token 之间的文本,以及 25% 长度在 4,096 到 16,384 token 之间的文本
  • 为了更好地将基础模型与人类偏好和下游应用对齐,作者采用了多阶段后训练方法,同时赋能思考(推理)和非思考模式
    • 在前两个阶段,通过长 CoT 冷启动微调和专注于数学与编码任务的强化学习 ,开发了强大的推理能力
    • 在最后两个阶段,将带有和不带有推理路径的数据合并为一个统一数据集进行进一步微调 ,使模型能够有效处理两种类型的输入,随后应用通用领域的强化学习以提升在广泛下游任务中的性能
    • 对于小模型,使用强到弱蒸馏(strong-to-weak distillation),利用从大模型的 Off-policy 和 On-policy 知识迁移来增强其能力
      • 从高级教师模型的蒸馏在性能和训练效率上显著优于强化学习

Architecture

  • Qwen3 系列包括 6 个 Dense 模型(Qwen3-0.6B、Qwen3-1.7B、Qwen3-4B、Qwen3-8B、Qwen3-14B 和 Qwen3-32B)和 2 个 MoE 模型(Qwen3-30B-A3B 和 Qwen3-235B-A22B)
    • 旗舰模型 Qwen3-235B-A22B 总参数为 235B,激活参数为 22B
  • Qwen3 Dense 模型的架构与 Qwen2.5 (2024) 类似,包括使用如下组件:
    • 分组查询注意力(Grouped Query Attention, GQA)(2023)
    • SwiGLU (2017)
    • 旋转位置嵌入(Rotary Positional Embeddings, RoPE)(2024)
    • RMSNorm (2023) 的预归一化(pre-normalization)
  • Qwen3 移除了 Qwen2 (2024) 中使用的 QKV 偏置(QKV-bias),并在注意力机制中引入了 QK 归一化(QK-Norm)(2023) 以确保 Qwen3 的训练稳定性
  • 模型架构的关键信息如表 1 所示
  • Qwen3 MoE 模型与 Qwen3 Dense 模型共享相同的基础架构,模型架构的关键信息如表 2 所示
    • 遵循 Qwen2.5-MoE (2024) 并实现了细粒度专家分割(fine-grained expert segmentation)(2024)
    • Qwen3 MoE 模型共有 128 个专家,每个 token 激活 8 个专家
    • 与 Qwen2.5-MoE 不同,Qwen3-MoE 设计排除了共享专家
    • Qwen3 采用全局批量负载均衡损失(global-batch load balancing loss)(2025) 以鼓励专家专业化
    • 这些架构和训练创新在下游任务中显著提升了模型性能
  • Qwen3 模型使用 Qwen 的分词器 (2023),它实现了 BBPE(Byte-level Byte-Pair Encoding)(2020; 2020; 2016),词表为 151,669

Pre-training

Pre-training Data

  • 与 Qwen2.5(2024)相比,Qwen3 显著扩大了预训练数据的规模和多样性
    • 作者收集了 36 万亿 token 的数据,覆盖 119 种语言和方言
      • 这些数据包含多个领域的高质量内容,例如代码、STEM(科学、技术、工程和数学)、推理任务、书籍、多语言文本以及合成数据
  • 作者对预训练数据做了如下扩展:
    • First,使用 Qwen2.5-VL 模型(2025)对大量 PDF 类文档进行文本识别,随后通过 Qwen2.5 模型(2024)对识别文本进行优化,从而获得额外的高质量文本 token,总量达到数万亿
    • Second,利用 Qwen2.5(2024)、Qwen2.5-Math(2024)和 Qwen2.5-Coder(2024)模型合成了数万亿不同格式的文本 token,涵盖教材、问答、指令和代码片段等,覆盖数十个领域
    • Third,通过引入更多语言数据进一步扩展了预训练语料库。与 Qwen2.5 相比,支持的语言数量从 29 种大幅增加到 119 种,显著提升了模型的跨语言能力
  • 作者开发了一套多语言数据标注系统,用于提升训练数据的质量和多样性
    • 该系统已应用于大规模预训练数据集,对超过 30 万亿 token 进行了多维度标注,包括教育价值、领域和安全性等
    • 这些细粒度的标注支持更高效的数据过滤和组合
    • 与以往研究(2023;2023;2024)在数据源或领域级别优化数据混合比例不同,Qwen3 通过在小规模代理模型上进行细粒度数据标签的消融实验,实现了实例级别的数据混合优化

Pre-training Stages

  • Qwen3 模型的预训练分为三个阶段:
    • 1)General Stage(S1) :在第一阶段,所有 Qwen3 模型在超过 30 万亿 token 上以 4,096 token 的序列长度进行训练
      • 此阶段模型已完全掌握语言能力和通用世界知识,训练数据覆盖 119 种语言和方言
    • 2)Reasoning Stage(S2) :为了进一步提升推理能力,作者优化了本阶段的预训练语料库,增加了 STEM、代码、推理和合成数据的比例
      • 模型以 4,096 token 的序列长度进一步预训练约 5 万亿高质量 token,并在此阶段加速学习率衰减
    • 3)Long Context Stage(S3) :在最后的预训练阶段,作者收集高质量的长上下文语料库,将 Qwen3 模型的上下文长度扩展到 32,768 token
      • 长上下文语料库中,75% 的文本长度介于 16,384 到 32,768 token 之间,25% 介于 4,096 到 16,384 token 之间
      • 遵循 Qwen2.5(2024)的方法,作者使用 ABF 技术(2023)将 RoPE 的基础频率从 10,000 增加到 1,000,000,同时引入 YARN(2023)和双块注意力(Dual Chunk Attention, DCA)(2024),在推理时实现序列长度容量的四倍提升
  • 与 Qwen2.5(2024)类似,Qwen3 基于上述三个阶段开发了超参数(如学习率 Scheduler 和 Batch Size)的扩展规律
    • 通过大量实验,作者系统研究了模型架构、训练数据、训练阶段与最优训练超参数之间的关系,最终为每个 Dense 或 MoE 模型预测了最优学习率和 Batch Size 策略

Pre-training Evaluation

  • Qwen3 系列的基础语言模型评估重点关注其在通用知识、推理、数学、科学知识、代码和多语言能力方面的表现。评估数据集包括 15 个基准测试:
    • 通用任务(General Tasks) :MMLU(2021a)(5-shot)、MMLU-Pro(2024)(5-shot,CoT)、MMLU-redux(2024)(5-shot)、BBH(2023)(3-shot,CoT)、SuperGPQA(2025)(5-shot,CoT)
    • 数学与 STEM 任务(Math & STEM Tasks) :GPQA(2023)(5-shot,CoT)、GSM8K(2021)(4-shot,CoT)、MATH(2021b)(4-shot,CoT)
    • 代码任务(Coding Tasks) :EvalPlus(2023a)(0-shot)(HumanEval(2021)、MBPP(2021)、Humaneval+、MBPP+ 的平均值)、MultiPL-E(2023)(0-shot)(Python、C++、Java、PHP、TypeScript、C#、Bash、JavaScript)、MBPP-3shot(2021)、CRUX-O of CRUXEval(2024)(1-shot)
    • 多语言任务(Multilingual Tasks) :MGSM(2023)(8-shot,CoT)、MMMLU(OpenAI,2024)(5-shot)、INCLUDE(2024)(5-shot)
  • 在基础模型的基线对比中,将 Qwen3 系列基础模型与 Qwen2.5 基础模型(2024)以及其他领先的开源基础模型进行了比较,包括 DeepSeek-V3 Base(2024a)、Gemma-3(2025)、Llama-3(2024)和 Llama-4(Meta-AI,2025)系列基础模型
    • 所有模型均使用相同的评估流程和广泛采用的评估设置,以确保公平比较
Summary of Evaluation Results
  • 基于整体评估结果,论文中总结了 Qwen3 基础模型的关键结论:
    • (1) 与之前开源的 SOTA Dense 和 MoE 基础模型(如 DeepSeek-V3 Base、Llama-4-Maverick Base 和 Qwen2.5-72B-Base)相比,Qwen3-235B-A22B-Base 在大多数任务中表现更优,且参数量显著更少
    • (2) 对于 Qwen3 MoE 基础模型,实验结果表明:
      • (a) 使用相同的预训练数据,Qwen3 MoE 基础模型仅需 1/5 的激活参数即可达到与 Dense 模型相当的性能;
      • (b) 由于架构改进、训练 token 规模扩大和更先进的训练策略,Qwen3 MoE 基础模型的性能优于 Qwen2.5 MoE 基础模型,且激活参数和总参数量更少;
      • (c) 即使仅使用 Qwen2.5 Dense 基础模型 1/10 的激活参数,Qwen3 MoE 基础模型也能达到相当的性能,显著降低了推理和训练成本
    • (3) Qwen3 Dense 基础模型的整体性能与更高参数规模的 Qwen2.5 基础模型相当
      • 例如,Qwen3-1.7B/4B/8B/14B/32B-Base 分别与 Qwen2.5-3B/7B/14B/32B/72B-Base 性能相当,尤其在 STEM、代码和推理基准测试中,Qwen3 Dense 基础模型的性能甚至超越了更高参数规模的 Qwen2.5 基础模型
  • 注:【此处省略一些评估细节】

Post-training

  • 图 1 展示了 Qwen3 系列模型的后训练流程,该流程围绕两个核心目标设计:
    • (1) 思维控制(Thinking Control) :通过整合“非思维模式(non-thinking mode)”和“思维模式(thinking mode)”,使用户能够灵活选择模型是否进行推理,并通过指定思维过程的 token 预算来控制思考深度
    • (2) 强到弱蒸馏(Strong-to-Weak Distillation) :旨在简化和优化轻量级模型的后训练过程
      • 通过利用大规模模型的知识,显著降低构建小规模模型所需的计算成本和开发工作量

Long-CoT Cold Start

  • 首先构建了一个涵盖数学、代码、逻辑推理和 STEM 问题的综合数据集,每个问题均配有已验证的参考答案或基于代码的测试用例
  • 该数据集用于长链思维(long Chain-of-Thought, long-CoT)训练的冷启动阶段
  • 数据集构建包含两阶段过滤流程:查询过滤(query filtering)和响应过滤(query filtering)
  • 查询过滤阶段:使用 Qwen2.5-72B-Instruct 识别并移除难以验证的查询(例如包含多个子问题或要求生成通用文本的查询),同时排除 Qwen2.5-72B-Instruct 无需 CoT 推理即可正确回答的查询,以确保仅包含需要深度推理的复杂问题
    • 使用 Qwen2.5-72B-Instruct 标注每个查询的领域,以保持数据集的领域平衡
  • 响应过滤阶段:保留验证集后,使用 QwQ-32B 为每个剩余查询生成 \(N\) 个候选响应
    • 若 QwQ-32B 无法生成正确解决方案,则由人工标注者评估响应准确性
    • 对于通过 Pass@\(N\) 的查询,进一步应用严格过滤标准,移除以下类型的响应:
      • (1) 最终答案错误;
      • (2) 包含大量重复内容;
      • (3) 明显猜测而无充分推理;
      • (4) 思维内容与总结不一致;
      • (5) 语言混合不当或风格突变;
      • (6) 疑似与验证集内容过度相似
  • 随后,使用精炼后的数据集子集进行推理模式的初始冷启动训练
    • 此阶段的目标是为模型奠定基础推理模式 ,而非过度强调即时推理性能,从而确保模型潜力不受限制,为后续RL阶段提供更大改进空间
    • 为实现这一目标,建议在此准备阶段尽量减少训练样本数量和训练步数

Reasoning RL

  • 推理强化学习阶段使用的 query-verifier 对需满足以下四个标准:
    • (1) 未在冷启动阶段使用;
    • (2) 冷启动模型可学习;
    • (3) 尽可能具有挑战性;
    • (4) 覆盖广泛的子领域
  • 最终收集了 3995 对 query-verifier ,并采用 GRPO(2024)更新模型参数
    • 实验表明,使用大的 Batch Size 和(每个查询)高 rollout 次数,结合 Off-policy 训练以提高样本效率,对训练过程有益
    • 此外,通过控制模型的熵(entropy)使其稳步增加或保持稳定 ,可以有效平衡探索与利用(exploration and exploitation),这对维持训练稳定性至关重要
      • 注:这里作者说模型的熵是稳步增加的,但大部分论文中给出的训练都是看到熵在下降的,作者应该是否做了一些特定的设计来提升模型在这方面的能力?
    • 结果表明,在单次 RL 训练过程中,无需手动干预超参数,即可实现训练奖励和验证性能的持续提升
      • 例如,Qwen3-235B-A22B 模型的 AIME’24 分数在 170 个 RL 训练步中从 70.1 提升至 85.1

Thinking Mode Fusion

  • 思维模式融合阶段的目标是将“非思维(non-thinking)”能力整合到已具备“思维(thinking)”能力的模型中
  • 这种方法使开发者能够管理和控制推理行为,同时降低部署独立模型以处理思维和非思维任务的成本和复杂性
  • 为实现这一目标,作者对推理强化学习模型进行持续 SFT ,并设计聊天模板以融合两种模式
  • 作者发现能够熟练处理两种模式的模型在不同思维预算下均表现稳定
Construction of SFT data
  • SFT 数据集结合了“thinking”和“non-thinking”数据
  • 为确保 Stage 2 模型的性能不受额外 SFT 影响 :
    • “thinking”数据通过使用 Stage 2 模型对 Stage 1 查询进行拒绝采样(rejection sampling)生成;
    • “non-thinking”数据则精心策划,涵盖编码、数学、指令遵循、多语言任务、创意写作、问答和角色扮演等多样化任务
    • 理解:因为 Stage 2 模型已经是训练好的了,为了增加思维链融合功能,额外的 SFT 是可能会导致模型出现问题的,这里使用 Stage 2 和 Stage 1 模型相关的数据来训练,从而保证 Stage 2 和 Stage 1 模型的原始能力?
  • 此外,作者采用自动生成的检查表评估“non-thinking”数据的响应质量,并特别增加低资源(low-resource)任务上的性能,作者特地增加了翻译任务的比例
Chat Template Design
  • 为更好整合两种模式并支持用户动态切换思维过程,作者设计了 Qwen3 的聊天模板(如表 9 所示)
    • 对于思维模式和非思维模式的样本,作者分别在用户查询或系统消息中引入 /think 和 /no_think 标志,使模型能够根据用户输入选择相应的思维模式
    • 对于非思维模式样本 ,作者在助手响应中保留空的思维块(thinking block)
      • 这一设计确保模型内部格式一致性,并允许开发者通过在聊天模板中拼接空的思维块来阻止模型进行思维行为
    • 默认情况下,模型以思维模式运行,因此作者添加了一些用户查询中不包含 /think 标志的思维模式训练样本
    • 对于更复杂的多轮对话,作者在用户查询中随机插入多个 /think 和 /no_think 标志,模型响应则遵循最后遇到的标志
Thinking Budget
  • 思维模式融合的额外优势在于,一旦模型学会以非思维和思维模式响应,它自然能够处理中间情况(即基于不完整思维生成响应)
  • 这一能力为实施模型思维过程的预算控制奠定了基础
    • 具体而言,当模型的思维长度达到用户定义的阈值时,手动停止思维过程,并插入停止思维指令:“Considering the limited time by the user, I have to give the solution based on the thinking directly now.\n</think>.\n\n”
    • 插入该指令后,模型基于已积累的推理生成最终响应
    • 值得注意的是,此能力并非通过显式训练获得,而是思维模式融合的自然结果

General RL

  • 通用强化学习阶段旨在广泛增强模型在多样化场景中的能力和稳定性
  • 为此,作者建立了一个覆盖 20 多项任务 的复杂奖励系统 ,每项任务均配备定制化评分标准,重点关注以下核心能力:
    • Instruction Following :确保模型准确解释并遵循用户指令,包括内容、格式、长度和结构化输出等要求,生成符合用户期望的响应
    • 格式遵循(Format Following) :除显式指令外,模型需遵循特定格式约定
      • 例如,通过 /think 和 /no_think 标志切换思维模式,并在最终输出中使用指定 token(如 <think> 和 </think>)分隔思维和响应部分
    • 偏好对齐(Preference Alignment) :针对开放式查询,偏好对齐侧重于提升模型的帮助性、参与度和风格,最终提供更自然和令人满意的用户体验
    • 智能体能力(Agent Ability) :训练模型通过指定接口正确调用工具
      • 在 RL rollout 过程中,模型可执行完整的多轮交互周期 ,并接收真实环境执行反馈 ,从而提升其在长视野决策任务中的性能和稳定性
    • 专项场景能力(Abilities for Specialized Scenarios) :在更专业的场景中,作者设计特定任务
      • 例如,在检索增强生成(Retrieval-Augmented Generation, RAG)任务中,引入奖励信号引导模型生成准确且上下文合适的响应 ,从而最小化幻觉风险
  • 为上述任务提供反馈时,作者采用三种不同类型的奖励:
    • (1)基于规则的奖励(Rule-based Reward) :广泛用于推理强化学习阶段,也适用于指令遵循(2024)和格式遵循等通用任务
      • 设计良好的基于规则的奖励可高精度评估模型输出的正确性,避免奖励破解(reward hacking)问题
    • (2)带参考答案的模型奖励(Model-based Reward with Reference Answer) :为每个查询提供参考答案,并提示 Qwen2.5-72B-Instruct 基于参考答案对模型响应评分
      • 该方法无需严格格式化即可灵活处理多样化任务,避免纯规则奖励可能导致的假阴性
    • (3)无参考答案的模型奖励(Model-based Reward without Reference Answer) :利用人类偏好数据训练奖励模型 ,为模型响应分配标量分数
      • 该方法不依赖参考答案,可处理更广泛查询,同时有效提升模型的参与度和帮助性

Strong-to-Weak Distillation

  • 强到弱蒸馏流程专为优化轻量级模型设计,涵盖 5 个 Dense 模型(Qwen3-0.6B、1.7B、4B、8B 和 14B)和 1 个 MoE 模型(Qwen3-30B-A3B)
    • 该方法在提升模型性能的同时,有效赋予其强大的模式切换能力
  • 蒸馏过程分为两个主要阶段:
    • (1) Off-policy 蒸馏(Off-policy Distillation) :在此初始阶段,作者结合教师模型在 /think 和 /no_think 模式下的输出进行响应蒸馏 ,帮助轻量级学生模型发展基础推理能力和思维模式切换能力,为后续 On-policy 训练阶段奠定基础
    • (2) On-policy 蒸馏(On-policy Distillation) :在此阶段,学生模型生成 On-policy 序列进行微调
      • 使用学生模型采样提示后,学生模型以 /think 或 /no_think 模式生成响应,并通过对齐其 logits 与教师模型(Qwen3-32B 或 Qwen3-235B-A22B)以最小化 KL 散度(Kullback-Leibler divergence)进行微调

Post-training Evaluation

  • For 全面评估指令调优模型的质量,采用自动化基准测试思维和非思维模式下的模型性能。这些基准分为以下几类:
    • 通用任务(General Tasks) :使用 MMLU-Redux(2024)、GPQA-Diamond(2023)、C-Eval(2023)和 LiveBench(2024-11-25)(2024)等基准
      • 对于 GPQA-Diamond,每个查询采样 10 次并报告平均准确率
    • 对齐任务(Alignment Tasks) :评估模型与人类偏好的对齐程度
      • 针对指令遵循性能,报告 IFEval(2023)的严格提示准确率;
      • 针对通用主题的人类偏好对齐,使用 Arena-Hard(2024)和 AlignBench v1.1(2023);
      • 针对写作任务,依赖 Creative Writing V3(2024)和 WritingBench(2025)评估模型的熟练度和创造力
    • 数学与文本推理(Math & Text Reasoning) :评估数学和逻辑推理能力,采用高阶数学基准 MATH-500(2023)、AIME’24 和 AIME’25(2025),以及文本推理任务 ZebraLogic(2025)和 AutoLogi(2025)
      • 对于 AIME 问题,每年试题包含 Part I 和 Part II,共 30 题,每题采样 64 次并以平均准确率作为最终分数
    • 智能体与编码(Agent & Coding) :测试模型在编码和智能体任务中的熟练度,使用 BFCL v3(2024)、LiveCodeBench(v5, 2024.10-2025.02)(2024)和 Codeforces Ratings from CodeElo(2025)
      • 对于 BFCL,所有 Qwen3 模型均采用 FC 格式评估,并使用 yarn 将模型部署至 64k 上下文长度以进行多轮评估
        • 部分基线来自 BFCL 排行榜,取 FC 和 Prompt 格式中的较高分;未在排行榜中报告的模型则评估 Prompt 格式
      • 对于 LiveCodeBench,非思维模式使用官方推荐提示,思维模式则调整提示模板以允许模型更自由地思考(移除限制 You will not return anything except for the program)
      • 为评估模型与竞技编程专家的性能差距,使用 CodeForces 计算 Elo 评分,每个问题最多生成八次独立推理尝试
    • 多语言任务(Multilingual Tasks) :评估四种任务:指令遵循、知识、数学和逻辑推理
      • 指令遵循使用 Multi-IF(2024)(覆盖 8 种关键语言);
      • 知识评估包含两类:区域知识通过 INCLUDE(2024)(覆盖 44 种语言)评估,通用知识通过 MMMLU(2024)(覆盖 14 种语言,排除未优化的约鲁巴语);
      • 数学任务采用 MT-AIME2024(2025)(涵盖 55 种语言)和 PolyMath(2025)(涵盖 18 种语言);
      • 逻辑推理使用 MlogiQA(覆盖 10 种语言,源自 2024)
  • 所有 Qwen3 模型采样超参数设置如下:
    • 在思维模式下的采样超参数设置为 temperature\(=0.6\)、top-p\(=0.95\)、top-k\(=20\);
      • 对于 Creative Writing v3 和 WritingBench,应用 presence penalty\(=1.5\) 以鼓励生成更多样化内容
      • 补充:presence penalty 会对已经生成过的词汇的概率值进行削弱
        • 值越大,削弱越厉害,生成的文本更加多样化;
        • 值越小,更容易生成重复的词,但文本会更加连贯
    • 非思维模式的采样超参数为 temperature\(=0.7\)、top-p \(=0.8\)、top-k \(=20\)、presence penalty\(=1.5\)
    • 两种模式的最大输出长度均设为 32,768 token,AIME’24 和 AIME’25 除外(扩展至 38,912 token 以提供充足思维空间)
      Summary of Evaluation Results
  • 从评估结果中,我们总结出最终确定的Qwen3模型的几个关键结论如下:
    • (1)我们的旗舰模型 Qwen3-235B-A22B 在思考模式和非思考模式下均展现出开源模型中的顶尖整体性能,超越了 DeepSeek-R1 和 DeepSeek-V3 等强基线模型
      • Qwen3-235B-A22B 与闭源领先模型(如 OpenAI-o1、Gemini2.5-Pro 和 GPT-4o)相比也具有高度竞争力,彰显了其深厚的推理能力和全面的通用能力
    • (2)我们的旗舰 Dense 模型 Qwen3-32B 在大多数基准测试中优于我们此前最强的推理模型 QwQ-32B,且性能与闭源的OpenAI-o3-mini 相当,表明其推理能力令人瞩目
      • Qwen3-32B 在非思考模式下的表现也极为出色,超越了我们此前的旗舰非推理 Dense 模型 Qwen2.5-72B-Instruct。
    • (3)我们的轻量级模型(包括 Qwen3-30B-A3B、Qwen3-14B 及其他较小的 Dense 模型)与参数规模相近或更大的开源模型相比,性能始终更优,证明了我们“Strong-to-Weak Distillation”方法的成功。
  • 注:【此处省略一些评估细节】

Discussion

The Effectiveness of Thinking Budget

  • 为验证 Qwen3 可通过增加思维预算提升智能水平,在数学、编码和 STEM 领域的四个基准上调整分配的思维预算
  • 如图 2 所示,Qwen3 展现出与分配思维预算相关的可扩展且平滑的性能提升
    • Thinking Budget 越大,效果越好
  • 若进一步将输出长度扩展至 32K 以上,模型性能有望在未来继续提升,作者将此探索留作未来工作

The Effectiveness and Efficiency of On-Policy Distillation

  • 通过比较蒸馏与直接强化学习在相同 Off-policy 蒸馏 8B 检查点后的性能和计算成本(以 GPU 小时计),评估 On-policy 蒸馏的有效性和效率
  • 注:为简化,以下仅关注数学和代码相关查询
  • 表 21 的结果表明,蒸馏在仅需约 1/10 GPU 小时的情况下,性能显著优于强化学习
    • 从教师 logits 蒸馏使学生模型能够扩展其探索空间并增强推理潜力,表现为蒸馏后 AIME’24 和 AIME’25 基准的 pass@64 分数较初始检查点有所提升;
    • 强化学习未带来 pass@64 分数的任何改进。
    • 这些观察凸显了利用更强教师模型指导学生模型学习的优势

The Effects of Thinking Mode Fusion and General RL

  • For 评估后训练中思维模式融合和通用强化学习的有效性,对 Qwen-32B 模型的各个阶段进行评估
  • 除前述数据集外,引入多个内部基准以监控其他能力:
    • CounterFactQA :包含反事实问题,模型需识别问题非事实并避免生成幻觉答案
    • LengthCtrl :包含带长度要求的创意写作任务,最终分数基于生成内容长度与目标长度的差异
    • ThinkFollow :包含随机插入 /think 和 /no_think 标志的多轮对话,测试模型能否根据用户查询正确切换思维模式
    • ToolUse :评估模型在单轮、多轮和多步工具调用过程中的稳定性,分数包括工具调用过程中的意图识别准确率、格式准确率和参数准确率
  • 结果如表 22 所示,可得出以下结论:
    • (1) Stage 3 将非思维模式整合至已通过前两阶段训练具备思维能力的模型中
      • ThinkFollow 基准分数 88.7 表明模型已具备初步模式切换能力,但仍偶有错误
      • Stage 3 还提升了模型在思维模式下的通用和指令遵循能力,CounterFactQA 提升 10.9 分,LengthCtrl 提升 8.0 分
    • (2) Stage 4 进一步强化模型在思维和非思维模式下的通用、指令遵循和智能体能力
      • ThinkFollow 分数提升至 98.9,确保准确模式切换
    • (3) 对于知识、STEM、数学和编码任务 ,思维模式融合和通用强化学习未带来显著提升
      • 相反,对于 AIME’24 和 LiveCodeBench 等挑战性任务,思维模式性能在这两个训练阶段后实际下降
      • 作者推测这种退化是由于模型在更广泛通用任务上训练,可能影响其处理复杂问题的专项能力
      • 在 Qwen3 开发中,作者选择接受这种性能权衡以增强模型的整体通用性

Future Work

  • 在不久的将来,作者的研究将聚焦于以下几个关键方向:
    • (1) 预训练扩展(Scale up pretraining) :作者将继续扩展预训练规模,使用质量更高、内容更多样的数据
    • (2) 架构优化(Improving model architecture) :改进模型架构和训练方法,以实现高效压缩、超长上下文支持等目标
    • (3) RL :增加计算资源投入,重点关注基于环境反馈的智能体强化学习系统,以构建能够处理需要推理时间扩展的复杂任务的智能体

Appendix

A.1 Additional Evaluation Results

A.1.1 Long-Context Ability
  • For 评估长上下文处理能力,在 RULER 基准测试 (2024) 中报告了结果(表 23)
  • 为实现长度外推(length extrapolation),使用 YARN (2023) 并设置缩放因子 \( \text{scaling_factor} = 4 \)
  • 在思考模式下,作者将思考预算(thinking budget)设为 8192 token,以减少对超长输入的冗余推理
  • 结果显示:
    • (1) 在非思考模式下,Qwen3 在长上下文处理任务中优于同规模的 Qwen2.5 模型
    • (2) 在思考模式下,模型性能略有下降
      • 作者推测思考内容对这些检索任务(无需依赖推理)帮助有限 ,甚至可能干扰检索过程
      • 未来版本将重点提升思考模式下的长上下文能力

A.1.2 Multilingual Ability

  • 表 24-35 展示了 Qwen3 系列模型在西班牙语、法语、葡萄牙语、意大利语、阿拉伯语、日语、韩语、印尼语、俄语、越南语、德语和泰语等多种语言中的详细基准得分
    • 这些结果表明,Qwen3 系列模型在所有评估基准中均表现优异,展现了强大的多语言能力
  • 为更广泛评估 Qwen3 的多语言表现,作者使用 Belebele (2023) 基准测试,覆盖 80 种优化语言(表 36 按语系列出)
  • 表 37 展示了 Qwen3 与其他基线模型在 Belebele 基准上的性能对比
  • 结果显示,Qwen3 在同等规模下与 Gemma 模型表现相当,同时显著优于 Qwen2.5

附录:Qwen3-MoE 源码

  • 参考博客:图解 Qwen3 MoE 模型源码
    • 包含一些流程图和源码,比较清晰
1…596061…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