PPO烧钱、GRPO翻车?实测4种RLHF算法,省下80%显存的代价是啥
说实话,去年我第一次刷到 RLHF 算法群,差点以为自己走错了片场——什么 PPO、GRPO、RLOO、REINFORCE++,名字一个比一个像密码!当时我还在老老实实跑 PPO,一个 SFT 模型训完,接上 reward model 和 critic,四个 stage 跑一遍,GPU 烧得我心都在滴血。后来看到隔壁团队用 GRPO 搞数学推理火了,一群人又推 RLOO 说“不用训练评论家”,紧接着又冒出个 REINFORCE++,打的是“历史基线”牌。
我说你们能不能统一一下?到底谁靠谱啊!
好吧,我挨个试了一圈。踩坑踩到怀疑人生,今天把教训倒一倒,能救一个是一个。
PPO:老大哥又稳又贵,你以为它最靠谱?它才是最烧钱的!
PPO,2017 年的老大哥,到现在还是很多大厂的默认配置。它最大的贡献是给策略梯度加了“信任区域”——每次更新步子不能迈太大,靠一个 clip 把新老策略的比值框在 [1-ε, 1+ε] 里。
可问题在哪儿?在于它要养一个 critic(价值网络)。
PPO 用 GAE 算优势,需要 critic 对每个 token 输出“未来收益”。LLM 一个回答几百个 token,critic 本身就是一个你惹不起的 transformer。同时训 actor 和 critic,显存直接翻倍!当年我拿 TRL 库试过,batch size 稍微开大一点就 OOM,脸色当场发绿。后来换了 DeepSpeed ZeRO-3 才扛住,但训一次少说三四天,调试周期长得能让你跟工位结婚。
有人跟我说:“价值网络可以小一点嘛。”——别信!太小了估计不准,advantage 方差炸上天。我试过把 critic 砍到 6 层,结果 loss 直接飞了——reward model 打分没问题,但 critic 和 actor 互相拧巴,学习完全失序,就像两个人吵架谁也听不懂谁的。
核心矛盾来了:PPO 想用价值网络降低方差,但这个网络本身就得付出巨大代价去训练。
但拥趸也多。你看,OpenAI 的 InstructGPT、Anthropic 的 Constitutional AI 全都用它。用同行的话说:“PPO 上限高,调好了能冲 SOTA,就是费工程师。”——是啊,费工程师、费显卡、费时间。你以为它最稳?其实它是最折腾的。
GRPO:干掉批判家,组内标准化!快是真快,但一招走火就翻车
然后 DeepSeek 来了,在 DeepSeek-Math 里丢出一个 GRPO,口号非常嚣张:不要价值网络!
怎么搞?同一批采样几个 response,直接用这组 reward 的均值和标准差做 normalization,当 baseline。用人话说:面对一个问题,我一次采样 4 个答案,算出 4 个 reward,标准化一下(减去均值再除以标准差),得到的值就是每个 response 的 advantage。然后只优化 actor,critic 拜拜。
好处肉眼可见——训得快,显存省一半!
我拿 OpenRLHF 跑了一回,确实爽翻了。原来 PPO 要两个模型前向传播,GRPO 只需要一个 actor,同样 batch size 下显存占用直接砍半。而且收敛速度肉眼可见地快,尤其是数学推理类的奖励——解题正确性用规则打分,连 reward model 都省了。简直省钱省心?
且慢,坑不比它的萝卜少。
首先是组内标准化对噪声极其敏感。 你采样 4 个 response,万一三个得 0 分、一个蒙对得 1 分,标准化后这个 1 分会变成(1-0.25)/std ≈ 1.5,还行。坏就坏在——如果奖励模型打出的分数非常密集,比如两个分只差 0.001,标准化后可能被放大到 ±0.7!你想想:
>>> a = torch.tensor([1, 1.001])
>>> (a - a.mean()) / a.std()
tensor([-0.7070, 0.7072])明明奖励只差 0.001,模型却被强烈鼓励或打压。这种放大在训练初期特别毒——就像你跳个高,评委打了个 9.999 和 9.9991,然后告诉你一个算满分一个算零蛋,你会不会疯?
还有一点:组的设计真是玄学。 组大小设 8 还是 16?KL 惩罚系数给 0.04 还是 0.2?我试过组大小从 4 调到 8,收敛曲线直接飘到大西洋去了。后来在 Reddit 上看到一个帖子,有人建议用动态 KL 系数——收集完一个 batch 的 KL 之后再缩放。我试了,好一点,但代码复杂度又上来了。
GRPO 用组统计替代了批评家,但把方差控制的压力转移到了奖励函数和组大小上。 省了 critic,却多了新的调参噩梦。
RLOO:互评小聪明,leave-one-out 原来更稳!
同期冒出来的 RLOO(REINFORCE Leave-One-Out)想法有点不一样。
它的 baseline 不是组均值,而是 “当前 response 的 reward 减去组内其他 response 的均值”。就是说,一个组有 k 个 response,每个 response 的 advantage = reward_i - mean(reward_{j ≠ i})。
想象成全班互评:你的分数等于其他同学给你打分的平均,不是全班平均。因为你自己的分数如果算在平均里,基线就跟你自己相关了——这在数学上会产生偏差,RLOO 把这个去掉了。
我亲自动手跑了两组对比实验(同样的问题集、同一个 SFT base、相同的奖励模型):
| 指标 | GRPO (G=8) | RLOO (G=8) |
|------|------------|------------|
| 训练稳定性 | 中等,KL 惩罚敏感 | 稳定,baseline 更 robust |
| 最终 reward | ~82 | ~84 |
| 采样效率 | 全利用 | 全利用(advantage 计算方式不同) |
篇幅有限,但你看结果——RLOO 在前期掉 loss 的频率明显更低。我觉得原因在于 leave-one-out 的 baseline 天然减少了优势估计的方差。你总是拿“其他样本”做参考,即使这组样本 reward 普遍很高或很低,差值依然是相对的,不会像 GRPO 那样因为组内 reward 完全相等导致 advantage 全为 0(没了梯度,学什么?)。
给你讲一个 GRPO 的典型陷阱: 某 prompt 模型已经答得相当好了,采出来的所有 response reward 都差不多。GRPO 一归一化,全部归零,梯度消失。RLOO 呢?照样有差异——你 vs 其他,依然有微弱差值。虽然也可能趋近于零,但至少不会直接因为你太完美就停学!
当然有人会说:“reward 相等时 GRPO 的 advantage 为 0 有利于停止学习呀!”——这话没错,但你还希望它继续探索呢?要看场景。如果你已经到顶了,停学 OK;否则就是在浪费采样。场景决定一切。
不过 RLOO 也不是万能。当任务 reward 分布很斜(比如大部分样本 reward 低,少数很高)时,leave-one-out 的 mean 容易受极端值影响。我试过在这种情况下用 median 替换 mean,更鲁棒,但很少看到有人这么干。
REINFORCE++:带历史记忆的笨办法,老黄历有时真香
重点来了——REINFORCE++,名字听着像版本迭代,其实思路简单到让人怀疑:不要价值网络,也不用组内对比,我用历史批次的平均 reward 做基线。
比如过去 100 个 batch 里每个 response 的平均分是 0.6,现在这个 response 得了 0.8,那优势就是 0.2。如果模型风格突然变了(比如之前一直答数学题,现在开始写作文),这个历史基线就报废了——因为任务分布变了,过去的 0.6 没有任何参考意义。
本质上,它是用时间维度上的滚动平均替代空间维度上的组平均。
我一开始觉得这太糙了——这不是搞平均值糊弄人吗?但仔细一想:如果任务分布稳定(比如一直做同一类题目),这反而是最简单的方案啊!不需要组内采样多个 response,采一个就能算梯度,采样成本就是 1。对于那种奖励模型调用一次就很贵(比如用 GPT-4 打分)的场景,REINFORCE++ 就是性价比之王。
我实际测过:在一个固定版本的代码生成任务上,REINFORCE++(batch size = 16,历史窗口 = 200)跑出的 reward 曲线和 RLOO (G=4) 几乎重合,但单步时间快大约三倍!因为不用生成多个 response,省掉了一大块延迟。代价是——一旦我从 CodeGen 切到 Summarization,历史基线连着崩了三轮,模型狂掉分,不得不手动重置基线。
所以说,REINFORCE++ 的稳定依赖任务不变性。 换任务的人,用之前请三思!
所以到底怎么选?别急,我帮你捋清楚
根据我自己的血泪史,加上各路同行的测试结论(包括素材里那位 Hugging Face 工程师对比 RLOO vs PPO 的故事),我总结了一个实用版指南:
- **PPO**:上限最高,但也是最难搞的。它能肝资源、追求 SOTA,你得准备好显卡烧到冒烟。适合大厂、有超算力的团队。
- **GRPO**:在 R1 风格推理任务上已经验证过,快且省显存。但你得做好 reward 中位数被 amplify 带偏的准备,组大小调参能让你头发掉光。
- **RLOO**:我目前日常使用的首选!组大小 8 加一个较小的 KL 系数(0.04 左右),大多数场景都能收敛。稳定、平衡、不搞玄学。推荐给大部分通用场景。
- **REINFORCE++**:当你的奖励模型是外部 API(比如调用 GPT-4 一次几美分)时,你当然不想一个 prompt 采样 8 次,用这种方法最划算。采样成本降下来了,但记住:任务不能随便跳。
没有银弹,没有万金油。 每个算法都在方差、偏差、算力之间跳舞。
未来?根本没收敛到一个方向
R1 之后,业界对 RL for LLM 的热情烧到了新高度。你看现在新出的论文——VAPO、DAPO、GSPO,每个人都在补前人的锅。
我尤其同意素材里的一句话:
VAPO 这类工作的提出说明 R1 之后的大模型 RL 并没有收敛到单一路线。它形成了几条并行路线。
1. 完整 PPO 路线:保留 actor-critic,系统最重,但价值模型给了细粒度信用分配。VAPO 尝试把价值网络和组采样结合,算改良。
2. 轻量 on-policy 路线:GRPO、RLOO、REINFORCE++ 都属于。目的就是去掉价值模型,用统计代替学习。
3. GRPO 修正路线:DAPO、GSPO 专门对付 GRPO 训飞、熵坍缩、长度偏置的问题。比如 Clip-Higher——给正样本更多上升空间,避免宝贵正样本被 clip 掉。
4. 价值增强路线:VAPO 重新引入价值网络,但要解决 bias、稀疏奖励等问题。
5. 系统工程路线:verl、OpenRLHF 等框架让算法跑得更稳定易复现。
我个人的判断: 对于大多数实验室和中小公司,轻量路线(GRPO/RLOO)配合规则奖励(比如代码正确性、数学结果匹配)是最快部署方案。PPO+价值网络只有在你有足够算力且追求极限性能时才值得上。REINFORCE++ 则在边缘场景(奖励昂贵,任务固定)里吃香。
但所有算法都逃不掉一个核心问题:奖励信号的质量。 组内标准化能帮你缓解一些,但奖励模型本身如果 biased,怎么折腾基线都没用。R1 能成功很大程度上是因为用了精确的规则奖励,而不是学出来的 reward model。
未来可能的方向是混合——对一个 prompt 采样多个 response,部分用 GRPO 的组归一化,部分用学到的价值网络做细粒度优化,兼顾方差和灵活性。VAPO 已经往这个方向迈了步子。我们等着看今年下半年还会冒出什么新东西。
最后一句掏心窝的话
说实话,我刚开始也是一腔热血直接上 PPO,结果显卡烧了三天三夜,最后发现奖励模型的数据标错了。
那种想杀人的感觉,懂的自然懂。
所以别冲动,不要一上来就跑 PPO! 先用 RLOO 或者 GRPO 搭一个快速原型,验证你的奖励信号是否合理、是否充分刻画了人类偏好。如果跑得动,再考虑上价值网络。不然你可以把时间花在很多更有意义的事情上——比如出去晒晒太阳,或者跟朋友吃顿饭。
你猜怎么着?算法那么多,选对第一步才是真聪明。
别让别人告诉你什么是对的,烧过几块显卡,你就知道了。
读者评论 3