1. 从奖励到优势GRPO到底在解决什么问题第一次接触GRPOGroup Relative Policy Optimization组相对策略优化是在做一批对话模型的偏好对齐实验时。当时手头只有几张消费级显卡跑PPOProximal Policy Optimization需要同时加载策略模型、参考模型、奖励模型和 critic 模型显存直接爆掉。后来看到GRPO的思路第一反应是“这不就是把critic砍掉用组内相对比较来替代价值估计吗”试了一轮下来效果居然比预期稳得多。GRPO的核心定位很清晰它是一种无需独立价值网络critic-free的策略优化算法专门针对大语言模型在偏好对齐、数学推理、代码生成等场景下的强化学习微调。它解决的问题也很具体——传统PPO在语言模型上训练时critic模型和策略模型参数量相当显存占用翻倍训练成本极高而GRPO通过“同一问题采样一组回答用组内奖励的均值和标准差做归一化”来估算优势值直接绕开了价值函数拟合这一步。这篇文章适合谁看如果你正在做RLHF基于人类反馈的强化学习、推理增强训练或者单纯想搞清楚“奖励值”和“优势值”在GRPO里到底怎么算、为什么这么算那接下来的内容应该能帮你省下不少翻文档和调参的时间。我会从算法设计思路、奖励值处理、优势值计算、实操流程到常见坑一层层拆开讲。2. GRPO整体设计思路与方案选型2.1 为什么砍掉Critic显存与稳定性的双重考量PPO的标准流程里优势函数 ( A(s,a) Q(s,a) - V(s) ) 依赖一个学出来的价值网络 ( V(s) )。在传统强化学习任务比如Atari游戏里状态空间小、网络轻量critic的开销可以接受。但到了大语言模型场景情况完全变了。一个7B参数的策略模型critic通常也要7B量级才能给出靠谱的价值估计。这意味着训练时至少同时驻留两份7B模型还不算参考模型和奖励模型显存直接翻倍。更麻烦的是critic本身也需要大量样本才能学好而语言模型的奖励信号往往是稀疏的、只在序列末尾给出critic拟合难度很大容易引入偏差。GRPO的设计者做了一个很聪明的取舍既然同一个问题可以采样多个回答那组内回答之间的相对好坏本身就提供了优势信号的估计。不需要额外学一个价值网络直接用组内奖励的统计量来归一化就能得到类似优势的效果。这个思路和“留一法交叉验证”有点像——用同伴的表现作为基准而不是用一个全局的价值函数。2.2 组相对优势的直觉同伴比较替代绝对打分举个生活化的例子。假设你要评估一个学生的水平有两种方式绝对打分请一个老师给这个学生打分但老师可能标准不一今天严明天松。相对比较让这个学生和同班同学做同一套题看他在班里排第几。GRPO选的是第二种。对同一个prompt采样G个回答比如G8每个回答得到一个奖励值 ( r_i )。然后计算这组奖励的均值 ( \mu ) 和标准差 ( \sigma )每个回答的优势值就是[ A_i \frac{r_i - \mu}{\sigma} ]这个归一化后的值直接替代了PPO里的优势函数。好处很明显不需要critic省显存组内比较天然消除了奖励模型的系统性偏差如果奖励模型整体偏高组内归一化后影响被抵消实现简单少了一个需要调参的网络。2.3 与PPO、GRPO、RLOO的横向对比为了把选型逻辑讲清楚我整理了一张对比表维度PPOGRPORLOOLeave-One-Out是否需要critic需要不需要不需要优势估计方式( Q-V )组内归一化留一法基线显存占用高策略critic中仅策略中仅策略采样需求每prompt少量样本每prompt一组样本每prompt一组样本实现复杂度高中中适用场景通用RLLLM偏好对齐LLM偏好对齐从表里能看出来GRPO和RLOO都属于“用组内比较替代critic”的路线。区别在于RLOO用的是留一法均值作为基线而GRPO用的是组内均值和标准差做标准化。GRPO的标准化多了一步除以标准差这让优势值的尺度更稳定对学习率的敏感度更低。我在实际对比中发现GRPO在奖励方差较大的任务比如数学推理有的回答全对有的全错里训练曲线比RLOO更平滑。注意GRPO并不是万能的。如果任务本身奖励信号非常稠密、每一步都有反馈那critic可能还是有价值的。GRPO的优势主要体现在“序列级奖励、稀疏反馈”的LLM场景。3. 奖励值处理从原始信号到可用奖励3.1 奖励模型的输出到底怎么用在GRPO流程里奖励值通常来自一个奖励模型Reward ModelRM或者规则函数。奖励模型的输出一般是一个标量分数比如对回答质量打一个-10到10的分。但直接拿这个分数做归一化有个问题不同prompt的奖励分布可能差异很大。有的问题简单所有回答都拿高分有的问题难所有回答都拿低分。如果直接跨prompt比较优势值会失真。所以GRPO的做法是在每个prompt内部做归一化而不是全局归一化。这一点很关键。我见过有人把整个batch的奖励放一起算均值和标准差结果训练极不稳定。正确的做法是对每个prompt的G个回答单独算这组的 ( \mu ) 和 ( \sigma )。3.2 奖励塑形的几个实用技巧原始奖励信号往往需要一些“塑形”才能用好。我总结了几条实操中验证过的技巧长度惩罚要谨慎有些实现会对过长回答加惩罚防止模型啰嗦。但如果惩罚系数太大模型会学会输出极短的无意义回答。建议先用小系数如0.001试观察输出长度分布。格式奖励单独加如果任务要求特定格式比如数学题要写“答案XXX”可以给符合格式的回答额外加一个小奖励如0.5加速模型学会格式。奖励裁剪把奖励值裁剪到合理范围如[-5, 5]防止个别异常值主导归一化。因为标准差对异常值敏感一个极端奖励会让整组优势值被压缩。多奖励加权如果有多个奖励源如准确性奖励格式奖励长度奖励建议先分别归一化再加权求和而不是直接相加。否则量纲大的奖励会淹没量纲小的。3.3 奖励归一化的数学细节与边界情况归一化公式看起来简单但有几个边界情况必须处理[ A_i \frac{r_i - \mu}{\sigma \epsilon} ]其中 ( \epsilon ) 是一个很小的数如1e-8防止除以零。什么时候 ( \sigma ) 会接近零当组内所有回答的奖励几乎一样时。比如一个特别简单的问题8个回答全对奖励都是1.0那 ( \sigma \approx 0 )优势值会变成0/0。这种情况下我的处理方式是如果 ( \sigma ) 某个阈值如1e-4直接把整组的优势值设为0跳过这个prompt的更新。因为组内没有区分度更新没有意义强行归一化只会放大噪声。另一个边界是G1的情况。如果每个prompt只采样一个回答那组内均值和标准差都无从谈起GRPO退化成没有baseline的REINFORCE方差极大。所以GRPO必须保证G≥2实践中常用G4到G16。G越大优势估计越稳但采样成本也越高。我一般用G8作为起点。4. 优势值计算组内归一化的完整实现4.1 从奖励到优势的逐步计算假设一个batch里有B个prompt每个prompt采样G个回答。奖励张量的形状是[B, G]。优势值计算的步骤如下对每个prompt计算组内均值mean rewards.mean(dim1, keepdimTrue)形状[B, 1]。计算组内标准差std rewards.std(dim1, keepdimTrue)形状[B, 1]。归一化advantages (rewards - mean) / (std eps)形状[B, G]。对标准差过小的组把优势值置零。用PyTorch写出来大概是这样import torch def compute_grpo_advantages(rewards, eps1e-8, std_threshold1e-4): # rewards: [batch_size, group_size] mean rewards.mean(dim1, keepdimTrue) std rewards.std(dim1, keepdimTrue) # 标记标准差过小的组 valid_mask (std std_threshold).float() advantages (rewards - mean) / (std eps) advantages advantages * valid_mask return advantages这段代码里valid_mask的作用就是处理前面说的边界情况。实测下来加上这个mask之后训练稳定性有明显提升尤其是在训练早期模型输出多样性不足的时候。4.2 优势值如何进入策略更新算出来的优势值 ( A_i ) 会作为权重乘以对数概率的梯度。GRPO的损失函数大致是[ L -\frac{1}{B \cdot G} \sum_{i1}^{B} \sum_{j1}^{G} \min\left( \rho_{ij} A_{ij}, \text{clip}(\rho_{ij}, 1-\epsilon, 1\epsilon) A_{ij} \right) ]其中 ( \rho_{ij} \frac{\pi_\theta(a_{ij}|s_i)}{\pi_{\theta_{old}}(a_{ij}|s_i)} ) 是新旧策略的概率比。这个形式和PPO的clip损失几乎一样区别只在于优势值的来源。还有一个细节GRPO通常会加一个KL散度惩罚项约束新策略不要偏离参考模型太远。这个KL项是逐token计算的系数一般设0.01到0.1之间。系数太大模型学不动系数太小模型会跑偏输出变得混乱。4.3 优势值尺度对训练的影响优势值经过归一化后理论上均值0、标准差1。但实际训练中由于clip的存在和KL惩罚有效优势值的尺度会被压缩。我观察到一个现象如果优势值尺度过大策略更新会过于激进模型输出多样性迅速下降尺度过小学习信号太弱训练几乎停滞。控制尺度的手段有几个调整学习率。GRPO对学习率比PPO更敏感因为优势值已经归一化了学习率直接决定更新幅度。我一般从1e-6开始试最大不超过5e-6。调整clip范围。默认0.2如果训练不稳定可以降到0.1。调整KL系数。KL系数越大策略越保守有效优势值被压制得越厉害。实操心得训练初期建议把KL系数设大一点如0.05让模型先稳定下来等奖励曲线开始上升后再逐步降到0.01。这个“先紧后松”的策略比固定KL系数效果好很多。5. 完整实操流程与关键环节实现5.1 训练流程的五个阶段GRPO的完整训练流程可以拆成五个阶段我按实际执行的顺序来讲阶段一数据准备与prompt采样。准备一批prompt比如数学题、对话指令每个prompt需要能被奖励模型或规则函数打分。数据质量直接决定训练上限建议prompt难度分布要均匀太简单的题组内奖励全一样优势值为零浪费采样。阶段二组内采样。对每个prompt用当前策略模型采样G个回答。采样温度一般设0.7到1.0保证组内有多样性。温度太低所有回答几乎一样优势值又变成零。我通常用0.8。阶段三奖励计算。把G个回答分别送入奖励模型或规则函数得到G个奖励值。如果是规则函数比如数学题对答案直接算对错给1或0。如果是奖励模型注意batch推理别一个一个跑太慢。阶段四优势值计算。按第4节的方法算组内归一化优势值。这一步是纯张量运算很快。阶段五策略更新。用优势值加权的clip损失更新策略模型同时计算KL惩罚。更新完一轮后回到阶段二用新策略重新采样。5.2 关键参数配置与计算过程下面是我在一批7B模型数学推理任务上的实际配置供参考参数取值说明组大小G8每个prompt采样8个回答学习率2e-6比PPO小因为优势值已归一化KL系数0.02先0.05预热后降到0.02Clip范围0.2标准值采样温度0.8保证组内多样性Batch内prompt数16显存允许的话可以更大训练轮数2-3 epoch太多会过拟合奖励模型显存估算7B策略模型fp16约14GB 参考模型14GB 奖励模型如果也是7B14GB 激活值。总共约45-50GB单张A100 80GB可以跑或者两张40GB卡做模型并行。5.3 训练现场的观察与调参记录第一次跑GRPO时我遇到奖励曲线先升后降的情况。前100步奖励从0.3涨到0.6然后开始掉。排查后发现是KL系数太小当时设的0.005模型跑偏了开始输出重复的、能骗过奖励模型的回答。把KL系数调到0.05后重新跑奖励曲线变成缓慢但稳定上升最终到0.72。虽然上升慢了但没有崩溃。这个教训让我意识到GRPO的稳定性很大程度上依赖KL约束不能为了追求快速上升而放松KL。另一个观察是组大小G的影响。G4时优势值噪声较大训练曲线抖动明显G16时曲线平滑但采样成本翻倍。G8是一个性价比不错的平衡点。如果显存和计算资源充足G16会带来更稳的训练。6. 常见问题与排查技巧实录6.1 奖励不涨或下降的排查路径这是最常见的问题。我整理了一个排查顺序检查优势值是否全为零。如果组内奖励全一样优势值为零模型根本不更新。打印每个batch的优势值标准差如果大部分接近零说明prompt太简单或采样温度太低。检查KL系数。KL太小模型跑偏KL太大模型学不动。先试0.05再逐步降。检查学习率。GRPO对学习率敏感2e-6是安全起点。如果奖励完全不涨试试5e-6如果奖励震荡降到1e-6。检查奖励模型是否可靠。奖励模型本身如果有偏差GRPO会放大这个偏差。可以人工抽查一些高奖励回答看是否真的质量高。检查数据分布。如果prompt难度两极分化简单题优势值为零难题奖励全低有效训练信号很少。建议筛选中等难度的prompt。6.2 显存不足的优化手段GRPO虽然省了critic但参考模型和奖励模型还是占显存。几个优化手段参考模型用LoRA如果参考模型只是用来算KL可以用低秩适配器显存占用大幅降低。奖励模型量化奖励模型可以用8bit或4bit量化推理精度损失可接受。梯度检查点策略模型开启gradient checkpointing用时间换显存。减小batch sizeprompt数从16降到8显存减半但训练速度变慢。序列长度裁剪限制回答最大长度比如512 token减少激活值占用。6.3 训练不稳定的典型表现与对策表现可能原因对策奖励突然暴跌KL系数太小策略跑偏提高KL系数回滚到上一个checkpoint输出重复奖励模型偏好重复文本加重复惩罚检查奖励模型优势值方差过大奖励异常值奖励裁剪检查奖励模型输出范围训练后期奖励停滞学习率太小或KL太大降KL微调学习率组内奖励全相同prompt太简单或温度太低提高温度筛选prompt避坑技巧训练过程中一定要定期保存checkpoint并且记录每个checkpoint的奖励和KL值。GRPO训练崩溃往往很突然有checkpoint才能回滚。我一般每50步存一次。7. 我对GRPO落地的一些个人体会GRPO最吸引我的地方是它把“优势估计”这个原本需要额外网络的任务转化成了一个纯统计问题。组内归一化虽然简单但背后有扎实的逻辑同一个问题的多个回答天然构成了一个对照实验组内比较比跨组比较更公平。不过它也不是没有代价。GRPO需要每个prompt采样多个回答采样成本是PPO的G倍。如果奖励模型推理很慢这个成本会很痛。我的做法是奖励模型用小的比如1.5B策略模型用大的7B这样奖励计算不会成为瓶颈。另外GRPO对prompt质量很敏感。如果prompt太简单组内奖励没区分度优势值为零白采样如果太难所有回答都拿低分也没有区分度。所以数据筛选这一步不能省。我一般会先用当前模型跑一遍把那些组内奖励标准差接近零的prompt过滤掉再用来训练。最后分享一个小技巧如果训练中途奖励曲线卡住了不妨把组大小G临时调大比如从8调到16跑几百步看看。有时候优势值噪声太大导致模型学不动增大G能降低噪声让训练重新动起来。这个技巧我在两个项目里都用过效果不错。