PPO
PPO的主要贡献其实是解决传统RL中,容易受到单次更新过大,震荡导致训练不稳定的问题。
完整架构
PPO 采用的是 Actor-Critic (AC) 架构。
Actor(策略网络)
- 输入:当前状态 \(s\)(比如:棋盘局面)。
- 输出:动作的概率分布 \(\pi(a|s)\)(比如:下在 A 点的概率是 80%)。
Critic(价值网络)
- 输入:当前状态 \(s\)。
- 输出:一个实数 \(V(s)\),代表这个状态平均能拿多少分。
- 作用:它预估一个基准线,用来告诉 Actor:“你这一步表现得比平时好,还是比平时烂。”
优化目标
PPO 的目标函数通常表示为:
- 概率比率 \(r_t(\theta)\):
这是新策略与旧策略输出概率的比值:\(r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}\)。
- 如果 \(r_t > 1\),说明这个动作在新策略中变得更合规。
-
如果 \(r_t < 1\),说明在新策略中发生的概率降低了。
-
优势函数 \(\hat{A}_t\):
判断这个动作比平均预期好多少
\(\hat{A}_t = Q(s, a) - V(s)\)
(即:实际做这个动作的价值 - 该状态下的平均价值)
- \(\hat{A}_t > 0\):这个动作是“惊喜”,表现优于平均。
-
\(\hat{A}_t < 0\):这个动作是“败笔”,表现低于平均。
-
截断机制(The Clipping):
公式中的 \(\text{clip}(r_t, 1-\epsilon, 1+\epsilon)\) 将比率限制在 \([0.8, 1.2]\) 之间(假设 \(\epsilon=0.2\))。即便某个动作效果极好,PPO 也不允许一次性把它的概率提升超过 20%。这防止了由于单次采样波动导致的策略剧烈震荡。
Note
目标函数的最简形式是 \(r_t(\theta) \cdot \hat{A}_t\)。
- 如果 \(\hat{A}_t\) 为正(好动作),我们要让 \(r_t\) 变大 \(\rightarrow\) 增加该动作概率。
- 如果 \(\hat{A}_t\) 为负(坏动作),我们要让 \(r_t\) 变小 \(\rightarrow\) 减少该动作概率。
这就实现了一个自动导航:奖励好的动作被不断强化,奖励差的被不断削弱。
损失函数
为了符合深度学习代码的逻辑,我们统一看最小化的形式:
1. 策略项 \(L^{CLIP}\)
就是我们上面讨论的截断目标。它训练Actor去获取更高的奖励,同时用截断机制让训练不会崩溃。
2. 价值项 \(L^{VF} = (V_{predict} - V_{target})^2\)
这是 Critic 的损失(通常是均方误差)。Critic 必须准确预测当前状态能拿多少分。如果 Critic 预测不准,优势函数 \(\hat{A}_t\) 就会乱套,Actor 也会跟着学坏。 所以要最小化这个误差。
3. 熵项 \(S[\pi]\)
如果 Actor 发现一种方法能得分,它可能会永远只做这一个动作。熵 \(S\) 越高,代表动作越多样。减去熵(即最小化负熵)是强制模型别太早“收敛”,多去试试别的可能。
工作流程
- 采样阶段:Actor 在环境里跑,积累一堆经验(状态、动作、奖励)。
- 评价阶段:
- Critic 给这些状态打分 \(V(s)\)。
- 计算优势 \(\hat{A}_t = \text{实际收益} - V(s)\)。
- 学习阶段:
- 用 \(\hat{A}_t\) 去更新 Actor,让好动作概率变大(受 CLIP 限制)。
- 用实际收益去更新 Critic,让它下次打分更准(\(L^{VF}\))。
- 循环:重复以上步骤。
Note
在 OpenAI 2017 年的原始 PPO 算法中,主要的约束手段是Clipping。
当 PPO 被引入到大模型对齐时,情况变了。单纯靠 Clipping 挡不住模型“学坏”。LLM 的参数量巨大,非常容易在奖励模型(Reward Model)上找漏洞。比如你让它写诗,它发现只要疯狂重复“美丽”这个词,Reward Model 就会给高分。模型会迅速偏离人类语言逻辑,变成一堆乱码。
解决方案就是在目标函数中添加一个KL散度项,保证后训练模型的分布不至于太偏离原始的模型。
其中 \(\pi_{ref}\) 是SFT模型。
Note
标准 RL(机器人/游戏):通常只有 2 个模型(Actor + Critic)。环境(Environment)直接给出奖励。
LLM RLHF(如 ChatGPT):通常需要 4 个模型。
- Actor
- Critic
- Reference Model(即 SFT 模型)
- Reward Model(模拟人类偏好的“裁判”,替代了真实环境的奖励)
Tip
SFT 模型 (Supervised Fine-Tuning):
- 定义:在基座模型上用人类高质量对话数据微调后的模型。
- 地位:是 RL 训练的起点,也是计算 KL 散度的参照基准(Ref Model)。
- 特点:让模型具备了“对话能力”和“格式规范”,但还没达到“逻辑巅峰”。
GRPO
架构演进
在 LLM 的标准 PPO 流程中,我们通常需要同时维护 4 个模型:
- Policy Model (Actor):正在练兵的模型。
- Reference Model (Ref):不动的基准,计算 KL 散度用。
- Reward Model (RM):打分器。
- Value Model (Critic):预估分数的教练。
GRPO 的核心创新: 它发现 Critic 模型在处理大规模推理任务(如数学、代码)时既占显存又难训练。于是,GRPO 直接砍掉了 Critic 模型。
- PPO 架构:Actor + Ref + RM + Critic。
- GRPO 架构:Actor + Ref + RM。
目标函数与优势函数
这是 GRPO 最精妙的地方。它改变了“好坏”的定义方式。
PPO 的优势函数 \(\hat{A}_t\):绝对对比
PPO 依赖 Critic 告诉它:此时此刻,这个状态 \(s\) 预期能拿多少分。
GRPO 的优势函数 \(\hat{A}_i\):相对对比
GRPO 采用组内对比的方式。对于同一个问题,模型生成一组 \(G\) 个答案 \(\{O_1, O_2, ..., O_G\}\)。
-
用 Reward Model 给这 \(G\) 个答案分别打分 \(\{r_1, r_2, ..., r_G\}\)。
-
计算这组得分的均值 \(\text{mean}(r)\) 和标准差 \(\text{std}(r)\)。
-
优势函数计算:
\(\hat{A}_i = \frac{r_i - \text{mean}(r)}{\text{std}(r)}\)
损失函数
GRPO 的损失函数公式如下,它保留了 PPO 的 Clipping,但整合了 KL 惩罚:
对比 PPO 的损失函数:
- 取消了 \(L^{VF}\):因为没有 Critic,所以不需要训练价值预测误差。
- KL 项的位置:在 PPO 中,KL 往往被混合进 Reward 里计算;在 GRPO 中,它通常作为公式中独立的一项进行显式惩罚,这让训练在推理任务中更加稳健。
工作流程
| 步骤 | PPO 工作流 | GRPO 工作流 |
|---|---|---|
| 采样 | 采样 1 个或少量答案。 | 采样一组(如 64 个)答案。 |
| 评估 | Critic 预测每个状态的价值。 | 直接计算这组答案的得分分布。 |
| 对齐 | 算出单点的优势 \(A\)。 | 算出每个答案在组内的排名(标准化)。 |
| 更新 | 更新 Actor 和 Critic。 | 仅更新 Actor。 |
长链条思维
显存空间:省下的钱用来思考
在深度学习中,显存是极其宝贵的资产。大模型的显存消耗主要在两个地方:模型参数和上下文长度(KV Cache)。
- PPO 的困境:你需要同时加载 Actor、Ref、RM 和 Critic。如果模型是 70B 的,多一个 Critic 就意味着多出几十 GB 的显存占用。为了塞下这个 Critic,你不得不缩短训练时的上下文长度(比如限制在 4k 窗口)。
- GRPO 的优势:砍掉 Critic 后,省出来的显存可以用来支持更长的上下文(比如 32k 甚至 128k)。
- 为什么对长链条重要?:复杂的数学题或代码题,模型需要写出几千甚至上万字的推理过程(Thinking Process)。如果上下文窗口不够长,模型推导到一半就断了。GRPO 让模型有足够的空间去进行深度思考。
奖励的稀疏性:不再需要每一步都打分
长链条推理有一个巨大的难题:中间过程很难评估,只有最后结果是确定的。
- PPO 的做法:PPO 依赖 Critic 为推理过程的每一个 Token(每一个字)预测价值。这非常难!因为逻辑推导中,只要中间错了一步,后面全盘皆错。Critic 往往很难精准预测长达几千字的推理链条中,哪一步是真正的转折点。
- GRPO 的做法(组内对比):
- 模型针对一个难题,吐出 64 个推理过程(有的写了 500 字,有的写了 3000 字)。
- 最后只看结果:算对的给 1 分,算错的给 0 分。
- 优势函数生效:通过这 64 个样本的均值和标准差,GRPO 会自动发现:那些推导过程详尽、逻辑严密且最后算对的样本,其得分显著高于群体平均值。
- 结果导向的逻辑自我演化:模型在不断的“组内比武”中,会逐渐发现“多思考、写出完整推导链条”能提高算对的概率。它不需要教练(Critic)时刻在耳边纠正,它只需要看到“那一群分身里谁赢了”,然后模仿赢家。
“组内对比”天然适合推理任务
推理任务(Reasoning)有一个特点:条条大路通罗马。 一道数学题可以有三种解法。
- PPO 如果用一个固定的 Critic,可能会死板地认定某一种解法是高分,限制了模型的发散思维。
- GRPO 通过 64 个样本的横向对比,只要这几种解法最后都算对了,它们在组内都会被识别为“优秀样本”。这极大地鼓励了模型探索不同的、更深层次的逻辑链路。
GSPO
GSPO 的核心思想是通过分组(Group)和堆叠(Stacked)来处理那些单一策略难以覆盖的复杂场景。
架构区别
- PPO/GRPO 架构:通常是一个单一的 Policy 网络。即便 GRPO 砍掉了 Critic,它的 Actor 本身还是一个整体。
- GSPO 架构:引入了分层或堆叠的概念。它将策略分解为多个子策略(Sub-policies)或不同的功能模块。
- 底层策略(Base/Low-level):处理基础动作。
- 高层策略(High-level/Meta):负责在不同任务或子策略之间进行切换和组合。
- 堆叠结构:模型不是一次性输出结果,而是通过多个层级(Stack)的输出进行组合,最终形成决策。
多目标与分层奖励
GSPO 的目标函数不仅仅是最大化最终奖励,它引入了多粒度的目标:
- 局部目标(Local Objective):每个堆叠层(Stack)都有自己的局部优化目标,确保子任务的完成质量。
- 全局平衡:通过权重分配,确保各个子策略在协同工作时不会发生冲突。
- GSPO 公式特征:通常会在 PPO 的截断目标基础上,增加一个层级一致性项。其目标是让每一层不仅对自己负责,还要为上一层的意图服务。
多重 Loss
GSPO 的损失函数比 PPO 更复杂,通常是多个 Loss 的加权总和:
- 分层策略损失 (\(L_{i}^{CLIP}\)):每一层策略都有自己的剪裁损失,确保每一层的更新都是稳健的。
- 协调损失 (\(L_{Coordination}\)):这是 GSPO 的特色,用于惩罚层级之间的不协调。例如,高层策略想往左,底层策略却执行了往右,这种冲突会被该项捕捉并修正。
- 对比 GRPO:GRPO 彻底删除了 Critic 损失(\(L^{VF}\)),而 GSPO 可能依然保留 Critic(或者每一层都有一个微型 Critic),因为它需要精细化地评估每一层的贡献。
工作流程
| 步骤 | PPO/GRPO 流程 | GSPO 流程 |
|---|---|---|
| 采样 | 顺序输出动作或文本。 | 分层采样:高层先定调,底层再填充细节。 |
| 评估 | 评价整个序列的好坏。 | 多维评估:既评价最终结果,也评价各层之间的“衔接”是否合理。 |
| 更新 | 整体更新网络参数。 | 分步/解耦更新:可以先固定高层练底层,或交替训练,防止互相干扰。 |
GSPO 的出现主要是为了应对“维度灾难”和“长期依赖”:
- 处理极端复杂的任务:当一个任务包含多个子步骤(比如自动驾驶中的路线规划、避障、加速),单一的 PPO 很难同时学好所有细节。GSPO 通过堆叠将压力分担。
- 增强可解释性:你可以清晰地看到是哪一层策略出了问题(是高层规划错了,还是底层执行不到位)。
- 训练稳定性:在处理非常长的任务时,GSPO 的分层结构能提供更频繁的“中间反馈”,避免模型在长链条中迷失方向。