大模型后训练全解:SFT、RLHF/PPO、DPO 的原理、实践与选择

本文覆盖范围:SFT 监督微调、RLHF(PPO)强化学习对齐、DPO 直接偏好优化,以及它们的变体、工具链、实战代码和选择决策。结合 InstructGPT、LLaMA 2/3、Zephyr、DeepSeek-R1、Qwen3 等真实案例说明。


一、为什么需要后训练(Post-Training)?

预训练(Pre-Training)让一个语言模型学会了"下一个 token 是什么"------它掌握了语言规律、广博的世界知识、甚至初步的推理能力。但预训练的优化目标是最大化训练语料的对数似然,这意味着模型学会的是"互联网平均水平的文字接龙",而不是"对人类有帮助、无害、诚实的回答"。

给一个纯预训练模型发送"帮我写一封道歉信",它可能会继续生成"帮我写一封道歉信的示例......"或者索性开始胡说八道------因为训练数据里这类格式的文本不少。它不理解"用户"和"助手"的角色关系,不知道什么是有用的回答,也不懂得拒绝有害请求。

后训练(Post-Training)正是解决这个问题的一套流程,其核心目标是:

  • 行为对齐(Behavioral Alignment):让模型按照指令行事,而不只是续写文本
  • 偏好对齐(Preference Alignment):让模型的输出符合人类的价值偏好(有用、无害、诚实)
  • 能力激活(Capability Activation):激发模型在推理、代码、数学等特定领域的潜力

一个完整的后训练历史可以分为三个阶段:第一阶段,InstructGPT 提出了 SFT + RLHF 的标准流程,让模型能够遵循指令,代表模型是 GPT-3.5 和早期 ChatGPT;第二阶段,DPO 通过消除独立奖励模型降低了对齐的复杂度,让中小团队也能做对齐,代表模型是 Zephyr、Intel NeuralChat、早期 LLaMA 微调版本;第三阶段,DeepSeek-R1 证明了纯 RL 能产生突破性推理能力,GRPO 成为标准,代表模型是 DeepSeek-R1、QwQ、Kimi k1.5。

理解这三个阶段,就等于理解了整个后训练技术的演化逻辑。下面我们逐一深入。


二、SFT:监督微调,一切的起点

2.1 什么是 SFT?

SFT(Supervised Fine-Tuning,监督微调)是后训练的第一步,也是最直观的一步:给模型看大量高质量的(指令,回答)对,用标准的交叉熵损失训练模型去模仿这些示范回答。

从优化角度,SFT 的损失函数是:

其中 是指令(prompt), 是期望的回答, 是模型。这与预训练的语言建模损失在形式上完全一样,差别只在于:SFT 的数据是精心设计的高质量(指令, 回答)对,而且只在回答部分计算 loss,不对指令部分计算 loss(让模型学会"如何回答",而不是"如何提问")。

这一点在代码上体现为:将指令部分的 token 的 label 设置为 -100(PyTorch 会忽略 label=-100 的位置),只让模型在回答 token 上反向传播。

2.2 SFT 数据的格式

现代大模型的 SFT 数据通常用 ChatML 格式组织多轮对话:

复制代码
<|im_start|>system
你是一个有帮助的助手。<|im_end|>
<|im_start|>user
帮我解释一下什么是黑洞。<|im_end|>
<|im_start|>assistant
黑洞是宇宙中一种极端的天体,其引力强到连光都无法逃脱......<|im_end|>

这种格式明确区分了系统提示、用户输入和模型回答,让模型学会角色扮演。

2.3 SFT 用在哪些模型中?

Stanford Alpaca(2023):最早的开源 SFT 实验之一。用 GPT-3.5 生成的 52K 条指令-回答对,对 LLaMA-7B 做 SFT,就能得到一个基本能对话的模型。成本极低但效果惊人,开启了"用 AI 生成 SFT 数据"的先河。

InstructGPT(OpenAI, 2022):SFT 是 RLHF 三阶段流程的第一步。先用人工标注的约 13000 条(prompt, 演示回答)对做 SFT,得到一个基础对话模型,再继续做 RLHF。

LLaMA 2-Chat(Meta, 2023):在经过 SFT 预热后,再做 RLHF(迭代式 PPO + 拒绝采样)。SFT 数据来自 Meta 内部的人工标注对话。

DeepSeek-R1-Distill 系列:通过对 LLaMA 3 和 Qwen2.5 基座模型,用 DeepSeek-R1 生成的 80 万条长链式推理(CoT)数据做 SFT,直接蒸馏出了具备推理能力的小模型------完全不用 RL。这说明 SFT 在数据质量足够高时,能够有效传递大模型的推理模式。

2.4 SFT 的局限性

SFT 的本质是模仿学习(Imitation Learning),它有两个根本局限:

第一,覆盖范围限于训练数据。模型只能学到训练数据中展示过的行为模式。对于训练数据没有涉及的新场景,SFT 模型的泛化能力有限。

