GMPO
Paper · arXiv 2507.20673 · 2025

GMPO:把 token 级奖励的算术平均换成几何平均

GRPO 对一条序列里所有 token 的重要性加权奖励做算术平均。一个 token 的 ρ 冲到 10,平均值只被摊薄一点点,但它在梯度里的权重就是 10。 GMPO 把 Σ 换成 Π 再开 |o| 次方,整条序列的每个 token 共享同一个几何平均数作为权重。 代价几乎为零,换来的是更窄的 ρ 区间和更高的探索熵。

Yuzhong Zhao 等 · UCAS / CUHK / HKUST / Microsoft Research arXiv 2507.20673 ↗ 代码 ↗
TL;DR · 30 秒抓住核心

不稳定的源头不在采样,在 loss 里的那一次平均。GRPO 的目标是 token 级重要性加权奖励的算术平均,它对少数极端 ρ 非常敏感。

GMPO 只改一处:把算术平均换成几何平均。目标值域因此被 AM–GM 不等式压在 GRPO 之下,梯度权重也从「每个 token 各算各的 ρt」变成「整条序列一个 GM(ρ)」。

因为不再需要靠窄裁剪压住离群值,论文把裁剪区间放宽到 e−0.4 ~ e0.4,探索空间反而变大——熵更高、KL 更小、梯度范数更平。

+4.1%
R1-Distill-Qwen-7B 五基准平均 Pass@1
63.4 vs GRPO 59.3
52.7
Qwen2.5-Math-7B 同设置平均
GRPO 51.2
e±0.4
token 级裁剪区间
GRPO 为 (0.8, 1.2)
01

算术平均把离群 token 的权重,原样留在了梯度里

读完这节你应该知道:为什么「loss 看起来没炸」和「更新已经炸了」可以同时发生。

GRPO 对每个问题采样一组 rollout,用组内奖励的均值和标准差把奖励归一化成优势 Âi。对第 i 条 rollout 的第 t 个 token,重要性采样率是

ρi,t(θ) = πθ(oi,t | q, oi,<t) / πθold(oi,t | q, oi,<t)
比值偏离 1 越多,说明这条 rollout 上的策略已经偏离采样时的旧策略越远

去掉 KL 项和裁剪项之后,GRPO 的目标就是 token 级重要性加权奖励的算术平均(原文 Eq. 2):

J*GRPO(πθ) = Eq,{oi} [ (1/G) Σi=1G (1/|oi|) Σt=1|oi| ρi,t(θ) Âi ]
两个平均叠在一起:先在序列内对 token 求平均,再在组内对 rollout 求平均

关键在下一步。对参数求梯度,ρ 的导数会重新乘回一个 ρ(原文 Lemma 1:∇ρ = ρ·∇log π),于是序列内的 1/|o| 和求和一起,变成了这样一个形式(原文 Eq. 5):

∇θJ*GRPO = (1/(G·|oi|)) Σt ρi,t(θ) · Âi · ∇θ log πθ(oi,t | q, oi,<t)
每个 token 的梯度权重,是它自己的那个 ρi,t
核心不对称

loss 里被摊薄,梯度里没有

一个 token 的 ρ 涨到 10,它在 loss 里的贡献只多出 (10−1)/|o|——序列有 3000 个 token 时,曲线几乎看不出来。但在梯度里,这个 token 那一项的系数就是 10,没有任何摊薄。于是监控曲线平静,参数更新却已经被单个 token 拽走。

论文的图 1 记录的就是这个现象:GRPO 训练过程中 ρt(θ) 的取值范围随步数不断扩大,极端值频繁出现;GMPO 的 ρ 区间则保持在更窄的带内,离群值明显更少。作者据此把问题定义为:目标函数对重要性加权奖励的离群值过敏,而不是采样或奖励本身有问题。

这也解释了为什么单纯加裁剪不是终点:裁剪是在梯度已经算出来之后做截断,它压住了幅度,但没有改变「每个 token 各用一个 ρ」这个结构。下一节看前人都试过什么。

02

两条现成的路,改的都是「约束」,不是「平均」

看完这节你应该知道:为什么把裁剪调紧或调松、把聚合搬到序列级,都绕不开同一个问题。

路线 A

继续用算术平均,只动裁剪

GRPO 用一个不宽的区间 (0.8, 1.2) 把 ρ 按住。DAPO 的做法是 clip-higher,把上界从 1.2 放到 1.28,给探索留一点缝。

能解决:单步更新过猛,训练初期不容易崩。

卡在:裁剪区间一窄,策略很快变得确定,熵掉下去,探索没了;区间一宽,算术平均又原样把离群值放大回来。稳定和探索被绑在同一个旋钮上,只能二选一。

路线 B

