GRPO 对一条序列里所有 token 的重要性加权奖励做算术平均。一个 token 的 ρ 冲到 10,平均值只被摊薄一点点,但它在梯度里的权重就是 10。
GMPO 把 Σ 换成 Π 再开 |o| 次方,整条序列的每个 token 共享同一个几何平均数作为权重。
代价几乎为零,换来的是更窄的 ρ 区间和更高的探索熵。
不稳定的源头不在采样,在 loss 里的那一次平均。GRPO 的目标是 token 级重要性加权奖励的算术平均,它对少数极端 ρ 非常敏感。
GMPO 只改一处:把算术平均换成几何平均。目标值域因此被 AM–GM 不等式压在 GRPO 之下,梯度权重也从「每个 token 各算各的 ρt」变成「整条序列一个 GM(ρ)」。
因为不再需要靠窄裁剪压住离群值,论文把裁剪区间放宽到 e−0.4 ~ e0.4,探索空间反而变大——熵更高、KL 更小、梯度范数更平。
读完这节你应该知道:为什么「loss 看起来没炸」和「更新已经炸了」可以同时发生。
GRPO 对每个问题采样一组 rollout,用组内奖励的均值和标准差把奖励归一化成优势 Âi。对第 i 条 rollout 的第 t 个 token,重要性采样率是
去掉 KL 项和裁剪项之后,GRPO 的目标就是 token 级重要性加权奖励的算术平均(原文 Eq. 2):
关键在下一步。对参数求梯度,ρ 的导数会重新乘回一个 ρ(原文 Lemma 1:∇ρ = ρ·∇log π),于是序列内的 1/|o| 和求和一起,变成了这样一个形式(原文 Eq. 5):
一个 token 的 ρ 涨到 10,它在 loss 里的贡献只多出 (10−1)/|o|——序列有 3000 个 token 时,曲线几乎看不出来。但在梯度里,这个 token 那一项的系数就是 10,没有任何摊薄。于是监控曲线平静,参数更新却已经被单个 token 拽走。
论文的图 1 记录的就是这个现象:GRPO 训练过程中 ρt(θ) 的取值范围随步数不断扩大,极端值频繁出现;GMPO 的 ρ 区间则保持在更窄的带内,离群值明显更少。作者据此把问题定义为:目标函数对重要性加权奖励的离群值过敏,而不是采样或奖励本身有问题。
这也解释了为什么单纯加裁剪不是终点:裁剪是在梯度已经算出来之后做截断,它压住了幅度,但没有改变「每个 token 各用一个 ρ」这个结构。下一节看前人都试过什么。
看完这节你应该知道:为什么把裁剪调紧或调松、把聚合搬到序列级,都绕不开同一个问题。
GRPO 用一个不宽的区间 (0.8, 1.2) 把 ρ 按住。DAPO 的做法是 clip-higher,把上界从 1.2 放到 1.28,给探索留一点缝。
能解决:单步更新过猛,训练初期不容易崩。
卡在:裁剪区间一窄,策略很快变得确定,熵掉下去,探索没了;区间一宽,算术平均又原样把离群值放大回来。稳定和探索被绑在同一个旋钮上,只能二选一。
DeepSeek-R1 直接最大化序列级奖励 (Πt ρi,t) Âi,裁剪也放在序列级:clip(Πρ, εlow, εhigh)。
能解决:不再逐 token 放大单个比值。
卡在:连乘会随序列长度伸缩——论文图 6 显示,正奖励轨迹的序列级比值在缺省 1/|o| 归一化时会随回答变长而变得非常大。而且序列级裁剪一旦触发,整条序列所有 token 的梯度一起归零,代价过于粗暴。
两条路的共同前提是:聚合方式不动,只约束它的输入。GMPO 换的是聚合本身——把算术平均换成几何平均,同时保留 token 级裁剪。这样长度伸缩被 1/|o| 次方抵掉,而裁剪仍然只作用于单个 token,不会一刀切掉整条序列。
论文用图 3 把这件事量化了:在相同的训练步数下,GRPO (0.8, 1.2) 的 ρ 区间比 GMPO (e−0.4, e0.4) 更宽,序列级裁剪的 GMPO 变体又比 token 级裁剪更宽。裁剪更宽、区间反而更窄,这是后面所有结论的起点。
这一节只有三件事:目标函数怎么写、值域为什么更窄、梯度权重为什么更稳。
GMPO 的目标函数(原文 Eq. 3)把序列内的求和换成连乘,再开 |oi| 次方;sgn(Âi) 负责把优化方向取回来:
加上 token 级裁剪后就是实际训练用的形式(原文 Eq. 4):对每个 token 先做 min[ρÂ, clip(ρ, εlow, εhigh)Â],再取绝对值、连乘、开方、乘符号。论文取 (εlow, εhigh) = (e−0.4, e0.4),约等于 (0.67, 1.49)。
由算术平均 ≥ 几何平均,直接得到
举个能手算的例子:一条序列 8 个 token,其中 7 个 ρ=1,1 个 ρ=6。算术平均是 13/8 = 1.625,几何平均是 61/8 ≈ 1.251。差距不大,但梯度的差距是 6 倍对 1.25 倍。
一个 token 的 ρ 极端,它那一项的梯度就极端,直接把更新方向拽过去。
括号里和 t 无关。不管第几个 token,系数都是同一个数。
把 Eq. 3 里的绝对值拆开:Âi 在序列内是常数,连乘 |Âi| 共 |oi| 次再开 |oi| 次方,正好还原成 |Âi|。所以
(Πt |ρi,tÂi|)1/|o| = |Âi| · (Πt ρi,t)1/|o|
几何平均作用在 重要性采样率 上,优势的幅度是一次方进入的。原文 Algorithm 1 的最后一行 loss = -advantage * importance_sampling_ratio 也印证了这一点:先算出 exp(mean(log ρ)),再乘 advantage。
下面是一条 8 个 token 的序列。滑块控制序列内 ρ 的离散度和某一个 token 的离群倍数;组内正确数决定 Â 的大小,切换正负样本可以看 sgn 怎么工作。图里对比的是 Eq. 5 与 Eq. 6 中、乘在 ∇log π 前面的那个系数。
—
—
序列长度固定为 8,真实训练里一条回答最多 3000 个 token。长度越长,几何平均对单个离群值越不敏感:一个 ρ=6 的 token 在 8 个 token 里把 GM 拉到 61/8≈1.25,在 1000 个 token 里只拉到 61/1000≈1.0018。
模拟里的 8 个 ρ 由一个固定向量乘上离散度得到,不来自真实策略;Â 由二值奖励的组内归一化公式算出,和论文一致:Â = (r − mean) / std。当 k 条正确时,正确样本的 Â = √((8−k)/k),错误样本为 −√(k/(8−k))。
真实训练中 ρ 的极端值分布在时间和 token 两个维度上,图里只截取了一条序列的一个瞬间。
工程上它没有多一次采样、没有 critic、没有额外前向;代价是一条序列上多一次求和。
原文 Algorithm 1 只有十来行,核心是把「连乘再开方」搬到对数域。直接对 3000 个 ρ 做连乘会下溢,取对数后变成求和,数值上稳定得多:
sgn_A = 1 if advantage > 0 else -1:先把优势的符号取出来。sgn_A * (log πnew − log πold):把符号并进对数比,等价于对 ρ·sgn(Â) 取对数。clamp(·, −ε, ε) 再 min(·, ·):这就是 PPO 那个「取更保守一侧」的 min,只不过作用在每个 token 上,ε 默认 0.4。log ρ。exp( sum(mask) / mask.sum() ):对有效 token 求平均再取指数——一次性得到 GM(ρ)。loss = −advantage × ratio:整条序列只乘一次 advantage。对比 GRPO,多出来的计算量是 O(|o|) 的累加和一次 exp,反向传播时所有 token 共享同一个标量系数。论文没有给出 wall-clock 或显存对比,所以「开销可忽略」是结构上的判断,不是论文里的测量数字。
如果只写 Πt |min[ρÂ, clip(ρ)Â]| 而不开 |o| 次方,序列级比值会随回答长度迅速放大——论文图 6 展示的正是正奖励轨迹上这个量随长度失控的过程。去掉这个归一化项,平均分从 52.7 掉到 52.0(Table 4 第 4 行)。
从采样到更新,两条路共享前四步;分叉只发生在「怎么把逐 token 的量压成一个标量」。
把它放回 PPO 的框架看会更清楚:策略梯度方法本来就要给每个 token 的 ∇log π 乘一个系数。GRPO 让系数随 token 变化,GMPO 把它压成每序列一个标量。真正被换掉的是「系数怎么算」,不是「要不要算梯度」。
先看三张表,再看四个容易被平均分掩盖的细节。
| 模型 | AIME24 | AMC | MATH500 | Minerva | Oly. | Avg. |
|---|---|---|---|---|---|---|
| GRPO-1.5B | 23.3 | 49.4 | 75.2 | 25.7 | 39.0 | 42.5 |
| GMPO-1.5B | 20.0 | 53.0 | 77.6 | 30.1 | 38.7 | 43.9 |
| GRPO-7B | 40.0 | 59.0 | 83.4 | 32.4 | 41.3 | 51.2 |
| GMPO-7B | 43.3 | 61.4 | 82.0 | 33.5 | 43.6 | 52.7 |
| GRPO-7B (R1-Distill) | 43.3 | 67.5 | 89.0 | 39.7 | 56.7 | 59.3 |
| GMPO-7B (R1-Distill) | 46.6 | 78.3 | 91.4 | 37.9 | 62.5 | 63.4 |
Pass@1,%。评测时 temperature = 0.0,每题只生成一个答案。AIME24 共 30 题,一道题约等于 3.3 分。
| 设置 | 基准 | GRPO | GMPO |
|---|---|---|---|
| Qwen2.5-VL-Instruct-7B | Geometry3K | 53.3 | 54.7 |
| Qwen3-32B (MoE) | MATH500 | 94.6 | 96.7 |
多模态评测 temperature = 0.5,每题生成 16 个答案;MoE 的完整设置见原文附录 B。
| # | 训练目标(Qwen2.5-Math-7B) | Avg. |
|---|---|---|
| 0 | Pre-RL 模型 | 26.5 |
| 1 | GRPO(算术平均) | 51.2 |
| 2 | GMPO,不裁剪 | 52.3 |
| 3 | GMPO,序列级裁剪 | 52.6 |
| 4 | GMPO,去掉 1/|o| 归一化 | 52.0 |
| 5 | GMPO(token 级裁剪) | 52.7 |
| 裁剪区间 (εlow, εhigh) | AIME24 | AMC | MATH500 | Minerva | Oly. | Avg. |
|---|---|---|---|---|---|---|
| (e−0.2, e0.2) | 36.6 | 60.2 | 84.2 | 35.7 | 45.0 | 52.4 |
| (e−0.4, e0.4) | 43.3 | 61.4 | 82.0 | 33.5 | 43.6 | 52.7 |
| (e−0.8, e0.8) | 40.0 | 60.2 | 82.2 | 33.5 | 44.7 | 52.1 |
| (−∞, +∞) | 40.0 | 63.9 | 80.6 | 33.5 | 43.7 | 52.3 |
e±0.8 只有 52.1,完全放开是 52.3,e±0.4 的 52.7 最好。论文的解释是更宽的区间让 ρ 波动变大,探索收益被不稳定性吃掉。1/|o| 归一化值 0.7 分。去掉它从 52.7 掉到 52.0。几何平均和长度归一化是一套的,不能只取一半。训练曲线层面,论文图 4 报告了四个方向一致的观察:GMPO 的 token 熵更高(探索更久)、梯度范数更平、相对 pre-RL 模型的 KL 更小、验证分数更高。在 MoE 的 CountDown 任务上,这个差距变成了定性差别——图 5 里 GRPO 在约 250 步后崩溃,GMPO 保持稳定。
论文没有做的实验,和它做了但不支持外推的部分,分开放。
Eq. 6 里每个 token 的系数完全相同。如果一条序列内部质量差异很大——前半段推理正确、后半段跑偏——GMPO 没有机制给正确的 token 更大权重、给跑偏的 token 更小权重。它压住的是跨序列的离群值,不是序列内部的不均匀。GRPO 的逐 token 权重在这一点上反而更细。
训练数据只有 MATH Levels 3–5、DeepScaleR、CountDown 和 Geometry3K;评测是五个数学基准加一个视觉问答基准。代码生成、通用对话、多轮 agent 任务都没有数据。奖励全部可验证、二值,稀疏或带噪的奖励模型场景没有覆盖。
实验覆盖 1.5B、7B、32B(MoE),没有更大的模型,也没有不同规模下增益如何变化的曲线。7B 到 32B 之间只有 MATH500 一个点(94.6 → 96.7),不足以支撑「越大越有效」的说法。
论文说实现简单、在 log 空间计算保证数值稳定,但没有吞吐、显存、单步耗时的对比,也没有报告多次运行的方差或随机种子。表里的每个数字都是一次训练的结果,AIME24 这种 30 题的基准,一道题的波动就接近 3.3 分。要用在线上训练系统里,这些得自己补测。
一句话总结:GMPO 改的是「怎么把逐 token 的量聚合成一个标量」,它让这个标量对单个极端 ρ 不敏感,代价是放弃了序列内部的差异化加权。这也解释了为什么它的收益稳定但不大——问题被缩小了,没有被消除。