目录

GRPO 训练 DeepSeek-V3 的数学能力:从 rollout 到参数更新

把一批数学题完整追踪到模型参数:奖励如何变成 advantage,ratio 与 KL 又如何变成梯度

目录

假设模型面对一道数学题,四次生成中只有一次答对。训练系统不会把标准答案当作交叉熵标签直接喂回模型,而是把四份回答放在一起比较:答对的回答得到正的相对优势,答错的回答得到负的相对优势,再通过当前模型对这些 token 的概率计算梯度。

这就是本文要复原的核心链路:

prompt
  → 旧策略采样多份回答
  → reward 函数打分
  → 组内标准化得到 advantage
  → 当前策略重新计算 log-probability
  → ratio + clip + KL 构成 loss
  → backward() 更新 actor 参数

本文只讨论可验证最终答案的数学任务,并使用教学设定解释机制。DeepSeek-V3 的完整训练还包含预训练、SFT、代码与写作等任务,以及从 DeepSeek-R1 系列蒸馏推理能力的后训练流程;下面的数学例子不是官方训练配置的逐项复现。DeepSeek-V3 技术报告,第 5 节

1. 30 秒结论

先记住四个判断。

  1. GRPO 调整的是生成倾向,不是把答案写入参数。 模型先自己生成回答,reward 只负责给回答评分,真正参与反向传播的是当前策略对已生成 token 的 log-probability。
  2. advantage 是组内相对量。 同一道题生成 \(G\) 份回答,用这一组回答的分数估计 baseline;一组全对或全错时,reward 驱动的 advantage 会变成零。
  3. ratio 让旧样本可以用于当前策略的局部更新。 它比较当前模型与采样时旧模型对同一个 token 的概率,clip 限制在旧样本上过度更新,KL 则约束当前策略不要偏离参考模型太远。
  4. 这条链路不等于 DeepSeek-V3 未公开代码的精确复现。 V3 报告和 DeepSeekMath 论文在目标函数写法、回答级与 token 级 ratio 等细节上存在需要区分的表述;本文采用 DeepSeekMath 中更适合逐 token 解释的教学形式。

DeepSeek-V3 是总参数约 671B、每个 token 激活约 37B 参数的 MoE 模型;官方材料说明其训练路线包括预训练、SFT 和 RL。官方模型介绍 这些架构数字说明了 actor 的规模,但不能据此推断某一次数学 RL 更新会同时激活固定的 37B 参数:MoE 路由会随 token 和专家选择变化。

2. 读完后应能回答

  • 一条数学 RL 数据中,题目、标准答案、模型回答分别进入哪个组件?
  • 为什么 GRPO 不需要单独训练 critic/value model?
  • reward 如何变成组内 advantage,又如何作用到每个回答 token?
  • 第一次更新时 ratio 数值可以是 \(1\),为什么仍然有梯度?
  • 旧策略、当前策略和参考策略什么时候固定,什么时候刷新?
  • 哪些结论可以由这个算例支持,哪些不能外推成真实 V3 配置?

3. 概念与符号

符号 / 概念含义本文中的边界
\(q\)数学题 prompt输入不包含标准答案
\(o_i\)第 \(i\) 份完整回答由旧策略采样得到
\(G\)每道题的回答数量不是更新次数
\(\pi_\theta\)当前正在训练的 actor参数会被更新
\(\pi_{\mathrm{old}}\)采样当前 rollout 的旧策略当前 rollout 内固定
\(\pi_{\mathrm{ref}}\)KL 约束使用的参考策略通常固定或慢速更新
\(r_i\)第 \(i\) 份回答的 reward本例只检查最终答案和格式
\(A_i\)组内标准化后的 advantage最终结果监督下广播到回答 token
\(\rho_{i,t}\)当前策略与旧策略对 token \(t\) 的概率比是局部 token ratio,不是整段完整比值
rollout从题目开始到回答结束的一次采样轨迹状态是前缀,动作是下一个 token

最简的语言模型 rollout 可以写成:

\[ s_t=(q,o_{<t}),\qquad a_t=o_t,\qquad s_{t+1}=(q,o_{\leq t}). \]

也就是说,状态是题目加已经生成的前缀,动作是下一个 token,生成结束或达到长度上限后得到完整回答,再由 reward 函数评分。

