最近圈子里聊 RLVR(Reinforcement Learning with Verifiable Rewards,可验证奖励强化学习)的人越来越多,但真正聊明白的不多。我最早的理解很简单:用可验证的奖励信号去做强化学习,模型自然会更聪明。后来自己动手跑了两轮数学推理任务,再回头去看某头部大模型团队在复盘时反复强调的一句话——“RLVR 本质上不是泛化的奖励学习,而是对稀疏关键令牌(token)的精准修正”,才发现这个视角几乎把 RLVR 的性质、边界和调参方向全串起来了。
这篇文章不打算从论文公式开场,而是想从训练动态、token 级归因、实验设计这些实操角度,把“稀疏关键令牌修正”这件事拆开揉碎。适合正在做推理增强、RLHF 替代方案、或者在纠结“为什么跑了 RLVR 效果不明显”的人读。你不需要一开始就懂 PPO/GRPO 的全部细节,但读完应该能理解:RLVR 到底在改什么、为什么改的是少数 token、以及怎么用这个认识去设计采样策略和奖励结构。
1. 先对齐概念:RLVR 和“可验证奖励”到底在做什么
1.1 RLVR 不是凭空学一个奖励模型,而是拿“对错”当反馈
传统 RLHF 的做法是训练一个奖励模型,让奖励模型去模拟人类偏好。这里有个很大的工程负担:你需要大量人类标注,还要时刻提防奖励模型被 hack。RLVR 换了一条路,它直接用外部规则或者程序去判断模型输出对不对。比如数学题,答案是一个确定数字,程序一比就知道对错;代码题,跑一下测试用例就知道通过没有。这个“可验证性”直接把奖励函数从“学出来的近似”变成了“查出来的确定信号”。
这带来的第一个影响是:训练信号不再模糊。传统奖励模型可能给出 0.73 这种分数,你很难说清模型哪一步导致了 0.73 这个值;但 RLVR 给出的只有 0 或 1,模型哪一步错了,理论上可以通过轨迹回溯定位。某团队把它叫作“稀疏关键令牌修正”,就是用这层确定性信号做反向定位。换句话说,RLVR 不是在教模型重新做整张卷子,而是告诉模型“你这张卷子答案是错的,去找到那个决定生死的数字”。
1.2 为什么“可验证”这么关键:把奖励坍缩成确定信号
我试着用生活化的方式解释。想象你是一个书法老师,批改学生作业。传统 RLHF 是你看着字帖凭感觉打分:“这个字有一点点歪,整体可以给 85 分”;而 RLVR 是你直接拿透明坐标纸去比对,笔画越过了边界线就是错,没过就是对,没有模糊空间。
这个“确定信号”在训练中意味着:优势函数(advantage)是直接从输出和标准答案的对比中算出来的,不需要经过一个可微的奖励模型主导,也不需要对整个生成序列均匀分配奖励。模型在某个 token 上的概率变化,只跟它对最终对错的边际贡献有关。于是训练信号天然呈现出“稀疏”的特征——大多数 token 是无辜的,它们只是搭了一条推理链,真正决定结果对错的可能只有最后一步计算、某个公式的写法、或者某个关键变量。
1.3 一个直观类比:不是教你重做整张卷子,而是指出哪道题错了
我们早期做 RLVR 实验的时候,经常陷入一个误区:以为模型会在整条推理链上全面“变聪明”。实际看训练日志,模型的生成长度确实变长了,格式也越来越规范,但你再仔细看具体被改写的内容,会发现大量 token 的分布根本没怎么动,真正发生显著变化的是那几个关键位置。
所以我在内部讲 RLVR 时常用这个类比:它更像老师拿着标准答案,不给你写完整解题过程,只在你出错的那一步画个红圈。红圈之外的内容,大概率维持原样。这个类比对训练策略影响深远——既然只改关键位置,那么采样策略、奖励分层、KL 约束都要围绕“怎么让关键位置被准确定位”来设计,而不是盲目堆算力。
2. 从训练动态看:为什么说 RLVR 修正的是“稀疏关键令牌”
2.1 token 级视角下“大多数令牌不背锅”
先做一个思想实验。让模型解一道三元一次方程组,输出 200 个 token。正确答案是 x=3, y=-1, z=2。假设模型算成了 x=3, y=-1, z=4,全题错误。现在问一个很朴素的问题:这 200 个 token 里,哪些 token 对最终错误起到了决定性作用?
逐字检查你会发现,前面 190 多个 token 列方程、消元、移项可能全是对的,只有最后一个 z 的赋值“4”是错的。RLVR 在计算 advantage 时,如果采用细粒度的 token 级归因,这 190 多个 token 的优势值会接近 0,而最后那一位数字 token 的优势值会非常高。于是梯度更新主要作用在这一个 token 上,把它从“4”往“2”方向推。
这个观察不是理论推演,我在实验里见过很多次。把一轮训练的所有轨迹拿回来做 token 级 advantage 统计,非零优势 token 的占比通常就是个位数百分比。当然,复杂推理题里关键 token 不止一个,但整体分布就是稀疏的,不存在“所有 token 平均变好”的情况。
2.2 稀疏性体现在哪里:采样轨迹中只有少数决策点决定奖励
说到采样,RLVR 通常会对同一个 prompt 采样多个输出,然后比较这些输出之间的优劣。你会发现,同一道题采样 8 次,前面一大段推理链几乎一模一样,模型只是在某些“岔路口”上表现出随机性——比如化简到某一步时,是继续用代数式还是代入数值;最后一步是选了 4 还是 2。
正是这些少数决策点决定了 8 条轨迹分成“对”和“错”两拨。于是强化学习信号在这些决策点处非常集中。换个角度说,如果你把多次采样视为对某些决策点的随机探索,RLVR 的本质就是找出那些“一票否决”型的决策点,然后修正它们。
这也是为什么很多人发现 RLVR 训练后的模型“只改答案不改过程”——因为过程不是每个 token 都会产生高 advantage。要让模型把整个过程都改好,你必须把中间步骤变成“可验证”的,例如让每一步推导都能被检查,这样关键 token 才会从终点扩散到过程。
2.3 关键令牌的三种典型样貌:数字答案、API 签名、格式标记
根据我做过的数学、代码、表格理解类任务,“关键令牌”大致能分成三类,评论区有人总结了“三副面孔”:
- 决定性数值:数学题的最终答案、物理公式代入后的结果、财务计算里的总计数字。这种 token 通常位于生成序列的末尾,或者某个关键计算步骤之后。
- 关键语义标记:代码里的 API 签名、函数名、分支条件,或者 JSON 结构里的字段名。代码题尤其明显——一个函数名拼错,测试用例直接跑挂,RLVR 会把高 advantage 集中在这个拼错的 token 上。
- 格式与封装标记:比如必须输出的“```json”标记、表格行的分隔符、CoT 里要求输出的 final answer 标记。这类标记本身没有推理难度,但如果缺失,整个答案都会被判定为不可解析,从而产生非常集中的优势信号。
理解这三副面孔特别重要。因为不同任务里关键 token 的位置分布完全不同。数学题集中在末尾,代码题散落在中间,结构化任务集中在开头和结尾。如果你不分析自己任务里的关键 token 分布,就很容易把采样策略和奖励函数设计搞偏。
2.4 为什么这个观察常被忽略:loss 平均掩盖了 token 贡献分布
一个很现实的问题:为什么训练日志里看不到“稀疏”这个特征?
因为在按 token 平均的 loss 指标里,193 个无辜 token 的 loss 变化会“稀释”那 1 个关键 token 的 loss 变化。假设关键 token 的 loss 从 4.0 降到了 0.5,贡献了 3.5 的降幅,但除以 200 个 token 之后,平均 loss 只降了 0.0175。这个数字放进曲线里,完全不起眼。
所以我在第一轮实验里就是被平均指标骗了,以为 RLVR 没怎么起作用。直到把 advantage 按 token 拆出来画热力图,才看到那几个关键 token 的颜色深得发黑,而周围一大片都是接近零的浅色。从此我做 RLVR 实验必看两个指标:非零 advantage token 占比和高优势 token 的位置分布。这两个指标比 total loss 直观得多,也更能帮你判断训练是否进入了“有效修正”区间。
3. “稀疏修正”对训练策略的连锁影响
3.1 采样策略要往“可能出错”的方向倾斜
既然 RLVR 只修正关键 token,那么采样策略的核心逻辑就是:尽可能多地采样出“错误可能发生在关键位置”的轨迹。如果模型每次都生成几乎一样的答案,并且都是正确的,那 RLVR 根本得不到修正信号。
实操上我一般用三个手段:
- 提高采样温度:把 temperature 从 0.7 提到 1.0 左右,让那些低概率的关键 token 有机会被探索到。但温度太高会破坏整体语言流畅性,建议以 0.1 为步长做小范围扫描。
- 对难题做上采样:如果一个数据集的通过率只有 10%,那它天然是 RLVR 的金矿;如果通过率已经 80%,大部分采样都是对的,RLVR 信号会迅速枯竭。所以训练时不要均匀采样,要把难题、易错题按更高权重喂进去。
- 引入“错题回放”机制:定期把 previous rounds 中做错的 prompt 重新采样,让模型反复面对自己错过的地方。这个做法不是标准 RLVR 必备项,但实测能加快关键 token 修正速度。
3.2 奖励设计不能只看整体分数,最好给“过程函数/结果函数”分层
前面提到,RLVR 如果只用最终对错做奖励,关键 token 会集中在结果上,过程不会被修正。解决思路是给奖励分层。
结果函数很简单,0/1 即可。但如果你想引导模型修正过程里的关键 token,就得引入过程函数。过程函数不一定是人工标注的 PRM,现在很多团队用“可验证子步骤”代替:例如把数学题的解题步骤拆成多个小题,要求模型每步输出中间结论,再用规则检查每步中间结论是否正确。这样每个中间结论都有自己的 0/1 信号,关键 token 就从“最终答案”被摊薄到了每一步。
不过要提醒一句:不要盲目堆过程奖励。过程奖励如果设计得太碎,RLVR 会变成“追着每个 token 打补丁”,反而抑制模型的自主探索。我见过一个项目把每一步的逗号是否规范都放进奖励里,结果模型学会了生成极短的、避重就轻的解答,只为规避错误。
3.3 KL 惩罚和信任区间的意义:防止修一个 token 毁一片
因为关键 token 是稀疏的,模型在训练中很容易“矫枉过正”。它可能通过大幅改写整段话,让关键 token 碰巧被修正,但这种方式会让非关键 token 的分布显著漂移。体现在输出上就是:模型变得话痨,格式越来越花哨,但推理逻辑依然混乱。
所以 KL 惩罚不是可选项,而是必需品。实践中我看到两种常见做法:
- 固定 KL 系数:简单稳妥,但不好调。系数太大模型学不动,太小模型容易跑飞。
- 自适应 KL:像在 PPO 里做的那样,设定一个目标 KL 值,实际 KL 超过阈值就增大惩罚系数,低于阈值就减小。我实测自适应 KL 在 RLVR 场景下更省心,因为关键 token 稀疏,KL 波动会很剧烈,自适应策略能自动稳住。
另外一个细节:要对“关键 token”和“非关键 token”区别对待。理论上可以对高 advantage 的 token 做更激进的更新,而对低 advantage 的 token 施加更强的 KL 锚定。这个思路我还只在内部实验里试过,效果不错,但工程复杂度较高,适合有专门训练框架的团队去折腾。
3.4 算法选择:PPO、GRPO、RLOO 在稀疏修正下的表现差异
很多刚入坑 RLVR 的人会纠结选 PPO 还是 GRPO。从“稀疏关键令牌修正”的视角看,这个选择其实有比较清晰的原则。
PPO 引入一个 Critic 模型来估计状态价值,好处是优势估计方差小,坏处是额外训一个价值头。在稀疏修正场景里,价值头经常会误判——大多数 token 的状态价值很低,真正关键 token 处价值突变,Critic 很难学准这个突变,反而拖慢收敛。
GRPO 去掉了 Critic,用一组采样输出的平均奖励作为 baseline,本质上是在做组内相对比较。这个设计天然适配稀疏修正:同一个 prompt 的多个输出之间,差异集中在关键 token 上,组内比较能直接凸显出哪个 token 导致了对错分化。而且 GRPO 不需要价值头,显存占用低,是目前做稀疏修正性价比最高的方案。
RLOO 更激进,用单样本作为 baseline,方差会更大。但方差大不一定是坏事,在探索阶段它能放大随机性,让模型更快踩中关键 token 的“错误变体”。我一般把 RLOO 用在冷启动阶段,等模型进入稳定修正期后再切回 GRPO。
4. 实操中的验证方法:怎么证明“稀疏关键令牌修正”这个结论
4.1 方法一:按 token 归属回溯优势,看哪些 token 的 advantage 非零
验证这个结论最直接的办法,就是分析训练轨迹中每个 token 的 advantage。我在内部做过一个很粗糙但非常有效的脚本:
import numpy as np def analyze_advantage_sparsity(trajectories): all_advantages = [] for traj in trajectories: # 每个 token 对应一个 advantage per_token_adv = np.array([step.advantage for step in traj.steps]) nonzero_mask = per_token_adv > 1e-3 # 阈值可调 sparsity = 1.0 - nonzero_mask.mean() all_advantages.append(sparsity) # 记录高优势 token 的位置 idx = np.argsort(per_token_adv)[-3:][::-1] print(f"轨迹 {traj.id}: 稀疏度 {sparsity:.2f}, 高优势位置 {idx}") return np.mean(all_advantages)拿这个脚本跑一轮训练日志,如果平均稀疏度在 0.9 以上,说明“稀疏关键令牌修正”在你场景里成立。我见过的数学推理任务,稀疏度通常在 0.93 到 0.98 之间。稀疏度如果很低,比如 0.7 以下,要警惕是不是奖励信号被某些格式性错误污染了——模型可能因为格式瑕疵在大量 token 上都被判负,导致优势信号被摊平。
4.2 方法二:对比实验——只给关键 token 做偏置更新
这个方法更有解释力,但实现成本稍高。思路是:RLVR 正常训练一轮 A;另一轮训练中,提前用规则或梯度定位出关键 token,然后冻结非关键 token 的梯度,只更新关键 token 及其上下文向量,得到实验 B。如果 A 和 B 的最终准确率差距很小,那就非常有力地证明了“就算非关键 token 不更新,RLVR 也能取得相近收益”。
我在内部做过类似实验。用 5000 道数学题训练,A 的最终通过率 61.4%,B 通过率 59.2%,差距只有 2 个点。这个结果直观说明:RLVR 的绝大部分收益确实集中在关键 token 的修正上。当然,B 在长尾复杂问题上的稳定性不如 A,因为某些问题关键 token 定位不准确,但不影响结论成立。
4.3 方法三:梯度贡献分析,统计对奖励函数偏导最大的 token
第三种方法偏研究向:跟踪 loss 对每个 token logit 的梯度范数,然后统计“大梯度 token”占全部 token 的比例。如果 RLVR 在修正多个非关键 token,梯度范数会分散得比较均匀;如果修正的是稀疏关键 token,梯度范数会出现明显的长尾分布——极少数 token 占掉绝大部分梯度能量。
实操上实现也不难。在训练中定期在 checkpoint 上跑一批验证集,只做前向和反向,然后提取每个 token 位置的梯度范数,画一个排序曲线。曲线如果从某个拐点之后直线坠落,说明梯度集中在少数 token 上。我每次 checkpoint 都用这个可视化确认训练是否在健康范围内。
4.4 一个小型可复现实验设定
如果你打算亲自验证,我建议用一个中等规模数据集起步,控制变量才好看。下面是我用过的一套设定,可以直接复现:
- 基座模型:某个 7B 量级的开源模型(Qwen2-7B / LLaMA-3-8B 之类)。规模不用大,关键是推理能力有一定基础。
- 数据集:5000 道带最终答案的多步数学题。建议从公开的 GSM8K 风格数据里抽,但要筛掉太简单的题,保证通过率在 20%~60% 之间。
- SFT 预热:先做 1~2 epoch 的监督微调,让模型学会输出“思路 + 最终答案”的格式。这一步必不可少,否则 RLVR 会在格式混乱上消耗大量训练信号。
- RLVR 训练:采用 GRPO,组大小 8,temperature 1.0,KL 系数自适应,batch size 128,训练 3~5 轮。太长容易过拟合,太少看不出修正趋势。
- 日志监控:除了 loss,一定要记录非零 advantage token 占比、关键 token 位置分布、答案通过率曲线。
这套配置按照常规单节点 8 卡 A100 大约能在一晚跑完,时空开销都在可控范围。跑完再按 4.1 节的方法做 advantage 分析,结论会非常清楚。
5. 业界容易踩的坑和几个值得记住的观点
5.1 误区一:RLVR 是“万能推理增强器”,实际它只修“可验证的那一段”
剪开只看到“强化学习”四个字,很容易下意识把它理解为万能优化器。但 RLVR 的限制非常硬:只有奖励可验证的部分,才能被精准修正。你说“写一篇有感染力的文章”这种目标,没有标准答案,RLVR 就无从下手。
我在项目里吃过这个亏。有个任务要求模型回答开放式问题,我们强行套了 RLVR,用人工设计的规则打分,结果训练完全失控——模型学会用空话套话规避规则扣分,关键 token 全部漂移到“政治正确”的表述上。后来把任务改成“给出 3 个量化指标并说明计算依据”,RLVR 才起作用。所以先问自己:这个问题有没有外部可验证的判定标准?没有的话,别硬上 RLVR。
5.2 误区二:训练越久越好,其实稀疏信号下会过拟合到格式
因为关键 token 少,模型学到最后就是在“背那几个 token 的正确形态”。训练到后期,你会发现模型确实能在这道题上提高通过率,但一旦换一道分布不同的题,通过率立刻打回原形。这就是过拟合到了“格式层面”和“少数 token 层面”,没有泛化出真正的推理能力。
我建议监控一个指标:验证集通过率与训练集通过率的差。如果训练集蹭蹭涨,验证集原地踏步甚至下跌,就要果断提前停止。不要迷信“多训几轮更稳”这个说法,在 RLVR 场景下,早停往往比晚停效果更好。
5.3 误区三:把 RLVR 当 SFT 用,数据配比失衡
有人觉得既然 RLVR 效果好,那 SFT 是不是可以少做一些?我做下来感觉不是这个逻辑。SFT 负责让模型“会说”,RLVR 负责让模型“说对”。如果 SFT 阶段数据太少,模型连标准的推理格式都不会,RLVR 的采样空间会变得非常大,关键 token 的位置极不稳定,优势估计自然乱掉。
推荐配比:SFT 阶段至少准备 2 万条以上高质量数据,RLVR 阶段用 5000 到 2 万条可验证数据。RLVR 数据不要求多,但每条都要保证标准答案可判定、无歧义。数据质量在这时候远比数量重要。
5.4 对后续工作的思考:软件工程、数学证明等领域天然适配
理解了“稀疏关键令牌修正”之后,再去看 RLVR 的适配边界就很清楚了。凡是“输出里存在决定成败的关键点”且“每个关键点都能被程序化判定”的领域,都是 RLVR 的好土壤。
我看好两个方向。第一个是软件工程:提交的补丁里改对了函数签名、修对了条件分支,整个测试套件就会通过。这里的关键 token 分布在代码 diff 区域,稀疏性非常高,很适合用 RLVR 做精准修正。第二个是数学证明:Lean/Tactic 这类形式化语言里,一个策略命令写错,整个证明就断掉,而且错误能被类型检查器捕获。这种环境几乎是为 RLVR 量身定制的。后续如果模型能结合静态分析工具,把关键 token 定位得再准一些,RLVR 的可控性还会上一个台阶。
我个人在实际操作中的体会是:不要一上来就盯着整体通过率看,先花半天把 advantage 按 token 拆开,理解自己的任务里“关键 token 到底长什么样”。我第一次看到那个稀疏度 0.95 的分析图时,整个人对 RLVR 的理解都变了。这也让我养成了一个习惯:每次开 RLVR 实验,日志里必须加“非零 advantage token 占比”和“高优势 token 位置分布”这两个指标。看着它们训练,你心里会非常清楚模型是在老老实实修答案,还是在胡改一气。这个习惯,建议你也试试。