1670 words
8 minutes
RLHF(三):从 GRPO 到 DAPO

1. GRPO#

前两篇文章中讲了 PPO 的流程,在 PPO 中需要随着 actor 模型的更新去不断更新 critic 模型,以便于更好的预测新 value。

GRPO 在 PPO 的优势计算上做了改进,我们从旧策略中为同一个问题或状态采样多个输出,将这些输出的平均奖励作为基线,高于平均值产生正优势,低于平均值产生负优势:

Ai=rimean({r1,r2,,rG})std({r1,r2,,rG})A_i = \frac{r_i - \operatorname{mean}(\{r_1, r_2, \ldots, r_G\})}{\operatorname{std}(\{r_1, r_2, \ldots, r_G\})}

这样算优势的时候就不需要 critic 模型给出的每个位置的未来收益预测了,直接省去了 critic 这个模型。

剩下的包括 clip 等操作都继承了 PPO 的思想。

2. DAPO#

在 GRPO 的基础上,DAPO 做了四点优化:

  1. Clip-Higher
  2. 动态采样(Dynamic Sampling)
  3. Token级梯度损失(Token-Level Policy Gradient Loss)
  4. 过长奖励整形(Overlong Reward Shaping)

2.1 Clip-Higher#

考虑采样比:

rt(θ)=πθ(otst)πθold(otst)r_t(\theta)=\frac{\pi_{\theta}(o_t \mid s_t)}{\pi_{\theta_{\mathrm{old}}}(o_t \mid s_t)}

标准的 clip 会把倍数限制在 [1ϵ,1+ϵ][1-\epsilon, 1+\epsilon] ,这里限制的是倍数而不是绝对增加量。

这就导致了旧模型对某个 token 的概率是 poldp_{old} ,在标准 clip 下新概率的理论上限就是 pnew(1+ϵ)poldp_{new}\leq (1+\epsilon)p_{old} ,这对旧模型的高概率 token 和低概率 token 的影响完全不一样。

例如 pold=0.9p_{old}=0.9 , ϵ=0.2\epsilon=0.2 ,那么新策略的上界就是 0.9×1.2=1.080.9\times1.2=1.08 ,由于概率不可能超过 11 ,所以这个 clip 上界其实不起作用。

如果 pold=0.2p_{old}=0.2 ,那上界就变成了 0.2×1.2=0.240.2\times1.2=0.24 ,这个上升空间就很小了。假设当前模型经过这次学习,本来想把它提到 0.40.4 。你直觉上会觉得 0.20.2 提到 0.40.4 ,翻倍了,说明这个 token 很有价值。但从 clip 的角度看 ratio 远大于 1.21.2 ,所以正向部分的更新就被砍掉了,导致了低旧概率 token 的正向更新被过早压制。

人话讲就是本来就高概率的 token,更容易继续吃到更新红利,本来低概率的 token,就算这次立功了,也可能因为 clip 太严而涨不上去。 于是模型会越来越偏向自己原来熟悉、原来就常生成的 token,而不愿意真正把那些少见但关键的 token 学起来。

这在模型推理里很要命,因为推理过程里有些 token 一开始确实不是高概率的,但它们可能非常关键。比如一个转折词、一个中间推导动作、一个纠错动作等等。

DAPO 把 clip 的区间有方向的放开成:

[1ϵlow,1+ϵhigh][1-\epsilon_{low}, 1+\epsilon_{high}]

其中 ϵhigh>ϵlow\epsilon_{high}>\epsilon_{low} ,对负向更新,仍然保留较强约束,但对正向更新,,给更多空间。

2.2 动态采样(Dynamic Sampling)#

考虑 GRPO 在 PPO 的基础上做的改进,从旧策略中为同一个问题或状态采样多个输出,将这些输出的平均奖励作为基线,但如果某个问题采样出来的回答奖励全是一样的,那么这组样本的优势就是 00 ,不会给策略更新提供有效梯度。

DAPO 在采样时额外加了一条规则,对每个查询,采样的响应集不能全部获得0或1的奖励。如果所有样本都是0或所有都是1,则会抽取额外的样本,直到违反此条件,可以表示为:

