13 分钟阅读

简介

如果你想先看通用 RL 主线,可以先读从长期回报、Credit Assignment 到 PPO;如果你想看不局限于 LLM 的策略梯度、Actor-Critic、GAE、PPO 细节,可以再看语言模型强化学习基础:从策略梯度到 PPO。这篇则专门聚焦在 RL 放到 LLM post-train 语境后,状态、动作、奖励、Critic、KL、GRPO 都分别对应什么

大模型Agent RL训练多轮planning技术 简要的梳理一下RLHF算法:

  1. PPO :把生成的每个token当成一个”action”,对模型的每个输出进行监督,这个过程使用的是value model/critic model完成的,loss上加上了裁剪机制限制策略的更新幅度,避免模型”学偏”.
  2. GRPO :GRPO是PPO的改进版,不依赖于value network,通过生成同一个样本的多个输出,然后计算每个输出的奖励与组内平均奖励的差值,然后使用KL散度来约束模型与reference model的偏离程度。
  3. REINFORCE++ : 在基础的REINFORCE基础上增加”历史基线”机制,比如用过去多个batch的average reward作为当前的基线,避免单一的batch的波动的影响。 GRPO跟PPO的区别就是advantage(降低方差用的)是sampling过程产生的样本的reward,求均值,方差得到的, 因为跟ppo差别很小,所以在开源的代码在实现ppo的时候,顺带GRPO就实现了,GRPO虽然只需要rule-based reward,但是你需要根据经验设计这个reward,对于喜欢调参的人员当然是好事,对于想偷懒的人士就不太友好.

rl的初衷是最大化(轨迹)累积回报。朴素策略梯度可以把同一条轨迹的 return 用到所有 action 上;actor-critic 再通过 Critic / GAE 估计更细粒度的 $A_t$。PPO 使用 clipped surrogate objective 限制有利方向上的过度更新;GRPO 使用 group 内的归一化奖励差异作为整条 response 共享的 Advantage。GSPO 不是把 Advantage 细化到 token,而是把重要性比率、clip 和优化粒度从 token-level 提升到 sequence-level。

在llm 语境下,动作空间 = 词表(离散),预测token是一个多分类问题。SFT是针对Token级别的反馈(对token进行优化和反向传播,每一个token相同的贡献),而RL是针对整个答案文本的评价(对整个语句进行优化和反向传播)。

  1. sft的优化逻辑。逐 token 模仿学习(偏向语言建模),
    1. Loss 计算方式:常用交叉熵损失(Cross-Entropy Loss)。 \(loss_t = -logP_\theta(y_t \mid y_{<t}, x)\) \(\text{Loss} = -\frac{1}{N} \sum_{t=1}^{N} \log P_{\theta}(y_t \mid y_{<t}, x)\) $y_t$是真实token,$y<t$ 是前面生成的 token,N 是 token 数量。
    2. 反向传播:整个 response 的所有 token loss 加起来(通常是 求和 或 平均),这样 response 的 loss 就是一个 标量,再进行反向传播。所以每个 token 的贡献是均等的
    3. 例如输入 “User: 你好\nAssistant: 我很好”,在监督微调时,模型预测 “我” 的概率与标注答案比对,计算 loss。预测 “很” 的概率与真实答案比对,再计算 loss……依次类推。训练过程就是让模型学会模仿人工答案的逐 token 分布。
  2. RLHF优化逻辑。整句优化(偏向人类偏好)。
    1. 训练目标不是让模型模仿 token,而是让整个 句子/输出序列 的质量更高(即 reward 更大)。
    2. Loss 计算方式:用 Policy Gradient (策略梯度) 方法,比如 PPO。梯度更新时,reward 对 整条输出序列 贡献一个分数。每个 token 的更新权重不再是均等的,而是由策略概率分布 + reward 信号共同决定,比如ppo每个 token 的更新强度 = 优势 $A_t$ × 概率比 $r_t(\theta)$。如果 token 在新策略里更被偏好($r_t$ > 1),且 reward 较高,则这个 token 的梯度被放大。如果 token 导致 reward 低,则会被削弱。每个 token 并不是直接用 cross-entropy,而是有权重的负 log 概率: \(\text{loss}_t = - A_t \cdot \log p_{\theta}(y_t \mid y_{<t})\) $A_t$ 是 advantage(整条序列的 reward 减 baseline),$\pi_{\theta}$是当前策略概率,每个 token 的“loss”本质上是 带权重的负 log 概率。
    3. 反向传播:把整个序列(甚至整个 batch)的所有 token loss 求和/平均,反向传播 → 更新参数。不是逐 token 单独更新,而是 序列/batch 一次性反向传播。
  3. 在实现层面,无论 SFT 还是 PPO,都会对每个 token 算 loss,然后反向传播梯度。区别只是:SFT 的 loss 是“平均的负 log prob”,而 PPO/GRPO/GSPO 的 loss 在“负 log prob”前面多了一个权重(advantage/reward)。

RL4LMs/rl 与llm post-train

强化学习的最终目标是什么,一言以蔽之:让LLM在某个评测维度下,rollout的数学期望最大。如何理解呢?评测指的是:当LLM输出了一大堆token,你要怎么eval这个response。这里分为两种

  1. Verified Reward,例如代码题,数学题,response是可以通过rule based的方法验证的
  2. Model-based reward,需要LLM as a Judge给出reward 总之,你要有办法eval模型的rollout,最后需要给出一个标量(最新的on-policy distillation不用)。假设某个$\tau$对应的reward很高,那就提高生成那个$\tau$的概率即可,这也就是训练模型的本质。
RL 概念 LLM 对应  
状态 (State) $s_t$ prompt + 已生成的 tokens  
动作 (Action) $a_t$ 下一个要生成的 token,动作空间即词表  
策略 (Policy) $\pi_\theta (a_t s_t)$ LLM 的推理过程/softmax 后的概率分布/输出分布
奖励 (Reward) R 回答质量、格式、正确性、偏好分  
V(s) 当前上下文下,这条回答最后大概能拿多少分  
A(s,a) 在这个上下文下,选这个 token 比平均更好多少  
PPO 别让模型因为一批 reward 数据就把分布改得太激进  

log-prob/对数概率

log-prob 是连接概率世界和梯度世界的桥梁,是强化学习中“概率 → 损失 → 梯度”转化的关键中介。

$\pi_\theta(y_t|x, y_{<t})$ 模型给 token y_t 的概率,那么 $\text{log-prob}(y_t) = \log \pi_\theta(y_t|x, y_{<t})$ 是模型给出该 token 的对数概率。取对数的原因主要有三个:

  1. 数值稳定性。概率常常非常小(例如 $10^{-6}$),而对数后能避免下溢:$\log(10^{-6}) = -13.8$
  2. 便于求和。序列的整体概率是 token 概率的乘积:$P(y|x) = \prod_t \pi_\theta(y_t|x, y_{<t})$ 对数后变成可加形式: $\log P(y|x) = \sum_t \log \pi_\theta(y_t|x, y_{<t}) $ 方便计算和优化。
  3. 梯度友好。对数使得梯度公式简洁: 比如在策略梯度中,$\nabla_\theta \log \pi_\theta(a_t|s_t) $形式简单且方向正确。

从通用策略梯度到 token-level objective

如果从通用 RL 的视角往 LLM post-train 过渡,最自然的起点还是策略梯度。

一些基础概念,放到 LLM 语境里可以这样理解:

  • $\pi$(Policy,策略):即 LLM 模型
  • $\theta$(Parameter,参数):即模型参数
  • $s$(State,交互状态):即上文,初始状态可以看成 $s_1$
  • $a$(Action,交互行为):即输出的 token
  • $\tau$(Trajectory,轨迹):$\tau = { s_1,a_1,r_1,s_2,a_2,r_2,\dots,s_T,a_T,r_T }$

Reward Function(奖励函数)用于评估某个状态 / 动作序列的好坏:

\[R(\tau) = \sum_{t=1}^{T} r_t\]

因为同一个上下文下,模型并不一定每次都输出同样的 token,所以每条轨迹 $\tau$ 都有自己的采样概率,通常记作 $p_\theta(\tau)$。于是,模型参数 $\theta$ 下的期望奖励可以写成:

\[\overline{R}_\theta = \sum_{\tau} R(\tau) p_\theta(\tau)\]

策略梯度希望做的,就是调整模型参数 $\theta$,让这个期望奖励尽可能大。通过 log-trick,优化目标会逐步从“整条轨迹的奖励”拆到“每一步 action 的对数概率”上。也正是从这里开始,RL for LLM 才真正走向 token 级训练信号。

