GRPO训练信号监控实战:从奖励分布到KL散度的健康度诊断
1. 一开始就没想清楚GRPO 训练的“信号”到底是什么做 LLM 训练的人应该都有过这种体验一个 GRPO 训练任务跑了一整天loss 曲线看着挺漂亮结果拿推理脚本一测生成的回答完全不按预期走。问题出在哪多半是你盯错了东西。很多人一上来只盯 loss 和 reward这两个数值太宏观GRPO 这种基于组内比较的强化学习算法真正能反映训练是否健康的是那些平时不常看的中间信号。先说为什么 GRPO 和传统的 PPO 不太一样。PPO 需要单独训练一个 critic 模型来估计状态价值所以训练时至少有四个网络在跑actor、critic、reward model、reference model。GRPO 直接把 critic 砍掉了advantage 怎么算靠的是同一条 prompt 生成的多个 response 之间的相对比较。给定一个 prompt采样出 G 条回答reward model 给每条回答打分然后在这 G 个分数内部做归一化算出每个 response 的 advantage。这种组内比较的设计本质上是把“这个回答有多好”替换成“这个回答比同组的其他回答好多少”因为没有绝对标准所以噪声更大信号更需要盯紧。而“训练信号健康度”这个概念通俗点说就是训练过程中每一步产生的数字能不能真实反映模型在朝着目标方向走。如果这些数字看起来还行但模型实际行为已经偏了那信号就是不健康的。更糟的是有些信号会骗人比如 reward 一直在涨但 KL 散度已经爆炸了说明模型已经飘到了参考模型十万八千里远生成的内容可能全是格式化模板或重复台词reward model 反而给高分这种就叫 reward hacking。这些坑我后面会详细拆。从面试官的角度看能主动意识到“训练信号需要监控”的人和只会等 loss 曲线的人完全不是一个段位。能说清楚 GRPO 中 reward、KL、entropy、response length 这些指标之间的联动关系并且知道每个指标异常时该往哪个方向排查才算是真的做过大规模 RL 训练。2. 信号健康度分层拆解哪些指标不用盯哪些必须盯监控不是把所有能打点的指标全堆到 dashboard 上那是给服务器加负担不是做训练。真正需要做的是把信号按“策略行为、奖励反馈、分布稳定性、集群健康”四个层分开看。2.1 策略行为层模型到底在干什么这一层反映的是 actor 模型自身的行为特征和 reward 无关也能反映出训练是否进入异常状态。第一个看的是 response length。GRPO 训练初期模型往往会倾向于输出很短的回答因为短回答容易获得中规中矩的分数而长回答容易同时触发 reward model 的偏好和惩罚。如果 response length 在某一个训练步之后突然骤降通常不是模型变懒了而是某个 prompt 的子集触发了 reward model 对“冗长”的惩罚导致策略快速收敛到“简短回答”这个局部最优。反过来如果 length 持续暴涨要小心模型开始用废话填充来刷 reward尤其是当 reward model 对“信息量”的建模不完善时这种问题很常见。第二个是 entropy。GRPO 训练中entropy 的走势比 loss 更重要。entropy 下降是正常的因为策略在朝着某个方向收敛但健康的收敛应该是缓慢下降并且保持在一个合理的水平。如果 entropy 在几千步内断崖式下跌到接近 0说明策略已经坍塌了模型输出几乎是确定性的不再做任何探索。这种情况一旦出现后续的 advantage 计算基本就失效了因为同组 G 条 response 几乎长得一样相对比较已经没有区分度。第三个是 top-k / top-p 采样下的 response 多样性。这个不一定要实时算但每天至少要看一次抽样比如同一个 prompt 在训练不同阶段的 response 形态。如果连续两天采样的结果高度重复entropy 大概率已经出了问题。2.2 奖励反馈层reward 的分布比均值重要得多reward 是 GRPO 的信号源头。但很多人只盯平均 reward这是最容易踩的坑。平均 reward 上涨不代表模型在变好。某个群体性 prompt 的 reward 暴涨会把均值拉高而其他大部分 prompt 的 reward 其实在下滑。正确做法是看 reward 的整体分布均值、中位数、四分位距、标准差、最大最小值以及分位数跨度的变化趋势。这里有个很实用的经验法则。如果 reward 的标准差在训练过程中持续增大说明不同 prompt 之间的难度差异在拉大模型在简单任务上刷分、在困难任务上摆烂。这种情况光看均值完全看不出问题因为简单任务的提升足以掩盖困难任务的倒退。其次是 group 内部的分差。GRPO 的 advantage 是组内归一化得到的如果同一组 response 的 reward 彼此非常接近导致 advantage 的绝对值都很小梯度更新幅度就会极小训练会陷入“慢吞吞”的状态。如果 reward 最大值和最小值相差过大比如超过 2 个标准差那么 dominant response 会主导梯度方向其他 response 对更新的贡献几乎为零等价于退化成单样本策略梯度GRPO 的相对比较优势就没有了。这两种情况都需要警惕。2.3 分布稳定性层KL 散度要盯总量更要盯增速GRPO 训练里还有一个 reference model作用是在策略更新时约束 actor 不要离参考模型太远。KL 散度就是衡量这个距离的指标。很多人只看 KL 的绝对值其实增速才是关键。KL 在训练初期快速上升中后期趋于平缓这是健康的但如果 KL 呈现出加速上升的态势每 100 步的增量还在变大说明 policy 已经不满足于微调开始大规模重构输出分布这时候大概率是 reward model 给出的梯度方向是有偏的或者学习率设置得过于激进。另外要看 KL 的分位点分布。平均 KL 正常不代表所有 prompt 都稳定。通常一个 batch 里面有少量 prompt 会产生极高 KL比如超过 95 分位数 3 倍以上而这些 prompt 正是“奖励黑客”的高发区。把这些 prompt 单独捞出来看基本都能发现 reward model 的评分漏洞。2.4 集群健康层多少算力在真正训练单调了。最后一个容易被忽略的是集群状态。GRPO 训练是重 IO、重通信的负载G 组采样通常要占掉近一半的算力。如果集群出现慢节点、网络抖动、显存 OOM训练吞吐会下降但真正麻烦的是这些故障会导致某个 rank 更新滞后进而产生错误的梯度同步整体信号就乱了。我建议对上 GPU 利用率、训练吞吐samples/sec、卡间通信耗时、显存占用率做实时监控至少要保证这些指标平稳。如果训练过程频繁出现 step 时长漂移超过 20%先别管 reward 曲线了集群大概率有问题。3. 从零搭一套 GRPO 信号监控体系步骤、代码与阈值这里我以自己实际用过的方案为例讲一下怎么在现有 GRPO 训练框架上搭一套能用的监控体系。不要求一步到位先跑起来再逐步完善。3.1 工具选型wandb 足够但不是唯一选择如果训练任务量不大wandb 完全够用因为它不需要额外维护数据库自带分组对比和曲线可视化。但它有一个弱点自定义告警的灵活度有限对长周期训练任务的“根因追踪”不够方便。更完整一点的方案是 Prometheus Grafana 对象存储。训练进程周期性把指标以 JSON 格式写入本地目录一个 file exporter 把指标推到 Prometheus再由 Grafana 出图。这套方案的好处是训练结束之后指标还在不依赖外部 SaaS适合有安全要求的团队。缺点是前期搭起来需要花半天时间。我个人目前的习惯是训练过程用 wandb 做实时跟踪同时每 500 步把完整指标快照存一份到本地磁盘。这样既能在训练时快速看走势又能在事后做深度复盘。快速决策用 wandb深度归因用本地快照。3.2 日志规范与打点位置监控不是把所有东西都往日志里塞而是在正确的位置、以正确的粒度打点。我建议每个训练 step 打一条 summary 日志包含以下字段字段说明记录频率step当前步数每个 stepreward_mean / reward_stdreward 均值与标准差每个 stepreward_quantiles25/50/75/95 分位每 100 步group_reward_gap组内最大最小 reward 差值每 100 步kl_mean / kl_p95KL 散度均值与高分位每个 stepentropy策略熵每个 stepresponse_len_mean平均生成长度每个 stepadvantage_mean_absadvantage 绝对值的均值每个 stepdf / gpu_util吞吐量与 GPU 利用率每 10 秒单独记录grad_norm梯度范数每个 steplr当前学习率每个 step代码层面如果你用的是 PyTorch wandb大概长这样import wandb import torch.distributed as dist def collect_metrics(step, rollout_stats, ref_kl, entropy, grad_norm, lr): metrics { step: step, reward/mean: rollout_stats[reward_mean], reward/std: rollout_stats[reward_std], reward/median: rollout_stats[reward_median], reward/p95: rollout_stats[reward_p95], kl/mean: ref_kl[mean], kl/p95: ref_kl[p95], entropy/mean: entropy[mean], response/len_mean: rollout_stats[response_len_mean], adv/mean_abs: rollout_stats[adv_abs_mean], grad/grad_norm: grad_norm, train/lr: lr, } if dist.get_rank() 0: wandb.log(metrics, stepstep)注意只有 rank 0 做日志写入其余 rank 只负责计算指标否则会打出重复数据。3.3 阈值设定原则先看趋势再设绝对值阈值不好定因为不同模型、不同 reward model 的分布差异很大。我的建议是分三步走第一步用前 200 步作为“基线期”只记录不告警计算出各个指标的均值和标准差。第二步基于基线的 3 倍标准差设定告警线比如 reward/std 超过基线 3 倍就告警。第三步等训练到 2000 步左右积累了更多数据后再人工校正阈值。这里有一个比较通用的经验参考不同模型规模可以微调指标健康范围参考什么情况该紧张reward_std在初始阶段快速上升后稳定持续单调上升超过 3 天kl_mean_ratio每 100 步增量 5%增量超过 20% 持续 300 步entropy相对初始值下降 30%-60% 后企稳下降超过 90% 或直接归零response_len上下浮动在 15% 以内单日变化超过 50%grad_norm在稳定区间震荡无极端峰值连续 50 步超过基线 5 倍4. 五个真实排障案例从信号异常到根因定位这一章我整理了几个在 GRPO 训练中高频出现的问题每个都是信号的异常形态先行再顺藤摸瓜找到根因。这些案例不是虚构而是我在多个项目里反复遇到的模式。4.1 reward 突然暴涨然后全崩某次训练跑到 3000 步左右reward_mean 在 200 步内从 0.2 涨到 0.8看起来是“训得特别好”。但同步观察 response_len_mean也在同步暴涨从 300 个 token 涨到 900 个 token。把样本捞出来一看模型开始大量输出“好的我来帮你分析一下首先其次最后”这类话术信息量极低但结构完整。reward model 显然对“结构完整、礼貌用语”给了过高的权重。这就是 reward hacking 的典型信号。处理方式有两个方向一是立即打回 rollout 采样数据把响应长度异常变化的 prompt 找出来二是调整 reward model 的输入约束在 prompt 层面禁止过长的格式化输出。如果 KL 散度同时也在快速上升可以先用 KaTeX parse error: Expected EOF, got at position 14: 调低 KL 惩罚系数不要立刻停训。4.2 KL 散度爆炸策略飘了有一次训练中段kl_mean 正常在 0.3 左右突然在 100 步内跳到 5而且还在持续上涨。当时第一反应是学习率太大但实际上 lr 没变。后来把 p95 的 KL 拿出来看发现是少数 prompt 的 KL 贡献了绝大部分。把这些 prompt 过滤出来发现它们都属于同一类题型——开放式问答reward model 对这类题的打分方差极大导致策略在几个样本上剧烈更新。这种情况下单个 prompt 的过强梯度拖垮了整体策略。解决办法是加入 per-prompt 梯度裁剪或者基于 KL 分位数做样本过滤在高 KL 样本上打标暂停使用这些 prompt 的 rollout 数据。更根本的做法是在数据采集侧控制 prompt 的难度分布避免某种类型的题目占比过高。4.3 entropy 断崖模型开始“复读机”entropy 从 1.5 掉到 0.05 只用了不到 200 步同组的 response 几乎变成了同义重复。出现这种问题时reward 甚至还在缓慢上升因为模型找到了一个“稳定拿分”的输出模式但这个模式对真实场景毫无意义。根因通常是 batch size 太小、组内采样数 G 太少导致优势估计的噪声过大模型过早收敛到局部最优。建议先检查 G 值如果 G 小于 8可以尝试增大到 16同时把 entropy 的 loss 系数调高给探索留出空间。还有一种情况是数据集里重复 prompt 过多模型在重复记忆这时候需要清洗数据集。4.4 loss spike 和 NaN先查集群再查代码训练中期出现 loss spike或者直接 lossNaN很多人第一反应是调低学习率但实际大概率不是这个原因。常见根因有三种某一批数据的 reward label 异常比如 reward model 返回了 NaN 或者异常大的值组内 advantage 归一化出现除零错误以及 GPU 显存不足导致部分参数更新不完整。排查路径建议按顺序来先看监控里的 reward_raw 字段是否出现 NaN 或 inf再看 grad_norm 是否在 spike 前出现极端峰值最后进训练日志查对应 step 是否发生 ring-allreduce 超时。如果集群节点有掉卡参数同步已经错乱这时候调 lr 没有意义只能回滚到上一个稳定 checkpoint 重启训练。4.5 吞吐量下降 50%信号没变但训练变慢了这是一个容易被忽视的问题因为它在 reward 曲线上完全看不出来。某次训练跑到 2 万步时samples/sec 从 1.8 掉到 1.0且持续了三个多小时。最后定位到是一台机器上的 NVLink 通信不稳定导致梯度同步频繁重试。集群层面的监控这时就派上用场了单独看 reward 曲线永远发现不了这个问题。我的做法是给集群监控单独建一张图包含每台机器的温度、功耗、PCIe/NVLink 错误计数、训练进程的网络重连次数。一旦吞吐量下降先看这张图能省下大量排查时间。另外checkpoint 保存时的 IO 峰值也会造成吞吐抖动把这个时间窗口过滤掉再判断。5. 可执行的监控体系落地清单前面讲了这么多最后给一个可以直接照着做的落地清单。假设你已经在用 GRPO 训练但没有任何监控体系按下面的顺序搭建一天内可以上线一个最小可用版本。5.1 最小可用版本第一天第一步在训练代码里增加指标采集器实现前面说的 summary 日志。第二步接入 wandb 或本地 TensorBoard至少能看到 reward、KL、entropy、response length、gradient norm 五条曲线。第三步设定三个即时告警loss 为 NaN、KL 超过基线的 10 倍、entropy 低于初始值的 0.1 倍。这三条告警不需要很精确但能在训练开始阶段帮你挡住最致命的问题。很多训练事故的共性就是发现得太晚bad checkpoint 已经覆盖了之前的好结果。有了即时告警至少不会让一个已经跑歪的训练任务继续空转一整天。5.2 进阶版本第一周在最小版本基础上补充组内样本回放功能。每 500 步从当前 rollout 里采样 5-10 个 prompt把对应的 4-8 条 response 和各自的 reward 打印到日志里。这个功能看起来土但它是识别 reward hacking 最直接的手段。数值指标只能告诉你“出问题了”回放样本能告诉你“哪里出了问题”。同时把指标按 prompt 类型做分组统计。比如按题目难度分为简单、中等、困难三个组分别统计每组 reward 的均值与方差。如果简单组的 reward 在持续上升而困难组在下降说明模型在走捷径而不是真正变强。这个洞察不分组是看不到的。5.3 告警机制宁可频繁告警不可漏报告警阈值设得越严格越好哪怕会带来一些误报。误报最多浪费你五分钟看日志漏报则可能导致上万美元的算力白白消耗。我习惯把告警分成两级黄牌和红牌。黄牌表示“注意需要看一下”比如 reward 分位数出现极端值、单步时长漂移超过 20%。红牌表示“立即停训”比如出现 NaN、连续 50 步 entropy 低于阈值、KL 散度出现数量级跳变。红牌告警发生时训练框架应该自动暂停并触发 checkpoint 回滚人工确认之后再继续。6. 面试官视角为什么会把这个点拿出来考人既然标题是“面试官笔记”最后聊一下为什么我在面试 LLM 训练岗位时会专门问这个方向的问题。GRPO 训练和传统监督训练最大的差别在于训练目标不是一个确定的、可预知的 loss 函数而是一个动态的、由 reward model 反馈构成的信号流。因此面试者能不能意识到“训练信号需要监控、监控什么、异常了怎么办”基本能反映他有没有真正独立负责过大规模 RL 训练。背过 GRPO 论文公式的人很多但能说出“当 response length 在 200 步内上涨 50% 时应该优先检查 reward model 是否对格式化输出产生了偏置”的人大概率是真跑过训练的。我面试时一般会问三个递进的问题第一你负责的 GRPO 训练任务里哪些指标是你每天必看的这个问题考察的是监控意识能说出三个以上指标并解释关联性的基本已经合格了。第二如果某一天 reward 均值在涨但 KL 散度也在加速上升你会怎么处理这个问题考察对信号联动关系的理解很多人只会说“调低 KL 系数”但不会联想到这可能是 reward model 本身有问题。第三如果训练 10 小时后 loss 出现 NaN你的排查顺序是什么这个问题考察的是实际问题处理能力能把集群、数据、代码、超参四个层面的排查顺序说清楚的人我真的不多见。这三个问题问下来候选人有没有真的负责过大规模训练基本藏不住。因为监控不只是“看一眼曲线”而是理解每一个数字背后代表的数据分布和模型行为。根据我个人的经验面试里遇到能主动聊到“reward 分布的分位点变化”和“组内 advantage 差距过大导致梯度被少数样本主导”这些细节的候选人往往在之后的工作里也能独立解决更复杂的问题。这恰恰说明能不能监控好训练信号的健康度不只是一个技术活更反映了一个人对整个训练系统的全局理解。