第二,无法表达"哪个更好"。SFT 给模型展示的是"正确"答案,但没有展示"哪种正确答案更好"。对于同一个问题,简洁清晰的回答和冗长啰嗦的回答,在 SFT 的 loss 里差别不大------只要都是"正确"的。

第二个局限正是 RLHF 和 DPO 要解决的问题。

2.5 用 TRL 的 SFTTrainer 做实战

HuggingFace TRL 库提供了 SFTTrainer,封装了 SFT 的完整流程:

python 复制代码
from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import SFTConfig, SFTTrainer
from peft import LoraConfig

# 加载基础模型
model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2.5-7B",
    torch_dtype="auto",
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B")

# LoRA 配置:只训练部分参数,节省显存
lora_config = LoraConfig(
    r=64,
    lora_alpha=128,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM"
)

# 加载对话数据集(ChatML 格式)
dataset = load_dataset("trl-lib/Capybara", split="train")

# SFT 训练配置
sft_config = SFTConfig(
    output_dir="./sft_output",
    num_train_epochs=3,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    learning_rate=2e-4,
    warmup_ratio=0.03,
    lr_scheduler_type="cosine",
    bf16=True,
    logging_steps=10,
    save_steps=500,
    max_length=2048,
    # 关键:只在 assistant 的回答部分计算 loss
    dataset_text_field="messages",
)

trainer = SFTTrainer(
    model=model,
    args=sft_config,
    train_dataset=dataset,
    peft_config=lora_config,
    tokenizer=tokenizer,
)

trainer.train()
trainer.save_model("./sft_final")

对于自定义数据集,数据格式需要包含 messages 字段,每条样本是一个对话列表:

复制代码
# 自定义数据集格式
{
    "messages": [
        {"role": "system", "content": "你是一个专业的法律顾问。"},
        {"role": "user", "content": "合同违约怎么处理?"},
        {"role": "assistant", "content": "合同违约的处理方式包括......"}
    ]
}

TRL 的 SFTTrainer 会自动检测对话格式,应用对应的 chat template,并将 assistant 之外的 token 的 label 设为 -100。


三、RLHF:用人类反馈做强化学习

3.1 为什么需要 RLHF?

SFT 之后,模型已经能按格式回答问题了,但回答质量的细微差别------是否更有帮助、是否更安全、语气是否合适------SFT 数据难以精确刻画。

这里有一个著名的洞察,来自 InstructGPT 论文:与其让标注员写出"完美答案"(这很难),不如让他们比较两个答案哪个更好(这相对容易)。人类擅长做评判,不擅长从头创作完美示范。

RLHF(Reinforcement Learning from Human Feedback)正是利用了这一点:收集人类对模型输出的偏好比较,训练一个奖励模型来量化这种偏好,然后用强化学习(通常是 PPO)来优化模型使其最大化奖励模型的得分。

3.2 RLHF 的三个阶段

阶段一:SFT(已覆盖)

预训练模型 → SFT 微调 → 得到 ,作为后续的初始策略和参考模型。

阶段二:训练奖励模型(Reward Model, RM)

收集偏好数据:对同一个 prompt,让 SFT 模型生成多个回答,让人工标注员对这些回答进行排序(哪个更好)。这个排序数据被整理成对 ,其中 是被偏好的(chosen)回答, 是被拒绝的(rejected)回答。

奖励模型的训练目标是:让 ,即给好的回答打更高的分。标准做法是在 SFT 模型的基础上添加一个回归头(regression head),训练损失为:

这是一个 Bradley-Terry 模型------只关心两个回答奖励分的相对大小,不需要绝对分数。

阶段三:用 PPO 做强化学习

有了奖励模型,现在把语言模型的生成过程视为一个强化学习问题:

  • 状态(State):当前的 prompt 和已生成的 token 序列
  • 动作(Action):生成下一个 token(词表大小的离散动作空间)
  • 奖励(Reward):只在序列结束时给予一次奖励(来自奖励模型的评分)

问题是奖励函数不连续、序列很长(稀疏奖励),直接做梯度优化困难。PPO 通过重要性采样和 clip 操作解决了训练稳定性问题,同时加入 KL 散度约束防止模型偏离 SFT 版本太远。在3.3中详细补充解释了使用PPO的重要性。

完整的 PPO 优化目标是:

其中 是 KL 惩罚系数。KL 项有两个作用:防止奖励黑客(reward hacking,模型学会用奇怪的方式骗过奖励模型而不是真正有用);防止模型能力退化(偏离 SFT 太远会丢失已学到的知识)。

3.3 语言模型的 RL 难题,以及 PPO 如何解决它

要理解为什么 PPO 是 RLHF 的标准算法,需要先搞清楚"直接用 RL 优化语言模型"面临哪些根本性困难。

