跳到主要内容
一组采样全错的时候,梯度不是变小,是精确等于零

一组采样全错的时候,梯度不是变小,是精确等于零

图南
图南

· 阅读约 9 分钟

训过 RLVR 的人大概都见过这条曲线:前几百步 reward 涨得挺像回事,然后某个 checkpoint 之后突然躺平,一路平的。学习率调大调小都没用。换个 seed 重跑,有时候能多撑几百步,最后还是躺。

大多数人的第一反应是“奖励太稀疏”。这个判断对了一半,但因果反了。稀疏本身不致命,十道题蒙对一道,RLVR 照样能爬,而且爬得挺稳。真正致命的是另一种情况:某个 prompt 采出来的这一组轨迹,一条都没对。这时候已经不是信号弱,是信号精确等于零。这篇讲完,你大概能分清这两种看起来像同一个现象的失败——因为它们的处理方式完全不一样。

先把 GRPO 那一步的算式摆出来,因为“零奖励”这个叫法容易让人以为是指 reward 等于 0 导致 loss 等于 0,不是这个意思。

假设组大小 G = 8,verifier 是数学题的答案比对,对错二值。这一组八条全错,reward 向量就是八个 0。GRPO 的 advantage 做组内归一化,减均值再除标准差:均值是 0,标准差也是 0,分子分母一起归零,实现里那个 eps 一兜,吐出来一个全零的 advantage 向量。梯度就是零。我查了一下,这种实现不会给你报 NaN,也不会告警,它会安静地返回零。这也是为什么它在日志里特别难发现。

再往下拆一层,这才是“崩溃”这个词真正的分量:这个零是自我维持的。策略没从这组里学到任何东西,下一轮碰到同类题还是不会,还是全错,还是零方差。一批样本里这种组占比越高,能贡献梯度的样本越少,等效 batch 越小,训练越抖,越学不会。正反馈,往下走的。你在 loss 曲线上看到的“突然躺平”,其实在方差上早就开始了。

这里最容易被搞混的是:全对的那一组,方差同样是零,数学上是同一种病。区别只在于全对那侧不疼,因为模型已经会了,你不需要它再学。所以 RLVR 的有效学习区间被夹在中间一个带里,太简单的题白烧 token,太难的题梯度归零。而且这个带比“有对有错”要窄。

举个具体的:G = 8,一条对七条错。均值 0.125,标准差大概 0.33。那条对的 advantage 是 (1 − 0.125) / 0.33,差不多 2.6,七条错的是 −0.38。也就是说这一组的梯度几乎全由那一条成功轨迹撑着,七条失败的贡献被压得很扁。训练能走,但方差大,走得像喝多了。反过来七条对一条错,偏的方向相反。真正稳的是中间那一段。

至于为什么它会变成 RLVR 特有的病,而不是 RL 通病:因为 verifier 只给二值,没有部分分。RLHF 那套 reward model 给的是连续分,同样八条几乎不可能分毫不差,方差天然就非零。可验证奖励的好处是干净、不撒谎,代价就是把“这一组全错”变成一种常态风险。同一件事的两面。

那最直接的办法是什么?多采几条,直到有一条对的,只拿这条做正样本,变相 rejection sampling。这个办法能用,成本是 1/p。通过率 1% 的题,平均要采一百条才出一条对的,而这还是平均值,方差大得很。更麻烦的是它绕开了问题本身:你把那一条挑出来当正样本,模型学到的是这条轨迹的形状,不是它前九十九条错在哪儿。

(你可能会问,那把全错组整个跳过不就行了?跳过和全错在梯度上是一回事,都是零,只是省了点算力。省算力和学会是两件事。)

10 月 9 号挂到 arXiv 上那篇(编号 2610.13594),抓的就是这个点。它的主张用大白话说就一句:全错的那组轨迹不该直接扔,里面写着模型到底哪儿不会。

一组全错的 rollout 不是“没信号”,是一份诊断报告,只是现在没人读。失败和失败不是一回事:把题读错了,思路对但第三步符号搞反,或者压根没敢下手、在那儿绕圈子输出废话——这三种,你给的补救完全不是一个东西。reward 都是 0。这三个分类是我自己举的,论文里没这么分,但道理通用。

论文里批评的现有做法,大致两类。一类是预先写一个提示库,失败了按规则或者按相似度捞一条塞回去。另一类是事后修正,把错答案改一改拿去当正样本。

这两类的毛病是同一个:它们是离策略的。提示库里的那条提示是写给“一般人”的,不是写给这一次的。它不知道这次错在哪一步,只能覆盖一个平均情况。事后修正更别扭,你拿一个改过的答案当正样本,模型学到的是“这个改过的答案是对的”,不是“我当时怎么走岔的”。认知短板那部分信息,在修正这个动作里就蒸发了,剩下的只是一个干净的正样本。

