介绍 POPO:一个即插即用的简单方法,无需额外生成任何样本,就能让 RLVR 的每个训练批次都装满有效数据。
可验证奖励强化学习(RLVR)就像一位极有耐心的家教。给模型一道题,让它尝试 k 次,逐一判对错,再引导它向“比平均水平更好”的回答靠拢。GRPO 把这件事写成优势函数:每个回答的奖励减去组内均值,再除以组内标准差。
现在设想一道模型每次都能做对的题,或者一道它从来做不对的题。每次尝试得分都一样,这组回答里不存在“比平均更好”,所有优势值都是零。模型花了大量 GPU 时间写出八条长长的思维链,却什么也没学到。
亲手试试:点击下面的回答,在对错之间切换。
这并不是个别现象。论文实验显示,原始 GRPO 训练批次中有效组的比例通常不到一半。无论是数学(DeepScaleR)、算术规划(Countdown)还是视觉几何都是如此。而且随着模型变强,更多题目会变成“全对”的简单组,问题会越来越严重。
多 rollout 一些题目,丢掉零方差的,不断重复直到凑满一个批次。
代价:额外 rollout 的开销可能比 RL 更新本身还大。
在 rollout 前预测哪些题目是“中等难度”,例如 MoPPS、GRESO。
代价:模型在不断变化、每道题历史数据又少,预测很难做准。
往全错的组里塞一个历史上的正确答案,例如 ARPO。
代价:全对的组依然无效;组内混入不同策略的回答,会让优势估计失真。
想象一位足球教练,他有一条铁律:场上每个位置都必须由真正能踢的人来填。首发球员临场受伤时,他不会去街上现拉一个陌生人,那相当于 DAPO 的额外 rollout。他也不会硬塞一个半伤不愈的球员凑数,那相当于轨迹回放。他会换上上一场刚踢得不错的替补。
这就是优先组回放,它遵循两条规则:
为什么“新”能代表“接近当前策略”?PPO 式裁剪让每一步更新都很小。因此两个策略之间的差距,按总变差距离衡量,最多随间隔步数线性增长:相隔 n 步时不超过 εn/2。所以新鲜度就是一个免费的相似度代理,完全不用计算 KL 散度。
两个细节让它既便宜又干净。第一,缓冲区最多只存一个批次的组,内存开销几乎可以忽略。第二,由于是整组回放,组内每条回答都来自同一个策略。这样组内优势依然定义良好,生成数据的行为策略也是确定的,而这一点对下一步至关重要。
回放组是由一个较旧的策略生成的,记作 πβ。如果直接假装它是新数据,梯度就会有偏差。已有工作有两种处理方式,POPO 采取了第三种。
✗ 只要 πβ ≠ πold 就有偏
消融实验中直接崩溃。
✓ 无偏
✗ 把模型拴在一个更差的策略上,而且每个回放样本拴的位置还不一样。裁剪触发过于频繁。
✓ 无偏:第一个因子负责校正分布
✓ 与在策略数据同一根“缰绳”:裁剪始终锚定 πold
关键技巧在于:完整的重要性比率 πθ/πβ 可以拆成两个因子,各司其职:
橙色因子校正数据从哪里来。蓝色比率决定这一步最多能走多远,它使用的信任域与新鲜数据完全相同。
论文证明:在两个比率都未被裁剪的位置,该目标与完整校正的 πβ 版本给出完全相同的值和梯度。唯一的区别是缰绳拴在哪个策略上。这就像一个导航仪:它会考虑地图是在哪里绘制的,但下一次转弯永远从你此刻所站的位置算起。
校正过去,锚定当下。
落到代码上,POPO 只多了一个过滤、一个小队列和一次乘法:
buffer = FIFO(capacity=B) # 存储组及其 rollout 时的对数概率 for step in range(T): groups = rollout(policy, sample_prompts(B), k) # 与 GRPO 成本相同 on_eff = [g for g in groups if std(g.rewards) > 0] # 丢弃无效组 off_eff = buffer.newest(B - len(on_eff)) # 用最新的组补满 loss = grpo_loss(on_eff) w = exp(logp_old(off_eff) - off_eff.logp_beta).clamp(max=2.0).detach() loss += (w * grpo_token_loss(off_eff)).aggregate() # 解耦校正 optimize(policy, loss) buffer.push(on_eff) # 存入本步的有效组
实际实现中,论文还将重要性权重 w 截断在 2.0 以内,以抑制罕见的离群值。论文未观察到由方差引起的不稳定。
POPO 的对比对象包括 GRPO、DAPO(昂贵的“金标准”)、MoPPS(预测式采样)和 ARPO(轨迹回放)。实验覆盖四种设置:Countdown 上的 Qwen2.5-3B、Geometry3k 上的 Qwen2.5-VL-3B,以及 DeepScaleR 数学数据上的 DeepSeek-R1-Distill-Qwen 1.5B 与 7B。
规律在所有设置中都成立:POPO 与 DAPO 持平或非常接近,并明显领先 GRPO、ARPO 和 MoPPS,而开销却与原始 GRPO 相近。相比 GRPO 略多的训练时间其实是个好信号:POPO 训练出的模型会写出更长的推理链,趋势与 DAPO 一致,而更长的推理被认为与更强的推理能力相关。
几个值得细看的亮点:
POPO 的每个部件都不可或缺。下面是在 Countdown 上去掉或替换各个部件后的结果:
准确率相当,但更慢:4.8 小时对比 3.2 小时。新鲜度是免费且有效的距离替代指标。
只比 GRPO 略好。批次变小会让梯度更嘈杂,所以关键在于补满批次。
性能明显下降,说明质量过滤很重要。
直接崩溃。而 1 倍随机缓冲区只是略差,说明新鲜度很重要,但 POPO 对新鲜度的小幅变化并不脆弱。
学习变慢,这正是“缰绳拴在过去”问题的体现。
由于偏差未被校正,性能崩溃。
POPO 是一个插件,而不是一套全新的算法,论文也正是这样测试它的:
只记住最近一个批次的缓冲区是刻意“健忘”的。它放弃复用更早但可能有价值的组,换取更小的离策略差距,也不会刻意挑选最有信息量的组。作者提出了一个未来方向:短期缓冲区加上一个小型长期“蓄水池”,用来保存特别有价值的组。他们还建议每步生成更少的新 rollout,更多地依赖回放。此外,零方差判定假设奖励是二值(或近似二值)的。对于连续奖励,可以改用低方差阈值。
生成是 RLVR 中最昂贵的环节,而其中相当大一部分却因零梯度组被白白浪费。POPO 的解法小巧得令人耳目一新:保留上一批次的有效组,替换掉今天的无效组,再乘上一个重要性权重,让数学保持严谨。回报是:以 GRPO 量级的 rollout 预算,得到 DAPO 级别的结果。
批次里的每一个位置都应该教会模型一点东西,而做到这一点不应再多花一次 rollout。