s.t., 0<{oiis_equivalent(a,oi)}<G\text{s.t.},\ 0 < \left|\{\, o_i \mid \texttt{is\_equivalent}(a,o_i)\,\}\right| < G

也就是对于 GG 个回答,正确回答的数量不能是 00 也不能是 GG

2.3 Token级梯度损失(Token-Level Policy Gradient Loss)#

GRPO 的聚合方式是:

1Gi=1G1oit=1oi()\frac{1}{G}\sum_{i=1}^{G}\frac{1}{|o_i|}\sum_{t=1}^{|o_i|}(\cdots)

也就是先在每条回答内部按 token 求平均,再在 GG 条回答之间求平均。于是第 ii 条回答里,单个 token 的权重实际上是:

1G1oi\frac{1}{G}\cdot\frac{1}{|o_i|}

说明一条回答越长,里面每个 token 分到的权重就越小。

举个例子,假如我们对于一个问题采样了两个回答 AABB

其中回答 AA 的长度是 200200 个 token,回答 BB 的长度是 1010 个 token 。

那么回答 AA 中每个 token 的权重是:

1200×12=1400\frac{1}{200}\times\frac{1}{2}=\frac{1}{400}

而回答 BB 中每个 token 的权重是:

110×12=120\frac{1}{10}\times\frac{1}{2}=\frac{1}{20}

可以看到较短回答 BB 中的每个 token 影响力是长回答 AA 里每个 token 的 2020 倍,而这不是因为短回答更重要,而仅仅只是因为它更短。

这会导致如果一条长回答其实质量很高,里面有很多有价值的推理 token,本来应该给模型提供强学习信号;但在 GRPO 的样本级平均下,这些 token 的贡献会被 1oi\frac{1}{|o_i|} 稀释掉。反过来,如果一条长回答质量很差,里面有很多重复、绕圈、无效推理,负面信号也会被稀释。于是长回答不管好坏,都容易发不出声音。

同时模型可能更偏向短回答,因为短回答里的 token 单个影响更大,而长回答无论好坏都更容易被弱化。这会干扰长链推理训练,让模型对长 CoT 的学习不充分,甚至出现长度行为异常。

DAPO 的改法就是把平均方式改掉。它把聚合从:

1Gi=1G1oit=1oi()\frac{1}{G}\sum_{i=1}^{G}\frac{1}{|o_i|}\sum_{t=1}^{|o_i|}(\cdots)

改成:

1i=1Goii=1Gt=1oi()\frac{1}{\sum_{i=1}^{G} |o_i|}\sum_{i=1}^{G}\sum_{t=1}^{|o_i|} (\cdots)

这样一来,来自不同回答的所有 token 的权重都变成了:

1ioi\frac{1}{\sum_i |o_i|}

回到上面的例子里,用了 DAPO 的方法后每个 token 的基础权重就都变为了 1210\frac{1}{210}

2.4 过长奖励整形(Overlong Reward Shaping)#

在 RL 训练里,通常都会给生成长度设一个上限。超过上限的回答会被截断。

问题在于一个被截断的回答,可能有两种完全不同的情况。第一种,它本来就在扯淡;第二种,它其实推理方向是对的,只是还没来得及输出最终答案就被截断了。

要是一刀切把这种样本一律当成坏样本重罚,模型会被误导,但如果完全不管,它又会学会无节制地拉长输出。

DAPO 的做法是对过长响应使用软惩罚,当回答长度超过第一个阈值后,开始加一个和长度相关的惩罚,惩罚会随着超长程度继续增大,而且是线性增长的。

这样一来模型一旦开始明显拖长,就会逐步付出代价,但不是刚超一点点就被判死刑。

因为超长不等于错误。很多长链推理样本只是还没结束,而不是思路错了。如果直接把所有超长样本当成 00 分或负分,模型会混淆 推理质量差 还是 推理太长

RLHF(三):从 GRPO 到 DAPO
https://fuwari.vercel.app/posts/note/rlhfgrpo/
Author
P19E99
Published at
2026-03-11
License
CC BY-NC-SA 4.0