困难一:动作空间是离散的,无法直接求梯度

强化学习的目标是最大化期望累积奖励。在连续动作空间(比如控制机器人关节角度)里,可以直接对动作求梯度,用梯度上升来改进策略。

但语言模型的"动作"是从词表中采样一个 token------这是一个离散的采样操作。离散采样不可微,梯度无法通过采样操作反向传播回模型参数。这意味着你没法用一个简单的 loss.backward() 来更新模型,RL 必须用策略梯度(Policy Gradient)方法:通过"好的回答就增大其概率,坏的回答就减小其概率"这样的估计来间接更新参数。

困难二:稀疏奖励

一个完整的回答可能有几百到几千个 token。但奖励模型只在整条回答生成完毕之后,对整个回答打一个分数------这就是稀疏奖励(Sparse Reward)。

"稀疏"的意思是:模型在生成过程中,对每一步(每个 token)的决策都是在"盲飞",没有任何即时信号告诉它这一步走得好不好,直到最后才得到一个全局评分。举个极端的例子:生成了 500 个 token,奖励模型打了 6 分。你不知道是前 100 个 token 写得好、还是后 100 个,还是某个关键转折点决定了这个分。

这种信用分配(credit assignment)问题让训练极其困难------模型很难从稀疏信号中学到"哪一步导致了好结果"。

困难三:每步 policy 更新后数据立即过期

策略梯度方法要求用"当前策略"生成的数据来计算梯度更新当前策略(on-policy)。这意味着每次更新模型参数之后,刚才生成的那批数据就作废了,必须重新采样------计算效率极低。

更糟的是,如果你想多次利用同一批数据做几步梯度更新(提升数据效率),每更新一步,当前策略就和生成数据时的旧策略之间的差距就大了一步。如果差距太大,梯度估计就会偏差很大,甚至导致策略崩溃(更新步子太大,模型直接退化)。


PPO 如何解决这三个问题

PPO(Proximal Policy Optimization,近端策略优化)是一个策略梯度算法,专门为解决上面第三个问题------"如何安全地多次利用旧数据"------而设计的,同时配合其他机制处理前两个问题。

重要性采样(Importance Sampling):让旧数据可以复用

核心思路是:用当前策略 的期望奖励来表达,但实际采样来自旧策略 ,通过乘以一个修正系数(重要性权重)来补偿两者之间的分布差异:

这个比值 就是重要性权重。当 时,说明当前策略比旧策略更倾向于生成这个 token; 则相反。通过乘以这个比值,就可以用旧数据来近似估计当前策略的梯度。

但问题是:如果 差距太大,这个比值可以变得非常大或非常小,导致梯度估计方差爆炸,更新极不稳定。

Clip 截断:给更新幅度加保险

PPO 的核心创新就在这里------对重要性权重进行截断(clip),防止单步更新幅度过大:

其中 通常取 0.1 或 0.2。这个公式的含义是:

  • 如果 (这个 token 是好的,应该增大概率),当 时,梯度被截断------不允许当前策略比旧策略在这个方向上走太远
  • 如果 (这个 token 是坏的,应该减小概率),当 时,同样截断

min 的目的是:总是选择"更保守"的那个估计,确保策略更新是悲观的而非激进的。这个简单的截断操作使得 PPO 在实践中极其稳定,即便在每批数据上做多次梯度更新也不容易崩溃。

优势函数(Advantage):解决稀疏奖励的信号分配

策略梯度不能直接用原始奖励 ,而是用优势函数 。优势函数的定义是:在状态 下采取动作 的实际回报,与该状态下平均期望回报之差:

其中 是价值函数(当前状态的期望回报), 是采取了动作 之后的实际累积回报。 意味着这步动作比平均水平好,应该增强; 意味着比平均水平差,应该抑制。

用优势而非原始奖励的好处是:减少了梯度估计的方差(即使奖励绝对值很大,优势函数代表的是相对增益,更稳定),并且通过价值函数 对奖励信号做了时序上的分解,缓解了稀疏奖励带来的信用分配问题。

但要计算 ,你需要一个能估计"当前序列接下来能拿多少分"的网络------这就是 Critic 模型的来历。


为什么 PPO 需要四个模型

这里从头捋清楚。在进入 PPO 阶段之前,已经存在三个模型:

① SFT 模型(Reference Model,参考模型)

SFT 阶段训练完的模型,在 PPO 阶段被冻结,不参与训练。它的作用是提供 KL 散度约束的基准------PPO 在优化策略模型时,会惩罚策略模型与 SFT 模型之间的 KL 散度过大。这防止了奖励黑客:如果策略模型可以无限偏离 SFT 模型,它可能会学会用乱码或奇怪格式来骗奖励模型打高分,同时完全丧失语言能力。冻结的参考模型是一个"语言能力的锚点"。

② 奖励模型(Reward Model,RM)

