组相对策略优化(Group Relative Policy Optimization, GRPO)[323] 是一种专为语言模型设计的强化学习算法,它消除了对独立评论家(critic)网络的需求。GRPO 由 DeepSeek 在 DeepSeekMath 工作中提出,随后在 DeepSeek-R1 [69] 中被扩展到更大规模,已经迅速成为 LLM 训练中的主流 RL 方法——被大多数开源对齐框架(TRL、OpenRLHF、veRL)作为默认算法采用。

其核心思想看似简单却出人意料地有效:与其训练一个神经网络去预测期望奖励(reward)——即 PPO 中的评论家(critic)——GRPO 通过对同一 prompt 生成多条响应、利用该组的奖励统计量作为 baseline,从经验上估计这一基线。这从显存中去掉了一整个模型,将工程复杂度减半,而且——令人意外的是——往往优于 PPO,因为经验基线比训练不充分的价值函数(value function)更准确。

GRPO 在下列场景中尤其有效:

  • 推理任务:具有可验证的奖励(reward)(数学、代码),二值正确性提供干净信号。
  • 大模型(70B 及以上):去掉评论家带来的显存节省至关重要。
  • 多轮对话(Multi-Turn)与 Agent 场景:跨工具调用(Tool Calling)的价值估计本就难以处理。

本章涵盖 GRPO 的动机、算法、关键变体(Dr. GRPO、DAPO、2-GRPO、GDPO)以及基于 TRL 的实战实现。

动机

PPO 的价值模型(评论家)在语言任务上存在三大问题:

  1. 显存:价值头(value head)与策略共享主干(70B 模型占 140GB)。若分离则显存翻倍。
  2. 精度:对部分序列预测期望奖励极其困难。价值函数经常出错 → advantage 出错 → 梯度方向出错。
  3. 训练:价值头需要大量样本才能收敛。RL 早期它给出嘈杂的预测,破坏策略学习的稳定性。

GRPO 的关键洞见[323]:与其学习 V⁡(s),不如从一组样本中经验地估计它。对同一 prompt 生成 G 条响应,计算它们的奖励,并用组统计量作为 baseline。

算法

  1. 对每个 prompt x,采样 G 条补全(completion):{y1,…,yG}∼πθ(⋅|x)
  2. 对每条打分:ri=R⁡(x,yi)
  3. 组内归一化:A^i=ri−μGσG,其中 μG=1G​∑jrj,σG=std​({rj})
  4. 用这些 advantage 应用 PPO 风格的 clipped 更新
A^i=ri−μGσG,L=𝔼[min(rt(θ)A^i,clip(rt(θ),1±ϵ)A^i)]−βDKL[πθ∥πref](7.1)
图 7.1:GRPO 实战:对一个数学 prompt 采样 G=5G{=}5 条响应。三条正确(r=1r{=}1),两条错误(r=0r{=}0)。组均值 μG=0.6\mu_{G}{=}0.6 充当 baseline;正确响应获得正 adv
图 7.1:GRPO 实战:对一个数学 prompt 采样 G=5 条响应。三条正确(r=1),两条错误(r=0)。组均值 μG=0.6 充当 baseline;正确响应获得正 advantage(强化),错误响应获得负 advantage(抑制)。

TRL 实现

下面给出一个使用 HuggingFace TRL 的最小可运行示例。

from trl import GRPOConfig, GRPOTrainer
from transformers import AutoModelForCausalLM, AutoTokenizer
 
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct",
    torch_dtype=torch.bfloat16, attn_implementation="flash_attention_2")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
 
grpo_config = GRPOConfig(
    output_dir="./grpo_output",
    num_generations=8,           # G = group size
    temperature=1.0,             # High temp for diversity within group
    max_completion_length=2048,  # Max response length
    beta=0.04,                   # KL penalty coefficient
    learning_rate=1e-6,
    per_device_train_batch_size=2,  # Prompts per device (x8 gens = 16 responses)
    gradient_accumulation_steps=8,
    num_train_epochs=2,
    bf16=True,
    gradient_checkpointing=True,
    max_grad_norm=0.5,
    logging_steps=10,
    # vLLM generation for speed (critical for GRPO due to 8x generation)
    use_vllm=True,
    vllm_gpu_memory_utilization=0.7,
)
 
# Reward function: binary correctness for math
def reward_fn(completions, prompts, **kwargs):
    """Return list of floats: 1.0 if correct, 0.0 if wrong."""
    rewards = []
    for completion, prompt in zip(completions, prompts):
        answer = extract_answer(completion)
        expected = get_ground_truth(prompt)
        rewards.append(1.0 if answer == expected else 0.0)
    return rewards
 