但 LLM 场景有一个很具体的问题:奖励通常是 sequence-level 的,也就是整段回答结束以后才拿到一个 scalar reward。reward 只能告诉我们“哪条输出整体更好”,却不能天然告诉我们“这条输出里的每个 token 分别该负多大责任”。因此,真正困难的并不是写出一个 sequence-level 的目标,而是如何把这个目标稳定地拆成 token-level 的优化信号。

这也是为什么在 LLM RL 中,常常会看到下面这条主线:

  1. 先有 sequence-level reward
  2. 再减去 baseline,得到相对好坏
  3. 再用 Critic / GAE / group relative reward 等方式,把它变成更稳定的 Advantage
  4. 最后再把 Advantage 乘到每个 token 的 $\log \pi_\theta(a_t \mid s_t)$ 上

一句话概括这条主线:样本拿到的是一个绝对、序列级、每条一个的标量 reward;真正用来更新模型的是 Advantage 加权后的逐 token loss。

\[\underbrace{R(\tau)}_{\text{绝对、序列级、给定}}\ \xrightarrow{\ \text{减 baseline}\ }\ \underbrace{A}_{\text{相对好坏}}\ \xrightarrow{\ \text{加权 log-prob}\ }\ \underbrace{L_t}_{\text{逐 token loss}}\]

这里必须区分两个容易混淆的概念:loss 是按 token 计算的,不代表 Advantage 一定具有 token 级的差异。在 PPO + Critic/GAE 中,通常可以为不同 token 估计不同的 $A_t$;在 GRPO 中,先计算整条 response 的 $A_i$,然后把同一个 $A_i$ 广播给这条 response 的所有 token。后者虽然也会产生逐 token loss,但本质上仍然是 response-level Advantage,没有精细解决 token 之间的 credit assignment。

一个 reward 如何变成每个 token 的 loss

用一个最小例子一步步看。假设:

  • prompt 是 abc
  • 模型 rollout 得到 response def
  • 奖励函数给整条 response 一个标量 reward:$R=1$

这仍然是一个 rollout 样本,不是三个独立样本。但由于自回归模型在三个位置都做了一次 token 预测,因此会得到三个 log-prob:

\[\log \pi_\theta(d \mid abc),\quad \log \pi_\theta(e \mid abcd),\quad \log \pi_\theta(f \mid abcde)\]

最朴素的策略梯度可以把每个位置的 loss 写成:

\[L_d=-A_d\log \pi_\theta(d \mid abc)\] \[L_e=-A_e\log \pi_\theta(e \mid abcd)\] \[L_f=-A_f\log \pi_\theta(f \mid abcde)\]

最后把 response 中有效 token 的 loss 求和或平均,再做一次反向传播:

\[L=\frac{L_d+L_e+L_f}{3}\]

如果 $A_t>0$,优化会提高对应 token 在该上下文中的概率;如果 $A_t<0$,则会降低它的概率。因此,reward 并没有被直接转换成 d/e/f 各自的监督标签,而是经过 baseline / Advantage 后,成为各位置 log-prob 前面的更新权重。

不同算法的关键区别在 Advantage 从哪里来:

  • PPO + Critic/GAE:可能得到三个不同的 $A_d,A_e,A_f$,从而对不同 token 做较细的信用分配。
  • GRPO:先根据同一 prompt 下多条 response 的组内奖励计算一个 $A_i$,然后令 $A_d=A_e=A_f=A_i$。三个位置都有 loss,但共用同一个好坏信号。
  • 朴素 REINFORCE:也常把整条轨迹的 return(或减去 baseline 后的结果)用于所有 token,粒度同样较粗。

PPO / GRPO 的实际实现还会引入新旧策略的概率比和 clip。对第 $t$ 个 token:

\[r_t(\theta)=\frac{\pi_\theta(a_t\mid s_t)}{\pi_{\theta_{old}}(a_t\mid s_t)}\] \[L_t^{clip}=-\min\left(r_t(\theta)A_t,\operatorname{clip}(r_t(\theta),1-\epsilon,1+\epsilon)A_t\right)\]

工程实现中,只对 response token 计算这些 loss,prompt token 和 padding token 会被 mask 掉。整个 response / batch 的有效 token loss 聚合后统一反向传播,并不是生成一个 token 就立刻更新一次模型。

从这个角度看,PPO、GRPO、GSPO 的真正差别,并不只是“公式长得不同”,还包括 Advantage 如何估计、是否具有 token 级差异,以及概率比和约束作用在哪个粒度。

  1. 宏观层
    1. 教 vs 发掘:这可能是大部分人对SFT和RL的直觉,一个要老师手把手教,一个追求自我探索,上限可想而知。
    2. 非唯一解:如果你有绝对的最佳答案,那用SFT应该是又快又好。但很多问题是没有唯一答案的,所以SFT面临泛化性挑战,或者说涌现不出智能。
    3. 规模化:监督数据是很难规模化的,难以收集方方面面的高质量标注数据。从‘人类模拟器’的角度,RL有望通过探索来扩展训练数据,甚至获得未知数据,比如LLM用于科研领域。
  2. 微观层
    1. Token-level vs Output-level:SFT可以看成一种token level的反馈,通过交叉熵损失函数计算每个位置的误差。而RL是output level,会评估整体输出的好坏。例子:
      1. sft:输入 “春暖花_“,参考输出为”开”,模型若生成 “谢”,则该token产生损失梯度。
      2. rl:输入 “写一首关于春天的诗”,给生成的诗句进行综合评分(如4.5/5分),对每个token都会估计全局收益。
    2. 定性和定量的偏好:SFT通过离线数据处理流程获得了高质量的样本,因此LLM学到了我要按照xyz这种方式说话;但RL中会引入优势值,计算当前答案比baseline好多少,根据优势值得到梯度,因此模型可能更清楚不同层次答案的差异。并且能够通过策略梯度支持数值化的奖励,而不只是偏序。从这个角度看,DPO也是只能做到定性,a比b好,但没有建模好多少;

RL for LLM本质理解大型语言模型的演进,长期以来依赖于标准的监督学习(Supervised Learning)范式,主要体现在预训练(Pretrain)和指令微调(SFT)两个阶段。该范式的核心在于,模型需要依赖人类给出的、从输入到输出的完整监督信号进行学习。若要仅凭此路径达到通用人工智能(AGI)的高度,必须满足两个近乎理想化的前提条件:

  1. 监督数据的无限性与完备性:数据量级需趋于无穷,且其分布能覆盖所有可能遇到的问题,以确保模型的全知性。
  2. 监督信号的绝对完美性:所有监督数据必须准确无误,不存在任何错误或偏见,以确保模型的正确性。 然而,在现实中,这两点均难以实现。一方面,高质量的人类标注数据已出现“数据瓶颈”,其生产成本高昂且效率有限(我们已经用完了几乎所有的互联网信息,把人类历史上所有的数据都压缩到了模型之中,现在我们已经只能依靠标注数据和合成数据勉强提升模型的性能了)。另一方面,人类知识本身存在边界(如许多科学未解之谜),且在标注过程中不可避免地会引入错误和主观偏见。因此,探索一种能够突破上述局限性的新扩展方法(scaling method)势在必行。这种新方法需要满足:
  3. 数据能够以更高效、低成本的方式进行规模化扩展。
  4. 对监督信号的依赖可以放宽,不再要求“专家级别”的完美答案。

RL之所以被视为LLM持续进化的关键,源于其两个显著特征:

  1. 数据由模型与环境交互自发生成:这从根本上解决了数据来源的限制,为模型的持续学习提供了近乎无限的原材料。
  2. 监督信息从“生成式”退化为“验证式”:RL的核心是奖励信号(reward),它不要求监督者提供完美的“专家答案”,而只需对模型生成的答案进行有效性或质量的“验证”。基于“验证答案的难度远低于生成答案”这一基本事实,RL大幅降低了对监督信息质量和标注难度的要求

图解大模型RLHF系列之:人人都能看懂的PPO原理与源码解读 文章后半部分没有跟上。 强化学习在LLM中的应用:给定prompt,调整policy,生成符合人类喜好(RM偏序信号)的response

  1. 状态S:输入prompt
  2. 在t时刻,模型根据上文,产出一个token,这个token即对应着强化学习中的动作,我们记为$A_t$。因此不难理解,在llm语境下,强化学习任务的动作空间就对应着词表
  3. 在 t时刻,模型产出token $A_t$ 对应着的即时收益为 $R_{t}$,总收益为$V_{t}$ ,这个收益即可以理解为“对人类喜好的衡量”。此刻,模型的状态从 $S_{t}$变为$S_{t+1}$,也就是从“上文”变成“上文 + 新产出的token”
  4. 在llm语境下, 智能体是语言模型本身,环境则对应着它产出的语料