用人类偏好数据(chosen/rejected 对)单独训练的一个打分网络,在 PPO 阶段也被冻结。它负责对策略模型生成的每条完整回答给出一个标量分数,这个分数就是稀疏奖励信号的来源。没有奖励模型,PPO 就不知道往哪个方向优化。

这两个模型(参考模型和奖励模型)加在一起,就是 RLHF 体系在进入 PPO 前就需要准备好的部分。

③ Actor 模型(策略模型,Policy)

这是我们真正要训练的目标模型,初始化自 SFT 模型,在 PPO 过程中持续更新。它负责接收 prompt,生成回答,参数不断被梯度更新。

④ Critic 模型(价值模型,Value Model)

如上所述,Critic 是 PPO 引入的额外模型,负责估计当前状态(已生成的序列)的期望未来奖励 ,用于计算优势函数 。没有 Critic,PPO 无法计算优势,只能用原始奖励做策略梯度,方差极大,训练极不稳定。

Critic 通常初始化自奖励模型(因为奖励模型已经理解了"什么样的输出是好的"),并在训练过程中与 Actor 一起更新。在实现上,Critic 的大小通常与 Actor 相同------因为它需要处理同样的长序列输入,同样需要深度理解语义。


四个模型的协作流程是这样的:

这四个模型在训练时通常需要同时保持在 GPU 内存中(或通过 offload 换出),这正是 PPO-RLHF 内存开销极大的根本原因。对于一个 7B 的 Actor,在 BF16 下约需 14GB;Critic 同样 14GB;Reference 14GB;RM 14GB------合计约 56GB,还不算梯度、优化器状态、激活值。这就是为什么完整的 PPO-RLHF 需要多卡甚至大规模集群,也是 DPO(只需 Actor + Reference,两个模型)和 GRPO(消除 Critic)被广泛采用的核心动机。

3.4 真实案例:InstructGPT 和 LLaMA 2

InstructGPT(OpenAI, 2022):标准 RLHF 三阶段流程的教科书案例。用约 33000 个偏好比较对训练奖励模型,用 PPO 对策略模型做 RL 优化。论文中著名的结论是:经过 RLHF 的 1.3B 参数模型在人类偏好评分上超过了未经 RLHF 的 175B 参数模型------说明对齐的重要性远超单纯的参数规模。

LLaMA 2-Chat(Meta, 2023):Meta 的 LLaMA 2-Chat 模型通过对大规模助手风格语料做 SFT,然后用迭代式 RLHF 训练。训练了独立的有用性和安全性奖励模型,使用来自 Meta 自身聊天数据集的数百万人类偏好比较。RLHF 在拒绝采样和 PPO 步骤之间交替进行。

3.5 RLHF 的局限性

RLHF/PPO 的工程复杂度和计算成本极高,而且存在以下问题:

奖励黑客(Reward Hacking):模型学会了取悦奖励模型而不是真正有用。例如,某些奖励模型喜欢长回答,模型就会不断生成冗余内容来刷高分,而不是给出简洁有效的回答。

训练不稳定:PPO 本身就对超参数敏感,在语言模型这种极大的动作空间(词表大小的动作)上更难调优。

数据收集成本:收集高质量的人类偏好标注数据成本高昂,且难以规模化。

这些局限性催生了 DPO 的出现。


四、DPO:把 RLHF 重新表述为分类问题

4.1 DPO 的核心洞察

DPO(Direct Preference Optimization,直接偏好优化)由 Rafailov et al. 在 2023 年提出,它的出发点是:RLHF 的 PPO 优化步骤是否真的必要?

答案是------在某些条件下,不必要。DPO 论文的关键贡献是一个数学推导,证明了:在 RLHF 的 KL 约束优化问题中,最优策略 与参考策略 之间存在一个闭合形式的关系,可以直接用来绕过奖励模型的显式训练。

推导步骤如下:

第一步:RLHF 的优化目标(带 KL 约束):

第二步 :可以证明,该优化问题的最优解 满足:

其中 是归一化常数。

第三步 :从上式反解出奖励函数

第四步 :将这个表达式代入 Bradley-Terry 奖励模型的偏好概率公式, 被约掉,得到 DPO 的损失函数:

这个公式可以用语言来解读:DPO 希望模型在偏好回答 上的相对提升 (相比参考模型)大于在拒绝回答 上的相对提升 。简单说:让好的回答的概率增大,让坏的回答的概率减小,同时约束不要偏离参考模型太远(由 控制)。

这里的关键字是"相对" :DPO 不是直接最大化 ,而是最大化 的差距。(冻结的 SFT 模型)起到了归一化的作用。

4.2 DPO 的优势与代价

优势:

  • 不需要显式训练奖励模型
  • 不需要 PPO 的复杂 RL 循环
  • 只需要 Actor 和 Reference 两个模型(内存需求减半)
  • 训练稳定,像普通的有监督训练一样,超参数易调