# Can combine multiple reward functions!
def format_reward_fn(completions, **kwargs):
    """Bonus for using proper LaTeX formatting."""
    return [0.5 if "\\boxed{" in c else 0.0 for c in completions]
 
trainer = GRPOTrainer(
    model=model,
    args=grpo_config,
    reward_funcs=[reward_fn, format_reward_fn],  # Multi-objective!
    train_dataset=math_dataset,
    tokenizer=tokenizer,
)
trainer.train()

组大小分析

G信号质量计算开销何时使用2非常嘈杂(如同抛硬币)低不建议使用——过于嘈杂,难以稳定学习4中等中等快速实验、简单任务(通过率 > 50%)8良好(标准)高默认选择。对大多数任务而言平衡性良好16优秀很高困难任务(通过率 < 20%),需要多次尝试才能得到正样本32近乎完美极高仅当你拥有海量算力且任务极难时才使用

GRPO 变体与扩展

GRPO 组中的多样性

方法它如何促进多样性
熵奖励在奖励中加入 α​H​(πθ)。直接惩罚低熵(确定性)的策略。
KL 惩罚−βDKL[πθ∥πref] 防止坍塌到单一模式。
拒绝采样生成大量候选,按奖励保留前 k 个。自然会筛选出多样且高质量的响应。
Best-of-N在推理时:生成 N 条响应,为全部打分,返回最优者。多样性来自采样。
使用多样化配对的直接偏好优化(DPO)在 chosen/rejected 于方法上有别(而非仅在质量上有别)的配对上训练。
多奖励使用多个奖励模型(安全性、有用性、代码质量)。防止坍塌到单一维度。

表 7.1:RL 训练中促进多样性的方法。

后训练对齐(RLHF、DPO)常常因典型性偏差而降低输出多样性:人类标注者系统性地偏好熟悉、「典型」的文本,而非新颖的替代方案。这种模式坍塌是数据层面的现象,并不纯粹是算法问题。

言语化采样(Verbalized Sampling, VS)[422] 是一种无需训练的 prompting 策略,它要求模型在单次生成中显式说出一个概率分布,从而绕开这种坍塌。

# Verbalized Sampling: prompt model to output distribution
def verbalized_sample(model, tokenizer, task, n=5):
    prompt = (
        f"{task}\n\n"
        f"Generate {n} different responses and assign a probability "
        f"to each (probabilities should sum to 1.0). "
        f"Format: [response] (probability: X.XX)"
    )
    output = model.generate(
        tokenizer(prompt, return_tensors="pt").input_ids,
        max_new_tokens=1024,
        temperature=0.7,
        do_sample=True,
    )
    # Parse responses and probabilities from output
    responses, probs = parse_verbalized_distribution(
        tokenizer.decode(output[0])
    )
    # Sample from the verbalized distribution
    import random
    chosen = random.choices(responses, weights=probs, k=1)[0]
    return chosen

在深入各项扩展之前,先简要回顾前文建立的基础 GRPO 算法。其核心机制——采样一组补全、对其奖励做归一化、再施加 clipped 的策略梯度——十分简洁而优雅。然而,实践者很快发现了若干具体的失效模式:预训练偏差稀释梯度(Dr. GRPO)、对称裁剪限制探索(DAPO)、组规模过大造成浪费(2-GRPO),以及多目标场景下的奖励尺度失衡(GDPO)。以下各节将逐一讨论这些问题。

DAPO ——Dynamic Adaptive Policy Optimization

标准 PPO/GRPO 在 [1−ϵ,1+ϵ] 处对重要性比值(importance ratio)做对称裁剪。DAPO 将其替换为非对称的区间:

clipDAPO​(ρ,A)={clip⁡(ρ, 1−ϵ, 1+ϵhigh)if ​A>0clip⁡(ρ, 1−ϵ, 1+ϵ)if ​A≤0

其中 ϵhigh>ϵ(典型取值:ϵ=0.2、ϵhigh=0.28)。当 advantage 为正时,策略被允许更进一步朝好的 token 移动;当 advantage 为负时,则适用通常的保守裁剪,以避免过度抑制。

基础 GRPO 将损失除以序列数量G。DAPO 则除以所有序列的token 总数:

ℒtoken=−1∑i=1G|oi|∑i=1G∑t=1|oi|min(ρi,tA^i,clipDAPO(ρi,t,A^i)A^i).

这样可以防止长补全仅仅因为包含更多 token 就在梯度信号中占据主导。

当一条补全被截断(在最大长度预算内没有出现 EOS token)时,它提供的是误导性信号:模型会因为那些生成正确、却恰好位于截断边界之前的 token 而受到惩罚。DAPO 会将这些补全整体屏蔽掉:

mi=𝟏[EOS∈oi],ℒfiltered=−∑i=1Gmi​∑t(⋯)∑i=1Gmi​|oi|.

与硬性屏蔽不同,一种更温和的变体施加长度惩罚,它随着补全接近最大长度 Lmax 而平滑增大:

ri←ri−λ⋅max⁡(0,|oi|−LcacheLmax−Lcache),

其中 Lcache 是「安全」长度阈值。

DAPO 会重新采样那些整组补全都获得相同奖励(全部正确或全部错误)的 prompt,因为这类组在归一化之后贡献的梯度为零。这样可以在整个训练过程中保持有效 batch size 稳定。

GSPO ——Group Sequence Policy Optimization

GSPO [51] 将序列级重要性权重定义为逐 token 比值的几何平均,它等于完整序列概率比的 |oi| 次方根:

si​(θ)=(πθ​(oi∣q)πold​(oi∣q))1/|oi|=exp⁡(1|oi|​∑t=1|oi|log⁡πθ​(oi,t|q,oi,<t)πold​(oi,t|q,oi,<t)).

这是经过长度归一化的序列概率比。GSPO 的 loss 对每条序列只裁剪这一个标量:

ℒGSPO=−1G∑i=1Gmin(si(θ)A^i,clip(si(θ),1−ϵ,1+ϵ)A^i).

Dr. GRPO ——Debiased Reward GRPO

Dr. GRPO 修改逐 token 的梯度权重,以考虑该 token 对奖励信号的边际贡献。模型已经赋予高概率的 token(无论奖励如何)会被降权:

wi,t=A^i⋅(1−πref​(oi,t|q,oi,<t)),

其中 πref 是参考(预训练)模型。这是一种token 效率:梯度集中在策略真正需要改变的 token 上。

2-GRPO ——最简的两次 Rollout GRPO

关键洞见在于:GRPO 的有效性并非主要来自精确的 advantage 估计(后者需要很大的 G)。相反,它来自一个隐式的对比目标,其结构与 DPO 相似:

ℒ2-GRPO≈−𝔼(o+,o−)∼πθ​[log⁡σ⁡(β​log⁡πθ​(o+|q)πold​(o+|q)−β​log⁡πθ​(o−|q)πold​(o−|q))],

其中 o+ 是奖励更高的补全,o− 是奖励更低的补全。当 G=2 时,这种对比结构是显式的。当 G=16 时,同样的信号仍然存在,但被冗余的配对稀释了。

SAPO ——Soft Adaptive Policy Optimization

SAPO 用一个平滑的代理目标取代 min⁡(ρ​A,clip⁡(ρ,⋅)​A) 目标:

ℒSAPO​(ρ,A)={−A⋅σ(ρ−1τ+)⋅ρif ​A>0−A⋅σ(1−ρτ−)⋅ρif ​A≤0

其中 σ 是 sigmoid 函数,τ+,τ− 是非对称的 temperature 参数。temperature 越高,门控越柔和(探索更多);temperature 越低,则越接近硬裁剪。

TIS 与 MIS ——Truncated 与 Masked Importance Sampling

TIS 通过将梯度乘以一个截断后的修正因子来修正偏差:

wTIS​(oi)=min⁡(C,πtrain​(oi|q)πvllm​(oi|q)),

其中 πtrain 是训练前向传播得到的概率,πvllm 是 vLLM 报告的概率。在 C 处的截断可防止极端修正破坏训练稳定性。

MIS 采取更激进的做法:对任何修正比超过阈值 C 的序列,将其梯度置零:

wMIS(oi)=[πtrain​(oi|q)πvllm​(oi|q)≤C].

这种做法更保守,但避免了使用较大(即使是截断后的)修正权重的风险。

TIS 与 MIS 既可以应用在 token 级,也可以应用在序列级:

  • 序列级:把比值计算为所有 token 上的几何平均(如 GSPO 那样)。理论上正确,但方差更高。
  • token 级:为每个 token 分别计算比值。有偏(逐 token 修正的乘积并不等于序列修正),但方差更低。

VESPO ——Variational Sequence-Level Soft Policy Optimization

VESPO 从变分目标出发,为每条轨迹 τ 推导出加权函数 W⁡(τ)。最终的梯度权重形如:

g⁡(τ)=W​(τ)k⋅exp⁡(λ⁡(1−W⁡(τ))),

其中 W⁡(τ)=πθ​(τ)/πold​(τ) 是序列级重要性权重,k 控制加权的锐度,λ 控制对陈旧(低权重)轨迹的指数衰减。该核:

  • 在各处都平滑(裁剪边界处没有不连续的梯度)。
  • 通过指数项自然地降低陈旧轨迹(W≪1)的权重。
  • 是非对称的:高权重轨迹(W>1)与低权重轨迹的处理方式不同。

DPPO ——Direct Policy Divergence Policy Optimization

DPPO 直接用新旧策略分布之间的全变差(Total Variation, TV)或 KL 散度来计算信赖域约束:

ℒDPPO=−𝔼[A^⋅πθ(o|q)⋅𝟏[D(πθ∥πold)≤δ]],

其中 D 是所选用的散度度量。实践中,DPPO 用 token 级的二值掩码或 top-k 掩码来近似它:

  • binary_tv:屏蔽满足 |πθ−πold|>δ 的 token。
  • binary_kl:屏蔽满足 πθ​log⁡(πθ/πold)>δ 的 token。
  • topk_tv:仅保留按 TV 贡献排序的前 k 个 token。
  • topk_kl:仅保留按 KL 贡献排序的前 k 个 token。

ScaleRL 和 CISPO

标准 GRPO 在单个 prompt 的 G 条补全构成的组内对奖励做归一化。CISPO 则在整个 batch范围内对奖励做归一化:

A^i=ri−μbatchσbatch+ϵ,

其中 μbatch 和 σbatch 在当前训练 batch 的所有奖励(reward)上计算。这提供了更稳定的 baseline,并防止任何单一 prompt 主导 gradient。

CISPO 结合了 batch 级缩放、DAPO 的 token 级 loss 聚合以及非对称 clipping:

ℒCISPO=−1∑i,tmi,t∑i=1G∑t=1|oi|mi,t⋅min(ρi,tA^i,clipDAPO(ρi,t,A^i)A^i),

其中 mi,t 是过长过滤 mask。

GDPO ——Group Reward-Decoupled Policy Optimization

其核心机制是在聚合前独立归一化每项奖励:

A^n(i)=rn(i)−μnσn+ϵ,A^(i)=∑n=1NwnA^n(i),

其中 rn(i) 是补全(completion)i 的第 n 项奖励,μn 和 σn 是组内奖励 n 的均值与标准差,wn 是用户指定的权重。

GOPO ——Group Ordinal Policy Optimization

GOPO [54] 始于一个简单观察:奖励模型是用成对比较(“A 是否优于 B?”)训练的,因此只有其输出的排序是可信的——原始数值分数本身并没有内在含义。然而 GRPO 却把这些原始幅度直接喂入优势计算。对于奖励不可验证的任务——摘要、开放式对话、指令遵循——这种不匹配会引入噪声:在输出空间的某个区域,0.6 个奖励分的差距可能反映真实的质量差异,而在另一个区域却毫无意义。

关键洞见:完全丢弃奖励的幅度信息。只使用组内奖励的序数排名。

算法:给定一组 N 个响应 {o1,…,oN},其奖励为 {r1,…,rN}:

  1. 按奖励对响应排名:赋予排名 rank​(oi)∈{1,…,N}(1 = 最差,N = 最好)。
  2. 将原始优势替换为基于排名的分数:A^iGOPO=f⁡(rank​(oi)N)(7.2)其中 f 是单调变换(例如线性映射到 [−1,1],或分位数归一化)。
  3. 使用基于排名的优势,应用 PPO 风格的 clipped 目标函数。

与 GRPO 的对比:

方面GRPOGOPO优势信号A^i=(ri−μ)/σ(使用幅度)A^i=f⁡(ranki/N)(仅使用序数排名)对奖励量级的敏感度高——标定不当的 RM 分数会扭曲优势无——对单调奖励变换保持不变最适合的场景可验证的奖励(二值、标定良好)不可验证的奖励(基于 RM、量级含噪)

经验收益(在不可验证任务上相对 GRPO):

  • 奖励曲线(训练与 held-out)在整个优化过程中都高于 GRPO
  • 由独立 LLM 评估器判定的胜率在大多数训练 checkpoint 上都有提升
  • 收敛明显更快——用更少的 gradient step 达到 GRPO 的最终质量
  • 当奖励模型噪声更大或标定更差时,这一优势会更加明显