从trpo,ppo开始到后来的AWR,CFGRL,其实核心思想都是一样的:在“不要离旧策略太远”的前提下,尽可能把策略往更优的方向推一小步。这些方法最后的统一更新方式基本上可以写成

\(\nabla_\theta \mathcal{L}_{\text{actor}} \approx -\mathbb{E}\big[w(s, a)\, \nabla_\theta \log \pi_\theta(a|s)\big].\) 这个目标是很多方法的“共同祖先”,但不同方法会在不同层面做近似。

  1. Policy Gradient, $\hat{A} > 0$ 增大这个动作概率, $\hat{A} < 0$ 减小这个动作概率。 \(w_{\text{PG}}(s, a) = \hat{A}(s, a)\)
  2. PPO,对naive的policy gradient乘上了一个因子/ratio $r_\theta(s, a)$, 并且对因子做了截断/clip。 PS:ratio clip \(w_{\text{PPO}}(s, a) = r_\theta(s, a)\hat{A}(s, a)\)
  3. GRPO,沿用 PPO 那套 ratio×clip,唯一差别是 $\hat{A}$ 不再来自 critic+GAE,而是组内相对的归一化优势(同一条输出 $o_i$ 的所有 token 共用这一个 $\hat{A}_i$)。 \(w_{\text{GRPO}}(s, a) = r_\theta(s, a)\,\hat{A}_i,\quad \hat{A}_i = \frac{r_i - \text{mean}}{\text{std}}\)

所以 PG → PPO → GRPO 在这张“共同祖先”表里,差的其实只有 $w$ 里那两件事:要不要乘 ratio(带 clip)、以及 $\hat{A}$ 从哪来(裸 return / critic+GAE / 组内相对)。

(DPO 不在这条线上:它是离线偏好优化,直接在 $(y_w, y_l)$ 偏好对上做闭式优化,绕开了 rollout 和 reward model,没有“采样 → 加权 $\log\pi$”这一步。硬要类比,它的梯度也能写成“按隐式奖励差给 $\log\pi$ 加权”,但那是另一支,不和 PG/PPO/GRPO 共享同一个在线祖先——这也呼应前面说的 DPO 只能定性 a>b、给不出“好多少”。)

PS:在强化学习中,模型的输出概率被称为模型的策略。无论我们如何训练LLM,不变的部分是其输入空间(提示词的字符串)和输出空间(所有token组成的词表)。在有了RLHF这一步之后,llm就不仅仅是统计模型。

PPO(Proximal Policy Optimization)

在 LLM 应用环境中,我们应用 PPO 算法,是把 LLM 当成智能体,但什么是环境呢?似乎不像下围棋、玩游戏这种传统 RL 场景中那样容易定义,奖励从何而来呢?那我们就训练一个 RM 来充当这样角色(RM 扮演的是「环境」),它最主要的目标就是给 LLM 这个智能体以外部的 「奖励信号」,这个奖励代表了 LLM 的决策(输出响应)有多符合人类的期望或偏好。PS: PPO 需要 Reward 来训练 Critic。

为什么ppo算法中引入critic model可以降低方差?经典的蒙特卡洛策略梯度算法,例如REINFORCE,通过直接优化参数化策略进行学习,但其核心缺陷在于梯度估计的高方差。这种高方差主要源于其对完整样本轨迹回报的依赖,导致策略更新过程不稳定且收敛效率低下。为解决这一关键问题,PPO算法引入了Critic(评论家)模型作为一项核心改进。Critic通过学习状态价值函数充当一个动态的基线(baseline),其目标正是显著降低策略梯度估计的方差,从而提升学习的稳定性和效率。

  1. 什么是高方差?为什么它是个问题?想象一下,你正在努力学习如何投篮。如果你仅仅根据多轮投篮后整场比赛的输赢(类似于 RL 中的蒙特卡洛回报)来判断,那么你对每一次投篮的反馈就会非常嘈杂。也许你投出了一个好球,但你的队伍由于其他因素仍然输了比赛。或者,也许一个运气球进了,尽管你的姿势并不好。这与像 REINFORCE 这样的基本策略梯度方法中发生的情况类似。它们基于在整个回合(episode)中累积的总奖励来估计动作的“好坏”。即使动作或环境的随机性只有微小的变化,这些奖励也可能会剧烈波动。反馈(梯度估计)中的这种高方差意味着:
    1. 不稳定的更新: 策略可能会在每次更新时被随机地推向不同的方向。
    2. 缓慢的收敛: 从嘈杂的信号中辨别出动作的真实、潜在质量需要很长时间。
  2. Critic 登场:理性的声音。评估 Actor 所采取的动作,或者更常见地,它估计一个特定状态有多好。它学习一个价值函数,通常是状态价值函数 $V(s)$,表示智能体从状态 $s$开始并遵循当前策略可以获得的预期未来总奖励。这个由 Critic 学到的 $V(s)$充当了一个智能的基线 (baseline)

公式

PPO 不仅仅着眼于原始的、嘈杂的回报$G_t$(从时间$t$开始的折扣奖励之和),而是利用 Critic 的基线来计算所谓的优势函数 (Advantage function) $A(s_t,a_t)$。Critic 的任务就是预测:从当前这个前缀(在语言模型的上下文中,$s_t$可以理解为prompt + partial response)出发,最终能获得多少 reward?$A(s_t,a_t)$其核心思想是确定在状态$s_t$下采取动作$a_t$比该状态下的平均预期要好多少。

有了 $V(s)$ 之后,就可以计算 优势函数(Advantage Function): \(A(s,a) = Q(s,a) - V(s)\)

其中 $Q(s,a)$ 是“在状态 $s$ 下采取 action $a$ 后的期望累积奖励”。但在实践中,我们并不直接估计 $Q$,而是用蒙特卡洛回报(Monte Carlo Return) 来近似: \(R_t = \sum_{k=t}^T \gamma^{k-t} r_k\)

但由于 RM 只在 $T$ 时刻给出一个 scalar reward(设为 $r_T$,中间 $r_t = 0$),所以: \(R_t = \gamma^{T-t} r_T\)

于是优势函数简化为: \(A_t = R_t - V(s_t) = \gamma^{T-t} r_T - V(s_t)\) PS:不直接用rm($r_T$),也不直接用critic($ V(s_t)$),而结合在一起算$A_t$。

这个 $A_t$ 就是我们用来更新 policy 的核心信号。它衡量的是:“在 $t$ 时刻采取当前 action,比平均水平好多少?”——这就是 token-level 的训练信号。

然后,PPO(以及一般的 Actor-Critic 方法)中的策略梯度更新使用这个优势:鼓励 Actor 采取导致正优势的动作,而不鼓励采取导致负优势的动作。

方差降低背后的数学原理。策略梯度定理允许我们将预期总奖励$J(\theta)$关于策略参数 $\theta$的梯度写为:

\[\nabla_{\theta}J(\theta) = \mathbb{E}_{\tau \sim \pi_{\theta}} [ \sum_{t=0}^{T-1} \psi_t \nabla_{\theta} \log \pi_{\theta}(a_t | s_t) ]\]

在这里,$ \psi_t$ 是衡量在状态 $ s_t $ 下动作 $ a_t $“好坏” 的某种指标。在 REINFORCE 中,$\psi_t = G_t $(从时间 $t$ 开始的回报)。在像 PPO 这样的 Actor-Critic 方法中,$\psi_t = A(s_t, a_t) \approx G_t - V(s_t)$

直观理解:为什么减去基线有效?把它想象成按曲线给考试评分。教授不仅仅看你的原始分数$G_t$,还会考虑班级在该难度考试中的平均分$ V(s_t)$。你的“优势”就是你比平均水平好(或差)多少。这种相对衡量通常比原始分数更能稳定地反映你的理解程度,因为原始分数可能会受到考试异常简单或困难的影响。类似地,从 $G_t$中减去 $ V(s_t)$

  1. 中心化奖励: 如果智能体处于一个通常较好的状态($ V(s_t)$较高),即使是一个不错的动作也可能导致回报$G_t$ 很高,但不会远高于 $ V(s_t)$。优势 $A(s_t,a_t)$会很小,正确地表明该动作对于那个好状态来说只是“平均水平”,只有“超出预期”的 action 才会被强化。
  2. 减少状态价值方差的影响: 某些状态本质上比其他状态更有价值。通过减去状态的价值,我们将学习信号集中在动作本身的后果上,而不是状态的内在价值。如果一个好状态下的所有动作都会导致高回报,那么仅使用 $G_t$无法清楚地区分哪个动作是最佳的。优势函数有助于做出这种区分。 这使得学习信号(优势)的噪声更小,更专注于动作的相对质量,从而带来更稳定和高效的学习。

伪代码