4. 真正的问题:如何让高分回答更容易出现

4.1 这不是从零开始靠 reward 学数学

DeepSeek-V3 的路线是预训练、SFT 和 RL。RL 阶段面对的是一个已经具备语言和一定解题能力的模型;它要改变的是不同解法、格式和行为的概率分布,而不是从空白网络中直接写出数学知识。

设 SFT 后的模型参数为 \(\theta_0\)。对同一道题,它可能生成多种回答:

  • 推导和最终答案都正确;
  • 中间计算错误;
  • 推导基本正确,但最终格式不符合判分器要求;
  • 过程看起来合理,最终答案却错误。

GRPO 的目标是提高高 reward 回答的相对概率,降低低 reward 回答的相对概率。它不等于把 reference_answer 拼接到 prompt 中,也不等于用 reward 替代语言模型的交叉熵标签。

4.2 一条数据中各字段去哪里

可以把一条训练数据写成:

{
  "id": "math_001",
  "prompt": "3盒苹果,每盒12个,吃掉5个,还剩几个?请将最终答案写在\\boxed{}中。",
  "reference_answer": "31"
}

两个字段进入不同组件:

prompt ───────────────→ actor,供模型生成回答
reference_answer ─────→ reward 函数,用来检查最终答案
训练方式训练时的解答从哪里来
SFT数据集预先提供目标解答,模型学习模仿
这里的 GRPO模型自己生成回答,判分器返回分数

因此,数学 RL 数据可以只提供题目和可验证的标准答案,而不提供标准解题过程。但不能由此说 V3 的训练完全不需要推理数据:它此前的 SFT,以及 V3 报告中提到的推理能力蒸馏,都属于其他训练阶段。

5. 第一步:旧策略 rollout

5.1 三个策略角色

为了避免把不同模型版本混在一起,先区分三个逻辑角色:

角色作用当前这批 rollout 内是否更新
当前策略 \(\pi_\theta\)正在训练的 actor是
旧策略 \(\pi_{\mathrm{old}}\)生成当前回答的策略版本否
参考策略 \(\pi_{\mathrm{ref}}\)提供 KL 约束的参考版本通常否

“三个角色”不等于显存中必须常驻三份完整 V3。旧策略可以由生成副本承担,也可以在采样后只保留已生成 token 的 old_logp;工程实现取决于推理服务、并行方式和显存预算。

5.2 同一道题生成四份回答

设这一轮开始时:

\[ \theta=\theta_0,\qquad \theta_{\mathrm{old}}=\theta_0. \]

用同一个策略对苹果题随机采样 \(G=4\) 次:

回答生成内容最终答案
\(o_1\)3×12=36,36-5=31\boxed{31}
\(o_2\)3×12=36,36+5=41\boxed{41}
\(o_3\)12+3=15,15-5=10\boxed{10}
\(o_4\)3×12=35,35-5=30\boxed{30}

这里的 \(G\) 是每道题的回答数量,不是优化器更新次数。若一次采样 \(B\) 道题,总回答数是 \(BG\)。

生成阶段通常保存:

题目 token
回答 token
回答有效位置 mask
生成时的 old_logp

对回答中的第 \(t\) 个 token:

\[ \ell^{\mathrm{old}}_{i,t} = \log\pi_{\theta_{\mathrm{old}}} (o_{i,t}\mid q,o_{i,<t}). \]

生成阶段通常不保留用于反向传播的计算图。后续训练会把已经采样的文本重新喂给当前 actor,重新计算带梯度的 log-probability。

6. 第二步:reward 与组内 advantage

6.1 一个最小 reward 函数

只看整数最终答案时,可以用如下教学版判分器:

import re

def reward_fn(text, reference_answer):
    match = re.search(
        r"\\boxed\{([+-]?\d+)\}\s*$",
        text.strip(),
    )
    return float(
        match is not None
        and int(match.group(1)) == int(reference_answer)
    )

于是四份回答的 reward 是:

\[ [r_1,r_2,r_3,r_4]=[1,0,0,0]. \]

这个函数只适合当前例子,不能当成通用数学判分器。分数、小数、集合和代数表达式可能有不同但等价的写法,需要解析器、规范化或符号等价性检查。