代价:

  • 依赖静态的离线偏好数据(offline)------如果数据是由另一个模型生成的,DPO 是"off-policy"的,效果可能不如 on-policy 的 PPO
  • DPO 的隐式奖励无法用于其他目的(如奖励信号用于 RL 探索)
  • 数据质量高度依赖偏好对的质量

4.3 DPO 在真实模型中的应用

Zephyr-7B(HuggingFace, 2023):Mistral-7B 基础上,用 ChatGPT 生成大规模合成数据集(UltraChat),再用奖励集成模型(UltraFeedback)打分得到偏好对,最后用 dDPO(蒸馏版 DPO)训练。这是 DPO 在开源生态的第一批成功案例之一。

LLaMA 3(Meta, 2024):DPO 也被用在 LLaMA-3 的后训练流程中,Meta 不满足于纯 PPO 的复杂性,引入了 DPO 进行偏好对齐。

DeepSeek LLM(DeepSeek, 2024):DeepSeek LLM 没有使用流行的 RLHF,而是选择了 DPO 进行人类偏好对齐。这种方法直接将两个不同生成结果之间的概率差异作为训练目标,相比 RL 更直观,更易于设计。

4.4 DPO 的变体

自 DPO 提出以来,研究社区提出了大量变体,每个都在解决 DPO 的某个具体问题:

IPO(Identity Preference Optimization):DPO 在某些条件下可能过拟合偏好对,IPO 通过直接对偏好概率做约束来解决。

KTO(Kahneman-Tversky Optimization):不需要偏好对(chosen/rejected)数据,只需要(prompt, response, 是否满意)的二元标注,数据收集成本更低。

SimPO(Simple Preference Optimization):用序列的平均对数概率(而非所有 token 的对数概率之和)计算奖励,减少了对生成长度的偏见,不需要参考模型,效果在很多任务上超过 DPO。

Online DPO(在线 DPO):用当前模型(而非历史模型)实时生成偏好对,变成"on-policy"训练。研究表明在线 DPO 效果显著优于离线 DPO。

ORPO(Odds Ratio Preference Optimization):把 SFT 损失和偏好对齐损失合并为一步,不需要参考模型,一步完成 SFT + 对齐。

4.5 用 TRL 的 DPOTrainer 做实战

以下是一个完整的 DPO 训练流程,包括数据准备和训练:

python 复制代码
from datasets import load_dataset, Dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import DPOConfig, DPOTrainer
from peft import LoraConfig
import torch

# 1. 加载 SFT 之后的模型作为起点
model = AutoModelForCausalLM.from_pretrained(
    "./sft_final",          # 用上一步 SFT 训练好的模型
    torch_dtype=torch.bfloat16,
    device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("./sft_final")

# 2. 偏好数据集格式:每条样本需要 prompt, chosen, rejected 三个字段
# 使用 UltraFeedback 二元偏好数据集
dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train")
# 该数据集的格式:{"prompt": [...], "chosen": [...], "rejected": [...]}
# 其中 prompt/chosen/rejected 均为 messages 列表(ChatML 格式)

# 3. 也可以自定义偏好数据集
def create_preference_dataset():
    data = [
        {
            "prompt": [{"role": "user", "content": "解释量子纠缠"}],
            "chosen": [{"role": "assistant", "content": "量子纠缠是指两个或多个粒子...(详细准确的解释)"}],
            "rejected": [{"role": "assistant", "content": "量子纠缠就是两个东西纠缠在一起,没什么好解释的。"}],
        },
        # 更多样本...
    ]
    return Dataset.from_list(data)

# 4. DPO 训练配置
dpo_config = DPOConfig(
    output_dir="./dpo_output",
    num_train_epochs=1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    learning_rate=5e-7,         # DPO 的学习率应比 SFT 小得多
    beta=0.1,                   # KL 惩罚系数,控制偏离参考模型的程度
    warmup_ratio=0.1,
    bf16=True,
    logging_steps=10,
    save_steps=500,
    # 重要:不要设置 max_length,防止截断偏好对
    max_length=None,
    max_prompt_length=512,
)

# 5. LoRA 配置(DPO 也支持 PEFT)
peft_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    task_type="CAUSAL_LM"
)

# 6. DPOTrainer 自动处理 reference model
# 如果传入 peft_config,ref_model 会自动从 model 的 base model 创建
trainer = DPOTrainer(
    model=model,
    ref_model=None,          # 使用 LoRA 时设为 None,TRL 会自动处理
    args=dpo_config,
    train_dataset=dataset,
    peft_config=peft_config,
    tokenizer=tokenizer,
)

trainer.train()

# 7. DPO 训练完成后,合并 LoRA 权重
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(
    "./sft_final", torch_dtype=torch.bfloat16
)
peft_model = PeftModel.from_pretrained(base_model, "./dpo_output/checkpoint-xxx")
merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("./dpo_final")