# 初始:SFT后的模型,拷贝一份作为参考,不参与更新
model = SFT_model 
ref_model = copy.deepcopy(SFT_model) # 用来计算KL散度,防止模型跑偏
value_model = Critic_model # 用来预测状态价值,辅助计算 advantage

for iteration in training:
    # --- 1. Rollout (采样阶段) ---
    with torch.no_grad():
        responses = model.generate(prompts)
        # 存下采样时的 logprob,作为基准
        logprob_old = model.logprob(prompts, responses)
        # 获取奖励(通常会减去与 ref_model 的 KL 惩罚)
        values = value_model(prompts, responses) 
        rewards = reward_model(prompts, responses) - KL(logprob_old, ref_model.logprob(...))
        # 用 GAE 等算法计算优势
        advantages = compute_gae(rewards, values)

    # --- 2. PPO update (学习阶段) ---
    for epoch in range(K):
        # 注意:这里计算的是当前最新权重下的概率
        logprob_new = model.logprob(prompts, responses) 
        
        # 计算重要性采样比率
        ratio = torch.exp(logprob_new - logprob_old)
        
        # PPO 核心:带截断的损失函数
        surr1 = ratio * advantages
        surr2 = torch.clamp(ratio, 1-eps, 1+eps) * advantages
        policy_loss = -torch.min(surr1, surr2).mean()
        
        # 更新参数:执行完这一步,model 就不再是产生 logprob_old 的那个模型了
        optimizer.zero_grad()
        policy_loss.backward()
        optimizer.step() 
        
        # 同时也会更新 value_model...

流程及示例

一个典型的 PPO 算法流程是这样的: actor model 的输入是prompt(今天天气怎么样?),输出是response(今天天气很好,适合出去玩。)。reference model的输入是prompt + actor_response,Reference Model 通过前向传播,为每个 token 计算概率分布。假设 Reference Model 的输出概率分布如下:

  1. 对于 token “今天”,概率分布为 [0.4, 0.3, 0.2, 0.1],其中 “今天” 的概率为 0.4。
  2. 对于 token “天气”,概率分布为 [0.1, 0.5, 0.3, 0.1],其中 “天气” 的概率为 0.5。
  3. 对于 token “很好”,概率分布为 [0.2, 0.3, 0.4, 0.1],其中 “很好” 的概率为 0.3。
  4. 对于 token “适合”,概率分布为 [0.3, 0.2, 0.4, 0.1],其中 “适合” 的概率为 0.4。
  5. 对于 token “出去”,概率分布为 [0.1, 0.2, 0.6, 0.1],其中 “出去” 的概率为 0.6。
  6. 对于 token “玩”,概率分布为 [0.2, 0.3, 0.4, 0.1],其中 “玩” 的概率为 0.4。 计算每个 token 的对数概率:
  7. “今天” 的对数概率:ln(0.4)
  8. “天气” 的对数概率:ln(0.5)
  9. “很好” 的对数概率:ln(0.3)
  10. “适合” 的对数概率:ln(0.4)
  11. “出去” 的对数概率:ln(0.6)
  12. “玩” 的对数概率:ln(0.4) 整个回复的参考对数概率为这些对数概率的总和:ln(0.4) + ln(0.5) + ln(0.3) + ln(0.4) + ln(0.6) + ln(0.4)

PS: 这个算是回答了 $p_{\theta}(a_t \mid s_t)$ 或 $\pi_{\theta}(a_t \mid s_t)$如何算

补充

PPO 属于 actor-critic 架构,其中 Critic 的作用就是计算 优势函数 (Advantage Function),从而减少策略梯度估计的方差,使训练更稳定、高效。RM 是 外部的奖励信号,是外部环境给与智能体的真实响应——虽然在 LLM 的这个场景里,我们没有特别准确的外部环境建模,退而求其次用另一个训练好的 RM 模型来代替了——而 Critic 是智能体内心对自己答案的评价。打个不准确的比方,你做一套卷子,Critic 是你自己检查自己的答案,给出的自我评价;而 RM 是老师用标准答案给你打分。这样看来,不要 Critic 是不是也行?无非就是我自己「莽」一点,自己不评估自己的答案,反正 RM(环境)会给我反馈,牵引我改进。确实可以,GRPO其实在 Actor-Critic 框架之前,RL 算法就是这样的,不要「基线」了而已。代价就是方差比较大,训练不稳定。其实是通过另一种更简单的「估算基线」的方法,取代了 Critic:就是采样多次,用 RM 评价的平均值来充当这个「基线」。Critic 不是提供额外的奖励来源,而是通过学习预测未来的期望回报,提供了一个动态的基准,用来校准 RM 提供的原始奖励信号,生成更稳定、信息量更大的 Advantage 信号,从而稳定并加速 PPO 的训练。

从更抽象的角度看,RL 本质是最大化期望轨迹回报,通过 log-trick,把优化目标拆到 action / token 的 log-prob 上。Advantage、Critic、GAE 等方法用于改进每一步训练权重的估计;GRPO 则用 response-level 的组内相对 Advantage 省掉 Critic,再把同一个 Advantage 用到该 response 的所有 token 上。

站在 LLM post-train 的角度看,PPO 这一套其实是在解决几个很具体的问题:

  1. 只有 Reward 时的朴素做法为什么不够?因为奖励信号波动很大,而且经常是整句级、末尾才给出,直接拿来训会导致方差很大。
  2. 引入 Critic,本质上是引入价值函数作为参考线(baseline),让训练从“只用 Reward” 进化成“用 Advantage 来衡量进步”。
  3. 加入 Clip 与 min 操作,是为了防止 surrogate objective 继续奖励过大的有利变化。例如 $A_t>0$ 时,概率比 $\frac{P(a_t \mid s_t)}{P_{old}(a_t \mid s_t)}$ 超过 $1+\varepsilon$ 后不再继续鼓励;$A_t<0$ 时则主要限制 ratio 低于 $1-\varepsilon$ 的方向。它不是把 ratio 本身硬限制在区间内。
  4. Reference Model 和 KL 的作用,则是防止策略为了追求短期 Reward 而偏离原始模型太远,出现作弊、模式坍塌或风格漂移。
  5. Critic 也不是没有代价。价值函数通常需要和 Actor 同等量级的模型去估计,成本很高,而且在只在回答末尾才给出一个整体 Reward 的场景里,训练一个足够细粒度、足够准确的 value function 也并不容易。

这也是为什么后面会出现 GRPO 这种路线:如果 Critic 难训,或者成本太高,那么就干脆不用 value model,而改成“同一问题采多条输出,直接拿组内相对分数当 baseline”。这样做虽然更粗糙,但工程上会轻一些。

从Policy Gradient到REINFORCE++,万字长文梳理强化学习最新进展

浅谈 RL 里面的 KL 散度个人认为,RL与SFT的区别在于,SFT是token level的0/1奖励,RL是句子level的离散奖励。当然,RL也可以往过程奖励(PRM)或者规则奖励(rule-based)去走。往过程奖励走,无非是引入一个sub-sentence level的监督信号,介于整句(或者说答案)与单个词之间的监督信息。往规则走,是希望整体系统不要被Reward Model所束缚,如果数据质量足够高+基座足够优秀,那么就不需要花里胡哨的reward形式,直接使用rule-based reward就行。这里的reward大多是(-1、0.2、1)这种三段式设计,本质上和SFT的0/1是差不多的。如果我们对(-1, 0.2, 1)做一次softmax,那么就变成了(0.08, 0.26, 0.64)。从某个视角来说,也算是one-hot label的平滑形式。大家都喜欢说,RL是泛化的,SFT是记忆的。我觉得,之所以造成这种现象,是因为RL学的比较难,所以聚焦于方法论,而SFT学的比较简单,那么就容易掉入过拟合陷阱,也就是SFT记住但无泛化。正是因为RL学的比较难,那么RL的acc涨的是比较慢的,好处但是就是,真的往解题的技巧上学。

深挖PPO,聊聊前身TRPO PPO的目标函数与Reinforce算法的目标函数还是有一定差异的,尤其是它采用了 $\pi_{\theta_{old}}$ 来采样数据并在目标函数中引入重要性采样 $\frac{\pi_{\theta}}{\pi_{\theta_{old}}}$ ,这其实并不直观,我们明明推导的是基于蒙特卡洛采样的Policy Gradient,怎么目标函数中有这么多不同的策略网络呢?为什么采样的策略和执行更新的策略不一样呢?为什么长得这么不一样的目标函数也可以算作蒙特卡洛采样呢?这篇文章就要来梳理这个问题,首先从TRPO说起。TRPO(Trust Region Policy Optimization)和PPO(Proximal Policy Optimization)的作者是同一人,TRPO也是PPO的前身工作。

Group Relative Policy Optimization(群体相对策略优化)

