注:本文包含 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 直接导致了高方差的梯度更新
- 随着 Rollout 的进行,策略模型逐渐偏离初始的 SFT 模型,开始探索到奖励模型未曾见过的状态(OOD 数据)
- 可能导致这一点的原因包含:
- KL Penalty 不足,导致模型偏离 Reference Model 太多,从而进入 RM 的 OOD 区间,打分开始变得激进且误差大
- 实验验证:完全关闭 KL Penalty 后,Advantages 的方差 和 \((\pi_\theta - \pi_{old})\) 方差
- KL Penalty 不足,导致模型偏离 Reference Model 太多,从而进入 RM 的 OOD 区间,打分开始变得激进且误差大
- 解法:增加 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 值相等)
- 当同一个组的 rewards 完全相同且是无理数时,可能因为精度问题导致组内归一化 Bug
- 可选的解法(亲测: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:4781
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:4801
2
3
4pg_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:4791
2
3negative_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
2token_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
2kld = 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:4661
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
4kld = 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:1911
actor/reward_kl_penalty_coeff = kl_ctrl.value #(beta,自适应调整)
实际实现时是设定一个 kl 目标,若未达到目标,则通过提升或降低 kl_coef 来调整模型朝达到目标的方向走
actor/grad_norm,Actor 梯度范数
文件:
verl/workers/actor/dp_actor.py:4861
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:6101
actor/lr = actor_lr_scheduler.get_last_lr()[0]
perf/mfu/actor,Actor MFU(模型浮点利用率)
- 文件:
verl/workers/fsdp_workers.py:7191
2estimated_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:2541
2
3
4
5vpredclipped = 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:2551
vf_clipfrac = masked_mean(vf_losses2 > vf_losses1, response_mask)
即被 clip 的价值预测所占 token 比例
critic/vpred_mean,价值预测均值
文件:
verl/workers/critic/dp_critic.py:2561
critic/vpred_mean = masked_mean(vpreds, response_mask)
当前 mini-batch 中,Critic 对 response token 的价值预测均值
critic/grad_norm,Critic 梯度范数
- 文件:
verl/workers/critic/dp_critic.py:2631
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:1781
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:1761
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/meanmean(token_level_scores.sum(-1)[non_aborted]),非中止样本的序列级得分均值,注意是对 Sequence 内部的 Token 做 sumcritic/score/maxmax(token_level_scores.sum(-1)[non_aborted])critic/score/minmin(token_level_scores.sum(-1)[non_aborted]) - 注:
token_level_scores是 reward function 输出的原始得分(未减去 KL 惩罚)
奖励(Reward)指标
- 具体指标
指标 计算方式 critic/rewards/meanmean(token_level_rewards.sum(-1)[non_aborted]),含KL 惩罚后的实际奖励均值critic/rewards/maxmax(token_level_rewards.sum(-1)[non_aborted])critic/rewards/minmin(token_level_rewards.sum(-1)[non_aborted]) - 注:
token_level_rewards = token_level_scores - beta * kld(若开启 KL penalty)
优势值(Advantages)指标
- 具体指标
指标 计算方式 critic/advantages/meanmean(advantages[response_mask]),所有有效 response token 的优势值均值critic/advantages/maxmax(advantages[response_mask])critic/advantages/minmin(advantages[response_mask])
回报(Returns)指标
- 具体指标:
指标 计算方式 critic/returns/meanmean(returns[response_mask]),有效 token 的回报均值(GAE 计算结果)critic/returns/maxmax(returns[response_mask])critic/returns/minmin(returns[response_mask])
价值预测(Values)指标(仅 use_critic=True 时)
- 具体指标
指标 计算方式 critic/values/meanmean(values[response_mask]),Critic 旧价值预测均值critic/values/maxmax(values[response_mask])critic/values/minmin(values[response_mask])critic/vf_explained_var1 - var(returns - values) / (var(returns) + 1e-5),Critic 价值函数解释方差,越接近 1 表示价值估计越准确
序列长度相关指标
- 均在
verl/trainer/ppo/metric_utils.py:compute_data_metrics中计算指标 计算方式 response_length/meanmean(response_mask.sum(-1).float()),所有样本 response token 数均值response_length/maxmax(response_length),response_length=response_mask.sum(-1).float()response_length/minmin(response_length)response_length/clip_ratiomean(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_ratiomean(response_length == 0),响应长度为 0(中止/异常)的样本比例prompt_length/meanmean(prompt_mask.sum(-1).float()),prompt token 数均值prompt_length/maxmax(prompt_length)prompt_length/minmin(prompt_length)prompt_length/clip_ratiomean(prompt_length == max_prompt_length),prompt被截断的比例
多轮对话相关指标(按条件展示)
- 当 batch 中存在
__num_turns__字段时上报(多轮对话场景):指标 计算方式 num_turns/meannum_turns.mean(),每条样本的对话轮数均值num_turns/maxnum_turns.max()num_turns/minnum_turns.min() - 当 batch 中存在
tool_call_counts字段时上报(工具调用场景):指标 计算方式 tool_call_counts/meantool_call_counts.mean()tool_call_counts/maxtool_call_counts.max()tool_call_counts/mintool_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
2timing_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_tokenssum(batch.meta_info["global_token_num"]),本step 处理的 token 总数perf/time_per_steptiming_raw["step"],每个训练步的总耗时(秒)perf/throughputtotal_num_tokens / (time * n_gpus),每 GPU 每秒处理的 token 数perf/max_memory_allocated_gbtorch.device.max_memory_allocated() / 1024³,GPU峰值显存分配(GB)perf/max_memory_reserved_gbtorch.device.max_memory_reserved() / 1024³,GPU 峰值显存预留(GB)perf/cpu_memory_used_gbpsutil.virtual_memory().used / 1024³,CPU 内存占用(GB)
训练状态指标
- 在
verl/trainer/ppo/ray_trainer.py:1343处直接赋值:指标 计算方式 training/global_step当前全局训练步数 self.global_stepstraining/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_diffmax - 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_corrcorrcoef(actor_probs, rollout_probs)[response_mask],Pearson 相关系数,参考 arXiv:2506.13585
验证集指标(按条件展示)
在
_validate()方法中,通过process_validation_metrics函数处理后以多种统计形式上报:1
2
3
4
5
6
7
8val-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/k1logprob - ref_logprob(一阶线性近似)abs` mse/k20.5 * (logprob - ref_logprob)²low_var_kl/k3exp(clamp(ref - log, -20, 20)) - (ref - log) -1(低方差估计,来自 Schulman 2020)