还要注意:这个 reward 没有逐步检查推理。如果一份回答的过程错误,但最终碰巧写出 31,它仍可能得到 1。因此 outcome reward 对信用分配很粗,不能单独证明模型学会了正确的解题过程。

6.2 GRPO 为什么不需要 critic

GRPO 的关键做法是用同一道题生成的一组回答估计相对 baseline,而不是像 PPO 那样额外训练一个 value/critic 模型。DeepSeekMath 论文 将其描述为 Group Relative Policy Optimization,并报告了不使用 critic 的设计。

对同一道题的 \(G\) 个 reward 做组内标准化:

\[ A_i = \frac{r_i-\bar r}{s_r+\delta}, \qquad \bar r=\frac{1}{G}\sum_{j=1}^{G}r_j. \]

其中 \(s_r\) 是这一组 reward 的标准差,\(\delta\) 是防止除零的小常数。本例采用样本标准差并忽略极小的 \(\delta\):

\[ \bar r=0.25,\qquad s_r=0.5, \]

所以:

\[ [A_1,A_2,A_3,A_4]=[1.5,-0.5,-0.5,-0.5]. \]

含义很直接:第一份回答比同组平均表现好,另外三份比平均表现差。

比较发生在同一道题内。 不能把完全不同题目的 reward 直接混在一起做这个组内比较。

6.3 同一个 advantage 如何作用到多个 token

在只提供最终结果的监督下,同一份回答的所有有效回答 token 通常共享同一个 advantage:

\[ A_{i,t}=A_i. \]

因此,\(o_1\) 中的 3、×、12、= 等 token 都收到 \(+1.5\) 的权重;\(o_2,o_3,o_4\) 的回答 token 都收到 \(-0.5\) 的权重。

这并不意味着算法知道哪一步是决定性步骤。它只知道整条回答的最终分数,所以信用分配比过程监督更粗。

如果一组回答全对或全错,所有 reward 相同,则:

\[ A_i=0. \]

此时这组数据的 reward 驱动策略梯度消失;如果目标里还有 KL 项,模型仍可能收到 KL 梯度。

7. 第三步:当前策略重新前向

现在四份回答、四个 advantage 都已经固定。训练阶段不再重新采样,而是把题目和回答喂回当前 actor,得到每个实际生成 token 的当前 log-probability:

\[ \ell_{i,t} = \log\pi_\theta(o_{i,t}\mid q,o_{i,<t}). \]

因果注意力保证位置 \(t\) 的输出只能使用题目和之前的前缀,不能偷看后面的 token。

7.1 取出实际 token 的 log-probability

模型通常返回:

logits: [batch, sequence_length, vocabulary_size]

需要先做 log_softmax,再取实际 target token 对应的词表位置:

def token_logps(model, input_ids, attention_mask):
    logits = model(
        input_ids=input_ids,
        attention_mask=attention_mask,
    ).logits

    log_probs = logits[:, :-1].log_softmax(dim=-1)
    targets = input_ids[:, 1:]

    return log_probs.gather(
        dim=-1,
        index=targets.unsqueeze(-1),
    ).squeeze(-1)

错开一位是因为位置 \(t\) 的输出预测位置 \(t+1\) 的 token。loss 只应计入回答有效位置,排除 prompt 和 padding,通常也包含回答结束标记。

“prompt 位置不直接计算 loss”不等于“prompt 的内部计算没有梯度”:回答 token 的概率依赖题目的隐藏表示,梯度仍然可以沿这条依赖回传。

8. 第四步:ratio、clip 与 KL

8.1 ratio 比较当前策略和旧策略

当前回答是旧策略采样出来的,但同一批回答可能被重复更新多次,因此需要比较当前策略是否已经偏离采样策略:

\[ \rho_{i,t} = \frac{ \pi_\theta(o_{i,t}\mid q,o_{i,<t}) }{ \pi_{\theta_{\mathrm{old}}}(o_{i,t}\mid q,o_{i,<t}) } = \exp\left( \ell_{i,t}-\ell^{\mathrm{old}}_{i,t} \right). \]

例如旧模型在同一个前缀下生成 − 的概率为 \(0.60\),当前模型对应概率为 \(0.66\),则:

\[ \rho=\frac{0.66}{0.60}=1.1. \]

这表示当前模型选择该 token 的概率是采样时的 \(1.1\) 倍。

从重要性采样的角度,对固定前缀和函数 \(f\):

\[ \begin{aligned} \mathbb E_{a\sim\pi_\theta(\cdot\mid s)}[f(a)] &=\sum_a\pi_\theta(a\mid s)f(a)\\ &=\mathbb E_{a\sim\pi_{\mathrm{old}}(\cdot\mid s)} \left[ \frac{\pi_\theta(a\mid s)} {\pi_{\mathrm{old}}(a\mid s)} f(a) \right]. \end{aligned} \]

直觉是:手上的动作来自旧模型,但可以按照新模型会多常选择它重新加权。

这里必须保留一个边界:逐 token 的 \(\rho_{i,t}\) 不是整条回答分布变化的完整校正。整段回答的概率比是:

\[ \rho_i^{\mathrm{seq}} = \frac{\pi_\theta(o_i\mid q)} {\pi_{\mathrm{old}}(o_i\mid q)} = \prod_t\rho_{i,t}. \]

逐 token clipped surrogate 与先把 ratio 连乘、再对整段 clip 并不等价。本文采用的是 DeepSeekMath 中适合解释 token 级梯度的形式,不能把它直接称为 DeepSeek-V3 未公开实现的逐行复现。

8.2 policy loss 与 clip

忽略 clip 和 KL 时,策略项可以写成:

\[ \ell^{\mathrm{policy}}_{i,t}=-\rho_{i,t}A_i. \]

为了避免在同一批旧样本上沿同一方向更新过头,引入 \(\epsilon\)-clip:

\[ \ell^{\mathrm{policy}}_{i,t} = -\min\left( \rho_{i,t}A_i,\; \operatorname{clip} (\rho_{i,t},1-\epsilon,1+\epsilon)A_i \right). \]

取教学设定 \(\epsilon=0.2\),看四个独立 token 的数值:

\(A\)旧概率当前概率\(\rho\)clipped policy loss
\(+1.5\)\(0.60\)\(0.66\)\(1.10\)\(-1.65\)
\(+1.5\)\(0.60\)\(0.75\)\(1.25\)\(-1.80\),进入平台
\(-0.5\)\(0.30\)\(0.27\)\(0.90\)\(+0.45\)
\(-0.5\)\(0.30\)\(0.21\)\(0.70\)\(+0.40\),进入平台

clip 不会硬性保证 \(\rho\) 永远落在 \([0.8,1.2]\) 内。它只是改变目标函数;参数共享、其他样本和 KL 梯度仍可能把实际概率推到区间之外。

8.3 KL 把策略拉回参考模型附近

参考模型对同一个 token 的 log-probability 为:

\[ \ell^{\mathrm{ref}}_{i,t} = \log\pi_{\mathrm{ref}}(o_{i,t}\mid q,o_{i,<t}). \]

一种常见的采样 KL 惩罚写作:

\[ \Delta_{i,t} = \ell^{\mathrm{ref}}_{i,t}-\ell_{i,t}, \qquad k_{i,t} = \exp(\Delta_{i,t})-\Delta_{i,t}-1. \]

于是单个 token 的总损失为:

\[ \ell_{i,t} = \ell^{\mathrm{policy}}_{i,t} + \beta k_{i,t}. \]

策略项推动模型朝高 reward 方向改变,KL 项限制这种改变不要过度偏离参考策略。

这是一种基于采样 token 的 KL 惩罚,不是每个 token 上已经精确求完词表期望的 KL;复用旧策略样本时,也不能无条件把它称为当前策略 KL 的无偏估计。

8.4 汇总成一个交给 backward 的标量

对一组回答,先按每个回答的有效 token 数归一化,再对回答取平均:

\[ L(\theta) = \frac{1}{G} \sum_{i=1}^{G} \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} \left[ -\min\left( \rho_{i,t}A_i,\; \operatorname{clip}(\rho_{i,t},1-\epsilon,1+\epsilon)A_i \right) +\beta k_{i,t} \right]. \]

如果一次有多道题,再对题目平均。到这里,才得到交给 backward() 的 loss。