GRPO 的创新:无 Critic 的 Advantage 估计

图中有以下几个关键点:

  1. 没有 Value Model(仅保留 Reward Model 作为监督的依据) 和输出 v(value)。PS:和PPO最大的区别是优势函数的计算,GRPO中用最后一个token的奖励算完优势之后,同一个seq中的所有token共用一个优势。
  2. 同一个 q 得出了一组的 o(从 1 到 G)(用于比较优势)。PS:PPO 只采样 1 个
  3. 计算 A(Advantage) 的算法从 GAE 变成了 Group Computation。PS:PPO使用GAE优势
  4. KL 散度计算不作用于 Reward Model,而是直接作用于 Policy Model。PS:虽然 deepseek-r1 使用规则作为 reward 训练,但 reward model 部分不是 GRPO 与 PPO 的主要区别。

可以把 GRPO 理解成:在“PPO 这套思想仍然成立”的前提下,把 Critic 这一支砍掉,直接用组内相对奖励去估计 baseline。也就是说,PPO 和 GRPO 的大方向非常接近,真正差别最大的地方还是 Advantage 的来源:

  1. PPO:通常依赖 Critic + GAE 来估计 Advantage
  2. GRPO:依赖同一问题下多条输出的组内相对分数来估计 Advantage

因此,GRPO 并不是完全换了一套世界观,而是把 “baseline / advantage 怎么来” 这件事做了一个更轻量、更偏采样式的替换。

公式

GRPO舍弃了传统PPO算法中的Critic模型(通常与策略模型大小相同)部分,转而通过直接从群体得分中估算baseline。在训练大语言模型llm时,一个最大的问题是中间状态很难评估(PPO的critic model总是试图精细地预测每个步骤的价值),由于语言生成是一个自回归式的序列决策过程,我们很难直接判断某个中间状态的好坏,——它是否能最终生成一个高质量答案,往往是不确定的。这就带来了一个核心问题:PPO中使用的critic model(即计算价值函数value function 用的模型)到底有没有用?它的意义有多大?准不准?这都是很难确定的。所以,PPO中critic model的意义虽然存在,但它的准确性是个大问题,限制了整体方法的可靠性。相比之下,GRPO采取了一种截然不同的思路:它直接让llm多次sample,生成完整的响应,然后用显式的奖励来评价这些最终结果。正因为一把梭哈,直接生成结果,完全跳过了对中间状态的评估,直接聚焦于完整输出的质量。既然中间状态这么难评估,那就干脆不评估,生成结果出来后自然可以通过设计好的奖励机制来判断好坏。这样一来,GRPO省去了预测中间状态价值的麻烦,直接依赖最终输出的奖励信号。更重要的是,这种方式可以通过显式设计reward奖励信号,而且必然是有效的。因为奖励是针对完整响应计算的,这种清晰的反馈比PPO中模糊的价值函数预测要可靠得多。

具体来说,对于每一个问题 $ q $ ,GRPO会从旧的策略模型参数 $ \pi_{\theta_{\text{old}}} $ 中采样一组输出 $ {o_1, o_2, o_3, \ldots, o_G} $,然后通过最大化GRPO目标函数以优化当前策略模型参数 $ \pi_\theta $。

辅助理解:不同的策略模型 $\pi$ 实际上是一个模型在不同参数阶段下的版本。

具体可以按如下理解,

  • $ \pi_{\theta_{\text{old}}} $:上一轮模型参数的模型,可以理解为 $ \pi_\theta $ 上一个iteration的模型。
  • $ \pi_\theta $:最新的模型参数的模型(正在更新的)。
  • $ \pi_{\theta_{\text{ref}}} $:初始模型参数。

原文公式如下图所示:

对第 $i$ 条输出的第 $t$ 个 token,先定义逐 token importance ratio:

\[r_{i,t}(\theta)=\frac{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}{\pi_{\theta_{\text{old}}}(o_{i,t}\mid q,o_{i,<t})}\]

在本文讨论的 outcome supervision 场景中,原始 GRPO 的 clipped objective 在 token 维度上计算,再在每条 response 内聚合:

\[\mathcal{J}_{\text{GRPO}}(\theta)= \mathbb{E}\left[ \frac{1}{G}\sum_{i=1}^{G}\frac{1}{|o_i|}\sum_{t=1}^{|o_i|} \left( \min\left(r_{i,t}(\theta)A_i,\operatorname{clip}(r_{i,t}(\theta),1-\varepsilon,1+\varepsilon)A_i\right) -\beta D_{KL}^{i,t} \right) \right]\]

其中,同一条 response 的所有 token 共用 $A_i$,但 importance ratio $r_{i,t}$ 是逐 token 计算的。逐 token 的 KL 估计为:

\[D_{KL}^{i,t}=\frac{\pi_{\text{ref}}(o_{i,t}\mid q,o_{i,<t})}{\pi_\theta(o_{i,t}\mid q,o_{i,<t})} -\log\frac{\pi_{\text{ref}}(o_{i,t}\mid q,o_{i,<t})}{\pi_\theta(o_{i,t}\mid q,o_{i,<t})}-1\]

$\varepsilon$ 控制 clipped surrogate objective 的截断区间,但不是策略参数实际学习步长的硬上限。

$ \beta $ 控制原始能力偏移惩罚的程度。主要是缓解灾难性遗忘的问题。

DeepSeek的GRPO算法是什么? - 梦想成真的回答 - 知乎最核心的就是逐 token 的 $r_{i,t}(\theta)A_i$

  1. q 表示此次的问题
  2. $o_i$ 表示旧的policy model 的第i个输出策略
  3. $\pi_\theta(o_{i,t}\mid q,o_{i,<t})$ 表示当前模型在给定前缀时输出第 $t$ 个 token 的概率
  4. $\pi_{\theta_{\text{old}}}(o_{i,t}\mid q,o_{i,<t})$ 表示旧策略对同一个 token 的概率

进而,$r_{i,t}(\theta)$描述当前策略相对旧策略在这个 token 上的概率变化。优化目标不是单独最大化 ratio,而是最大化 ratio 与 Advantage 共同构成的 clipped surrogate:$A_i>0$ 时鼓励提高该 token 的概率,$A_i<0$ 时鼓励降低它。clip 是目标函数裁剪,不是 gradient clipping;KL 则用于约束当前策略不要偏离 reference model 太远。

我们再说优势函数 (Advantage Function) $A_i$,R1中非常简单直接,就是reward score 做个标准化,得到的$A_i$就是第i个决策在多个决策中相比较baseline 好多少或者坏多少。如果$A_i$>0,那么就是正向激励,否则,$A_i$< 0 就是负向激励。

通过如下公式计算出:

\[A_i = \frac{r_i - \text{mean} ( \{r_1, r_2, \cdots, r_G\} )}{\text{std} ( \{r_1, r_2, \cdots, r_G\} )}.\]

这里两步——减组内均值再除组内标准差——各管一件事。减均值就是前面说的 baseline,把“恒正的奖励”变成“相对组内的好坏”;除 std 是做尺度归一:不同题难易不同,有的题一组 reward 普遍高、有的普遍低、方差也不一样,除以 std 后各组的优势被拉到可比的尺度,梯度步长不会被“这组题碰巧分偏高/偏低”带偏。

但这步归一化也埋了一个 GRPO 特有的退化点:当一组 G 条样本的 reward 全一样时(全对或全错),组内均值就等于每一条,分子 $r_i-\text{mean}$ 全为 0,优势整组归零(此时 std 也为 0,所以伪代码里要 +1e-4 防除零;但就算不除零,分子为 0 也让优势为 0)。优势为 0 → 这一组对梯度零贡献 → 整组白跑

这正对应前面「GRPO 不足」里说的“过难/过易样本优势为 0、回传不了有效梯度”:

  • 简单题:G 条大概率全对 → 白跑;
  • 难题(尤其长程任务):G 条可能全错(有限采样里压根没探到正确轨迹)→ 也白跑,而且一组长轨迹可能是几小时算力,最后零信号,工程上很肉疼。

所以 GRPO 真正“吃到”有效梯度的,是那些组内有对有错的中等难度题——这也是它对题目难度分布、采样数 $G$、温度都比较敏感的原因。(顺带一提:要不要除 std 本身也有争议,Dr. GRPO 等工作指出除 std 会给“低方差的题”不成比例的大优势,干脆把这一步去掉。)

现在可以解释 $r_{i,t}(\theta)A_i$ 为什么要把两项乘在一起。$A_i$ 表示整条 response 相对组内平均水平的好坏,$r_{i,t}(\theta)$ 表示当前模型相对旧模型在第 $t$ 个 token 上的概率变化。$A_i>0$ 时,目标鼓励提高这条 response 中已采样 token 的概率;$A_i<0$ 时则鼓励降低。因为同一条 response 的所有 token 共用 $A_i$,GRPO 会为每个 token 计算各自的 ratio 和 loss,但没有得到不同的 token-level Advantage。