关于 beta 参数 :这是 DPO 最重要的超参数。beta 越大,对偏离参考模型的惩罚越重,模型改变越保守;beta 越小,模型能更自由地向偏好方向优化,但也更可能过拟合或退化。通常取值范围是 0.01~0.5,0.1 是常用的默认值。


五、GRPO:DeepSeek-R1 的新范式

严格来说 GRPO 属于 RLHF 的变体,但它的影响力足以单独成章,尤其是在推理模型的训练上。

5.1 GRPO 的动机:消除 Critic 模型

PPO 需要一个与 Actor 等大的 Critic 模型来估计状态价值函数(Value Function),作为计算优势函数(Advantage)的基线。这个 Critic 模型是 RLHF/PPO 内存开销巨大的主要来源之一。

GRPO(Group Relative Policy Optimization)的思路是:用同一 prompt 的多个采样回答的平均奖励作为基线,代替 Critic 模型 。对于每个 prompt,生成一组 个回答 ,用可验证奖励函数评分,然后用组内归一化的相对奖励作为每个回答的优势:

这样完全不需要 Critic 模型,内存减少约 25%~50%(取决于具体实现)。

5.2 GRPO 与可验证奖励(RLVR)

GRPO 特别适合与可验证奖励(Verifiable Rewards)结合。可验证奖励是指可以用程序判断对错的任务:数学题(答案是否正确)、代码(是否能通过测试用例)、逻辑推理(结论是否有效)。

DeepSeek-R1 使用了 RLVR(Reinforcement Learning with Verifiable Rewards)结合 GRPO,完全绕开了人类偏好和奖励模型。与标准 RLHF 不同,RLVR 从确定性工具(如计算器、编译器)获取直接的二元反馈(正确或错误),而不是从人工标注示例中学习什么是"好"答案。

这一方案的优势是彻底:不需要人工标注偏好,不需要奖励模型,奖励信号来自程序化验证,无法被"黑客"。DeepSeek-R1 的成功证明了这条路线的可行性,也直接催生了整个开源推理模型生态(QwQ、Kimi k1.5、Qwen3 的 Thinking 模式等)。

用 TRL 训练 GRPO 的最简示例:

python 复制代码
from datasets import load_dataset
from trl import GRPOTrainer, GRPOConfig
from trl.rewards import accuracy_reward  # 内置的准确率奖励函数

# 数学推理数据集
dataset = load_dataset("trl-lib/DeepMath-103K", split="train")

config = GRPOConfig(
    output_dir="./grpo_output",
    num_train_epochs=1,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=16,
    learning_rate=1e-6,
    num_generations=8,       # 每个 prompt 采样 8 个回答
    max_new_tokens=512,
    bf16=True,
)

trainer = GRPOTrainer(
    model="Qwen/Qwen2.5-7B-Instruct",
    reward_funcs=accuracy_reward,   # 可验证的答案准确率奖励
    args=config,
    train_dataset=dataset,
)
trainer.train()

六、方法选择:什么时候用哪个?

这是最实际的问题。下面用几个维度帮你做决策。

6.1 按任务目标选择

你的目标是让模型学会某个特定领域的知识或格式SFT

例如:让通用模型学会回答医疗问诊、提取结构化信息、按特定格式输出 JSON、学习公司内部 FAQ。这类任务的关键在于数据质量,有 500~5000 条高质量的(指令, 回答)对,SFT 通常就足够了。不需要 RLHF 或 DPO。

你的目标是让模型的回答风格更贴合人类偏好(更友好、更安全、更有帮助)DPO(优先)或 RLHF

例如:通用对话助手的偏好对齐、减少有害内容、改善回答的礼貌程度。如果资源有限,DPO 是首选------它稳定、高效,数据要求相对低(只需偏好对,不需要复杂的 RL 基础设施)。

你的目标是提升数学、代码、推理等可验证任务的能力GRPO/RLVR

如果任务的对错可以用程序验证,GRPO + 可验证奖励是目前最有效的方案,也是 DeepSeek-R1、Qwen3 Thinking 等模型的核心路线。

你的目标是通用旗舰模型,追求极致的对话质量SFT → RLHF(PPO)

这是 OpenAI(GPT-4)、Anthropic(Claude)等顶级实验室的路线,效果最好,但需要巨大的工程投入和人工标注成本,不适合中小团队。

6.2 按资源约束选择

约束条件 推荐方法
单卡 24G 显存,快速验证 SFT + LoRA,或 DPO + LoRA
多卡服务器(4×80G),中等规模 DPO 全参数,或 SFT → DPO 两阶段
大规模集群(100+ GPU) SFT → RLHF(PPO),或 SFT → GRPO
无 GPU,只有 API 预算 用 GPT-4 生成 SFT 数据,再 SFT 小模型
无标注预算 用 AI 模型(如 GPT-4)生成偏好数据,再 DPO

