跳转至

PPO

PPO的主要贡献其实是解决传统RL中,容易受到单次更新过大,震荡导致训练不稳定的问题。

完整架构

PPO 采用的是 Actor-Critic (AC) 架构。

Actor(策略网络)

  • 输入:当前状态 \(s\)(比如:棋盘局面)。
  • 输出:动作的概率分布 \(\pi(a|s)\)(比如:下在 A 点的概率是 80%)。

Critic(价值网络)

  • 输入:当前状态 \(s\)
  • 输出:一个实数 \(V(s)\),代表这个状态平均能拿多少分
  • 作用:它预估一个基准线,用来告诉 Actor:“你这一步表现得比平时好,还是比平时烂。”

优化目标

PPO 的目标函数通常表示为:

\[L^{CLIP}(\theta) = \hat{\mathbb{E}}_t \left[ \min(r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t) \right]\]
  1. 概率比率 \(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\) 减少该动作概率。

这就实现了一个自动导航:奖励好的动作被不断强化,奖励差的被不断削弱。

损失函数

为了符合深度学习代码的逻辑,我们统一看最小化的形式:

\[Loss_{total} = \underbrace{- L^{CLIP}}_{策略提升} + \underbrace{c_1 L^{VF}}_{价值校准} - \underbrace{c_2 S[\pi]}_{保持探索}\]

1. 策略项 \(L^{CLIP}\)

就是我们上面讨论的截断目标。它训练Actor去获取更高的奖励,同时用截断机制让训练不会崩溃。

2. 价值项 \(L^{VF} = (V_{predict} - V_{target})^2\)

这是 Critic 的损失(通常是均方误差)。Critic 必须准确预测当前状态能拿多少分。如果 Critic 预测不准,优势函数 \(\hat{A}_t\) 就会乱套,Actor 也会跟着学坏。 所以要最小化这个误差。

3. 熵项 \(S[\pi]\)

如果 Actor 发现一种方法能得分,它可能会永远只做这一个动作。熵 \(S\) 越高,代表动作越多样。减去熵(即最小化负熵)是强制模型别太早“收敛”,多去试试别的可能。

工作流程

  1. 采样阶段:Actor 在环境里跑,积累一堆经验(状态、动作、奖励)。
  2. 评价阶段
  3. Critic 给这些状态打分 \(V(s)\)
  4. 计算优势 \(\hat{A}_t = \text{实际收益} - V(s)\)
  5. 学习阶段
  6. \(\hat{A}_t\) 去更新 Actor,让好动作概率变大(受 CLIP 限制)。
  7. 用实际收益去更新 Critic,让它下次打分更准(\(L^{VF}\))。
  8. 循环:重复以上步骤。

Note

在 OpenAI 2017 年的原始 PPO 算法中,主要的约束手段是Clipping。

当 PPO 被引入到大模型对齐时,情况变了。单纯靠 Clipping 挡不住模型“学坏”。LLM 的参数量巨大,非常容易在奖励模型(Reward Model)上找漏洞。比如你让它写诗,它发现只要疯狂重复“美丽”这个词,Reward Model 就会给高分。模型会迅速偏离人类语言逻辑,变成一堆乱码。

解决方案就是在目标函数中添加一个KL散度项,保证后训练模型的分布不至于太偏离原始的模型。

\[Reward_{final} = Reward_{RM} - \beta \text{KL}(\pi_{\theta} || \pi_{ref})\]

其中 \(\pi_{ref}\) 是SFT模型。

Note

标准 RL(机器人/游戏):通常只有 2 个模型(Actor + Critic)。环境(Environment)直接给出奖励。

LLM RLHF(如 ChatGPT):通常需要 4 个模型

  1. Actor
  2. Critic
  3. Reference Model(即 SFT 模型)
  4. Reward Model(模拟人类偏好的“裁判”,替代了真实环境的奖励)

Tip

SFT 模型 (Supervised Fine-Tuning)

  • 定义:在基座模型上用人类高质量对话数据微调后的模型。
  • 地位:是 RL 训练的起点,也是计算 KL 散度的参照基准(Ref Model)
  • 特点:让模型具备了“对话能力”和“格式规范”,但还没达到“逻辑巅峰”。

