RLVR 及其裂缝:可验证奖励到底教会了什么
RLVR 是我们对推理模型所能拿到的最好训练信号,也是最可能对我们撒谎的那个。这套说法很诱人:丢掉学习的奖励模型,用程序检查答案,奖励就没法再被钻空子。三篇论文——分别来自 2025 年 4 月、2025 年 6 月和 2025 年 10 月——从相反的两端各自在故事里找到了一道裂缝。随机奖励几乎贡献了一个流行数学模型家族的全部增益。单个训练样例也贡献了大部分增益。而当验证器自己标错时,循环在安静地拿噪声训练。
其中一种失败模式我在自己的训练运行里验证过,用的是一条用随机奖励付给模型的对照臂。第二种我在它咬人之前就做了防御性工程:我的验证器记录可枚举的逐样本失败类别——parse_failure、execution_error、executable_not_full_pass——所以验证器的一次漏判会以带标签的类别出现,而不是无声的噪声。第三种我是从一次复现得知的,而不是伤疤。它们收敛到同一个结论:RL 循环不再是瓶颈,验证器才是。这篇文章精读三篇论文,然后走一遍我在 VerifierForge 上跑过的对照臂——它把第一篇论文的警告变成了一个具体的数字。
领域地图
RLVR 用确定性检查取代奖励模型。pipeline 很小:
policy samples -> programmatic verifier -> binary reward -> GRPO update
GRPO 主导这个家族,因为它去掉了 critic:奖励对同一提示词的一组样本做归一化,策略用一个带裁剪的替代目标更新。它便宜、能扩展,也是如今大多数开源后训练运行在用的东西。我在我的 GRPO 笔记 里讲过这个家族谱系,所以这里我只需要与裂缝相关的部分:裁剪项、组归一化,以及验证器是循环里唯一真值来源这一事实。
RLVR 强的地方非常强。数学和代码有精确、便宜可查的答案,奖励信号足够稠密,Qwen2.5-Math 这一系的模型爬升很快。它被拉伸的地方,恰好是验证器变得模糊的地方:agentic 任务、长程轨迹、开放式写作。这不是巧合。让 RLVR 在数学上奏效的仪器,就是它在别处失灵的那个,而 agentic RL 继承了这篇文章里的每一道裂缝。
我在意的三道裂缝:
- 虚假奖励:奖励不携带任何信息,梯度依然在动。
- 有噪验证器:奖励有部分时间是错的,而且是无声的。
- 极端数据稀缺:一个样例就够了,这对着梯度到底在做什么说了些很深的东西。
精读:虚假奖励
Spurious Rewards: Rethinking Training Signals in RLVR(Rulin Shao 等人,2025)是那篇我希望每个 RLVR 从业者在第一次训练运行前都读过的论文。头条结果:在 Qwen2.5-Math-7B 上,用随机分配的奖励做 GRPO 训练把 MATH-500 提高 21.4 个百分点,几乎追平真值奖励带来的 29.1 个点。
随机奖励。模型在拿噪声付酬的同时在一个数学 benchmark 上变好了。
机制:GRPO 的裁剪替代目标带着一种偏差,即使奖励零信息,它也能放大模型从预训练中就已经偏好的行为。裁剪项本应通过封顶重要性比率来稳定训练,但封顶是不对称的:它限制更新能多用力地推动策略已经偏爱的样本。奖励有信息时,这种不对称无害甚至有用;奖励随机时,它就是更新里剩下的全部,于是策略漂向它本来就常做的事。论文的案例研究是一种他们称为代码推理的行为:把解决方案写成代码而不执行它。在虚假奖励下,它在 Qwen2.5-Math 模型里的出现频率从 65% 爬到 90% 以上。模型不是在学数学。它是在学着更用力地靠向基础模型原本就有的一个习惯。
对任何用验证器训练的人来说,有两个后果要紧。第一,效应依赖模型:同样的虚假奖励设置在 Llama3 或 OLMo2 上不产生增益。一个模型家族上的 RLVR 正结果只是关于那个家族本身的证据——这正是论文的收尾论点:在多样化的模型上验证 RL 方法,而不是只在一个事实上默认的选择上验证。第二,benchmark 增益不是能力增益。在损坏的奖励下 MATH-500 的提升是红旗,不是胜利。
这就是为什么我把对照臂视为不可谈判项,也是为什么下文我自己的工作中会存在 M3/M4 比较。
精读:单样例 RLVR
Reinforcement Learning for Reasoning in Large Language Models with One Training Example(Yiping Wang 等人,NeurIPS 2025)从另一头进攻这个问题:你最少需要多少信号?答案:一个样例。
用单个精挑细选的数学问题训练 Qwen2.5-Math-1.5B,把 MATH-500 从 36.0% 抬到 73.6%,比纯格式修正买到的多出 8.6 个点,六个数学 benchmark 的平均分从 17.6% 抬到 35.7%。一个样例追平 1.2k 样例的 DeepScaleR 子集:MATH-500 73.6%、平均 35.9%。两个样例勉强超过它:74.8% 和 36.6%。结果跨模型家族成立,包括 Qwen2.5-Math-7B、Llama3.2-3B-Instruct 和 DeepSeek-R1-Distill-Qwen-1.5B,也同时跨 GRPO 和 PPO 成立。
三个现象让这篇论文值得精读。饱和后泛化:训练准确率饱和后测试性能继续提升——这是记忆训练答案之外的东西的标志。跨类别泛化:单个样例提升了自己不属于的类别。以及那个消融:增益来自策略梯度损失,而不是 grokking 式的表示动态。论文还报告了关于标签鲁棒性和提示词修改的观察,值得带着有噪验证器的问题来读:即使是 oracle 式标签也不像看起来那么干净。
我想强调的是探索这个角度。作者们表明,促进探索——例如带正确系数的熵损失——对单样例训练能否奏效至关重要。只有一个样例时,梯度是单一的有噪方向;如果策略坍缩到它上面,你只学到一种行为。如果组保持多样,你得到一个持续有回报的搜索过程。搜索对模仿这个区分就是全部的游戏,也是决定一次 RLVR 运行在任何数据规模下能否泛化的同一个区分。
我在我的 paper-reproductions repo 里复现了这个结果,那里把它列为 NeurIPS 2025 论文,官方议程也确认了。为什么要在单样例结果上花一次运行?因为它是检验验证器是否携带信息的最便宜的探针。如果在你的验证器下模型无法从单个样例改进,再多数据也救不了这个循环。裂缝和机会是同一个对象。
精读:有噪验证器
RL with Verifiable yet Noisy Rewards under Imperfect Verifiers(2025)进攻另外两篇论文留着的那个假设:验证器是对的。它不是,而论文把这对训练的影响形式化了。
这个设定把验证器建模成一个带两个不对称噪声率的随机奖励信道:假阳性率 ρ0——接受错误答案;假阴性率 ρ1——拒绝正确答案。两者在实践中都很常见。对格式化输出做精确匹配的评分器会持续制造假阴性。比任务更窄的程序化检查会制造假阳性。无论哪种情况,二元奖励都有部分时间是错的,而策略把错误当真值来训练。
论文推导出两个轻量修正,实现为 GRPO pipeline 里的 hook。后向修正产生无偏的替代奖励,因此在期望上是无偏的策略梯度估计量:你可以像验证器是干净的一样训练。前向修正重新加权 score-function 项,使期望更新对齐干净梯度方向,而且它只需要假阴性率。两者都在合成与真实的验证器噪声下改进数学推理,噪声大时前向变体更稳定。
对我最有用的部分是申诉机制:一个轻量级 LLM 验证器重新检查被拒绝的样本,在线估计假阴性率,这个估计再喂给修正。它把「我的验证器有多错」从一种感觉变成一个可测量、持续更新的数字,而且很便宜,因为只有被拒绝的少数样本会被重新检查。
Takeaway: 有噪验证器不是避开 RLVR 的理由。它是给验证器加埋点并修正奖励的理由,就像你在信任任何测量设备的读数之前会先给它加埋点一样。
我的立场:我会造什么
把三篇论文并排放在一起,一幅一致的图景浮现出来。奖励是一种测量,不是真值。它可能是空的、近乎空的,或者错的,而在每种情况下循环都尽职地把它们变成梯度。循环做它被告知的事。你得到的产出被验证器约束,也被你能否分辨真正的增益与裁剪先验的伪影约束。
所以我会造、也确实造了的,是一个 验证器优先的训练栈,分三部分。
第一,把验证器审计作为标准步骤。任何运行之前,在带标签的留出集上估计假阳性与假阴性率,训练期间用申诉式采样器重新估计。把 ρ0 和 ρ1 挂在墙上、损失曲线旁边。漂移的验证器是漂移的奖励最早的警报。
第二,默认修正奖励。有噪验证器论文里的前向修正作为 hook 几乎免费,它消除了一整类无声的训练 bug。如果你的验证器拒绝正确答案——它确实会——那你现在就是在用有偏的估计量训练。
第三,训练循环内的对照臂。虚假奖励论文展示了危险;修法很便宜。保留同一次运行里的随机奖励臂和验证器奖励臂并比较它们。如果它们收敛,你的验证器没在干活,你的 benchmark 数字无论看起来多好都可疑。
还有一个设计要点。有噪验证器论文指出,许多 RLVR 系统把奖励二值化,恰恰是为了减少验证器作弊,而它形式化了这要付出的代价:信道坍缩成接受或拒绝,只剩两个噪声率。当验证器能说的不止是或否——例如像 VerifierForge 那样逐层打分——保留那层中间结构通常是值得的。边际处的信息才是把「教东西的奖励」和「只会排序的奖励」分开的东西。
单样例结果加上效率这一层后果:有了好验证器,你只需要很少数据,所以值得优化的循环是验证器反馈周期;数据 pipeline 可以保持很小。一个你信任的、又快又对的验证器,比再多一万个样例更值钱。这个权衡在 agentic 场景里变得更尖锐——那里真值检查几乎不存在,验证器问题更严重。我在我的 agentic RL 笔记 里写过这个。
我实际做了什么:VerifierForge
这个立场不是假设。VerifierForge 是我八天搭出来的训练 harness——核心循环独自完成,一位队友负责 UI 和演示视频——在线 web demo 在 verifierforge-web.vercel.app。你交给它一个程序化验证器;它用 GRPO 对着它训练一个小模型。旗舰评测是 SQL 补全,验证器逐层给回答打分:
extract -> parse-guard -> execute -> compare
分层形态对付噪声问题是对的本能:每个阶段是一道便宜而精确的门,信道因此保持干净,而不是信任一个黑盒裁判。每个样本都落入一个被记录的失败类别——解析失败、执行错误、可执行但未完全通过——所以验证器做了什么可以逐样本审计;什么都不留给感觉。冻结的 60 行留出考试上的结果:独立 pass@1 从 0.583 到 0.783,+20pp 增益,pass@8 从 0.767 到 0.900。
鉴于以上所有,我最在意的检查是证伪臂。我在同样的任务和冻结训练池上跑了一个虚假奖励对照:一条随机奖励运行(M4),用从不可变输入哈希导出的确定性 Bernoulli(0.5) 奖励付酬,与验证器奖励运行(M3)并列。这个不对称值得大声说出来,因为 repo 自己就说了:M3 是训练 400 步的 Qwen2.5-1.5B-Instruct,M4 是训练 200 步的 Qwen2.5-0.5B-Instruct,所以奖励不是唯一改变的变量。repo 自己的框架是对的:一次有用的证伪检查,不假装是严格因果实验,两条训练池曲线也都不是质量主张。这条臂展示了什么:M4 的训练池监视器在 0.4 到 0.5 之间来回摆动,收在 0.40,而 M3 收在 0.80。这里有一个需要对齐的地方:0.80 是 50 行训练池上的逐步监视器,与产生上面 0.783 的冻结 60 题留出考试是不同的仪器。而 M4 根本没有留出考试,这是设计使然。这个对照排除掉的东西很窄但值得拥有:验证器奖励的曲线不是无奖励运行会做的事。质量主张落在留出考试上,不在比较上。
那次构建的两道伤疤比头条数字更值钱。第一,一个隐藏的 total_epochs=10 默认值在第 120 步杀死了我第一次 400 步的运行:外层循环在 12 × 10 = 120 步结束,什么都没崩溃,运行只是看起来完成了。修法是一个配置护栏(trainer/grpo_config.py:185-194),在训练开始前,如果 total_epochs 会把运行封顶在批准的步数目标之下就抛出异常——它杀死的那类 bug 是无声的那种,配置版的虚假奖励。第二,checkpoint 选择。八个 checkpoint 全部考了同一份冻结的 60 题考试;第 350 步以 pass@1 0.783 胜出,而最后一步 400 掉到 71.7%。所以发布的 checkpoint 是验证过的最好的那个。我不发布最后一步。
我也在我的 paper-reproductions repo 里复现了 One-Shot RLVR,那个单样例结果。重点不是 benchmark 数字。是探针:验证器携带真实信息时,单个样例应当能推动模型。如果不能,问题在上游,在奖励里,加数据也修不好。
值得为之做工程的裂缝
这些都没有让 RLVR 变得不那么有吸引力。它让它变得精确。奖励信道是栈里你真正能改进的那一部分:在重要的地方把验证器做严格,测量它的噪声率,修正它的偏差,跑一条证明信号真实的对照臂。做到这些,下面的循环大多会自己照顾自己。
本文中链接的来源均已抓取并验证。