6.3 按数据类型选择

数据类型 推荐方法
高质量(指令, 回答)对 SFT
(prompt, 好回答, 坏回答)偏好三元组 DPO
(prompt, 回答, 满意/不满意)二元标注 KTO
数学/代码题目 + 正确答案 GRPO + 可验证奖励
人工排序的多个回答 RLHF(PPO)

6.4 现实的流水线建议

新兴共识是一个模块化流水线:SFT 用于指令遵循 → DPO/SimPO 用于通用偏好对齐 → GRPO/DAPO 结合可验证奖励用于推理能力。每一层解决不同类型的对齐问题------行为对齐、偏好对齐和逻辑对齐。

对于大多数工程实践者,以下两种组合最常见:

方案 A(通用对话模型)SFT(1-3轮)→ DPO(1轮) 这是 Zephyr、LLaMA 3 Instruct 等开源模型常用的轻量路线,效果稳定,工程简单。

方案 B(推理/代码模型)SFT 冷启动(少量 CoT 数据)→ GRPO/RLVR(大量可验证任务) 这是 DeepSeek-R1、Qwen3 Thinking 的路线,适合以推理能力为核心目标的模型。


七、完整工具链

7.1 HuggingFace TRL

TRL(Transformer Reinforcement Learning)是目前最广泛使用的后训练框架,支持:

Trainer 用途
SFTTrainer 监督微调
RewardTrainer 训练奖励模型
DPOTrainer DPO 及其变体(SimPO, IPO, KTO 等)
PPOTrainer 标准 RLHF PPO
GRPOTrainer GRPO(DeepSeek-R1 的方法)
ORPOTrainer ORPO(SFT + 对齐一步完成)

TRL 还提供了命令行接口,可以不写代码直接训练:

bash 复制代码
# SFT 训练
trl sft \
    --model_name_or_path Qwen/Qwen2.5-7B \
    --dataset_name trl-lib/Capybara \
    --output_dir ./sft_output \
    --num_train_epochs 3 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --learning_rate 2e-4 \
    --use_peft \
    --lora_r 64 \
    --bf16

# DPO 训练
trl dpo \
    --model_name_or_path ./sft_output \
    --dataset_name trl-lib/ultrafeedback_binarized \
    --output_dir ./dpo_output \
    --beta 0.1 \
    --learning_rate 5e-7 \
    --use_peft \
    --lora_r 16

7.2 ModelScope ms-swift

ms-swift 是 ModelScope 社区提供的大模型微调框架,支持 600+ LLM 和 400+ 多模态大模型的全参数或 PEFT 微调,包括 SFT、DPO、GRPO 等方法,以及 Megatron 并行训练技术。

bash 复制代码
# DPO 微调 Qwen3
CUDA_VISIBLE_DEVICES=0 swift rlhf \
    --rlhf_type dpo \
    --model Qwen/Qwen3-4B-Instruct \
    --dataset hjh0119/shareAI-Llama3-DPO-zh-en-emoji \
    --tuner_type lora \
    --output_dir output

# GRPO 微调
CUDA_VISIBLE_DEVICES=0,1,2,3 NPROC_PER_NODE=4 swift rlhf \
    --rlhf_type grpo \
    --model Qwen/Qwen3-4B-Instruct \
    --use_vllm true \
    --dataset AI-MO/NuminaMath-TIR \
    --output_dir output

7.3 OpenRLHF

专为大规模 RLHF 设计,基于 Ray 分布式架构,支持 70B+ 模型的全参数 PPO 训练:

bash 复制代码
# 70B 模型的完整 PPO-RLHF(需要大规模集群)
ray job submit --address="http://127.0.0.1:8265" -- \
    python3 -m openrlhf.cli.train_ppo_ray \
    --pretrain OpenRLHF/Llama-3-8b-sft-mixture \
    --reward_pretrain OpenRLHF/Llama-3-8b-rm-700k \
    --save_path ./checkpoint/llama3-8b-rlhf \
    --train_batch_size 128 \
    --rollout_batch_size 1024 \
    --actor_num_nodes 1 \
    --actor_num_gpus_per_node 8 \
    --reward_num_nodes 1 \
    --reward_num_gpus_per_node 8

7.4 Unsloth

针对单卡或小规模环境优化,通过内核级优化使训练速度提升 1.7x,显存减少 60%:

python 复制代码
from unsloth import FastLanguageModel
from trl import SFTTrainer

model, tokenizer = FastLanguageModel.from_pretrained(
    "unsloth/Qwen2.5-7B-Instruct-bnb-4bit",  # 4bit 量化
    max_seq_length=2048,
    load_in_4bit=True,
)

# 添加 LoRA
model = FastLanguageModel.get_peft_model(
    model,
    r=64,
    lora_alpha=128,
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)
# 后续与标准 TRL 完全兼容

八、常见坑与实战经验

