告别 PPO 与 DPO:深度解析 GRPO、DAPO 与 GSPO —— 下一代 LLM 对齐技术栈

The LLM Alignment Frontier A Deep Dive into PPO, DPO, GRPO, DAPO, and GSPO

在 2023-2024 年,RLHF(Reinforcement Learning from Human Feedback)的格局是二元对立的:

  1. PPO (Proximal Policy Optimization): 它是“正统”但昂贵的选择。为了维持训练稳定性,你不得不加载一个与 Policy Model 等大的 Critic Model (Value Network),这直接导致显存占用翻倍(2x Parameters + Optimizer States)。对于 70B+ 的模型,这意味着昂贵的 H100 集群成本。此外,PPO 的超参数敏感性(Hyperparameter Sensitivity)让无数工程师在 kl_coeffclip_range 的调优中崩溃。
  2. DPO (Direct Preference Optimization): 它是“高效”的替代品。通过将原本的 RL 问题转化为二分类(Preference Learning)问题,DPO 移除了 Critic Model。然而,到了 2025 年,我们发现 DPO 在 推理密集型任务(Reasoning/CoT) 上存在局限性。DPO 更多是在做“风格对齐”,而不是真正的“探索与利用(Exploration & Exploitation)”。它难以像 RL 那样通过尝试(Rollout)发现更优的解题路径。

现在的痛点是: 我们需要一种既能像 RL 那样具备强大“搜索”能力(激发 DeepSeek-R1 级别的推理能力),又不需要 PPO 那样昂贵显存开销的算法。

答案就是 Group-Based Policy Optimization 家族:GRPO、DAPO 与 GSPO。


🏗️ 架构演进:从 Token 级到 Group 级

1. GRPO (Group Relative Policy Optimization)

来源: DeepSeek-Math / DeepSeek-R1 Paper

GRPO 是这一波范式转移的基石。其核心创新在于彻底移除了 Critic Model

工作原理:
不同于 PPO 依赖 Value Network 来估计 Baseline ,GRPO 利用“群体统计”来作为 Baseline。
对于同一个 Prompt ,模型采样一组输出 (例如 )。
每个输出的优势函数(Advantage)通过组内归一化计算:

核心优势:

  • 显存节省: 只需要加载 Policy Model 和 Reference Model(用于 KL 散度计算)。
  • 适合推理: 通过采样多个 Path,模型能自动学会“哪种推理步骤更好”,非常适合数学和代码任务。

2. DAPO (Decoupled Clip & Dynamic Sampling)

来源: DAPO Paper (ArXiv 2025)

虽然 GRPO 解决了显存问题,但在长思维链(Long Chain-of-Thought)训练中容易出现熵坍塌(Entropy Collapse)和训练不稳定的问题。DAPO 是针对大规模推理训练的优化版。

关键改进:

  • Clip-Higher: 传统的 PPO/GRPO 限制更新幅度(Clip)。DAPO 发现对于推理任务,通过放宽上限(Clip-Higher),可以防止模型过早收敛到局部最优,保持多样性。
  • Dynamic Sampling: 动态过滤掉那些“全对”或“全错”的 Prompt 组。如果一组采样 个全是满分或全是零分,梯度就没有区分度(Variance=0),纯属浪费算力。DAPO 动态重采样以保证梯度的有效性。

3. GSPO (Group Sequence Policy Optimization)

来源: GSPO Paper (ArXiv 2025)

当你将模型扩展到 MoE (Mixture of Experts) 架构(如 Qwen3-MoE 或 DeepSeek-V3)时,Token 级的 GRPO 更新可能会因为 Expert 路由的稀疏性导致不稳定。

核心逻辑:
GSPO 将优化粒度从 Token 级 提升到了 Sequence 级

  • Token-level (GRPO): 每个 Token 都有自己的 Importance Ratio。
  • Sequence-level (GSPO): 整个序列共享一个 Importance Ratio。

这种方法在训练超大模型时表现出了极强的鲁棒性,尤其是在防止 MoE 模型的 Router 崩溃方面。


📊 算法决策矩阵

特性 PPO DPO GRPO DAPO GSPO
Critic Model ✅ 需要 (昂贵) ❌ 不需要 ❌ 不需要 ❌ 不需要 ❌ 不需要
主要场景 通用 RLHF 聊天/风格对齐 数学/代码/推理 长文本推理 (CoT) MoE/超大模型训练
显存占用
实现复杂度 极高
稳定性 低 (敏感) 极高