把聚合搬到序列级连乘

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 级裁剪更宽。裁剪更宽、区间反而更窄,这是后面所有结论的起点。

03

把 Σ 换成 Π 再开 |o| 次方,梯度权重变成整条序列一个数

这一节只有三件事:目标函数怎么写、值域为什么更窄、梯度权重为什么更稳。

GMPO 的目标函数(原文 Eq. 3)把序列内的求和换成连乘,再开 |oi| 次方;sgn(Âi) 负责把优化方向取回来:

J*GMPO(πθ) = E [ (1/G) Σi ( Πt=1|oi| |ρi,t(θ) Âi| )1/|oi| · sgn(Âi) ]
Eq. 3 · 取绝对值是为了让负数也能进连乘;符号最后由 sgn 统一还原

加上 token 级裁剪后就是实际训练用的形式(原文 Eq. 4):对每个 token 先做 min[ρÂ, clip(ρ, εlow, εhigh)Â],再取绝对值、连乘、开方、乘符号。论文取 (εlow, εhigh) = (e−0.4, e0.4),约等于 (0.67, 1.49)。

值域:AM–GM 给出一个硬上界

由算术平均 ≥ 几何平均,直接得到

|J*GMPO(πθ)| ≤ E[ (1/G) Σi (1/|oi|) Σt |ρi,t(θ) Âi| ] = |J*GRPO(πθ)|
同样的输入,GMPO 的目标值绝对值永远不超过 GRPO——这是论文所说「值域更窄、方差更低」的形式化依据

举个能手算的例子:一条序列 8 个 token,其中 7 个 ρ=1,1 个 ρ=6。算术平均是 13/8 = 1.625,几何平均是 61/8 ≈ 1.251。差距不大,但梯度的差距是 6 倍对 1.25 倍。

梯度:权重从「逐 token」变成「整条序列一个标量」

GRPO

每个 token 用自己的 ρ

∇J = (1/(G|oi|)) Σt ρi,t Âi ∇log πθ(oi,t)

一个 token 的 ρ 极端,它那一项的梯度就极端,直接把更新方向拽过去。

GMPO

整条序列共用一个 GM(ρ)

∇J = (1/(G|oi|)) Σt (Πk ρi,k)1/|oi| Âi ∇log πθ(oi,t)

括号里和 t 无关。不管第几个 token,系数都是同一个数。

Eq. 5 与 Eq. 6,为清晰起见都省略了裁剪项;完整推导见原文附录 A 的 Lemma 1–3
读公式时容易漏掉的一点

被「几何平均」的其实只有 ρ,不是 Â

把 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。

自己动手:一个离群 token 会怎样改写梯度权重

下面是一条 8 个 token 的序列。滑块控制序列内 ρ 的离散度和某一个 token 的离群倍数;组内正确数决定 Â 的大小,切换正负样本可以看 sgn 怎么工作。图里对比的是 Eq. 5 与 Eq. 6 中、乘在 ∇log π 前面的那个系数。

GRPO

逐 token 权重

—

—

GMPO

全序列同一权重

—

—

GRPO 权重 ρt·|Â| GMPO 权重 GM(ρ)·|Â|
当前这一条序列
拖动上面的滑块,或者点右侧另一个 rollout 类型。
这个模拟做了哪些简化?点开看与真实训练条件的差异

序列长度固定为 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 两个维度上,图里只截取了一条序列的一个瞬间。

04

只改一行 loss:log 空间求和,一次 exp

工程上它没有多一次采样、没有 critic、没有额外前向;代价是一条序列上多一次求和。

原文 Algorithm 1 只有十来行,核心是把「连乘再开方」搬到对数域。直接对 3000 个 ρ 做连乘会下溢,取对数后变成求和,数值上稳定得多:

Algorithm 1

逐行拆开

  1. sgn_A = 1 if advantage > 0 else -1:先把优势的符号取出来。
  2. sgn_A * (log πnew − log πold):把符号并进对数比,等价于对 ρ·sgn(Â) 取对数。
  3. clamp(·, −ε, ε) 再 min(·, ·):这就是 PPO 那个「取更保守一侧」的 min,只不过作用在每个 token 上,ε 默认 0.4。
  4. 把符号乘回去,得到每个 token 裁剪后的 log ρ。
  5. exp( sum(mask) / mask.sum() ):对有效 token 求平均再取指数——一次性得到 GM(ρ)。
  6. loss = −advantage × ratio:整条序列只乘一次 advantage。

对比 GRPO,多出来的计算量是 O(|o|) 的累加和一次 exp,反向传播时所有 token 共享同一个标量系数。论文没有给出 wall-clock 或显存对比,所以「开销可忽略」是结构上的判断,不是论文里的测量数字。

训练设置(原文 §4.1)

一个容易被忽略的细节

1/|o| 这个幂次不是装饰

