这篇文章比较了使用 veRL 在 GSM8K 数学推理 benchmark 上对 Qwen2.5-0.5B-Instruct 进行后训练时,PPO 和 GRPO 的表现。
基于 Qwen2.5-0.5B-Instruct 模型,以 GSM8K 为训练数据、使用基于规则的可验证正确性奖励 (Reinforcement Learning with Verifiable Rewards) 进行训练时,PPO 和 GRPO 达到了非常接近的测试准确率;同时,GRPO 因为不需要 critic 网络,训练速度更快。
具体来说:
- base model 在最终评测 pipeline 下的 GSM8K 得分为 45.19%。
- PPO 将准确率提升到 58.83%。
- GRPO 将准确率提升到 57.47%。
- 与 PPO 相比,GRPO 训练速度快 约 23%,每秒处理的 token 数多 约 33%。
代码和实验docker镜像:gong208/hands-on-modern-rl:ppo-vs-grpo-verl0.5-vllm0.10.1-ray2.55-20260623
为什么比较 PPO 和 GRPO?
PPO 是许多 RLHF pipeline 中常用的标准 RL 算法。在 LLM 场景中,PPO 通常会同时训练 actor model 和 critic model:
- actor 生成回答;
- critic 预测期望的未来回报,估计 policy optimization 中的 advantage。
critic 的作用是提供一个学习得到的 baseline 。不过,它也会带来额外成本:critic 是一个额外的模型,需要存储、训练和更新。
GRPO 移除了这个 critic model。GRPO方法中不再通过 critic model 估计 value,而是对同一个 prompt 采样多个回答,然后把每个回答与该组回答的平均 reward 进行比较。advantage 是根据组内的相对表现计算出来的。
换句话说:
| 方法 | Advantage 估计 | Advantage 估计中的 baseline |
|---|---|---|
| PPO | ,通常用 GAE 计算 | 学习得到的 value function / critic |
| GRPO | ,在采样组内计算 | 采样组内的平均 reward |
这使得 GRPO 对 LLM reasoning 任务很有吸引力,尤其是在 reward 容易验证的情况下。GSM8K 正是这样的设定:最终答案可以被提取出来,并与 ground-truth answer 进行比较。
此外,由于使用的是可验证 reward,这个实验不需要学习得到的 reward model。PPO 和 GRPO 都优化同一个基于规则的正确性 reward。
训练与评测设置
实验设置
PPO 和 GRPO 都在同一个 veRL pipeline 中训练。
控制变量如下:
| 设置 | 数值 |
|---|---|
| Model | Qwen2.5-0.5B-Instruct |
| Dataset | GSM8K train / test |
| Train set size | 7,473 道题 |
| Test set size | 1,319 道题 |
| Framework | veRL 0.5.0 + vLLM 0.10 |
| Hardware | 单张 NVIDIA L40S,48 GB |
| Epochs | 20 |
| Optimizer steps | 1,160 |
| Train batch size | 128 prompts |
| PPO mini-batch size | 64 |
| Samples per prompt | 4 |
| Max prompt length | 512 tokens |
| Max response length | 256 tokens |
| Actor learning rate | 1e-6 |
| KL regularization | actor 侧相对于 reference model 的 KL loss |
| KL coefficient | 0.001 |
| KL type | low_var_kl |
| Clip ratio | 0.2 |
| Entropy coefficient | 0 |
| Reward | 仅正确性 |
优化的 reward 是二元正确性:
score = 1,如果提取出的答案与 ground truth 匹配
score = 0,否则实验中也会计算并记录一个 format flag,但它不会被加入优化的 score。因此,训练 reward 并不会显式奖励长度、风格或答案格式;除了最终答案需要能够被 answer extractor 识别出来之外,格式本身不直接获得奖励。
两次运行之间唯一有意设置的算法差异是 advantage estimator:
| PPO | GRPO | |
|---|---|---|
| Advantage estimator | GAE | group-relative baseline |
| Critic network | yes | no |
| Critic learning rate | 1e-5 | N/A |
| Advantage baseline | 学习得到的 value function | 同一个 prompt 的 4 个回答的平均 reward |
相同的采样预算很重要。PPO 通常会以每个 prompt 生成一个回答的方式运行,而 GRPO 天然需要对每个 prompt 生成多个回答。在这里,两种方法都使用 rollout.n = 4,所以比较重点放在 advantage estimator 上,而不是简单地给 GRPO 更多采样数。
评测协议
最终比较对三个模型使用同一个 evaluation harness:
| 设置 | 数值 |
|---|---|
| Models evaluated | base, PPO, GRPO |
| Dataset | GSM8K test set |
| Number of problems | 1,319 |
| Prompting | 0-shot |
| Decoding | greedy |
| Max response length | 512 tokens |
| Precision | bf16 |
| Scoring | 与训练 reward 相同的 answer matcher |
base model 也通过与 PPO 和 GRPO 相同的 pipeline 进行评测,只是没有经过 RL 训练。这样,三者之间的比较是直接可比的。
结果
准确率结果
| Model | GSM8K test accuracy | Correct / total | Improvement over base |
|---|---|---|---|
| Qwen2.5-0.5B-Instruct | 45.19% | 596 / 1319 | — |
| PPO | 58.83% | 776 / 1319 | +13.64 pts |
| GRPO | 57.47% | 758 / 1319 | +12.28 pts |
PPO 和 GRPO 都显著优于 base model。
PPO 是这次单次运行中表现最好的方法,但 PPO 和 GRPO 之间的差距很小:
PPO - GRPO = 58.83% - 57.47% = 1.36 percentage points这对应于 1,319 道测试题中 PPO 比 GRPO 多答对 18 道。
我不会过度解读这个差距。这只是一个模型规模、一个数据集上的单次运行比较。在没有多个随机种子或 paired significance test 的情况下,更合适的解读是:
在这个设定中,PPO 和 GRPO 的最终准确率非常接近。
训练成本结果
| Metric | PPO | GRPO | GRPO vs PPO |
|---|---|---|---|
| Wall-clock time | 8.47 h | 6.49 h | −23% |
| GPU-hours | 8.47 | 6.49 | −23% |
| Estimated cost at $1.50 / GPU-h | $12.71 | $9.74 | −23% |
| Median throughput | 6,138 tok/s | 8,192 tok/s | +33% |
GRPO 更快,因为它不训练 critic。PPO 在每个 training step 中有一部分时间用于更新 value model,包括 critic forward pass、backward pass 和 optimizer step。GRPO 则用简单的 group-level reward baseline 代替这个学习得到的 value baseline。
在 Qwen2.5-0.5B-Instruct + GSM8K + 可验证正确性 reward 的设定下,GRPO 是更具成本效益的选择。它在避免 critic update 的同时,达到了几乎相同的准确率。
显存结果
显存结果稍微有些微妙。
| Metric | PPO | GRPO | Difference |
|---|---|---|---|
Peak GPU memory from nvidia-smi | 47.36 GB | 47.31 GB | ~0 GB |
| Torch max allocated | 50.71 GB | 45.19 GB | −5.52 GB |
nvidia-smi 报告的物理显存峰值看起来几乎相同。这很可能是因为 vLLM rollout engine 会预留一大块固定显存区域,所以两次运行看起来都会占满 GPU 的大部分显存。
PyTorch 的 max-allocated 指标显示出更清晰的差异:GRPO 使用的工作显存大约少 5.5 GB。这与算法层面的差异一致:PPO 需要维护和更新 critic model,而 GRPO 不需要。
在 0.5B 规模下,这个显存节省是真实存在的,但不是决定性的,因为两种方法都能放进单张 L40S。到了更大的模型规模,移除 critic 可能会变得更重要。
推理 profile
训练结束后,我还使用相同 prompt,在 GSM8K test set 上用 batched vLLM greedy decoding 对最终模型进行了推理 profile。
| Model | Avg output tokens | Total generation time | Decode throughput |
|---|---|---|---|
| Base | 296.8 | 17.0 s | 23,047 tok/s |
| PPO | 158.7 | 10.4 s | 20,127 tok/s |
| GRPO | 152.8 | 9.7 s | 20,846 tok/s |
最有意思的差异是输出长度。两个 RL 训练后的模型都比 base model 生成短得多的回答:
Base: ~297 tokens
PPO: ~159 tokens
GRPO: ~153 tokens因此,PPO 和 GRPO 基本上把回答长度减半了。
这种简洁性并不是被显式奖励出来的。reward 只检查正确性。不过,训练时 response budget 被限制在 256 tokens。一个冗长的解法更有可能在到达最终答案之前被截断,而被截断就会得到零 reward。因此,模型被间接推向了更短、更果断的推理方式。
这是 reward 和长度限制共同产生的 emergent side effect。
定性结果
定量结果表明 RL 提高了准确率。一个定性例子可以帮助说明模型行为发生了什么变化。
下面的例子来自一次较早的 sanity-check evaluation,当时比较的是 base model 和 PPO-trained model。两个模型都接收了相同的 4-shot chain-of-thought prompt,然后回答下面这道 GSM8K 题目:
Janet 的鸭子每天产 16 个蛋。她每天早上吃 3 个当早餐,并且每天用 4 个蛋给朋友烤松饼。她把剩下的蛋拿到农贸市场卖,每个新鲜鸭蛋卖 2 美元。她每天在农贸市场能赚多少钱?
正确解法是:
总共有 16 个蛋
早餐吃掉 3 个蛋
做松饼用掉 4 个蛋
16 - 3 - 4 = 9 个蛋可以卖
9 * 2 = 18 美元所以正确答案是 18。
基线模型输出
为了确定 Janet 每天在农贸市场能赚多少钱,我们需要按照以下步骤:
1. 计算鸭子每天产多少个蛋。
2. 计算卖蛋得到的总收入。
**步骤 1:计算鸭子每天产多少个蛋。**
Janet 的鸭子每天产 16 个蛋。
**步骤 2:计算卖蛋得到的总收入。**
Janet 每个新鲜鸭蛋卖 2 美元。因此,总收入计算如下:
总收入 = 每天产蛋数 × 每个蛋的价格
代入数值:
总收入 = 16 × 2 = 32
因此,Janet 每天在农贸市场赚 \boxed{32} 美元。base model 给出了错误答案 32。它识别出了产蛋数量和每个蛋的价格,但跳过了减法步骤。它忽略了早餐吃掉的蛋和做松饼用掉的蛋。
这是一个典型的 reasoning shortcut:回答看起来很有结构,但实际计算并不完整。
PPO model output
首先,我们需要计算 Janet 一天总共获得多少个蛋。她每天产 16 个蛋。
接下来,我们计算她一天用掉多少个蛋。她早餐吃 3 个蛋,又用 4 个蛋烤松饼,
所以她一天用掉 3 + 4 = 7 个蛋。
从总产蛋数中减去她用掉的蛋,就得到她卖掉的蛋数:
16 - 7 = 9 个蛋。
她每个蛋卖 2 美元,所以她每天的总收入是 9 × 2 = 18 美元。
因此,她每天在农贸市场赚 \boxed{18} 美元。PPO model 给出了正确答案 18。它在计算收入之前考虑了所有被消耗掉的蛋。
| Aspect | Base model | PPO model |
|---|---|---|
| Final answer | 错误 | 正确 |
| Main error | 跳过减法 | 考虑了消耗掉的蛋 |
| Reasoning style | 冗长但不完整 | 简洁且完整 |
| Format | 包含 boxed final answer | 包含 boxed final answer |
这个例子本身不应该被当作证明,但它展示了与整体结果相同的趋势:RL 训练减少了一些 reasoning shortcut,并鼓励模型完成必要的算术步骤。
讨论
为什么这个设定有利于 GRPO?
GSM8K 是一个 verifiable-reward task。最终答案可以被提取出来并与 ground-truth answer 比较。因此,在这个实验中,无论是 PPO 还是 GRPO,都不需要学习得到的 reward model。
这一点很重要,因为 reward 便宜且直接:
答案与 ground truth 匹配 → reward 1
答案与 ground truth 不匹配 → reward 0在这个设定中,GRPO 有天然优势。它可以对同一个 prompt 采样多个回答,并用基于规则的 reward 对这些回答进行比较。如果一个回答正确而另一个回答错误,group-relative advantage 就可以在不需要 critic 的情况下提供有用的学习信号。
因此在这个实验中,GRPO的 group-relative baseline 对于训练base model的推理能力已经足够。
不过,这个结论不一定能迁移到更困难的设定中,例如:
- reward 很 noisy;
- reward 来自学习得到的 preference model;
- 正确性不能被直接验证;
- 任务需要 long-horizon credit assignment;
- 存在许多部分正确的答案;
- 模型规模大得多;
- 训练稳定性比单次运行的最终准确率更重要。
在这些情况下,PPO 的 critic 仍然可能提供有用的 variance reduction 或训练稳定性。
局限性
这个实验有几个重要局限。
第一,它只使用了一个模型规模:Qwen2.5-0.5B-Instruct。对于更大的模型,结果可能会改变。critic 的作用可能会随着模型规模、batch size、reward quality 和训练稳定性的变化而变强或变弱。
第二,它只使用了一个数据集:GSM8K。GSM8K 包含的是短数学应用题,并且最终答案可验证。这与开放式 helpfulness、instruction following、对话、代码风格、安全性或 preference optimization 都非常不同。
第三,reward 是二元且基于规则的。这让实验比较干净,但也移除了 RLHF 中的许多复杂因素。在真实的 preference-based RLHF 中,reward model 可能并不完美,而 critic 的行为也可能不同。
最后,PPO 和 GRPO 都使用了 rollout.n = 4。这对于公平性是有用的,因为两种方法获得了相同的采样预算,但这不一定是最常见或最高效的 PPO 配置。
Takeaways
- PPO 和 GRPO 都显著提升了 base model。 在 GSM8K 上,base model 得分为 45.19%,PPO 达到 58.83%,GRPO 达到 57.47%,PPO 和 GRPO 的准确率非常接近。
- GRPO 更便宜。 GRPO 训练速度快约 23%,median throughput 高约 33%,原因是它移除了 critic update。
- critic 在这里没有带来明显的可测准确率收益。 在这个小模型、可验证 reward 的 GSM8K 设定中,PPO 学习得到的 value function 并没有带来足够的准确率提升来证明额外成本是值得的。不过这并不意味着 critic 通常都没必要。对于 noisy、preference-based、不可验证或 long-horizon 任务,PPO 的 critic 仍然可能有用。
- 两种 RL 方法都让模型输出更简洁。 base model 平均输出约 297 个 token,而 PPO 和 GRPO 分别平均约 159 和 153 个 token。尽管 reward 只评估正确性,但这种简洁性仍然出现了,可能是因为有限的 response length 会隐式惩罚那些冗长到无法到达最终答案的回答。
总体而言,这个实验表明:对于小型 LLM 在可验证数学推理任务上的训练,GRPO 是 PPO 的一个很强的低成本替代方案。它移除了 critic,降低了训练成本,同时仍然获得了与 PPO 几乎相同的准确率提升。
