我先说个真实感受:很多人一听到“LLM 强化学习(RL)”这六个字,第一反应是“这不是搞算法的才能碰吗”,第二反应是“PPO 那堆公式看得头皮发麻”。实际上,从 2024 年到 2025 年,能在榜单上刷出高分的大模型,几乎没有一个是只靠 SFT 硬怼出来的。不管是 ChatGPT 早期对齐用的 RLHF,还是 DeepSeek 在数学推理上用到的 GRPO,本质上都是让模型“在被表扬之后记住好行为,在被批评之后收敛坏行为”。这篇文章就用最白话的方式,把 PPO、DPO、GRPO、GSPO 这四个绕不开的 LLM 强化学习算法讲清楚,包括它们各自怎么想的、怎么工作的、工程上要花多大代价,以及你在自己项目里到底该选哪个。适合刚入门 LLM 训练、准备做毕业设计、或者在公司想快速落地强化对齐方案的朋友。
1. 为什么大模型需要“强化”这一段
1.1 SFT 之后,模型到底还缺什么
先聊一个基础问题:模型不是已经会“说话”了吗,为什么还要再来一轮强化学习?
ChatGPT 出现前后,“对齐(Alignment)”这个词被反复提起。预训练加 SFT 的目标是模仿人类写的文本,模型学到的其实是“怎么把下一句话接得通顺”,但“通顺”不等于“有用”,也不等于“符合偏好”。举个例子,你问模型“怎么把冰箱里的剩菜加工成晚餐”,SFT 出来的模型可能会非常流畅地写一篇《冰箱食材的哲学思考》,语句没有任何语法错误,但看完 800 字还没看到可操作步骤。这个问题的本质是:监督学习只能让模型靠近训练数据里的答案,但数据里“好答案”和“差答案”的差异没有被显式建模。
另外,SFT 数据通常是单轮静态的,模型没有机会尝试、反馈、再修正。强化学习的意义在于引入一个显式的“评价信号”,让模型在生成之后知道自己这一次做得好不好,然后朝着“好”的方向调整策略。这就是 RLHF 那套思路的起点,也是现在 LLM 后期训练越来越依赖 RL 的根本原因。
1.2 RLHF 的三段式:SFT、奖励模型、策略优化
RLHF 的标准流程可以分三步:
- 用高质量人工标注数据做 SFT,得到一个能正常对话的底座模型。
- 让这个底座模型生成大量回答,人工给这些回答排序或打分,训练一个奖励模型(Reward Model,简称 RM)。RM 的作用是“给一段文本打个分”,分数越高表示越符合人类偏好。
- 固定奖励模型,用强化学习算法更新底座模型,目标是把奖励分数最大化。但为了防止模型为了刷分而忘掉原有语言能力,通常还要加一个 KL 惩罚,让新模型不要偏离参考模型太远。
这个框架看起来简单,但第三步里“用哪个强化学习算法”就是文章标题里四个算法的分水岭。PPO 是最早上场且最稳的;DPO 跳过了显式奖励模型,直接把偏好写进损失函数;GRPO 把价值网络去掉,改用组内相对比较;GSPO 则是尝试把前面这些方法统一起来的新方案。
提示:如果你只是想给模型换个语气、调个风格,SFT 完全够用,不必上 RL。RL 真正发挥价值的地方是那些“答案好坏不容易由文本相似度判断,但结果可被明确评价”的任务,比如数学解题、代码生成、工具调用、多轮任务完成度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. PPO:RLHF 里的“老大哥”算法
2.1 PPO 在 LLM 里是怎么跑起来的
PPO 全称是 Proximal Policy Optimization,近端策略优化,它最早在连续控制领域出名,OpenAI 在 2017 年提出,后来被直接搬到了 RLHF 里。在 LLM 场景里,PPO 有四个模型同时驻留显存:Actor(要训练的策略模型)、Reference Model(参考模型,不更新)、Reward Model(给整体回答打分)、Critic(价值模型,估计状态价值)。这四个模型各司其职,跑一轮完整数据大体分这几步:
- 从 prompt 数据集里采样一批问题。
- Actor 根据当前策略生成回答。
- Reward Model 对(prompt,回答)整体打分,同时 Reference Model 计算当前 Actor 与参考模型的 KL 散度作为惩罚。
- Critic 模型对生成的状态计算预估价值,结合实际奖励用 GAE(广义优势估计)算出每个 token 的优势值 A。
- 用带 clip 的目标函数更新 Actor。
一句话总结 PPO 的直觉:如果这次生成带来了“比预期更好的结果”,就提高这些动作的概率;如果结果比预期差,就降低概率。但概率调整幅度不能过大,否则策略会震荡甚至崩溃。
2.2 clip 机制到底在哪起作用
PPO 公式里最关键的是重要性采样比率:
r_t(θ) = π_θ(a_t | s_t) / π_old(a_t | s_t)
这个比率表示新策略在同一个动作上的概率相对旧策略变了多少。如果 A > 0,我们希望 r 大一点;如果 A < 0,我们希望 r 小一点。但问题在于:如果新策略为了拿到更多奖励一下子走太远,训练会因为“一步跨太大”而崩掉。
所以 PPO 引入 clip 操作,把 r 限制在 [1-ε, 1+ε] 范围内,ε 通常取 0.2。意思是:就算你发现某个回答特别好,我也只允许你最多把它的概率提升 20%;特别差的回答,最多压低 20%。剩下的优势靠多次迭代慢慢积累。这个小限制是整个算法稳定性的关键。
在 LLM 的 RLHF 实践中,PPO 常被吐槽工程复杂。最大的痛点是 Critic 模型,它本身也要跟着训练,而且价值估计在小规模数据上经常不准。再加上 Reward Model、Reference Model,四个模型一起跑,对显存和工程能力要求都不低。
2.3 PPO 的工程代价和适用场景
如果你问一个做过 RLHF 的工程师“PPO 难不难”,他大概率会回答“不是难,是麻烦”。一次 PPO 训练,需要准备至少四份模型权重,Actor 和 Critic 需要做梯度更新,Reference 和 Reward 只做前向传播;为了省显存,通常还要做梯度检查点、混合精度、离线采样缓存,各种细节一个都不能少。
但是 PPO 到今天依然是“最稳的基线”。OpenAI 用它调出了早期的 InstructGPT,Anthropic 也大量使用基于 PPO 的对齐方案。如果你的团队有足够算力,希望在奖励模型打分、RL 训练稳定性上都有成熟兜底方案,PPO 是最靠谱的选择。小规模实验不推荐一上来就 Full PPO,因为调试成本非常高。
3. DPO:把 RL 问题直接改写成分类问题
3.1 DPO 的核心理念:绕开奖励模型
DPO 全称是 Direct Preference Optimization,直接偏好优化。它出现的动机很现实:PPO 太复杂了,奖励模型训练、价值模型训练、策略更新三个环节耦合在一起,任何一个环节出问题都会导致全局失败。DPO 的论文做了一个非常关键的推导:在奖励函数和策略满足某种约束的前提下,RLHF 的强化学习目标可以被改写成——直接用“偏好数据对”训练策略模型。
换句话说,不需要先训练一个 Reward Model,也不需要 Critic,只需要准备 (prompt, chosen, rejected) 三元组,就能让模型学会“选择被偏好的回答,避免被拒绝的回答”。
DPO 的核心损失函数拆开来看其实很直白:
L_DPO = -log σ( β × ( log(π_θ(y_w|x) / π_ref(y_w|x)) - log(π_θ(y_l|x) / π_ref(y_l|x)) ) )
y_w 是更受偏好的回答,y_l 是较差的回答。σ 是 sigmoid 函数。模型要做的,是拉开“chosen 相对参考模型概率比”和“rejected 相对参考模型概率比”的差距。
这里的 β 可以理解为一个温度系数,控制模型偏离参考模型的程度。β 越大,模型越激进地去讨好偏好数据;β 越小,模型越保守。
3.2 DPO 的优缺点和最佳实践
DPO 的优点非常明显:训练只需要 Actor + Reference 两个模型,显存消耗比 PPO 低很多,代码实现也简单,HuggingFace TRL 库开箱即用。对入门者或者算力有限的小团队来说,DPO 是一个几乎零门槛的上手方案。
但 DPO 也有几个不能忽视的短板:
- 它高度依赖偏好数据的质量。如果 chosen 和 rejected 的差异不明显,模型学不到东西;如果数据有噪音,模型很容易学到错误信号。
- 它没有一个显式的奖励信号,所以不能直接优化“解题正确率”这类外部指标。
- 它是纯离线算法,不会在训练过程中探索新样本,数据分布相对静态,和策略变化之间没有任何闭环反馈。
实际操作中,DPO 最常见的坑是数据“长度偏好”问题。模型很容易学到“更长的回答更受偏好”,于是开始生成又长又啰嗦的内容。解决办法一般是控制回答长度,或者在数据构造时让 chosen 和 rejected 的长度尽量接近。
我的习惯是:预算有限、数据是现成的偏好对、目标只是让模型风格更讨喜,那直接用 DPO;如果你希望模型在数学题或编程题上有实质正确率的提升,DPO 通常不是最优解,考虑下面的 GRPO。
4. GRPO:去掉 Critic,用“小组 PK”代替“老师打分”
4.1 组内相对优势是什么意思
GRPO 全称是 Group Relative Policy Optimization,组相对策略优化,由 DeepSeek 团队在 DeepSeekMath 项目里提出,后来在 DeepSeek-R1 等模型上被大规模使用。
它的出发点很直接:PPO 里的 Critic 价值模型又贵又难训,那能不能不学价值模型,直接用“一批样本的相对好坏”来估计优势?
GRPO 的做法是:对同一个 prompt,让模型生成 G 个回答(比如 8 个或 16 个)。然后用奖励函数给这 G 个回答分别打分,得到 r_1, r_2, ..., r_G。接下来对每个回答计算组内优势:
A_i = (r_i - mean(r_1...r_G)) / std(r_1...r_G)
这个公式表达的直觉非常朴素:一个回答好还是不好,不跟“一个绝对标准”比,而是跟你同组的伙伴比。如果它比组内平均分高,优势就是正的;如果低于组内平均分,优势就是负的。然后把这个优势套用到 PPO 风格的目标里,对策略做有限幅度的更新。
没有 Critic 之后,训练时至少有两个明显好处:显存占用下降(省掉一个完整模型),而且不再需要处理价值估计不准确的问题。对一个样本量小、任务规则清晰(比如数学答案对错、代码是否通过测试)的场景来说,这套方案效率非常高。
4.2 为什么 GRPO 在数学和代码任务上特别能打
GRPO 真正火起来,是因为这类“规则可验证”任务非常适合它。数学题答案对错是确定的,代码题是否通过测试是确定的,那就根本不需要训练一个奖励模型来“猜”好坏,直接用规则写一个打分函数就行。
真正的奖励信号越清晰,GRPO 的组内 PK 就越有效。同一个 prompt 下,模型生成 16 个回答,有对的也有错的,对的比组内平均分高,错的比组内平均分低,这样梯度信号非常强烈,模型很快就能知道“哪种推理路径能拿到分”。
还一个隐藏好处:GRPO 天然鼓励多样性。同一个 prompt 给多个回答机会,模型会尝试不同思路,模仿、变异、保留高分路径,这其实很像“群体搜索”。在需要探索多条解题路径的场景里,这个特性非常契合。
不过 GRPO 也不是没有缺点。组内归一化策略对组数 G 比较敏感,G 太小,优势估计方差大;G 太大,生成成本成倍上升。我的经验是,普通小规模实验从 8 或 16 开始,在数学类任务上可以试到 32 甚至 64,但要留意自己显存和采样时间是否扛得住。
5. GSPO:把 PPO 和 DPO 统一起来的尝试
5.1 GSPO 出现的大背景
GSPO 全称是 Group Sequence Policy Optimization,组序列策略优化,是 2025 年初由 Google DeepMind 研究团队提出的比较新的工作。它的定位不是“再发明一个新算法吊打所有人”,而是试图回答一个更理论的问题:为什么 PPO 和 DPO 看起来差别那么大,但实际应用效果有时又差不多?
论文的核心洞察是:PPO、GRPO、RLOO、DPO、KTO 这些方法,其实都可以被放到同一个框架里看。它们之间的差异主要来自两件事:一是“基线怎么选”(是学一个 Critic,还是用组内平均,还是用固定常数),二是“损失函数长什么样”(是 policy gradient 目标,还是 preference contrast 目标)。
搞明白这件事之后,GSPO 的方案就很清晰了:不再训练 Critic,直接把同一个 prompt 的生成序列放到一个组里,用组内平均奖励作为基线,再配合一个类似对比学习的策略更新目标。这样你不需要 PPO 那套繁琐的组件,也不需要为 DPO 单独准备离线偏好对,在线采样 + 组内相对比较就够用。
5.2 GSPO 的核心更新思路
想理解 GSPO,可以把它拆成几个步骤:
- 给同一个 prompt 采样 K 个序列。
- 用奖励模型或规则函数给每个序列打分。
- 计算组内平均值作为 baseline,得到每个序列相对组内的“盈亏”。
- 用对比风格的目标函数更新模型:奖励高于组均值的序列,概率要被抬高;低于组均值的序列,概率要被压低。
如果用最简化的方式写它的更新信号,差不多是:
L_GSPO ≈ -log σ( β × (R_k - baseline) )
其中 baseline 是组内奖励的均值。这个形式看起来很像 DPO,但它又是在线采样、使用真实奖励的。也就是说,GSPO 同时拿到了 DPO 的简单性和 PPO 的在线优化能力。
从我看到的复现和社区反馈来看,GSPO 最大的价值是:在超参数选择上比 PPO 省心很多,稳定性也不错,效果能逼近甚至持平 PPO。如果你是一个小团队,想从 DPO 过渡到“带在线探索的 RL 训练”,GSPO 是一条性价比很高的路线。
当然,由于它非常新,工程上可参考的中文资料还比较少。如果你想在项目里使用,建议先去读原始论文《Group Sequence Policy Optimization for LLM Alignment》,再对着开源实现做适配。
6. 四个算法怎么选:对比和实操建议
6.1 横向对比速查表
对初学者来说,算法没有绝对好坏,只有“合不合适”。我把四个算法的关键差异整理成一张表:
| 算法 | 是否需要奖励模型 | 是否需要价值模型(Critic) | 训练范式 | 显存压力 | 超参数数量 | 最适合的场景 |
|---|---|---|---|---|---|---|
| PPO | 是 | 是 | 在线 RL | 高 | 多 | 通用对齐、资源充足、求稳 |
| DPO | 否 | 否 | 离线偏好优化 | 低 | 少 | 现成偏好对、快速调风格 |
| GRPO | 可选 | 否 | 在线 RL | 中 | 中 | 数学、代码等规则可验证任务 |
| GSPO | 可选 | 否 | 在线 RL | 中 | 少 | 从 DPO 过渡到在线 RL 的团队 |
这里补充一句:“是否需要奖励模型”要区别看待。GRPO 和 GSPO 在规则可验证任务里可以直接用规则函数,复杂的开放性任务仍然建议训练一个奖励模型。
6.2 从零开始跑一个小实验
我建议初学者按这个路径来入门:先跑 DPO,再跑 GRPO,最后挑战 PPO。GSPO 可以先读论文和源码,等技术成熟一点再上。
DPO 用 HuggingFace TRL 库是最方便的。数据格式是一个 JSONL,每行包含 prompt、chosen、rejected 三个字段。代码大致是:
python复制from datasets import load_dataset
from trl import DPOTrainer, DPOConfig
dataset = load_dataset("json", data_files="my_preference_data.jsonl")
config = DPOConfig(
output_dir="./dpo_output",
beta=0.1,
per_device_train_batch_size=4,
learning_rate=5e-6,
max_length=1024,
max_prompt_length=512,
)
trainer = DPOTrainer(
model="Qwen/Qwen2.5-7B-Instruct",
ref_model="Qwen/Qwen2.5-7B-Instruct",
train_dataset=dataset["train"],
tokenizer=None, # 会自动加载模型对应 tokenizer
args=config,
)
trainer.train()
这里几个细节需要提醒:beta 不要一上来就设很大,0.1 到 0.5 之间起步比较稳;学习率对 DPO 非常敏感,5e-6 到 1e-5 是 7B 模型常用区间;参考模型和策略模型初始权重必须相同,否则训练的起点就不公平。
GRPO 在 TRL 新版本里也有专门的 Trainer,核心点是自己写一个奖励函数:
python复制from trl import GRPOTrainer, GRPOConfig
def reward_func(prompts, completions, **kwargs):
rewards = []
for prompt, completion in zip(prompts, completions):
# 从 completion 中解析最终答案,和标准答案比对
answer = extract_answer(completion)
rewards.append(1.0 if answer == standard_answer_map.get(prompt) else 0.0)
return rewards
config = GRPOConfig(
output_dir="./grpo_output",
learning_rate=1e-6,
per_device_train_batch_size=8,
num_generations=8, # 每个 prompt 生成的回答数量
max_completion_length=1024,
)
trainer = GRPOTrainer(
model="Qwen/Qwen2.5-7B-Instruct",
reward_funcs=[reward_func],
train_dataset=dataset,
args=config,
)
trainer.train()
注意:不同 TRL 版本的接口会有变化,跑之前先看一眼官方文档。实际实验里,GRPO 的采样成本明显高于 DPO,因为每个 prompt 要生成 8 到 16 条回答,如果有 1000 条 prompt,那就是 8000 到 16000 次生成,时间预算要提前算好。
6.3 硬件资源和团队选择
聊到资源,很多人会吓一跳。PPO 在 7B 模型上做 Full Fine-tune,四个模型同时驻留显存,理想情况需要 4 张 A100-80G 起步;DPO 则两张 A100 或者一张 80G 卡就能跑;GRPO 介于两者之间,通常一张 80G 卡加 LoRA 也能跑小规模实验。
如果预算有限,我强烈建议先用 LoRA 或者 QLoRA 跑通流程,把任务数据、奖励函数、评估指标都调顺,再考虑全量微调。很多刚接触 RL 的人一上来就全参更新,结果光调试硬件环境就花了一周,这是最划不来的。
7. 常见问题与避坑心得
7.1 典型问题速查表
我自己在实验过程中踩过不少坑,整理成一张表,方便你照着排查:
| 现象 | 可能原因 | 排查思路 |
|---|---|---|
| Loss 涨但奖励也涨 | KL 惩罚过强,模型被限制住 | 适当降低 KL 系数 |
| 奖励涨但生成质量下降 | reward hacking,模型钻奖励空子 | 检查奖励函数是否有漏洞,加长度惩罚 |
| 生成的回答越来越短 | 奖励模型偏好简短答案 | 检查奖励和长度相关性 |
| DPO 训练后风格突变 | beta 设置过大 | 降低 beta,检查参考模型是否加载正确 |
| GRPO 训练不收敛 | 组内奖励方差太小 | 增大组数,或检查奖励函数是否有区分度 |
| 显存 OOM | 模型全参 + 大批量 | 加 gradient checkpointing,改用 LoRA |
| PPO 训练崩掉 | Critic 估计不稳定 | 降低学习率,增大 GAE lambda,延长 warmup |
7.2 几条很实在的实验经验
最后分享几个我个人的经验。第一,任何 RL 实验都要先在小数据集上跑通,几百条 prompt 就够,先把代码、显存、采样链路全部跑顺,再扩展到全量数据。我见过太多人直接用几万条数据跑,最后发现 reward function 写错了,一天白费。
第二,奖励函数的设计永远比算法选择重要。GRPO 和 GSPO 看起来很优雅,但如果你的奖励函数无法区分好回答和坏回答,再好的算法也学不到东西。设计奖励函数时,先拿几百条样本手工打分,看分数分布是否合理,然后再进入正式训练。
第三,训练过程中一定要保存中间 checkpoint,并且每隔一定的训练步数用固定评测集测一下模型输出。强化学习的奖励信号和人类感知质量并不总是正相关,你盯 Loss 曲线看不出问题,但实际生成质量可能已经开始悄悄劣化。
第四,如果你准备拿这个方向做毕业设计或者公司项目,不建议一上来就死磕 PPO。先用 DPO 做一个能讲得通的基线,再用 GRPO 尝试提升可验证任务的指标,最后如果时间富余,再探索 GSPO 这类新方法。这个思路既能保证有结果,又能在深度和创新性上都有话可说。
我在实际项目中,最常用的组合是“SFT 做底座 + GRPO 做数学/代码类优化 + DPO 做风格对齐”。这个组合在资源消耗和效果之间取得了比较好的平衡。如果你只有单卡,那就用 LoRA 加 DPO 起步,先把流程跑通,后面再逐步加码。等到某一天你发现 DPO 的离线数据已经限制住了模型的上限,再去看 GSPO,你会发现思路非常自然——原来在线采样、组内对比、对比学习这些概念,本来就是可以串在一起的。