GRPO

架构演进

在 LLM 的标准 PPO 流程中,我们通常需要同时维护 4 个模型

  1. Policy Model (Actor):正在练兵的模型。
  2. Reference Model (Ref):不动的基准,计算 KL 散度用。
  3. Reward Model (RM):打分器。
  4. Value Model (Critic):预估分数的教练。

GRPO 的核心创新: 它发现 Critic 模型在处理大规模推理任务(如数学、代码)时既占显存又难训练。于是,GRPO 直接砍掉了 Critic 模型

  • PPO 架构:Actor + Ref + RM + Critic
  • GRPO 架构:Actor + Ref + RM。

目标函数与优势函数

这是 GRPO 最精妙的地方。它改变了“好坏”的定义方式。

PPO 的优势函数 \(\hat{A}_t\):绝对对比

PPO 依赖 Critic 告诉它:此时此刻,这个状态 \(s\) 预期能拿多少分。

\[\hat{A}_t = \text{实际得分} - \text{Critic 预测的预期得分}\]

GRPO 的优势函数 \(\hat{A}_i\):相对对比

GRPO 采用组内对比的方式。对于同一个问题,模型生成一组 \(G\) 个答案 \(\{O_1, O_2, ..., O_G\}\)

  1. 用 Reward Model 给这 \(G\) 个答案分别打分 \(\{r_1, r_2, ..., r_G\}\)

  2. 计算这组得分的均值 \(\text{mean}(r)\)标准差 \(\text{std}(r)\)

  3. 优势函数计算

\(\hat{A}_i = \frac{r_i - \text{mean}(r)}{\text{std}(r)}\)

损失函数

GRPO 的损失函数公式如下,它保留了 PPO 的 Clipping,但整合了 KL 惩罚:

\[J_{GRPO}(\theta) = \mathbb{E} \left[ \frac{1}{G} \sum_{i=1}^G \left( \min \left( r_{i,\theta} \hat{A}_i, \text{clip}(r_{i,\theta}, 1-\epsilon, 1+\epsilon) \hat{A}_i \right) - \beta \cdot \text{KL}(\pi_\theta \| \pi_{ref}) \right) \right]\]

对比 PPO 的损失函数:

  1. 取消了 \(L^{VF}\):因为没有 Critic,所以不需要训练价值预测误差。
  2. 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 的加权总和:

\[Loss_{GSPO} = \sum_{i=1}^n w_i \cdot L_{i}^{CLIP} + L_{Coordination}\]
  1. 分层策略损失 (\(L_{i}^{CLIP}\)):每一层策略都有自己的剪裁损失,确保每一层的更新都是稳健的。
  2. 协调损失 (\(L_{Coordination}\)):这是 GSPO 的特色,用于惩罚层级之间的不协调。例如,高层策略想往左,底层策略却执行了往右,这种冲突会被该项捕捉并修正。
  3. 对比 GRPO:GRPO 彻底删除了 Critic 损失(\(L^{VF}\)),而 GSPO 可能依然保留 Critic(或者每一层都有一个微型 Critic),因为它需要精细化地评估每一层的贡献。

工作流程

步骤 PPO/GRPO 流程 GSPO 流程
采样 顺序输出动作或文本。 分层采样:高层先定调,底层再填充细节。
评估 评价整个序列的好坏。 多维评估:既评价最终结果,也评价各层之间的“衔接”是否合理。
更新 整体更新网络参数。 分步/解耦更新:可以先固定高层练底层,或交替训练,防止互相干扰。

GSPO 的出现主要是为了应对“维度灾难”“长期依赖”

  1. 处理极端复杂的任务:当一个任务包含多个子步骤(比如自动驾驶中的路线规划、避障、加速),单一的 PPO 很难同时学好所有细节。GSPO 通过堆叠将压力分担。
  2. 增强可解释性:你可以清晰地看到是哪一层策略出了问题(是高层规划错了,还是底层执行不到位)。
  3. 训练稳定性:在处理非常长的任务时,GSPO 的分层结构能提供更频繁的“中间反馈”,避免模型在长链条中迷失方向。