💻 实施:使用 TRL 实现 GRPO

截至 2025 年底,Hugging Face 的 trl 库已经原生支持 GRPO。这是目前大多数工程团队的首选落地路径。

1. 环境准备

pip install trl transformers accelerate bitsandbytes

2. 核心代码实现 (GRPOTrainer)

注意: 这里的关键在于 Reward Function 的设计。GRPO 非常适合 Rule-based Reward(如代码通过率、数学答案匹配)。

import torch
from datasets import load_dataset
from trl import GRPOTrainer, GRPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM

# 1. 配置路径与模型
model_id = "deepseek-ai/deepseek-r1-distill-llama-8b"
output_dir = "./grpo_reasoning_v1"

# 2. 定义奖励函数 (Reward Functions)
# GRPO 支持多个奖励函数并行,最终奖励是它们的加权和或直接求和
def correctness_reward_func(prompts, completions, answer, **kwargs):
    """
    检查补全内容是否包含正确答案。
    """
    rewards = []
    for completion, gold_answer in zip(completions, answer):
        # 简单的字符串匹配逻辑,实际场景可用更复杂的解析器
        if str(gold_answer) in completion:
            rewards.append(1.0)
        else:
            rewards.append(0.0)
    return rewards

def format_reward_func(completions, **kwargs):
    """
    强制模型输出特定的 CoT 格式,例如 <think>...</think>
    """
    rewards = []
    for completion in completions:
        if "<think>" in completion and "</think>" in completion:
            rewards.append(0.5)
        else:
            rewards.append(0.0)
    return rewards

# 3. 加载数据集
# 假设是一个包含 'prompt' 和 'answer' 列的数据集
dataset = load_dataset("json", data_files="math_reasoning_data.jsonl", split="train")

# 4. 配置 GRPO
training_args = GRPOConfig(
    output_dir=output_dir,
    num_train_epochs=1,
    per_device_train_batch_size=4,  # 显存允许的情况下尽量大
    gradient_accumulation_steps=4,
    learning_rate=5e-6,             # GRPO 通常需要较低的 LR
    logging_steps=10,
    max_completion_length=1024,     # 确保足够长以容纳 CoT
    num_generations=8,              # G: 每个 Prompt 采样的数量 (Group Size)
    beta=0.04,                      # KL 惩罚系数
    fp16=True,
)

# 5. 初始化 Trainer
# GRPOTrainer 自动处理 Policy Model 的加载和 Group Sampling
trainer = GRPOTrainer(
    model=model_id,
    args=training_args,
    train_dataset=dataset,
    reward_funcs=[correctness_reward_func, format_reward_func],
)

# 6. 开始训练
print("🚀 Starting GRPO Training...")
trainer.train()
trainer.save_model(output_dir)

🛠️ 落地执行清单

  1. 数据清洗 (Crucial): GRPO 依赖于模型在探索中偶然“撞”对答案。如果你的 Base Model 连 1% 的正确率都没有,GRPO 无法启动(Cold Start Problem)。
  • Action: 先做一轮 SFT (Supervised Fine-Tuning),使用高质量的 CoT 数据(如 OpenO1 或 DeepSeek 蒸馏数据),确保模型懂得基本的 <think> 格式。
  1. Reward Engineering: 不要只用一个 Sparse Reward(对/错)。
  • Action: 混合 Process Reward(格式正确、步骤清晰)和 Outcome Reward(答案正确)。
  1. Group Size ():
  • Action: 只要显存允许, 越大越好。推荐 。更大的 Group Size 能提供更准确的 Baseline 估计。
  1. 监控 KL 散度:
  • Action: 即使没有 Critic,KL 爆炸依然是训练崩溃的主因。如果在 TensorBoard 看到 KL 飙升,增大 beta 或减小 learning_rate

PPO 的时代并未结束,但在推理(Reasoning)和代码生成领域,GRPO 及其变体 (DAPO/GSPO) 已经确立了统治地位。它们用更少的显存换取了更强的探索能力。

  • 如果是常规微调:GRPO 是目前的 Sweet Spot。
  • 如果遇到长文本 CoT 不稳定:尝试 DAPO 的 Dynamic Sampling 策略。
  • 如果训练 MoE 巨型模型:必须上 GSPO

现在,去重构你的 Training Pipeline 吧。