9. 第五步:梯度如何改变模型参数

9.1 reward 不直接反向传播

先忽略 clip 和 KL,对一个 token:

\[ \ell=-A\rho. \]

由于 \(A\) 和旧策略概率固定:

\[ \nabla_\theta\ell = -A\rho\, \nabla_\theta \log\pi_\theta(o_t\mid q,o_{<t}). \]

因此梯度路径是:

GRPO loss
   ↓
ratio / KL 中的当前 log-probability
   ↓
log-softmax 与输出 logits
   ↓
输出层、Attention、MoE 等计算
   ↓
当前 actor 的可训练参数 θ

不会沿这条路径更新的包括:

已采样的 token ID
reward 函数
advantage 数值
缓存的 old_logp
冻结参考模型参数

reward 通过 \(A\) 决定梯度方向和权重,但不是从 reward 函数内部对离散采样过程求导。

9.2 一个 logit 的局部计算

设被采样 token 是 \(a\),其当前 logit 为 \(z_a\),概率为 \(p_a\)。有:

\[ \frac{\partial\log p_a}{\partial z_a}=1-p_a. \]

所以:

\[ \frac{\partial\ell}{\partial z_a} = -A\rho(1-p_a). \]

第一次更新前 \(\rho=1\)。对高 reward 回答中的某个 token:

\[ A=1.5,\qquad p_a=0.6, \]

则:

\[ \frac{\partial\ell}{\partial z_a} = -1.5(1-0.6)=-0.6. \]

梯度下降会倾向于提高该 token 的 logit。对低 reward 回答中的某个 token:

\[ A=-0.5,\qquad p_a=0.3, \]

则:

\[ \frac{\partial\ell}{\partial z_a} = -(-0.5)(1-0.3)=0.35, \]

梯度下降会倾向于降低该 token 的 logit。

这只是单个 loss 项的局部作用,不保证更新后每个高 reward token 的概率都上升。所有回答共享网络参数,同时还存在其他 token 的梯度和 KL 约束。

9.3 为什么第一次 loss 可以为零但仍有梯度

第一次更新前,当前策略和旧策略相同,因此:

\[ \rho_{i,t}=1. \]

忽略 KL,四份回答的 policy loss 平均值是:

\[ -\frac{1}{4}(1.5-0.5-0.5-0.5)=0. \]

但不同回答对应的是不同的 log-probability 函数,它们的导数并不会因为数值权重相加为零就自动抵消。

代码中的 ratio 也不能直接替换成常数 1:

ratio = (current_logp - old_logp).exp()

第一次更新时它的数值可能是 1,但它仍依赖带计算图的 current_logp。如果写成 ratio = 1.0,这条梯度路径就被切断了。

10. 旧策略什么时候刷新

假设一批 rollout 数据执行两次完整参数更新:

时刻使用的数据当前参数这批数据的旧策略
生成批 A新生成的回答\(\theta_0\)\(\theta_0\)
第一次更新前批 A\(\theta_0\)\(\theta_0\)
第二次更新前仍是批 A\(\theta_1\)仍是 \(\theta_0\)
生成批 B重新采样回答\(\theta_2\)改成 \(\theta_2\)

第二次更新时,回答 token、reward、advantage 和 old_logp 都不变;只有当前 log-probability 重新计算,因此 ratio、clip 状态和梯度会变化。

完成规定的更新后,actor 才用新参数重新 rollout,新的回答才绑定新的旧策略版本。

还要区分三个容易混淆的概念:

  • rollout batch:一次采样得到的数据;
  • mini-batch:把 rollout batch 切开后用于前向的子批次;
  • 梯度累积:多个 mini-batch 的梯度累积后再执行一次 optimizer.step()。

看到一次 forward() 和 backward(),不能据此判断旧策略应该刷新。

11. 一个最小的教学版训练循环

下面的代码展示一个 prompt、四份回答和两次更新。它刻意省略了分布式切分、推理服务、显存优化和真实数据管线,因此不是可直接训练 671B 模型的脚本。

G = 4
updates_per_rollout = 2

clip_eps = 0.2
beta = 0.04  # 教学设定,不是声称 DeepSeek-V3 官方使用这个值

