我最近集中读了三篇讨论GRPO训练技巧的论文,也在自己的复现实验里把其中提到的10余项技巧挨个过了一遍。先说结论:那些听起来很复杂的训练技巧,绝大多数并没有带来对得起成本的效果;真正撑起训练效果的,反而是几个最基础、最不起眼的设置。这篇记录适合正在跑LLM强化学习、尤其是用GRPO做推理增强的人参考。
1. 先摸清楚:GRPO训练技巧是怎么被“卷”出来的
1.1 为什么GRPO会有这么多技巧
GRPO是Group Relative Policy Optimization的缩写,思想其实一句话:对同一个prompt采样多个输出,用这组输出的相对好坏来决定哪个动作该被加强、哪个该被抑制。相比传统PPO需要一个Critic模型去估计基线,GRPO直接靠组内结果做归一化,省掉了一个大模型,训练起来更省显存,也更容易稳定。
但真把GRPO从玩具代码跑到“能提升推理能力”,中间有无数个拉扯。我列几个最常见的场景:
- 组大小设大了,显存爆掉;
- 温度设低了,采样出来全是一句话的变体;
- KL惩罚太重,模型学不动;
- 归一化选错范围,奖励信号直接没梯度;
- 训练后期出现奖励攻击,模型开始刷格式。
于是每个人在自己的项目里遇到问题,就加一个“技巧”上去。这些技巧散落在论文、技术博客和issue里,越积越多。三篇论文做的事情其实一致:把这些技巧放到同一个基准下做消融,看看到底哪些有效。
这里先提醒一句:技巧多不等于效果好。很多技巧是为了解决某个特定训练环境下的偶发bug被发明的,换到别的场景,可能不仅没用,还会让超参搜索空间膨胀。我们做评测时,最需要警惕的是幸存者偏差。
1.2 我评测用的统一环境
为了对比尽可能公平,三篇论文和我的复现都采用了同一类设置:
- 任务:数学运算与证明类问题,用规则校验结果,答案有确定性;
- 基座:同一个开源7B规模底座,经过固定步数SFT;
- 训练算法:GRPO,不引入PPO的Critic;
- 训练步数:2000步左右,batch size固定;
- 奖励:最终答案正确得1,格式正确但答案错误得0,完全不包含长度惩罚和风格加权。
之所以选数学任务,是为了让reward没有人为调制的空间。如果奖励本身被启发式污染了,技巧的评测就没有意义。三篇论文和我自己的复现都遵循这个原则,所以结论比较容易对齐。
1.3 什么叫“必要”
我判断“必要”有一套很朴素的标准:
- 消融后性能有明显下降,且复现稳定;
- 带来的收益超过它增加的成本(显存、时间、额外调参步数);
- 在不同随机种子下方向一致。
如果一个技巧只是“某个跑分好像高了一点”,换种子就失效,那我把它归为“可选项”,不写进必选清单。这些标准在后面所有表格里会反复用到。
2. 三篇论文的评测逻辑与关键结论对比
2.1 第一篇论文:把基础参数彻底扫了一遍
第一篇论文的核心是“基础参数到底对GRPO影响有多大”。作者没有发明花哨技巧,而是把组大小、采样温度、clip范围、KL系数和advantage归一化方式当成五个独立变量,做了五组消融。结果最让我意外的是:组大小和KL系数是影响最强的两个因素,而clip范围在0.1到0.3之间几乎不敏感。
具体来说:
- 组大小从8提到32,推理准确率提升明显;再提到64、128,收益曲线变得非常平,但训练开销线性上涨。这个“32附近拐点”在多个seed下都出现了。
- KL系数太小(比如0.001),模型会迅速离开指令微调分布,产生大量不可读输出;太大(比如1.0),训练几乎失效,模型一动不动。0.05左右是比较稳的区间。
- 采样温度在0.7和1.0之间差距不大,但低于0.5时,组内方差骤降,优势估计变得很不可靠。
这个结论直接否定了“把温度调低更稳”的经验。至少在这个任务上,温度低了不是稳,是瞎。
2.2 第二篇论文:把“复杂技巧清单”挨个拆掉
第二篇论文是专门针对社区技巧的消融。作者汇总了当时流传的一系列GRPO增强方案:动态KL调度、组间归一化、响应级去重、熵正则、梯度裁剪、EMA、优化器eps调整、参考模型冻结与迭代切换,总共8项。他们把每一项单独加到基线里,然后又把所有项全加起来,做了“完整版vs基线”的对比。
结论很有意思:
- 响应级去重和梯度裁剪有一点帮助,但主要是为了“防止训练崩”,不是提升上限;
- 熵正则、EMA、优化器调整基本没有可复现的收益;
- 动态KL调度几乎总是比固定KL要差,因为调度的触发条件本身就引入了一个新的超参;
- 组间归一化是负面技巧,会破坏组内相对比较的意义。
最关键的对比是:完整版(8项全加)比基线高了不到1个点,但训练时间多了40%,超参调试量翻倍。作者最后明确写了一句:复杂技巧是在给baseline不够稳的bug买单,而不是在给模型加能力。
这句话我印象深刻。日常做项目也是这个道理——一个技巧如果把你从85分拉到86分,但需要同时维护四个新超参,它就是不划算的。
2.3 第三篇论文:技巧的收益会随着训练规模“缩水”
第三篇论文把“要不要复杂技巧”放到规模效应里看。作者在1B、7B、32B三个规模的模型上分别评测了“基础版GRPO”和“复杂版GRPO”。复杂版包含组间归一化、动态KL、奖励整形、多阶段课程等一堆额外设计。
结果非常反直觉:在小模型(1B)上,复杂版确实比基础版好;到了7B,两者差距缩小;到32B,两个版本几乎打平。也就是说,技巧的收益很大程度来自“小模型欠拟合或训练不稳定”的补偿,一旦模型容量够大、训练步数够多,基础版自然会追上来。
这一点对工业界有很强的指导意义:不要只在小规模实验里验证技巧。你在1B模型上成立的技巧,换到7B或更大模型可能是在白费力气。如果资源有限,最好先把基础版在目标规模上跑通,再考虑精雕细琢。
2.4 三篇论文的交叉验证
把三篇放在一起看,结论非常收敛:
| 评测维度 | 第一篇结论 | 第二篇结论 | 第三篇结论 |
|---|---|---|---|
| 基础组大小 | 32是拐点 | 基线32够用 | 大规模仍32~64足够 |
| KL系数 | 中等值最稳 | 固定比动态好 | 复杂调度无优势 |
| advantage归一化 | 组内归一化必要 | 组间归一化有害 | 简单归一化够用 |
| 额外正则技巧 | 不显著 | 多数不可复现 | 随规模变大收益消失 |
| 总判断 | 参数扫描更重要 | 复杂技巧不值得 | 规模能弥补技巧 |
这也回答了一开始的问题:复杂训练技巧真的有大多数人想象中那么必要吗?三篇论文的答案几乎都是“不”。
3. 10余项GRPO训练技巧逐项评测
3.1 必须保留的核心技巧
组大小(Group Size)
GRPO的优势估计质量完全依赖组内样本量。组太小,奖励均值和方差的抽样误差过大,导致同一个正确样本也可能被归一化成负优势。我实测下来32是最性价比的选择。显存允许时上到64也行,但收益明显变缓。这里有个可复现的规律:把每次样本数从8提到32,在数学任务上的收敛步数几乎缩短一半,而32到64只有约5%的性能变化。
采样温度
推理模型的rollout需要在探索和利用之间平衡。温度太低,模型反复生成同样的套路,组内多样性不足;温度太高,生成内容偏离训练分布。三篇论文和我自己的实验都更推荐0.8到1.0。如果你担心模型乱说,不要先调低温度,而是先去看KL惩罚是否正常工作。
KL惩罚系数
GRPO与普通策略梯度最大的不同是它始终关联着一个参考模型。KL惩罚本质上在约束“新策略不要离开参考模型太远”,它决定了训练的前进速度和安全边际。系数太小的表现非常经典:前几百步loss很低,然后突然崩掉;系数太大则表现为loss纹丝不动。我建议在0.01到0.1之间做线性扫描,以“训练不同阶段KL值平稳上升”而不是“最终分数最高”来选。
组内advantage归一化
这是GRPO的立身之本,不算技巧,但有些实验会把normalization拿掉。拿掉后的结果是:模型被组内绝对奖励值带偏,严重时所有样本的loss梯度符号相同,策略往“无论问题难易都更啰嗦”的方向走。所以这条必须保留。
注意:这里说的归一化是同一prompt下的多个输出之间做mean/std归一化,不是把所有batch样本混在一起算。如果混在一起做全局归一化,等价于给不同难度的问题强行加权,等于把组内相对信息给丢掉了。
3.2 加了不亏但别指望翻盘的中性技巧
响应级去重
如果同一个prompt的采样结果里有多条完全相同的文本,把它们去掉再算advantage。这个操作能很轻微地提升训练稳定性,尤其在采样温度较高时。但大多数情况下收益可忽略,只是实现成本也低,所以喜欢留着。
梯度裁剪
当KL突然变大时,梯度裁剪是一种廉价的安全网。设定global norm不超过1.0左右即可。注意不要依赖它解决KL问题,它只是把爆炸延后,不是根治。
EMA或最后N个checkpoint平均
对大模型训练来说,EMA能在推理时减少方差,但GRPO训练后期本身就存在分布偏移,EMA模型往往不是“最好”的那个。用最后N步的checkpoint做平均,偶尔能拿到一个更稳的权重。我认为它更适合推理部署前的整理阶段,不必出现在训练主循环里。
optimizer特殊设置
比如调大epsilon、关闭weight decay、对bias参数不加正则。这些属于锦上添花。如果不能确定你的改动能带来什么可解释的变化,就不要动。
3.3 看着高级,实则会反噬的复杂技巧
组间归一化或全局归一化
这是最容易踩的坑。很多人觉得“反正都是归一化,组内组间有啥区别”。实际上GRPO的优势必须是“组内相对”,做成全局后,简单问题的正确样本会得到低优势,难问题的正确样本会得到高优势,策略最终偏向挑简单问题处理,而不是真正提升推理能力。
动态KL调度
常见做法是设定一个KL目标区间,超标就提高beta,太低就降低beta。听起来很动态,实际执行上会产生一个非常讨厌的延迟反馈:你踩了刹车,但策略过去了三步才减速,于是模型在KL上限附近反复振荡。固定一个小beta加一个温和的warmup,比任何自适应调度都稳。
复杂奖励整形
在数学任务里给“过程包含某些关键词”“答案格式长度接近某范围”加分,是最容易诱发奖励攻击的操作。模型会学习用无关内容填充答案,而不是努力求正确结果。如果你非要加,请保证所有额外奖励项的上限都远小于正确性奖励,并且定期人工检查生成样本。
多阶段课程学习
先训练简单题,再训练难题,看着符合直觉,实际上很难控制“简单题训练过头”导致的分布偏移。三篇论文里的课程学习版本都没有稳定胜出。如果要做,我建议保持单一数据分布,允许模型在组内自然遇到不同难度,靠advantage归一化自己去调节,效果会更稳。
迭代式替换参考模型
把参考模型每隔一段时间用当前策略替换。这个技巧在某些算法变体里有理论依据,但在GRPO框架下会抹掉KL锚点,上一轮的“游走”会被下一轮固化,跑几轮后策略常常出现退化。至少在三篇论文的评测里,这是明确不推荐的操作。
把14项技巧汇总成一张表:
| 技巧 | 我的复现结论 | 建议 |
|---|---|---|
| 组大小32 | 强正收益 | 必选 |
| 温度0.8~1.0 | 正收益 | 必选 |
| KL系数适中 | 强正收益 | 必选 |
| 组内advantage归一化 | 必需 | 必选 |
| 响应级去重 | 微弱正收益 | 可选 |
| 梯度裁剪 | 稳定性收益 | 可选 |
| EMA或checkpoint平均 | 收益不稳 | 可选 |
| optimizer特殊设置 | 基本无收益 | 可选 |
| 组间归一化 | 明确负面 | 别用 |
| 动态KL调度 | 负面 | 别用 |
| 复杂奖励整形 | 明确负面 | 别用 |
| 多阶段课程学习 | 无优势 | 别用 |
| 迭代式替换参考模型 | 负面 | 别用 |
| 熵正则 | 无稳定收益 | 别用 |
这个表的含金量在于:它把训练技巧从“别人加了我也加”的盲目状态,拉回到“先跑通基线,再按收益决策”的理性状态。
4. 实操过程与核心环节实现:一套能稳定复现的GRPO基线
4.1 最小可跑的GRPO训练管线
一个完整的训练循环通常包括四个阶段:
- 采样(rollout):对每个prompt,用当前策略采样G条响应;
- 打分(reward):用规则判断每个响应是否正确,得到标量奖励;
- 计算advantage:对同一prompt的G条响应的奖励做组内归一化: A_i = (r_i - mean(r_group)) / sqrt(var(r_group) + eps)
- 更新策略:根据advantage与KL惩罚构建loss,反向传播更新策略参数。
整个管线的关键不是用几十个构造函数,而是确保每个环节的数据shape和张量device都对。我见过大量训练崩溃,最后查出来是advantage没有按group分组,直接拿到所有样本上算mean/std。
4.2 核心实现片段
下面这段代码不是为了直接跑生产,而是为了说明“复杂技巧只是在上面的最小闭环上做加法”,所以你应该先理解这段代码,再决定要不要加复杂技巧。
def compute_grpo_loss( policy_logps, # [batch_size, G, seq_len] ref_logps, # [batch_size, G, seq_len] rewards, # [batch_size, G] beta=0.05, # KL 系数 eps=0.2, # clip 范围 ): batch_size, G = rewards.shape # 1. 组内归一化 mean = rewards.mean(dim=-1, keepdim=True) std = rewards.std(dim=-1, keepdim=True) + 1e-4 advantages = (rewards - mean) / std # 2. 序列级 logprob 按 masked 求和 policy_seq = policy_logps.sum(dim=-1) # [batch_size, G] ref_seq = ref_logps.sum(dim=-1) # 3. ratio + clipped surrogate ratio = (policy_seq - ref_seq.detach()).exp() surr1 = ratio * advantages surr2 = ratio.clamp(1 - eps, 1 + eps) * advantages policy_loss = -torch.min(surr1, surr2).mean() # 4. KL 惩罚 kl_penalty = (policy_seq - ref_seq).mean() return policy_loss + beta * kl_penalty要特别指出:上面的代码里第3步需要对ref_seq.detach(),否则参考模型的梯度会残留在反向传播里。很多刚接触GRPO的人会在这里踩坑,loss看起来没问题,实际策略和参考模型被同步更新了,等于KL惩罚失效。如果你发现训练后KL值始终接近0,先检查这里。
4.3 推荐配置
我长期使用的稳定配置如下,基本覆盖了前三篇论文的共识。
| 参数项 | 推荐值 | 说明 |
|---|---|---|
| group size | 32 | 性价比拐点 |
| rollout温度 | 1.0 | 多样性优先 |
| KL系数beta | 0.05 | 固定,不加调度 |
| clip范围eps | 0.2 | 不敏感范围中间值 |
| advantage归一化 | 组内 | 不可省略 |
| 采样长度上限 | 1024 tokens | 覆盖大多数数学题 |
| 优化器 | AdamW | lr 1e-6左右 |
| 学习率调度 | warmup + cosine | 前10%步数线性升 |
| 全局梯度裁剪 | 1.0 | 仅作安全网 |
| 训练步数 | 2000 | 以KL和accuracy波动判断 |
这里唯一容易忽视的是学习率。推理模型训练和SFT完全不同,策略从一个收敛的SFT模型出发,只在奖励信号上做轻微修正,lr超过2e-6会导致策略瞬间偏移,然后进入“高奖励但内容不可读”的状态。我自己的经验是7B模型用1e-6,1B模型可以放宽到2e-6,32B模型要降到5e-7左右。
4.4 为什么这套配置能复制
这套配置能复制的根本原因是它没有引入任何“状态量”。复杂技巧往往包含内部状态:KL调度的目标区间、课程学习的阶段、EMA的衰减速率。状态越多,复现越困难。而固定beta、固定group size、固定温度,让实验的可复现性大大提升。你要做的不是发明新技巧,而是先承认“基础配置本身就是最强的技巧”。
5. 常见问题与排查技巧实录
5.1 训练200步后KL爆炸,loss狂飙
这是最常见的翻车。原因大概率是KL系数太小,或者数据中出现了一条超长响应。解决办法:
- 立即调高beta,或者做10步warmup;
- 检查rollout长度截断是否生效,超长响应会导致不同batch的token量突变;
- 如果已经爆炸,不要指望它自己恢复,回退到最近的正常checkpoint,把beta加倍后再训练。
5.2 advantage全为0,训练毫无梯度
当组内所有响应奖励都一样时,组内归一化后的advantage变成0,loss没有信号。常见场景是:任务太简单,所有样本都答对了;或任务太难,所有样本都答错。这时需要检查数据分布,简单的题去掉,或者削减简单题的比例。不要试图通过加一个“全对也给一个小奖励”的技巧来解决,那会引入新的偏差。
5.3 模型开始刷“正确格式的废话”
奖励攻击在数学任务上通常表现为:模型学会了输出“答案:xxx”的格式,但内部计算方式完全不可解释。我排查时会人工抽50条生成样本,如果发现50条里超过一半是靠复制prompt中的数字而不是重新计算,就说明训练分布已经被带偏。要做的不是加“禁止重复token”的惩罚,而是恢复更严格的规则奖励,删除任何给格式加分的项。
5.4 不同seed结果差距过大
如果3个种子下最终准确率差距超过5个点,代表训练过程方差过高。优先检查:
- group size是否小于16;
- 学习率是否过大;
- 是否用了随机性很强的rollout温度又没配合seed固定;
- 是否在checkpoint选择时只看了最后一步。
随机种子的影响在强化学习中通常比监督学习大得多,所以所有消融实验建议至少跑2个seed,只看单次结果很容易被噪声欺骗。
把常见问题整理成速查表:
| 现象 | 最可能原因 | 处理优先级 |
|---|---|---|
| KL爆炸、loss飞升 | beta太小 / 长响应未截断 | 调大beta、回退checkpoint |
| advantage为0或恒定 | 任务难度极端 / group size太小 | 修正数据分布、提高group size |
| 输出格式稳定但答案不对 | 奖励整形过重 / 规则不严 | 去除格式奖励、加强规则校验 |
| 不同seed性能波动大 | group size小 / lr过大 | 增大group size、降lr |
| 训练步数后期不提升 | KL过强 / 学习率过小 | 降低beta、小幅度升lr |
| 参考模型与策略同损更新 | ref logits未detach | 修代码,必须阻断梯度 |
5.5 一个节省成本的评测建议
最后分享一个我认为很重要的实操心得。做GRPO技巧评测时,不用每次都从零训练2000步。你可以固定出一个10万样本的训练子集,先跑200步看KL动态和reward上升曲线。如果200步内KL没有失控、reward有上升趋势,大概率整体趋势不会差。这样筛掉无效技巧只需要20%的算力,剩下的再放到完整规模里验证。
我在复现三篇论文时,大量使用了这个“小步快跑”的筛选方法,才得以在有限的算力下完成十几项技巧的横向对比。这也是为什么我能把这些技巧分成“必选/可选/别用”三类的原因——你如果不做筛选,很容易被某个单种子下1个点的提升骗进复杂的配置里,最后付出至少3倍调参成本。
回到标题的问题:复杂训练技巧真的必要吗?我现在的态度很明确:绝大多数不是必要的,甚至是在给自己制造麻烦。先把组大小、温度、KL系数、组内归一化这四个基础点抓好,比堆十来个高级技巧有效得多。如果你正打算复现某个增强推理项目,我建议按这个顺序操作:先搭一个最小的GRPO闭环,再套入推荐配置,跑通后只做减法,不要做加法。等你把所有听来的技巧都去掉,剩下还能明显加分的那几项,才值得写进自己的项目文档里。
这个系列的后续我可能还会写一些关于奖励设计、采样负担和训练成本之间关系的记录。如果你也踩过GRPO训练的坑,欢迎在评论区补充你的翻车经历,有时候一个别人忽略的报错,就是某个复杂技巧该被删掉的证据。