8.1 SFT 的常见问题

灾难性遗忘(Catastrophic Forgetting):SFT 数据太集中在某个领域,导致模型在通用任务上退化。解决方法是在 SFT 数据里混入 5%~10% 的通用指令数据(如 Alpaca、OpenHermes),保持通用能力。

学习率过大:SFT 的学习率通常在 1e-5 到 2e-4 之间,大于此范围容易破坏预训练权重。推荐使用余弦调度(cosine schedule)配合 warmup。

过拟合:SFT 只需要 1~3 个 epoch,超过 3 个 epoch 通常会过拟合,导致模型回答死板、缺乏多样性。

8.2 DPO 的常见问题

偏好数据质量比数量更重要:差的偏好对(chosen 和 rejected 区别不明显)比没有偏好数据更糟糕,会把模型训歪。宁可用 1000 条高质量偏好对,也不用 10000 条模糊的偏好对。

beta 值过小导致退化beta 过小时,DPO 对 KL 约束的惩罚太弱,模型会在偏好方向上过度优化,丢失多样性甚至出现重复生成。建议从 0.1 开始,如果回答变得僵硬或重复,适当增大。

On-policy vs Off-policy:如果偏好数据是由另一个模型(如 GPT-4)生成的,这是 off-policy 数据,DPO 效果可能不如期望。理想情况是用当前模型本身生成候选回答,再通过奖励模型或规则筛选偏好对(on-policy DPO),实验证明效果更好。

8.3 RLHF/PPO 的常见问题

奖励模型过拟合:奖励模型如果在分布外输入上给出极端分数,PPO 会利用这一点进行奖励黑客。解决方法是加入 KL 惩罚(TRL 默认启用),并监控 KL 值不超过 5~10。

训练崩溃:PPO 训练不稳定时可能突然崩溃(loss 突然变为 NaN 或奖励骤降)。建议:降低学习率(1e-6 量级)、增大 KL 系数、使用梯度裁剪(max grad norm = 0.5~1.0)。


九、总结:三种方法的定位

把三种方法放在一个框架里看:

SFT 是"教会模型做某件事"。它通过示范回答告诉模型"这样做",是行为对齐的基础。几乎所有大模型都需要 SFT,是必经之路而非可选项。

RLHF/PPO 是"让模型越做越好"。通过奖励信号引导模型在给定的偏好分布上探索,适合追求极致效果的大规模训练场景。代价是工程复杂、计算昂贵,是顶级实验室的专属工具。

DPO 是"告诉模型什么更好"。通过偏好对直接优化策略,绕过了 RL 循环,是平衡效果与工程复杂度的最佳选择,适合大多数工程实践者。

GRPO 是"让模型通过试错发现推理方式"。结合可验证奖励,适合推理、代码等有客观正确答案的任务,是 2025 年后推理模型训练的主流范式。

理解这三者(以及它们的扩展),等于掌握了现代大模型后训练的核心工具箱。选对工具,远比堆参数更能决定模型的最终质量。


参考资料

  1. Ouyang et al., Training language models to follow instructions with human feedback(InstructGPT), NeurIPS 2022
  2. Rafailov et al., Direct Preference Optimization: Your Language Model is Secretly a Reward Model, NeurIPS 2023
  3. Shao et al., DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models, 2024
  4. Guo et al., DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning, 2025
  5. HuggingFace TRL Documentation: https://huggingface.co/docs/trl
  6. Philschmid Blog: How to align open LLMs in 2025 with DPO, 2025
  7. Sebastian Raschka: The State of Reinforcement Learning for LLM Reasoning, 2025
相关推荐
Kel2 小时前
LangChain.js 架构设计深度剖析
人工智能·设计模式·架构
百度Geek说2 小时前
我把 Karpathy 的 AutoResearch 搬到了软件开发领域,效果炸了
人工智能
嵌入式小企鹅2 小时前
国产大模型与芯片加速融合,RISC-V生态多点开花,AI编程工具迈入自动化新纪元
人工智能·学习·ai·嵌入式·算力·risc-v·半导体
数智大号2 小时前
聚焦 AI 音频创新 ,Shure 亮相 InfoComm 全场景解决方案破解协作难题
人工智能
做个文艺程序员2 小时前
Spring Boot 项目集成 OpenClAW【OpenClAW + Spring Boot 系列 第1篇】
java·人工智能·spring boot·开源
天一生水water2 小时前
CNN循环神经网络关键知识点
人工智能·rnn·cnn
一个喜欢分享的PHP技术2 小时前
AI在龙虾中,配置标准版mcp的方法
人工智能
醇氧2 小时前
Hermes Agent 学习(安装部署详细教程)
人工智能·python·学习·阿里云·ai·云计算
扬帆破浪2 小时前
WPS 文字免费开源AI插件:察元 AI 文档助手如何把大模型接进日常写作
人工智能·开源·wps