MENTOR 提的是“在策略教学干预”。“在策略”这个词在这儿容易被念歪,不是在线训练那个意思。我是这么理解的:干预的信息来源,是当前策略自己采出来的那条失败轨迹,不是预先写好的题库。干预的落点,是下一次采样的条件,不是这一次的答案输出。两条都对齐上,才叫在策略。

它做的是一个多智能体框架,有角色负责判断这次失败的根因,再据这个判断动态生成一条针对性提示,喂给学习智能体下一轮尝试。定位是实时导师,不是事后批改。诊断和给提示是同一次干预里的两个动作,不是一个跑完另一个再跑。

它还强调即插即用,能挂到 GRPO 这类策略优化流程上,不用动训练基础设施。这一条我觉得比论文里那些数字更值得看。训练循环里加一个东西,如果需要重写 rollout engine、改 reward server 的接口,那它在真实团队里活不过一个季度。能挂上去、能摘下来、摘下来原来那套照跑,这种设计才有可能被真的用起来。

实验在数学和代码生成上做的,结论是能缓解零奖励崩溃、比现有基线好。Llama-3.2-3B-Instruct 上,相对基座的平均相对提升最高到 78.3%。

这个数字得拆开看。“相对提升”这个口径,底数小的时候放大得特别厉害:从 12 提到 21,相对提升 75%,听着比“涨了 9 个点”唬人多了。而且它选了个 3B 的模型,这不是巧合。模型越小,全错组越多,崩溃越严重,能救回来的空间越大。效果最漂亮的地方恰好是问题最严重的地方——这两件事本来就是同一件事,不是什么双重优点。

顺着这个推一个预测:换到已经能过 80% 的模型上,全错组本来就少,增益会明显压下来。论文测的规模和任务类型没覆盖到这一点。要真是这样,MENTOR 的定位就更清楚了,它是给小模型、难任务、冷启动这类场景准备的脚手架,不是所有训练都该加的一道工序。

还有一层,我觉得是这套设计最脆弱的地方:提示泄漏。

数学题上,一条好的教学提示和答案之间那条线非常细。“你第三步符号搞反了”这句,是诊断,也是半个答案。学生照着这个重采样,答对的概率当然上去了,reward 从 0 变 1,梯度有了,崩溃缓解了。但这个 1 是谁的功劳?

在策略的干预有个特性:它会被非常忠实地学进去。提示指哪,模型走哪,因为那一步本来就是被这条提示条件采样出来的。于是优势函数把这个成功记在策略头上,而这次成功有一半是导师给的。这不说明方法没用,它说明“缓解零奖励崩溃”和“模型真的变强了”是两件事,中间夹着一个变量:提示里带了多少答案。

代码任务上这个泄漏会轻一点,因为单测不撒谎,提示说“你边界条件没处理”和把正确实现贴出来,测试结果上能看出差别。但也只是一点。一个够细的提示,离答案本来就不远。

更朴素的风险是导师会诊错。诊断那个角色凭什么判断根因?说到底还是模型自己的判断,只是换了个位置。(具体怎么实现的、喂了什么信号,我没看细,不乱讲。)但如果它诊断错了,在策略的干预会把这个错误忠实地传下去。一条指错方向的提示比不给提示更糟,它会让模型在一条错的路上多走几轮,而且每一轮都带梯度。

打住,拉回来。绕这么多,这篇论文真正值得拿走的,我觉得不是 MENTOR 这个框架。框架总会被下一个框架替代。值得拿走的是那个诊断视角:把“全错的一组”从废样本重新归类成读数。

零奖励崩溃这个说法听着像天灾,好像难度一上来训练就必然完蛋。但从方差那个角度看,它是一个可以数出来的量:你的 batch 里,有多大比例的 prompt 组,组内 reward 方差为零。这个数在训练日志里本来就是现成的,只是多数人盯平均 reward,不盯方差。而平均 reward 在崩之前往往是平的,甚至还在慢慢涨,因为它被那些中等难度的题撑着。方差先塌,平均值后塌。

所以开头那个区分是有用的。稀疏和方差归零看着像同一个现象,其实是两回事:一个是模型在爬、只是爬得慢,一个是梯度精确为零,乘任何学习率还是零。分不清这两件事,调参就是在赌。

再往下就是难度课程怎么排了——什么题该在什么时候喂进去,才能既不白烧 token 又不把方差打穿。这个坑先留着,改天填。