# actor:从已有模型初始化,参数可训练
# reference:本阶段固定的参考模型
# optimizer:只管理 actor 的可训练参数

for example in dataset:
    prompt = example["prompt"]
    gold = example["reference_answer"]

    # 采样和 old/ref logp 固定,不保留 actor 反向图。
    with torch.no_grad():
        ids, attention_mask, response_mask, texts = sample(
            actor,
            prompt,
            num_generations=G,
            temperature=1.0,
        )

        old_logp = token_logps(actor, ids, attention_mask)
        ref_logp = token_logps(reference, ids, attention_mask)

        rewards = torch.tensor(
            [reward_fn(text, gold) for text in texts],
            device=ids.device,
        )

        advantages = (
            (rewards - rewards.mean())
            / (rewards.std(unbiased=True) + 1e-8)
        )
        advantages = advantages[:, None]  # 广播到回答 token

    for _ in range(updates_per_rollout):
        optimizer.zero_grad()

        # 重新前向,保留当前 actor 的计算图。
        logp = token_logps(actor, ids, attention_mask)

        ratio = (logp - old_logp).exp()

        direct = ratio * advantages
        clipped = ratio.clamp(
            1 - clip_eps,
            1 + clip_eps,
        ) * advantages

        delta = ref_logp - logp
        kl = delta.exp() - delta - 1

        token_loss = -torch.minimum(direct, clipped) + beta * kl

        # 排除 prompt 和 padding;先按回答平均,再按组平均。
        sequence_loss = (
            (token_loss * response_mask).sum(dim=-1)
            / response_mask.sum(dim=-1)
        )
        loss = sequence_loss.mean()

        loss.backward()
        optimizer.step()

    # actor 已更新。
    # 下一轮重新采样,并保存对应的新 old_logp。

这个循环能否提升数学能力,最终要看独立数学评测上的正确率,而不是只看训练题 reward。loss、KL、熵和回答长度有诊断价值,但都不能单独替代正确率;不同 rollout 批次之间的 loss 也不能像普通 SFT 交叉熵那样直接比较。

12. 实验证据:哪些结论被支持

问题一:去掉 critic 是否仍能做 RL?

  • 对照: PPO 风格的 critic/value baseline 与 GRPO 的组内相对分数。
  • 证据: DeepSeekMath 将 GRPO 定义为不使用 critic、而由 group scores 估计 baseline 的方法,并报告其在数学任务上的提升。DeepSeekMath §1 与 §4.1
  • 支持: 组内比较可以构成一种资源更省的 baseline 估计方式。
  • 不能说明: 不需要 critic 就意味着所有任务、所有 reward 设计都能稳定训练。组大小、reward 方差、任务难度和数据质量仍然重要。

问题二:V3 的后训练是否只有数学 GRPO?

  • 对照: 把数学教学例子与 V3 的完整后训练路线区分开。
  • 证据: V3 技术报告描述了预训练后的 SFT 与 RL,并讨论了推理能力蒸馏;官方仓库同时给出 671B 总参数、37B 激活参数和 14.8T 预训练 token 等模型摘要信息。
  • 支持: 本文的数学 GRPO 是完整训练流程中的一个抽象子问题。
  • 不能说明: G=4、beta=0.04、两次 update 或苹果题 reward 是 V3 官方配置。它们只是为了让梯度链路可手算。

问题三:reward 是否证明模型学会了正确推理?

  • 对照: outcome reward 只检查最终答案,与逐步 process supervision 区分。
  • 证据: 本文的 reward 函数即使遇到错误过程但正确最终答案,也会返回 1。
  • 支持: outcome reward 可以推动最终结果变好。
  • 不能说明: 模型一定学会了可靠、可解释且每一步都正确的解法。

13. Claim–evidence map

Claim直接证据强度不能外推成什么
GRPO 可以用组内分数估计 baseline,不依赖单独 criticDeepSeekMath 对 GRPO 的方法描述来源结论所有 reward 任务都不需要 value model
V3 的训练包含预训练、SFT 与 RLDeepSeek-V3 技术报告第 1、5 节来源结论V3 数学阶段等同于本文教学循环
高 reward 回答的 token 会获得正向策略权重policy-gradient 目标与局部梯度推导综合判断,基于目标函数每个高 reward token 更新后概率都必然增加
第一次 ratio 数值为 1 仍然有梯度ratio 对当前 log-probability 的依赖数学推导把 ratio 写成常数 1 也能得到同样结果
outcome reward 的信用分配较粗同一回答的 advantage 广播到所有回答 token机制推导训练出的每一步推理都一定正确