接下来说 clip。它不是把 $r_{i,t}(\theta)$ 本身硬限制在 $[1-\varepsilon,1+\varepsilon]$,也不是梯度剪裁。它通过 min 形成单侧限制:$A_i>0$ 时不再奖励 ratio 超过 $1+\varepsilon$ 的增长;$A_i<0$ 时不再奖励 ratio 低于 $1-\varepsilon$ 的下降。朝不利方向移动时仍然保留梯度,以便把策略拉回来。

GRPO 希望逐 token 的 $D_{KL}^{i,t}$ 尽量小。令 $x=\frac{\pi_{\text{ref}}}{\pi_\theta}$,$x-\log x-1$ 在 $x=1$ 时取得最小值 0,因此目标是让当前策略与 reference model 的概率接近,而不是让这个比率单调变小。$\pi_{\text{ref}}$ 是冻结的初始/SFT 模型,整个 RL 过程保持不变;$\pi_{\theta_{\text{old}}}$ 是产生本轮 rollout 的旧策略;$\pi_\theta$ 则是当前正在更新的策略。

为什么 KL 要写成这个奇怪的样子? 因为它其实是 KL 散度的 k3 估计(Schulman 提出的一种蒙特卡洛估计)。标准 KL $\mathrm{KL}(\pi_\theta | \pi_{\text{ref}}) = E_{x \sim \pi_\theta}[\log \frac{\pi_\theta}{\pi_{\text{ref}}}]$ 要对整个词表分布求和才算得准,但 RL 里我们手上只有采样到的那几个 token,只能用单样本去估。记 $r = \frac{\pi_{\text{ref}}}{\pi_\theta}$:

  • 最朴素的估计是直接用 $\log\frac{\pi_\theta}{\pi_{\text{ref}}}=-\log r$。它无偏,但可正可负、方差大——单个样本上经常给出“负的 KL”,看着别扭、训练也抖。
  • k3 改用 $r - \log r - 1$(也就是公式里那个 $\frac{\pi_{\text{ref}}}{\pi_\theta} - \log\frac{\pi_{\text{ref}}}{\pi_\theta} - 1$),三个好处:① 恒 $\ge 0$($x-\ln x-1\ge 0$,$x=1$ 时取 0,正对应两分布相等);② 仍然无偏,其期望恰好等于真实的 $\mathrm{KL}(\pi_\theta | \pi_{\text{ref}})$;③ 方差比朴素估计更低。所以它“看着不像 KL”,但作为逐 token 估计、再平均的估计量,比朴素 log-ratio 更好用(伪代码里的 kl_loss 就是这一项)。

还要注意 KL 在 PPO 和 GRPO 里放的位置不一样:经典 RLHF-PPO 习惯把 KL 当成奖励惩罚塞进 reward(前面 PPO 伪代码里的 rewards = reward_model(...) - KL(...),即每步 $r_t$ 里就扣掉了 $\beta\log\frac{\pi_\theta}{\pi_{\text{ref}}}$);GRPO 则把 KL 当成独立的一项直接加在 loss 上(目标函数里那个 $-\beta D_{KL}$)。两者都是为了“别离参考模型太远”,区别只在它混进回报里、还是单列在损失里。

我们稍微总结下GRPO:GRPO去掉了value model,仅仅只训练policy model,并且使用reward score标准化的方式作为baseline,让模型找到更优的解法,为了更稳定的训练,clip项和KL散度变种都是辅佐让模型不要训飞,一步步慢慢学的手段。由于reward只在输出级别($o_1,o_2,…$)提供(没有每个 token 的奖励),GRPO把该输出的优势均匀地分配给该输出内所有token。PS:每个输出内部所有 token 共用同一个 Advantage;Actor-Critic + GAE 的区别是可以估计随 token 位置变化的 Advantage,并不是外部 reward 天然变成了 token-level。

把这件事接回 credit assignment,会更看清它的代价。 语言模型强化学习基础 里讲过,RL 的核心难点之一就是 credit assignment——一条轨迹整体好,不代表每个 token 都好,理想情况要能算出每个 token 各自的 $\hat{A}$(critic + GAE/TD 就干这个,单步优势 $=\delta_t$ 给了每个 token 自己的信号)。而 GRPO 把 critic 砍掉后,整条输出只有一个标量优势、再均匀摊给每个 token,等于把 credit assignment 退到了最粗的一档:哪怕一条 1000 token 的输出里只有第 50 步出错,GRPO 也只能把这 1000 个 token 一起奖励或惩罚,没法把锅精确甩给第 50 步。

用上篇「有偏与无偏」那条轴看,这就是 GRPO 的取舍:省掉 critic 避免了 learned value 的 bootstrap 误差,也让工程更轻;但组内均值包含当前样本自身,标准差归一和 clip 也会改变梯度估计,因此不能简单称为“无偏”。与此同时,整条输出共用一个 Advantage,牺牲了 token 级信用分配。输出越长、越是多步,这个粗粒度代价越大;GSPO 改善的是 importance ratio 的序列级一致性,并没有解决这项 credit assignment 问题。

伪代码

for iteration in training:
    # --- 1. Rollout ---
    with torch.no_grad():
        # group_responses: [B, G, L]
        # logprob_old: [B, G, L]
        # group_rewards: [B, G]
        
    # --- 2. Advantage (必须在分布式/全组维度计算) ---
    # 这里是 GRPO 的灵魂:组内标准化
    adv = (group_rewards - group_rewards.mean(dim=1, keepdim=True)) / (group_rewards.std(dim=1, keepdim=True) + 1e-4)
    # 广播到 token 维度: [B, G, 1] -> [B, G, L]
    adv = adv.unsqueeze(-1) 

    # --- 3. Update ---
    for epoch in range(K):
        # 这里的 model.logprob 需要返回每个 token 的 logprob: [B, G, L]
        logprob_current = model.logprob(prompts, group_responses)
        logprob_ref = ref_model.logprob(prompts, group_responses)
        
        ratio = torch.exp(logprob_current - logprob_old)
        
        # PPO Clip 部分
        surr1 = ratio * adv
        surr2 = torch.clamp(ratio, 1-eps, 1+eps) * adv
        # 这里取负数因为我们要 maximize reward
        policy_loss = -torch.min(surr1, surr2).mean() 
        
        # KL 惩罚项 (DeepSeek 风格: 直接对 logprob 做差)
        # 用来限制模型不要跑太远
        kl_loss = torch.exp(logprob_ref - logprob_current) - (logprob_ref - logprob_current) - 1
        
        total_loss = policy_loss + beta * kl_loss.mean()
        
        total_loss.backward()
        optimizer.step()

其它

可视化看GRPO学到了哪些东西

  1. 训练后的模型推理能力依然极度依赖base model。输出概率的改变大部分都发生在连接词、推理流程影响的词,而在单步公式、数字、推理这些基本能力上,模型输出几乎还是在沿用base模型认为最好的路径,说明这些基础能力几乎完全来自base model。这里还做了一个训练时间太长,已经训练崩溃了的checkpoint的可视化,可以看到一旦离base模型太远,正常输出都没法进行下去了,会出现重复、乱码等情况。同时可以看到,这个崩溃的实验其实还没有完全崩溃,输出的前面一段还是正常的,只是训练到了后期,才开始出现模式坍塌。从这个实验的观察可以推出,RL是不能远离base模型太多的,一旦把模型训练偏得多了一些,模型的输出就会崩溃,中断。导致无法输出最终答案,所有rollout的reward分数都是0,模型就没有正确的方向了。总之,目前的Math RL是强依赖一个非常强大的base model:不同大小的模型,相同算法RL后,提升的上限有很大的不同,RL可以通过激发base模型的长推理模式,充分发挥base模型的潜在推理能力。这意味着,想要获得最好的推理效果,就必须要在最好的base模型上面训练
  2. base模型中本来概率很高的token,依然在GRPO中被不断加强,在训练后likelihood变得更接近1,也就是进行了过度自信的优化。这样的优化对模型的生成准确率能力基本是没有帮助的,但是会导致对模型的修改,产生额外的学习税。并且在token的prob都被推高的情况下,也会影响模型的探索的可能,例如prob在比较高的情况下,例如0.99时,在同一个context下,做16次rollout还有15%的可能出现非最高的token,相当于每7个这种token,rollout 16次中会有一个非最高token被探索,但是如果prob推高至0.999,概率就会降低为1.6%。这些token的探索就会几乎不存在。
  3. 从模型的演变角度来说,对一个大模型做RL,是从base/SFT模型作为ref开始,逐渐训练远离这个ref模型,同时获得越来越高的reward的过程。但是与此同时,RL又不能离ref模型太远,否则轻则无法继续训练、重则模型崩溃,而且离ref模型渐行渐远的过程,模型会忘掉前面学过的知识,降智交智商税。在这两层看似矛盾的要求下,要想RL训练的好,大家提出了很多tricks。

    1. 第一种是让训练过程对ref模型修改的又快又好,这样可以最大限度保留原始模型的能力。
    2. 另一个思路是在模型训练的过程中,持续恢复智商。 目前证明有效的都是要让训练又快又好的tricks,而对于恢复智商类的tricks目前基本是没有用的。主要原因我认为是这些策略虽然初衷是好的,但是在LLM的训练过程中起到了拖后腿的作用,无脑将模型往回拉。