如果只写 Πt |min[ρÂ, clip(ρ)Â]| 而不开 |o| 次方,序列级比值会随回答长度迅速放大——论文图 6 展示的正是正奖励轨迹上这个量随长度失控的过程。去掉这个归一化项,平均分从 52.7 掉到 52.0(Table 4 第 4 行)。

05

一轮训练里,GMPO 只在最后一步换了聚合方式

从采样到更新,两条路共享前四步;分叉只发生在「怎么把逐 token 的量压成一个标量」。

prompt q 从训练集 Q 取一道题 π_old 采样 G = 8 条 rollout 每条最长 3,000 token reward r ∈ {0, 1} 组内归一化 → 优势 Â_i GRPO · 算术平均 GMPO · 几何平均 token 级裁剪 (0.8, 1.2) token 级裁剪 · log 空间 e⁻⁰·⁴ ~ e⁰·⁴ 求和再平均 (1/|o|) Σ ρ_t 再乘 Â 求平均再取指数 exp((1/|o|) Σ log ρ_t) 再乘 Â 梯度权重 ρ_t 每个 token 各不相同 梯度权重 GM(ρ) 整条序列同一个数 同一个标量系数乘在每条轨迹所有 token 的 ∇log π 上,离群 token 不再单独放大 → 用 ∇ 更新 π_θ,进入下一轮
图 1:按原文 Eq. 1–6 与 Algorithm 1 重绘的训练流程。左侧蓝色为 GRPO 的聚合路径,右侧陶土红为 GMPO;两者只在最后两步不同。

把它放回 PPO 的框架看会更清楚:策略梯度方法本来就要给每个 token 的 ∇log π 乘一个系数。GRPO 让系数随 token 变化,GMPO 把它压成每序列一个标量。真正被换掉的是「系数怎么算」,不是「要不要算梯度」。

06

平均分全面小胜,但单个 benchmark 并不是每项都赢

先看三张表,再看四个容易被平均分掩盖的细节。

模型AIME24AMCMATH500MinervaOly.Avg.
GRPO-1.5B23.349.475.225.739.042.5
GMPO-1.5B20.053.077.630.138.743.9
GRPO-7B40.059.083.432.441.351.2
GMPO-7B43.361.482.033.543.652.7
GRPO-7B (R1-Distill)43.367.589.039.756.759.3
GMPO-7B (R1-Distill)46.678.391.437.962.563.4

Pass@1,%。评测时 temperature = 0.0,每题只生成一个答案。AIME24 共 30 题,一道题约等于 3.3 分。

四个被平均分掩盖的细节

训练曲线层面,论文图 4 报告了四个方向一致的观察:GMPO 的 token 熵更高(探索更久)、梯度范数更平、相对 pre-RL 模型的 KL 更小、验证分数更高。在 MoE 的 CountDown 任务上,这个差距变成了定性差别——图 5 里 GRPO 在约 250 步后崩溃,GMPO 保持稳定。

07

它稳的是「聚合方式」,不是所有不稳定的来源

论文没有做的实验,和它做了但不支持外推的部分,分开放。

边界一

整条序列共用一个权重,是优点也是盲点

Eq. 6 里每个 token 的系数完全相同。如果一条序列内部质量差异很大——前半段推理正确、后半段跑偏——GMPO 没有机制给正确的 token 更大权重、给跑偏的 token 更小权重。它压住的是跨序列的离群值,不是序列内部的不均匀。GRPO 的逐 token 权重在这一点上反而更细。

边界二

任务面很窄:数学 + 几何

训练数据只有 MATH Levels 3–5、DeepScaleR、CountDown 和 Geometry3K;评测是五个数学基准加一个视觉问答基准。代码生成、通用对话、多轮 agent 任务都没有数据。奖励全部可验证、二值,稀疏或带噪的奖励模型场景没有覆盖。

边界三

规模最大到 32B,没有缩放曲线

实验覆盖 1.5B、7B、32B(MoE),没有更大的模型,也没有不同规模下增益如何变化的曲线。7B 到 32B 之间只有 MATH500 一个点(94.6 → 96.7),不足以支撑「越大越有效」的说法。

边界四

工程开销没有被测量

论文说实现简单、在 log 空间计算保证数值稳定,但没有吞吐、显存、单步耗时的对比,也没有报告多次运行的方差或随机种子。表里的每个数字都是一次训练的结果,AIME24 这种 30 题的基准,一道题的波动就接近 3.3 分。要用在线上训练系统里,这些得自己补测。

一句话总结:GMPO 改的是「怎么把逐 token 的量聚合成一个标量」,它让这个标量对单个极端 ρ 不敏感,代价是放弃了序列内部的差异化加权。这也解释了为什么它的收益稳定但不大——问题被缩小了,没有被消除。