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 等暂时没有崩溃,大概率也出现问题了

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 先稳定,然后突然提升, 那么大概率是在这里发生模型崩溃了

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 还没收敛

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

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)
    • 是对 response token 的熵按指定 loss 聚合模式计算的标量值
  • 补充:上述 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
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.pycompute_timing_metricscompute_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_unbalanceverl/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)