14. 局限与风险

14.1 教学超参数不是官方配置

本文使用 \(G=4\)、样本标准差、\(\epsilon=0.2\)、\(\beta=0.04\) 和两次更新,是为了完成一个能手算的例子。除非官方资料明确披露,否则不能把这些数字写成 DeepSeek-V3 的真实训练超参数。

14.2 最终答案 reward 容易产生投机行为

字符串匹配可能被格式、等价表达式或偶然猜中影响。更稳妥的判分器至少应处理:

  • 数值和代数表达式的等价性;
  • 分数、小数和单位;
  • 集合、区间与多答案格式;
  • 答案解析失败时的明确惩罚;
  • 必要时的过程验证或程序执行。

14.3 MoE 的参数更新不是固定的“37B”

37B 是每个 token 的激活参数量摘要,不是每一步都会被更新的固定参数集合。共享模块、路由器和被选中的专家会共同决定实际梯度落点;不同 token 的专家路径也可能不同。

14.4 策略目标不等于真实正确率

GRPO loss 是一个局部代理目标。它可能下降,但独立数学评测不提升;训练题 reward 可能提升,但模型出现答案格式投机、回答变长、KL 漂移或通用能力下降。因此验收至少应同时看:

维度要检查什么
能力独立题集正确率,按题型和难度分层
稳定性reward、KL、熵和回答长度曲线
泛化未见题型、不同语言和不同格式
保留能力通用知识、代码、指令遵循和安全评测
成本rollout 吞吐、训练 FLOPs、显存和 wall-clock

15. 复现与可证伪扩展

15.1 最小复现

不需要从 671B 模型开始。可以用一个小型 causal LM 和整数算术数据集验证下面四件事:

  1. 同一个 prompt 采样 \(G\) 份回答;
  2. 用可执行的答案解析器产生 \(r_i\);
  3. 检查全对、全错和混合 reward 时的 advantage;
  4. 保留 old_logp,重复更新同一批回答,观察 ratio、clip 比例和 KL 如何变化。

最小验收条件是:混合 reward 时高分回答的平均 log-probability 倾向上升,低分回答的平均 log-probability 倾向下降;全对或全错组的 reward advantage 为零;把 ratio 改成常数后,策略项不再产生同样的梯度。

15.2 一个可证伪的过程监督实验

假设: 对同一道题同时提供最终答案 reward 和逐步过程 reward,可以减少错误过程偶然得到正确答案时的策略漂移。

最小实验:

  • 固定模型、题目、采样温度、组大小和优化步数;
  • 对照组只使用 outcome reward;
  • 实验组在关键中间步骤加入 verifier;
  • 同时评估最终正确率、过程错误率、回答长度和 KL。

预测: 如果过程监督真的改善信用分配,实验组应在相同或更低回答长度下减少“错误过程、正确答案”的比例。

证伪条件: 实验组只提高训练题 reward,却不提高独立题集正确率,或带来明显的 KL 漂移与通用能力退化。

15.3 一个可证伪的 ratio 实验

假设: 对同一批 rollout 进行过多次更新,会让当前策略远离旧策略,使 clipped fraction 和 KL 上升,最终削弱训练稳定性。

最小实验: 固定 rollout 数据,只改变 updates_per_rollout,记录独立评测正确率、clip 比例、KL 和 entropy。

预测: 更新次数增加初期可能带来收益,但继续增加会出现 clip 比例和 KL 上升;若正确率不再改善,这说明“在旧样本上继续榨取”已经超过代理目标的有效范围。

16. 一句话带走

GRPO 的核心不是让 reward 对模型反向传播,而是用同题回答的相对得分给 token 级 log-probability 加权,再通过 ratio、clip 和 KL 把这种偏好转成一次受约束的参数更新;要判断它是否真的提升数学能力,最后仍要回到独立评测和清晰的 reward 边界。

参考资料