rollout 是一个强化学习专用词汇,指的是从一个特定的状态按照某个策略进行一系列动作和状态转移,在 LLM 语境下,“某个策略”就是 actor model 的初始状态,“进行一系列动作”指的就是推理,即输入 prompt 输出 response 的过程。跟着 verl 的代码梳理GRPO

GRPO 不依赖 绝对 reward 值,只关心 同一 prompt 下多个 sample 的相对好坏(只要给每个 sample 一个可比较的 reward 分数即可),用 group-wise relative advantage 来更新策略。GRPO 不“要求” Reward Model,但 Reward Model 依然是提升复杂、主观、sparse reward(比如reward function 只能给出0/1) 场景表现的利器

GRPO 不足(优化方向)

  1. 响应多样性下降 (熵崩塌)
    • 随着模型迭代,策略的确定性增强,随机性降低(回答多样性下降),模型缺乏探索(更多正确回答),容易陷入局部最优解。
  2. 过度思考
    • 原因:GRPO 采用的是 Sample-Level 加权损失,对于长回答中的错误容忍度更高,
    • 结果:
    1. 对于困难的问题,通常会输出冗长的思考过程;
    2. sample-level loss 由于无法有效惩罚长样本中低质量的 pattern, 例如乱码和重复的单词。
  3. Rollout 效率低
    • GRPO 的 rollout 过程是随机进行的(均匀采样),没有考虑样本的难度,导致:
    1. 对于困难问题,模型可能无法在有限的 rollout 次数内采样到正确答案
    2. 对于过难或者过于简单的样本则优势为0,无法回传有效梯度。
  4. 长样本截断、训练不稳定性。
    • (在RL训练中,通常会固定一个最大生成长度,并截断过长的样本)过长的响应被强行截断,导致reward也被截断(对这些被截断的样本进行错误的奖励函数设计会带来奖励噪声,并严重干扰训练过程)。
    • 策略或价值函数的更新波动,导致训练曲线震荡、收敛缓慢甚至发散;每次训练收敛后在评测集上指标的方差较大。

GSPO

GSPO(Group Sequence Policy Optimization,Qwen 团队提出)常被误解成“把 GRPO 的优势细化到每个 token”,其实方向恰恰相反。GRPO 确实是整条输出共用一个优势(上一节说过),但 GSPO 要动的不是优势的粒度,而是 重要性比率的粒度。

回忆 GRPO/PPO 的更新里都有一项重要性比率 $\frac{\pi_\theta(a_t \mid s_t)}{\pi_{old}(a_t \mid s_t)}$。GRPO 是逐 token 算这个比率的,而单个 token 的比率方差很大,序列越长、这些噪声累积得越厉害(对长回答、MoE 尤其明显),训练就容易抖。

GSPO 的做法是把重要性比率从 token 级提到序列级:整条回答只用一个比率(对每个 token 的 log-ratio 做长度归一,相当于几何平均),再在这个序列级比率上做 clip。这样“比率的粒度”就和“奖励本来就是序列级”这件事对齐了——是把比率“变粗、对齐到整句”,而不是把优势“变细到 token”。优势本身仍是组内相对的 $r^{(i)} - \bar{r}_{\text{group}}$,没变;变的只是这个比率到底算在单个 token 上、还是整句上(下面的代码对比,差异正落在这一处)。

详解Qwen3-GSPO和DeepSeek-GRPO两大强化学习算法的区别PS:建议细读,文章给的例子非常惊喜。

GRPO 的Loss的计算过程

  1. 算优势:每个句子的奖励减去组内平均奖励,得到相对优势(好句子为正,差句子为负),也就是A。
  2. 当前模型生成 token 的概率 ÷ 旧模型生成相同 token 的概率(importance ratio),也就是 $\pi_\theta \mid \pi_{\theta_{old}} $
  3. Clipped surrogate:根据 Advantage 的正负,单侧截断继续带来收益的 ratio 变化;ratio 本身仍可能超出 $[0.8,1.2]$
  4. 算基础损失:对每个 token 计算 clipped ratio 与 response-level Advantage 的乘积,再加负号。同一条 response 的 token 使用各自的 ratio,但共用同一个 Advantage。
  5. 加正则项(可选):加入 KL 散度,防止模型和初始版本差太远
  6. 总损失:Group的所有损失的平均值

GRPO 和 GSPO Loss的计算关键差异

其中最主要的差异在重要性计算那一步,GRPO是计算每个token的概率比

log_ratio = per_token_logps - old_per_token_logps  # 每个token的log概率差
log_importance_weights = log_ratio  # 保留token级粒度
coef_1 = torch.exp(log_importance_weights)  # 每个token的概率比

而GSPO是计算整个句子的平均概率比

log_ratio = per_token_logps - old_per_token_logps  # 每个token的log概率差
# 按句子平均:总log概率差 / 有效token数(避免padding影响)
log_importance_weights = (log_ratio * completion_mask).sum(-1) / completion_mask.sum(-1).clamp(min=1.0)
log_importance_weights = log_importance_weights.unsqueeze(-1)  # 扩展为(batch_size, 1)
coef_1 = torch.exp(log_importance_weights)  # 整个句子的平均概率比

长短程任务:GRPO 与 PPO 的天平

把本篇的 credit assignment、组内标准化退化,连同上下篇讲的 bias-variance 几条线收一下,正好能解释“2024 年大家爱用 GRPO、2025 年长程 Agentic 任务起来后又往 PPO/critic 回摆”这件事。两者的根本差别还是 advantage 怎么来:

  • GRPO:无 critic、纯结果奖励、组内相对 Advantage → 省掉 learned value 的 bootstrap 误差,但组内均值、标准差归一和 clip 本身仍会引入估计偏差;同时整条输出共用一个优势(credit assignment 最粗)。
  • PPO:有 critic → bootstrap 带来一点偏差,换来低方差,以及 GAE/TD 给的 token 级信用分配

短任务(数学、单测,几十到几千 token、可验证)为什么 GRPO 够用甚至更优:轨迹短 → 方差本就小;有清晰最终 return;省掉和 actor 同量级的 critic → 省显存、省一套训练。扔掉 critic 几乎无损。

长程任务(几十上百步、上十万 token 的 agent 轨迹)为什么天平倒向 critic:

  1. 方差随轨迹长度累积,GRPO 的高方差被放大;
  2. credit assignment 退到最粗——长输出里某一步坏了,GRPO 只能整条一起奖惩,定位不到是哪步;
  3. 退化更频繁——难题一组 G 条全错(采样压根没探到正解)→ 组内 reward 全一样 → 优势归零、几小时算力零信号;
  4. 对 agent 而言,开放环境 + harness/工具返回带噪,相当于一个随机环境;而随机环境下,“靠采样估 baseline”要拿到准估计所需的交互次数成倍放大,反倒是 learned value(critic)在样本效率上更划算。

所以“修 GRPO 让它扛长程”的代价,开始大于“退回 PPO/critic 好好调”。业界缓解长程的几条路线——把 critic 请回来做 token 级优势、用复合/过程奖励(PRM)、或 on-policy 蒸馏给 dense 的逐 token 监督——本质都是给长程补回 per-step 的密集信号,无非补在 baseline 上、还是补在 reward 上(下一节 V4 的多专家 on-policy 蒸馏,就是后者的一个例子)。

OPD/On-Policy Distillation

OPD把on-policy和offline优点结合起来,用老师模型对学生的每一步打分。让学生从自己当前的分布采样轨迹,这就是 on-policy 的含义,像蒸馏一样,由教师对每个 token 给出密集反馈,信号密度上来了。学生通过最小化与教师之间的 reverse KL 散度来更新,梯度方向是让学生在自己采样的 token 上,逐步向教师的概率分布靠近。

on-policy模型的学习内容是自己 rollout 出来的好的样本。这样做的好处有很多,举一些例子:

  1. 这样的模型不容易出现灾难性遗忘的问题。RL 的训练目标是“强化”自身生成的好的样本,而不是强行去拟合新的数据分布,对模型内部的知识不会产生破坏效果。
  2. 真正 inference 的时候会更加鲁棒。少量的 SFT 样本,只能教会模型强行记住某一条轨迹(A -> B -> C),但是一旦中途发生了些许扰动(如 A -> B’ -> ?),模型由于缺乏对轨迹的深入理解,就可能就会发生错乱。

但是 RL 也有它固有的问题,就是计算不够高效,每次 rollout 一条 trace,都只能获得一个最终的奖励信号。而对比 SFT,对于每一个 token,都有一个对应的 label 来约束更新。这样相比起来,RL 在训练中,模型从一次尝试中学到的内容太少了,效率较低。那么,能不能有一种方法,既具有 on-policy 的特征,又能像 SFT 那样,对每个 token 都加以监督呢?OPD 就是一个有效的尝试,引入蒸馏的思想来解决这个问题。核心的思想很简单,首先由 student model 来 rollout 样本(体现了 on-policy 特点);然后用 teacher model 计算每个 token 对应的 logit;最后拉近 student 和 teacher 在每个 token 上的 logit 分布即可(体现了蒸馏)。具体到实现方式层面,我们简单介绍几种常见的实现。按照Thinking Machine Lab 的实现,OPD 本质上就是通过采样的方法,优化模型策略 和教师策略 之间的 reverse KL,也就是:

\[\mathrm{KL}\big(\pi_\theta \parallel \pi_{\mathrm{teacher}}\big) = \mathbb{E}_{x \sim \pi_\theta}\Big[ \log \pi_\theta(x_{t+1} \mid x_{1..t}) - \log \pi_{\mathrm{teacher}}(x_{t+1} \mid x_{1..t}) \Big]\]

在实操的时候也很简单,首先使用需要训练的模型 进行 rollout;然后再使用上面右侧的公式计算出 logit 距离 teacher 的距离作为损失函数;最后梯度下降进行计算就可以了。

三种主流 OPD 实现 |类型| 计算规则| 特点| |—|—|—| |采样 Token OPD| 仅对学生实际采样的单个 Token 计算损失| 最轻量、工业界最常用,无额外显存开销| |全词表 OPD| 对整个词表所有 Token 计算 KL 散度 |梯度最密集,但显存 / 计算成本极高| |Top-K OPD| 仅对学生概率最高的前 K 个 Token 计算损失| 折中方案,兼顾效果与成本,本文实验默认使用|

OPD 成败的两大决定性条件

  1. 师生必须具备兼容的思维模式。即便教师基准精度更高,若师生推理逻辑、候选 Token 偏好差异过大(初始重叠率低),OPD 会彻底失效;早期思维模式的错位造成的损失,训练后期也无法修复。OPD 学习的不是「教师的高分能力」,而是教师的推理思维范式。
  2. 教师必须提供学生未掌握的全新知识。思维模式匹配≠OPD 一定成功。若师生来自同一训练流水线、同源数据,即便教师规模更大、精度更高,也无法提供可迁移的新知识,OPD 依然收效甚微。模型高分 ≠ 拥有新知识。同家族不同规模模型,只是对同一数据的拟合程度不同,底层分布几乎一致,无法产生 OPD 可利用的新知识。

OPD的基本流程如下:

  1. On-Policy采样:学生模型根据输入prompt自回归生成完整回答(不使用教师的输出)
  2. 教师评分:将学生生成的序列送入教师模型,获取逐token位置的logits
  3. 分布对齐:计算学生分布与教师分布之间的KL,以此作为训练损失
  4. 反向传播:更新学生模型参数,使其在自身生成的序列上接近教师的logits分布。损失函数设计
  5. Forward KL
  6. Reverse KL

这一流程与标准SFT的区别在于步骤1(on-policy vs 离线)和步骤3(软标签分布匹配 vs 硬标签CE损失)。与RL的区别在于步骤3(密集软标签 vs 稀疏标量奖励)。

OPD 的固有缺陷与适用边界(代价与局限)

  1. 奖励质量随序列长度衰减(长 Horizon 失效)。OPD 存在「最优序列长度区间」(实验中 3K~7K Token 效果最佳)。
  2. 全局有效奖励 ≠ 局部可优化梯度。教师的逐 Token 优势信号存在各向异性(不同位置信号相互抵消),梯度幅值极小,学生无法完成局部优化。

从 OPD 到 self-distillation。OPD 单纯的方法部分已经相当简洁有效了,感觉可优化的空间不大,唯独不好处理的点在于 teacher model 怎么获得。如果按照一般的想法,teacher model 使用一个 size 很大的开源模型,那么 tokenizer 很可能和 student model 不一致,那么蒸馏的 logit 和位置就对不齐,直接导致方法用不了;另一方面,虽说做实操我们总喜欢蒸馏更强的模型(不是),但做科研我们总是想提高模型的上限,那么简单的蒸馏就做不到这点了。所以最近看到不少 paper 都采用了 self-distillation 的思想,也就是自己蒸馏自己 —— 这样就避免了 tokenizer 不统一的问题。这类工作的核心问题在于,怎么让自己 rollout 更好的结果,作为 teacher。因此不少文章给出了解决方案:可以在模型输入的 prompt 里面,把专家的解答过程(demonstration)放进去,并让模型基于专家答案,给出解答过程(成为和符合自己模型风格的样本,后续再进行训练和监督)。这样一来,能保证最终 rollout 的质量,又能保证 on-policy 的特点。

LLM 的训练流程

一个领域(比如 Coder/Match/文本专家) LLM 的训练方案:re-train,SFT,RLHF/RLVR。怎么整合成一个混合通用模型呢?DeepSeek V4技术报告流程讲的很细致:先是 pre-train 得到一个 Base-Model,然后先按领域(数学、代码、agent、指令跟随等)分别训练 10 几个专家模型,每个专家都走过 SFT + GRPO 的完整 RL 流程,在自己领域里练到极致。然后关键的一步来了:把这些专家”合成”一个统一模型时,不是让 student 去抄 teacher 的输出分布,而是让 student 自己先 rollout 生成回答,再让多个 teacher 在 student 自己写出来的轨迹上逐 token 给反馈。这实际就是多专家的 on-policy 蒸馏(OPD)。PS:OPD并非一种绝对更好的蒸馏方式,它有它的适应前提。“Rethinking On-Policy Distillation of Large Language Models”指出,即使 teacher 更强,如果 student 和 teacher 的 top-k token 分布重叠率(overlap ratio)低,OPD 就失败。类比人类学习的故事,就是你开始自己做题前,还是要先认真读书预习,认真听老师讲,拉齐你们的基本概率分布!

汇总

强化学习在LLM训练中的作用的思考 建议细看下,不可避免的要与sft 对比。

  1. RL方法共享相同的更新原则:即通过对目标函数进行梯度更新来调整模型参数。最简单的形式表示为:$\theta \leftarrow \theta + \alpha\nabla J$。其中 $\theta$代表模型参数,$\alpha$是学习率,$\nabla J$是目标(通常是期望奖励)的梯度。然而,这个梯度的计算方式以及包含哪些项在不同方法之间可能有很大差异。
  2. 近端策略优化(PPO)是一种策略梯度方法,它在优化目标的同时,确保策略更新与之前的策略保持”近端”。它通过计算概率比率来实现:$r(\theta) =\frac{\pi_\theta(a \mid s)}{\pi_{\theta_{\text{old}}}(a \mid s)}$,这个比率然后乘以优势估计(通常使用广义优势估计或GAE计算),并应用裁剪操作以防止更新过于偏离旧策略。由此对精心设计的目标进行更新,使得策略变化较大时提供稳定性。
  3. 人类反馈的强化学习(RLHF)就是在PPO方法的基础上集成了人类偏好数据的一种方法。首先使用人类评注者提供的成对的比较或评分来训练奖励模型。随后的RL阶段使用这个奖励信号来优化模型,通常将其与PPO的技术如裁剪和KL散度惩罚结合起来,以确保渐进的更新。
  4. DeepSeek-R1的GRPO进一步修改了这一思想,消除了对之前PPO单独价值函数的使用。不依赖于状态价值的外部估计,而是就每个提示词生成一组回复,标准化得到的奖励分之后来计算群体相对优势,简化了架构并减少了计算开销,同时仍能捕获组内回复的差异性。

在强化学习优化算法层面,当前实践形成了一条从通用策略梯度到偏好优化的谱系,包括三类算法家族(PPO、DPO、GRPO)。Clip 通过截断 surrogate objective 在有利方向上的过度变化来提高训练稳定性,并不把 policy ratio 硬限制在某个区间;KL penalty 则用于惩罚当前策略与 reference policy 的偏离。

留下评论