Modern RL Objectives in Code: Bellman Targets, Trust Regions, PPO Clip, KL Estimators, and LLM Token/Sequence Granularity

本文重点包括:

  • Advantage 粒度需要同时核对信号来源和张量 shape。 PPO/RLHF 使用 response-level outcome reward、逐 token KL penalty、value function 和 GAE 得到 token-specific advantage;GRPO 得到 response-level group advantage 后复制到 token 维度参与 policy loss。
  • Loss reduction 的分母决定长 CoT 的梯度权重。 PPO/GRPO 常见 sample-level mean 让每条 response 等权;DAPO 改用 token-level denominator;Dr. GRPO 用常数长度预算并移除标准差归一化,分别处理 length bias 和 difficulty bias。
  • Clip 机制分成四条优化路径。 PPO/GRPO 的 min 截断有利方向越界 token 的梯度;DAPO 放宽正样本上界;CISPO 裁剪并 detach IS weight;GSPO 在 sequence-level ratio 上裁剪整条 response。
  • Reward shaping 影响 advantage 的语义。 RLHF 的 token-level KL penalty 控制当前策略相对 reference 的逐 token 偏离,并进入 critic/GAE;DAPO 的 overlong penalty 先修正整条 response reward,再进入 group advantage。
  • Bellman、policy gradient、TRPO trust region 保留后文所需的公式接口。 基础章节只承担 value target、policy update、ratio、clip 和梯度流向的回查功能。

目录

0. 阅读和来源说明

阅读顺序建议:

  1. Modern algorithms:先读统一粒度框架,再比较 PPO、GRPO、DAPO、Dr. GRPO、CISPO、GSPO、Reward Model、RLHF、DPO 的目标函数、粒度选择和训练稳定性问题。
  2. Training-Inference Mismatch:把 reward/verifier、长度、logprob、MoE routing 和评测协议错位放到同一张问题图里看。
  3. Basic concepts / Basic algorithms:当后文用到 Bellman target、GAE、importance ratio、actor-critic 或 TRPO/PPO 约束来源时再回查。
  4. Mathematical tools:回查 Bellman 推导、策略梯度定理、TRPO 二阶近似、Bradley-Terry、KL 非对称性和 KL estimator。

来源分层如下:

Basic concepts

这一节作为后文公式的最小回查区。已经熟悉 Bellman expectation/optimality、state value 和 action value 的读者,可以直接跳到 Modern algorithms

本节采用 Sutton & Barto 常见记号:时刻 $t$,智能体处于状态 $S_t$,按策略 $\pi$ 选择动作 $A_t$,环境转移到 $S_{t+1}$ 并返回即时奖励 $R_{t+1}$。大写字母表示随机变量,小写字母表示随机变量的具体取值。

Trajectory, Return, And Environment Model

Trajectory 是强化学习里最基本的数据对象:一条由策略和环境共同生成的随机链。

\[S_t \xrightarrow{A_t} S_{t+1}, R_{t+1} \xrightarrow{A_{t+1}} S_{t+2}, R_{t+2} \cdots\]

Discounted return 把未来奖励压回当前时刻:

\[G_t = R_{t+1} + \gamma R_{t+2} + \cdots = \sum_{k=0}^{\infty} \gamma^{k} R_{t+1+k}\]

递推写法是:

\[G_t = R_{t+1} + \gamma G_{t+1}\]

如果环境模型已知,最核心的两个概率对象是状态转移和奖励分布:

\[p(s^{\prime} \mid s,a), \quad p(r \mid s,a)\]

这两个对象决定 model-based dynamic programming 是否可用;如果它们未知,就要转向 MC、TD、Sarsa、Q-learning 这类 model-free 采样算法。

State Value And Bellman Expectation

State value 衡量“从状态 $s$ 出发并继续执行策略 $\pi$,未来总回报的期望”:

\[v_\pi(s) = \mathbb{E}[G_t \mid S_t=s] = \mathbb{E}[R_{t+1} \mid S_t=s] + \gamma\mathbb{E}[G_{t+1} \mid S_t=s]\]

Bellman expectation equation 把 $v_\pi(s)$ 拆成即时奖励和下一个状态价值。它的元素形式、矩阵形式和 expectation form 是同一件事的三种写法:

\[\begin{aligned} v_\pi(s) &= \sum_{a\in\mathcal{A}}\pi(a \mid s)\left[\sum_r p(r \mid s,a)r + \gamma \sum_{s^{\prime}\in \mathcal{S}}p(s^{\prime} \mid s,a) v_\pi(s^{\prime})\right] \\ v_\pi(s) &= r_\pi(s) + \gamma\sum_{s^{\prime}\in\mathcal{S}} p_\pi(s^{\prime} \mid s) v_\pi(s^{\prime}) \\ v_\pi &= r_\pi+\gamma P_\pi v_\pi \\ v_\pi(s) &= \mathbb{E}[R_{t+1} + \gamma v_\pi(S_{t+1}) \mid S_t=s]. \end{aligned}\]

解读:当前状态价值 = 即时奖励期望 + 下一个状态价值期望。元素形式、矩阵形式和 expectation form 的展开证明见 Bellman expectation equation 推导

如果状态按 $s_i$ 编号,状态数记为 $n=\lvert\mathcal{S}\rvert$,矩阵形式中的转移矩阵为:

\[\begin{aligned} v_\pi &= r_\pi+\gamma P_\pi v_\pi,\\ \left[P_\pi\right]_{i,j} &= p_\pi(s_j \mid s_i),\\ v_\pi(s_i) &= r_\pi(s_i)+\gamma\sum_{s_j\in\mathcal{S}}p_\pi(s_j \mid s_i)v_\pi(s_j). \end{aligned}\]

$P_\pi$ 是非负随机矩阵,每一行和为 1。由此可以得到两类求解方式:

  1. Closed-form solution: $v_\pi = (I -\gamma P_\pi)^{-1} r_\pi$,可逆性可用 Gershgorin circle theorem 证明。
  2. Iterative solution: $v_{k+1} = r_\pi + \gamma P_\pi v_k,\quad k = 0, 1, 2, \dots$,收敛性可通过证明误差 $v_k - v_\pi$ 收敛到 0 得到。

Bellman Optimality For State Value

Bellman expectation equation 评估给定策略;Bellman optimality equation 直接问“当前状态下能达到的最优价值是多少”。元素形式是:

\[v(s)=\max_{\pi(s)\in\Pi(s)}\sum_{a\in\mathcal{A}}\pi(a \mid s)q(s,a)\]

矩阵形式可以写成非线性固定点问题:

\[\begin{aligned} v &= \max_{\pi\in\Pi}(r_\pi+\gamma P_\pi v)=f(v),\\ \left[r_\pi\right]_s &= \sum_{a\in\mathcal{A}}\pi(a \mid s)\sum_{r\in\mathcal{R}}p(r \mid s,a)r,\\ \left[P_\pi\right]_{s,s^{\prime}} &= \sum_{a\in\mathcal{A}}\pi(a \mid s)p(s^{\prime} \mid s,a). \end{aligned}\]

因为 $f$ 是 contraction,非线性方程 $v=f(v)$ 有唯一固定点 $v^{\ast}$。证明见 Bellman optimality contraction

Value iteration 就是在反复应用这个 contraction:

\[\begin{aligned} v^{\ast} &= \max_{\pi\in\Pi}(r_\pi+\gamma P_\pi v^{\ast}),\\ v_{k+1} &= f(v_k)=\max_{\pi\in\Pi}(r_\pi+\gamma P_\pi v_k), \quad k=0,1,2,\dots \end{aligned}\]

求出 $v^{\ast}$ 后,最优策略由 greedy improvement 给出:

\[\pi^{\ast} = \mathrm{argmax}_{\pi\in\Pi}(r_\pi+\gamma P_\pi v^{\ast})\]

Action Value And State-Action Bellman Equations

Action value 衡量“已经在状态 $s$ 选定动作 $a$ 后,再继续执行策略 $\pi$ 的未来总回报期望”:

\[q_\pi(s,a) = \mathbb{E}[G_t \mid S_t=s,A_t=a]\]

它和 state value 的关系是:

\[v_\pi(s) = \sum_{a\in\mathcal{A}}\pi(a \mid s)q_\pi(s,a)\]

给定 $(s,a)$ 后,第一步动作已经不再由策略采样,因此动作价值的 Bellman expectation equation 先展开环境,再展开下一状态的策略:

\[q_\pi(s,a) = \sum_{r\in\mathcal{R}}p(r \mid s,a)r + \gamma\sum_{s^{\prime}\in\mathcal{S}}p(s^{\prime} \mid s,a)v_\pi(s^{\prime})\]

等价地,可以完全写成 action-value 递推:

\[\begin{aligned} q_\pi(s,a) &= \sum_{r\in\mathcal{R}}p(r \mid s,a)r + \gamma\sum_{s^{\prime}\in\mathcal{S}}p(s^{\prime} \mid s,a) \left(\sum_{a^{\prime}\in\mathcal{A}}\pi(a^{\prime} \mid s^{\prime})q_\pi(s^{\prime},a^{\prime})\right) \\ q_\pi(s,a) &= \mathbb{E}[R_{t+1} + \gamma q_\pi(S_{t+1},A_{t+1}) \mid S_t=s,A_t=a]. \end{aligned}\]

上面两个式子的等价性来自条件独立分解 $p(s^{\prime},a^{\prime} \mid s,a)=p(s^{\prime} \mid s,a)\pi(a^{\prime} \mid s^{\prime})$。直觉上,采取动作 $a_t$ 的价值 = 这个动作带来的即时奖励 + 它导致的下一状态的平均动作价值。

在所有 state-action pair 上写成向量方程:

\[\begin{aligned} q_\pi &= \tilde r+\gamma P\Pi q_\pi,\\ \left[q_\pi\right]_{(s,a)} &= q_\pi(s,a),\\ \left[\tilde r\right]_{(s,a)} &= \sum_{r\in\mathcal{R}}p(r \mid s,a)r,\\ \left[P\right]_{(s,a),s^{\prime}} &= p(s^{\prime} \mid s,a),\\ \Pi_{s^{\prime},a^{\prime}} &= \pi(a^{\prime} \mid s^{\prime}). \end{aligned}\]

Action value 的 Bellman optimality equation 是 Q-learning 和 DQN 的直接来源:

\[\begin{aligned} q^{\ast}(s,a) &= r(s,a) + \gamma\sum_{s^{\prime}\in\mathcal{S}} p(s^{\prime} \mid s,a) \max_{a^{\prime}} q^{\ast}(s^{\prime},a^{\prime}) \\ q^{\ast}(s,a) &= \mathbb{E}[R_{t+1} + \gamma \max_{a^{\prime}} q^{\ast}(S_{t+1},a^{\prime}) \mid S_t=s,A_t=a]. \end{aligned}\]

Basic algorithms

这一节保留 MC/TD/DQN、policy gradient 和 actor-critic 的关键公式,目的是支撑后文 PPO、GRPO、DAPO、CISPO、GSPO 的目标函数对照。若读者已经熟悉这些基础算法,可以把本节当作 reference appendix。

Value-based RL

Value-based 方法的主线是:先估计 $v(s)$ 或 $q(s,a)$,再通过 greedy 或 $\epsilon$-greedy 从价值函数中导出策略。各分支的差异集中在 target 构造、bootstrap、环境模型依赖和 on-policy/off-policy 设置。

Model-Based Dynamic Programming

Dynamic programming 假设环境模型已知,即奖励概率 $p(r \mid s,a)$ 和状态转移概率 $p(s^{\prime} \mid s,a)$ 可用。奖励概率可以进一步得到 $r(s,a)=\sum_r p(r \mid s,a)r$,转移概率告诉我们在状态 $s$ 执行动作 $a$ 后,会以什么概率到达各个 $s^{\prime}$。

Value Iteration

Value iteration 是 1-step truncated policy iteration。它直接迭代 Bellman optimality operator:

\[v_{k+1} = f(v_k) = \max_{\pi\in\Pi}(r_\pi + \gamma P_\pi v_k)\]

每一步可以拆成 policy update 和 value update:

\[\pi_{k+1} = \mathrm{argmax}_{\pi}(r_\pi + \gamma P_\pi v_k)\] \[v_{k+1} = r_{\pi_{k+1}} + \gamma P_{\pi_{k+1}} v_k\]

元素视角下,流程是:

\[v_k(s) \rightarrow q_k(s,a) \rightarrow a^{\ast}(s) \rightarrow \pi_{k+1}(a \mid s) \rightarrow v_{k+1}(s)\]

Policy Iteration

Policy iteration 是 $\infty$-step truncated policy iteration:先把当前策略评估充分,再做策略改进。

Policy evaluation 解 Bellman expectation equation:

\[v_{\pi_k} = r_{\pi_k} + \gamma P_{\pi_k} v_{\pi_k}\]

实际计算中常嵌入迭代:

\[v_{\pi_k}^{(j+1)} = r_{\pi_k} + \gamma P_{\pi_k} v_{\pi_k}^{(j)}\]

Policy improvement 基于当前策略的动作价值做 greedy 更新:

\[\pi_{k+1} = \mathrm{argmax}_{\pi}(r_\pi+\gamma P_{\pi}v_{\pi_k})\] \[\pi_{k+1} = \mathrm{argmax}_{\pi}\sum_a\pi(a \mid s)q_{\pi_k}(s,a)\]

这里 $q_{\pi_k}(s,a)$ 的作用很关键:policy evaluation 先估计 $v_{\pi_k}(s)$,再通过 system model 得到 $q_{\pi_k}(s,a)$;policy improvement 基于 $q_{\pi_k}(s,a)$ 得到新的 $\pi_{k+1}$。

Model-Free Value Learning

Model-free 方法从采样轨迹构造 target,不需要显式访问 $p(s^{\prime} \mid s,a)$ 和 $p(r \mid s,a)$。MC、TD、Sarsa、Q-learning 的差别主要体现在 target 的随机变量数量、是否等 episode 结束、以及下一步动作来自真实采样还是贪心最大化。

Monte Carlo Control

Monte Carlo 用完整 episode 的 return 来估计动作价值:

\[q_{\pi_k}(s,a) = \mathbb{E}[G_t \mid S_t=s,A_t=a]\]

从 $(s,a)$ 出发并继续执行 $\pi_k$,若采到 $n$ 条 episode,第 $i$ 条回报为 $g_{\pi_k}^{(i)}(s,a)$,则:

\[q_{\pi_k}(s,a) \approx q_k(s,a) = \frac{1}{n}\sum_{i=1}^{n} g_{\pi_k}^{(i)}(s,a)\]

MC control 的 policy improvement 和 policy iteration 类似,但样本使用方式可以不同:first visit / every visit 决定一条 episode 中同一状态动作对如何计数;exploring starts 或 $\epsilon$-greedy 决定是否能覆盖足够多的状态动作对。

MC 的特征是 non-bootstrapping、低偏差、高方差、非增量式。它必须等 episode 结束才能得到 $G_t$,因此长 episode 下学习信号来得慢。

TD(0) Policy Evaluation

TD learning 用 one-step bootstrap target 估计状态价值:

\[v_{t+1}(s_t) = v_t(s_t) -\alpha_t(s_t) \left[ v_t(s_t) - \left(r_{t+1}+\gamma v_t(s_{t+1})\right) \right]\]

对所有 $s\neq s_t$,估计保持不变。TD target 和 TD error 是:

\[\bar v_t = r_{t+1}+\gamma v_t(s_{t+1}), \quad \delta_t = v(s_t)-\bar v_t.\]

这个更新可以看作把 Robbins-Monro stochastic approximation 用在 Bellman expectation equation 上:

\[v_\pi(s) = \mathbb{E}[R_{t+1}+\gamma v_\pi(S_{t+1}) \mid S_t=s]\]

TD 的特征是 bootstrapping、低方差、高偏差、增量式;每收到一个 transition 就能更新一次。

Sarsa

Sarsa 是对 action value 的 on-policy TD control。它的 target 使用真实采样到的下一动作 $a_{t+1}$:

\[q_{t+1}(s_t,a_t) = q_t(s_t,a_t) - \alpha_t(s_t,a_t) \left[ q_t(s_t,a_t) - \left(r_{t+1} + \gamma q_t(s_{t+1}, a_{t+1})\right) \right]\]

其余 $(s,a) \neq (s_t,a_t)$ 保持不变。这个更新对应 action-value Bellman expectation equation:

\[q_\pi(s,a) = \mathbb{E}[R + \gamma q_\pi(S^{\prime},A^{\prime}) \mid s,a]\]

采样链路是:

\[s_t \xrightarrow{\pi_b} a_t \xrightarrow{model} r_{t+1},s_{t+1} \xrightarrow{\pi_b} a_{t+1}\]

Sarsa 的 target policy 和 behavior policy 都是同一个 $\epsilon$-greedy 策略,因此它估计的是当前行为策略的价值,会把探索动作带来的风险也计入价值估计。

Q-learning

Q-learning 是 off-policy TD control。它的 target 使用下一状态上的 greedy action,不使用真实采样到的 $a_{t+1}$:

\[q_{t+1}(s_t,a_t) = q_t(s_t,a_t) - \alpha_t(s_t,a_t) \left[ q_t(s_t,a_t) - \left(r_{t+1} + \gamma \max_{a\in\mathcal{A}(s_{t+1})} q_t(s_{t+1}, a)\right) \right]\]

它对应 Bellman optimality equation:

\[q^{\ast}(s,a) = \mathbb{E}[R_{t+1} + \gamma \max_{a\in\mathcal{A}(S_{t+1})} q^{\ast}(S_{t+1},a) \mid S_t=s,A_t=a]\]

采样链路只需要:

\[s_t \xrightarrow{\pi_b} a_t \xrightarrow{model} r_{t+1},s_{t+1}\]

行为策略可以是 $\epsilon$-greedy,但 target policy 是 greedy。Q-learning 估计的是最优策略价值,与当前行为策略的探索动作不完全绑定。

DQN And Function Approximation

DQN 把 Q-learning 的表格 $q(s,a)$ 替换为神经网络 $\hat q(s,a,w)$。训练目标是 squared Bellman optimality error:

\[J(w) = \mathbb{E}[(R + \gamma \max_{a^{\prime}\in\mathcal{A}(S^{\prime})} \hat{q}(S^{\prime},a^{\prime},w_T) - \hat{q}(S,A,w))^{2}]\]

如果 target 和 prediction 使用同一组参数 $w$,目标会随着预测一起移动,所以 DQN 使用 online network $w$ 和 target network $w_T$。梯度为:

\[\nabla_w J = -2\mathbb{E}[(R + \gamma \max_{a^{\prime}\in\mathcal{A}(S^{\prime})} \hat{q}(S^{\prime},a^{\prime},w_T) - \hat{q}(S,A,w)) \nabla_w \hat{q}(S,A,w)]\]

代码化实现要点是:gather 取真实执行动作的 Q 值,target network 只生成 bootstrap target,不接收当前 loss 的梯度。

        # batch 来自 replay buffer: (s, a, r, done, s_next)
        q_all_actions = online_q_net(states)  # [batch_size, num_actions]

        # gather 只取本次真实执行过的动作 a 的 Q 值,对应 \hat{q}(S,A,w)。
        q_sa = q_all_actions.gather(1, actions[:, None]).squeeze(1)

        with torch.no_grad():
            # target network 只生成 bootstrap target,不接收当前 loss 的梯度。
            next_q = target_q_net(next_states).amax(dim=-1)
            td_target = rewards + gamma * (1.0 - dones.float()) * next_q

        # Bellman optimality error: 让 online network 逼近固定一小段时间的 target。
        dqn_loss = torch.nn.functional.mse_loss(q_sa, td_target)

Overestimation And Double DQN

如果所有动作估计都带噪声,max operator 更容易选中被噪声推高的动作,所以最大化会带来过高估计:

\[\mathbb{E}[\max_a \hat{q}(s,a,w_T)] \ge \max_a\mathbb{E}[\hat{q}(s,a,w_T)]\]

Double DQN 把“选择动作”和“评估动作”分开:online network 选动作,target network 评价该动作。

\[a^{\ast} = \mathrm{argmax}_{a\in\mathcal{A}(s^{\prime})}\hat q(s^{\prime},a,w), \quad y = r+\gamma\hat q(s^{\prime},a^{\ast},w_T).\]

两个网络的误差不再通过同一个最大值运算直接叠加,q-value 过高估计得到缓解。

Deadly Triad And Stabilization

“致命三元组”指 function approximation、off-policy data、bootstrapping 同时出现时可能导致发散:

  1. 函数逼近误差:更新一个 $(s,a)$ 时,共享参数会隐含改变其他状态动作对。
  2. 离策略数据分布:behavior policy 和 target policy 不同,函数逼近器会被迫外推目标策略可能很少访问的状态或动作。
  3. 自举更新:TD target 包含下一状态的估计值,估计误差会被继续传播。

DQN 的基本稳定化手段是 target network 和 replay buffer:

  1. online network $w$ 每个 gradient step 更新;target network $w_T$ 每隔 $C$ 次迭代复制 $w$。
  2. replay buffer 存储 $\mathcal{B} = \lbrace(s,a,r,s^{\prime})\rbrace$,近似均匀采样以打破连续样本相关性。

原始 DQN 的训练方式是边交互边训练:每执行一步动作就从回放池采样训练一次,提高数据利用效率。

Dueling DQN

Dueling DQN 改变网络架构,把状态价值和动作优势拆开:

\[q(s,a) = v(s) + A(s,a) - \frac{1}{\lvert\mathcal{A}\rvert}\sum_{a^{\prime}\in\mathcal{A}} A(s,a^{\prime})\]

这个结构适合很多动作差异不明显的状态。实现上通常是共享 backbone 后接 value head 和 advantage head:

            features = backbone(states)
            values = value_head(features)          # shape: [batch_size, 1]
            advantages = advantage_head(features)  # shape: [batch_size, num_actions]
            q_values = values + advantages - advantages.mean(dim=1, keepdim=True)

On-Policy Vs Off-Policy

Target policy $\pi_T$ 是将要评估或改进的策略;behavior policy $\pi_b$ 是实际和环境交互、产生动作的策略。二者相同就是 on-policy,二者不同就是 off-policy。

Sarsa 是 on-policy:更新的 target policy 是 $\epsilon$-greedy policy,和采取动作的 behavior policy 相同。

Q-learning 是 off-policy:更新目标使用 greedy policy,而采样数据可以来自另一个 $\epsilon$-greedy behavior policy。

Policy-based RL

DQN 训练好后对同一个状态通常输出同一个 greedy 动作;策略网络直接输出动作分布。离散动作场景中,它输出 softmax 概率;连续动作场景中,它输出高斯分布等参数。随机性承担探索和概率分布优化的角色。

Policy Gradient Theorem

策略梯度把“提高好动作概率、降低坏动作概率”写成可反向传播的目标。主流可用形式是:

\[\nabla_\theta J(\theta) = \mathbb{E}_{s_t,a_t} \left[ \nabla_\theta\log\pi_\theta(a_t \mid s_t)A^{\pi}(s_t,a_t) \right], \quad A^{\pi}(s,a)=Q^{\pi}(s,a)-V^{\pi}(s).\]

完整证明见 策略梯度定理证明。那里会说明 trajectory likelihood-ratio、reward-to-go、baseline/advantage 和 discounted occupancy 形式之间的关系。

代码里只需要抓住两点:采样数据应来自当前策略或带重要性采样修正;advantage 是 actor 更新的权重,通常不让 actor loss 反向更新 critic。

# states/actions 来自当前策略采样的 rollout;old data 不能随便复用,否则分布已经变了。
dist = policy(states)
log_probs = dist.log_prob(actions)

# advantages 可以来自 MC return、TD error 或 GAE。
# detach 表示 advantage 是权重,不让 actor loss 反向更新 critic。
policy_loss = -(log_probs * advantages.detach()).mean()
policy_loss.backward()

梯度上升写法:

\[\theta_{t+1}=\theta_t+\alpha\nabla_\theta\log\pi_{\theta_t}(a_t \mid s_t)\hat{A}_t\]

梯度下降 loss 写法:

\[\mathcal{L}_{PG}(\theta)=-\log\pi_\theta(a_t \mid s_t)\hat{A}_t\]

REINFORCE

REINFORCE 是 Monte Carlo policy gradient。它用完整轨迹回报估计 $q_\pi(S,A)$:

\[\mathbb{E}_{s\sim S,A\sim\pi_\theta(S)} \left[ \nabla_\theta \ln\pi_\theta(A \mid S)q_\pi(S,A) \right]\]

实现流程:

  1. 按当前策略 $\pi_\theta$ 采样一条 episode:
\[\lbrace s_0, a_0, r_1, \dots, s_{T-1}, a_{T-1}, r_T\rbrace\]
  1. 从后往前计算每个时刻的 return:
            for reward in reversed(rewards):
                G = reward + gamma * G
                returns.insert(0, G)
  1. 用 $q_t(s_t,a_t)=\sum_{k=t+1}^{T}\gamma^{k-t-1}r_k$ 更新策略:
\[\theta_{t+1} = \theta_t + \alpha \nabla_\theta \ln\pi_{\theta_t}(a_t \mid s_t)q_t(s_t,a_t)\]

REINFORCE 是 on-policy:采样必须来自当前策略。策略一更新,旧 episode 的分布就不再严格匹配。它的主要问题是高方差,因为 $G_t$ 包含从 $t$ 到 episode 结束的所有随机性。

    # 前向传播:获取每个状态下的动作概率
    probs = policy(states_tensor)  # [T, action_dim]

    # 计算所采取动作的对数概率 log π(a_t|s_t)
    # gather(1, actions) 选取每个状态对应动作的概率
    action_probs = probs.gather(1, actions_tensor.unsqueeze(1)).squeeze(1)
    log_probs = torch.log(action_probs + 1e-8)  # 加小常数防止 log(0)

    # 策略梯度损失:-log π(a_t|s_t) * G_t
    loss = -(log_probs * returns_tensor).mean()

REINFORCE With Baseline

Baseline 的目标是降低方差而不改变梯度期望:

\[\mathbb{E}_{s\sim d^{\pi},A\sim\pi_\theta(\cdot \mid S)} \left[ \nabla_\theta \ln\pi_\theta(A \mid S)(q_\pi(S,A)-b(S)) \right]\]

baseline 项期望为 0:

\[\mathbb{E}_{s\sim S,A\sim\pi_\theta(S)} \left[ \nabla_\theta \ln\pi_\theta(A \mid S)b(S) \right] =0\]

理论最优 baseline 需要最小化梯度估计方差,实践中通常取 state value:

\[b(s)=\mathbb{E}_{A\sim\pi}\left[q_\pi(s,A)\right]=v_\pi(s)\]

用 MC return $g_t$ 近似 $q_t$ 时,策略更新为:

\[\theta_{t+1} = \theta_t+\alpha\nabla_\theta\ln\pi_{\theta_t}(a_t \mid s_t) \left(q_t(s_t,a_t)-v_\phi(s_t)\right)\]

价值网络训练:

\[\mathcal{L}_V(\phi)=\left(v_\phi(s_t)-g_t\right)^{2}\]

策略网络使用优势 $A_t=g_t-v_\phi(s_t)$:

    # 价值网络学习 V(s)
    values = value_net(states_t)
    value_loss = nn.MSELoss()(values, returns_t)

    # 用优势更新策略
    with torch.no_grad():
        values_pred = value_net(states_t)
    advantages = returns_t - values_pred
    policy_loss = -(log_probs * advantages).mean()

Q Actor-Critic

Q Actor-Critic 用一个 critic 近似 $q(s,a,w)$,再把它作为 actor 的策略梯度权重。每个时间步:

  1. 按 $\pi_\theta(a \mid s_t)$ 生成 $a_t$。
  2. 观察 $r_{t+1},s_{t+1}$。
  3. 再按 $\pi_\theta(a \mid s_{t+1})$ 生成 $a_{t+1}$。

Actor 更新:

\[\theta_{t+1} = \theta_t + \alpha \nabla_\theta \ln\pi_{\theta_t}(a_t \mid s_t)q(s_t,a_t, w_t)\]

Critic 用 TD 方式更新 action value:

\[w_{t+1} = w_t + \alpha_w[r_{t+1} + \gamma q(s_{t+1}, a_{t+1}, w_t) - q(s_t, a_t, w_t)]\nabla_w q(s_t,a_t,w_t)\]

QAC 的问题是需要维护 action-value critic;动作空间大或连续时,动作价值函数的学习会变得更难。

Advantage Actor-Critic

A2C 把 actor 的权重从 $q_t(s_t,a_t)$ 改成 advantage:

\[\theta_{t+1} = \theta_t+\alpha\nabla_\theta\ln\pi_{\theta_t}(a_t \mid s_t) \left[q_t(s_t,a_t)-v_t(s_t)\right]\]

其中 $\delta_t(s_t,a_t)=q_t(s_t,a_t)-v_t(s_t)$ 是优势函数。优势可以用 TD error 估计:

\[q_t(s_t,a_t) - v_t(s_t) \approx r_{t+1} + \gamma v_t(s_{t+1}) - v_t(s_t)\]

这个等价关系来自:

\[q_\pi(s_t,a_t) - v_\pi(s_t) = \mathbb{E}[R_{t+1} + \gamma v_\pi(S_{t+1}) - v_\pi(S_t) \mid S_t=s_t,A_t=a_t]\]

这样就不需要同时维护 action-value network 和 state-value baseline network;一个 state-value critic 就能给 actor 提供 TD advantage。

实现流程:

  1. 按 $\pi_\theta(a \mid s_t)$ 生成 $a_t$,观察 $r_{t+1},s_{t+1}$。
  2. 估计 TD error:
\[\delta_t=r_{t+1}+\gamma v(s_{t+1},w_t)-v(s_t,w_t)\]
  1. Actor 使用:
\[-\delta_t\log\pi_\theta(a_t \mid s_t)\]
  1. Critic 使用 $\delta_t^2$ 或等价的 value target loss。
        # TD Error
        td_target = reward + gamma * next_value
        td_error = td_target - value

        # Actor 损失:策略梯度 × 优势
        actor_loss = -log_prob * td_error.detach()

        # Critic 损失:让 V(s) 接近 TD Target
        critic_loss = td_error.pow(2)

        # 总损失
        loss = actor_loss + critic_loss

Off-Policy Actor-Critic

Off-policy actor-critic 允许 behavior policy $\beta$ 采样,target policy $\pi_\theta$ 更新。核心修正是 importance ratio:

\[\nabla_\theta J(\theta) = \mathbb{E}_{S\sim\rho, A\sim\beta(\cdot \mid S)} \left[ \frac{\pi_\theta(A \mid S)}{\beta(A \mid S)} \nabla_\theta\ln\pi_\theta(A \mid S)q_\pi(S,A) \right]\]

其中 off-policy state distribution 为:

\[\rho(s)=\sum_{s^{\prime}\in\mathcal{S}}d_\beta(s^{\prime})Pr_\pi(s \mid s^{\prime})\]

$Pr_\pi(s \mid s^{\prime})$ 是 discounted total transition probability。

带 baseline 的形式是:

\[\nabla_\theta J(\theta) = \mathbb{E}_{S\sim\rho, A\sim\beta(\cdot \mid S)} \left[ \frac{\pi_\theta(A \mid S)}{\beta(A \mid S)} \nabla_\theta\ln\pi_\theta(A \mid S)(q_\pi(S,A)-v_\pi(S)) \right]\]

实现上,给定 behavior policy $\beta(a \mid s)$:

  1. 用 $\beta(a \mid s_t)$ 采样 $a_t$,观察 $r_{t+1},s_{t+1}$。
  2. 用 $\delta_t=r_{t+1}+\gamma v(s_{t+1},w_t)-v(s_t,w_t)$ 估计 advantage。
  3. Actor loss 使用 importance ratio:
\[-\frac{\pi_\theta(a_t \mid s_t)}{\beta(a_t \mid s_t)}\delta_t\log\pi_\theta(a_t \mid s_t)\]
  1. Critic 也可以用 importance ratio 加权 TD 更新:
\[w_{t+1}=w_t+\alpha_w \frac{\pi_\theta(a_t \mid s_t)}{\beta(a_t \mid s_t)} \delta_t\nabla_w v(s_t,w_t)\]

Modern algorithms

LLM RL 的粒度问题:reward、advantage、ratio、clip 与 loss aggregation

现代 LLM RL 里的 token-level vs sequence-level 需要拆成五个对象:reward 评价单位、advantage 信号来源、importance ratio 修正单位、clip 对象、loss reduction 分母。一条 response $y_i=(y_{i,1},\dots,y_{i,L_i})$ 进入训练时,这五个对象可以选择不同粒度。DAPO、Dr. GRPO、CISPO 和 GSPO 的分歧就落在这些对象的不同组合上。

本文的术语约定是:response-level 指一条生成回答一个标量对象,例如 outcome reward 或 group advantage;token-shaped 指代码里的张量带有 token 维度;token-specific 指数值真的随 token/prefix 改变;sequence-level ratio/likelihood 保留给 GSPO 这类整条序列似然比,因为论文术语通常这样写。

奖励:outcome reward 与 shaped token reward

RLHF/RLVR 里的主奖励通常是 response-level outcome reward:reward model 或 verifier 看完整回答 $y_i$ 后给一个标量 $R_i=R(x,y_i)$。训练时仍然可以构造 token-level shaped reward。PPO/RLHF 为了用 critic 和 GAE 计算每个位置的 advantage,常把整段 reward 和逐 token KL penalty 组合起来:

\[r_{i,t}^{shaped} = \begin{cases} -\beta\left(\log \pi_\theta(y_{i,t} \mid x,y_{i,\lt t})-\log \pi_{ref}(y_{i,t} \mid x,y_{i,\lt t})\right),& t\lt L_i\\ R(x,y_i)-\beta\left(\log \pi_\theta(y_{i,t} \mid x,y_{i,\lt t})-\log \pi_{ref}(y_{i,t} \mid x,y_{i,\lt t})\right),& t=L_i \end{cases}\]

监督信号 $R(x,y_i)$ 评价整条 response;token-level KL penalty 表示当前策略在该 token 上相对 reference policy 的偏离。PPO/RLHF 的 shaped reward 常用 sampled log-ratio,也就是 k1 形式;GRPO/DeepSeekMath 的目标函数常用 k3 estimator。KL penalty 负责约束策略漂移,不承担 token 正误归因。PPO 再用 value model 和 GAE 把 shaped reward 递推成 $\hat A_{i,t}$。GRPO/RLVR 的规则 verifier 通常不训练 critic,而是把组内相对优势 $\hat A_i$ 复制到整条 response 的所有 token。

PPO 和 GRPO 都可以在目标函数中出现 KL 项,但 KL 的 estimator 和进入位置不同。PPO/RLHF 常把 k1 log-ratio 写进 shaped reward,然后通过 critic/GAE 影响 token-specific advantage;GRPO 通常先用 response-level reward 做组内归一化得到 $\hat A_i$,再把 k3 token-level KL estimator 作为 policy objective 里的 regularizer。GRPO 中“同一条 response 内值都一样”的对象是 $\hat A_{i,t}$;token-level KL 和完整 token loss 仍会随位置变化。k1/k2/k3 的比较见 KL divergence estimation

Advantage:credit assignment 的细度

PPO 的 advantage 通常同时具备 token-shaped 和 token-specific 两个性质。critic 估计每个 prefix state 的 value,GAE 把 shaped reward 递推成每个 token/prefix 位置自己的优势:

\[\hat A_{i,t}^{GAE} = \sum_{k=0}^{L_i-t}(\gamma\lambda)^k \left(r_{i,t+k}^{shaped}+\gamma V_\phi(s_{i,t+k+1})-V_\phi(s_{i,t+k})\right).\]

GRPO/DAPO/CISPO/GSPO 在 outcome reward 场景中常用 response-level group advantage,然后为了和 token logprob 相乘,把它扩展成 token-shaped tensor:

\[\hat A_i = \frac{R_i-\frac{1}{G}\sum_{j=1}^{G}R_j} {\sqrt{\frac{1}{G}\sum_{j=1}^{G}\left(R_j-\frac{1}{G}\sum_{k=1}^{G}R_k\right)^2}+\epsilon}, \quad \hat A_{i,t}=\hat A_i.\]

这个写法去掉 critic,适合数学题、代码题等可验证任务;同一条 response 内所有 token 的 advantage 数值完全相同,关键 token 与模板性 token 使用同一个更新方向。判断 GRPO 的 credit assignment 粒度时,应检查 $\hat A_{i,t}$ 是否随 $t$ 改变,下标本身不足以说明语义粒度。若未来有 step-level verifier 或 process reward,advantage 可以细到步骤或 token,但 ratio 和 clip 的设计还需要重新匹配。

Loss aggregation:看分母就能判断长 response 的权重

设 $\ell_{i,t}$ 是一个 token 的 policy objective,例如 clipped surrogate。GRPO/PPO 常见的 sample-level reduction 先在每条 response 内平均,再在 response 间平均:

\[J_{\text{sample-mean}} = \frac{1}{G}\sum_{i=1}^{G} \frac{1}{L_i}\sum_{t=1}^{L_i}\ell_{i,t}.\]

这个目标让每条 response 对总 loss 等权。高质量长 response 的总权重和短 response 相同,因此单个 token 的贡献被 $1/L_i$ 稀释;低质量长 response 也会被同样稀释,重复、拖长、无效推理的惩罚不够强。

DAPO 的 token-level policy gradient loss 把所有有效 token 放进同一个分母:

\[J_{\text{token-mean}} = \frac{1}{\sum_{i=1}^{G}L_i} \sum_{i=1}^{G}\sum_{t=1}^{L_i}\ell_{i,t}.\]

这个目标让每个 token 的训练权重更接近等价。Dr. GRPO 从同一类长度偏置出发,指出 response-length normalization 和 group standard deviation normalization 都可能引入偏差;它用常数长度预算归一化、去掉组内标准差缩放等方式减少长度和难度对梯度尺度的耦合。DAPO 与 Dr. GRPO 在“不要让长 response 被样本均值系统性稀释”上方向一致,但 DAPO 同时包含 Clip-Higher、Dynamic Sampling 和 Overlong Reward Shaping,Dr. GRPO 还强调标准差归一化带来的 difficulty bias。

Ratio 与 clip:off-policy correction 的单位

token-level ratio 按每个 token 修正旧策略 rollout 和当前策略之间的差异:

\[r_{i,t}(\theta)= \frac{\pi_\theta(y_{i,t} \mid x,y_{i,\lt t})} {\pi_{old}(y_{i,t} \mid x,y_{i,\lt t})}.\]

PPO/GRPO/DAPO 在 token 上做 clipped surrogate:

\[\ell_{i,t}^{clip}= \min\left(r_{i,t}\hat A_{i,t}, clip(r_{i,t},1-\epsilon_{low},1+\epsilon_{high})\hat A_{i,t}\right).\]

这个目标的优势是细粒度、易实现;风险是长 response 中每个 token 都有独立 ratio,少数极端 token 会放大方差,并且在 PPO 的 min 结构下,有利方向越界的 token 可能直接失去梯度。DAPO 的 Clip-Higher 放宽正向上界,主要保护低概率但高奖励 token;CISPO 则改为裁剪 IS weight 并 stop-gradient,让越界 token 仍然通过 $\log\pi_\theta$ 贡献梯度。

GSPO 的优化对象是 ratio 粒度:如果 outcome reward 和 group advantage 都是 response-level 标量,重要性采样比值也应使用整条序列的似然比,避免让每个 token 的局部 ratio 独立修正同一个 response-level 信号:

\[s_i(\theta)= \exp\left( \frac{1}{L_i}\sum_{t=1}^{L_i}\log r_{i,t}(\theta) \right).\]

GSPO 的 clip 判断发生在整条 response 上:

\[\ell_i^{seq}= \min\left(s_i\hat A_i, clip(s_i,1-\epsilon,1+\epsilon)\hat A_i\right).\]

GSPO 的分析对象是 ratio 粒度。原始 verifier/RM 只评价整段 response 时,每个 token 各自的 ratio 会把细粒度 logprob 噪声注入 response-level credit。MoE 中 expert routing 变化、推理引擎与训练引擎重算 logprob 的微小差异,都会在 token ratio 上被放大;sequence-level ratio 对这类细粒度波动更宽容。

算法演进图

问题对象 典型现象 代表方法 优化方向
reward shaping response reward 需要 token-specific advantage PPO/RLHF 将 KL penalty 写到 token,最终 RM reward 放到末尾,用 critic/GAE 做 credit assignment
group advantage critic 成本高,outcome reward 只有整段分数 GRPO/RLVR 同一 prompt 下多 response 组内比较,得到 response-level advantage,再复制成 token-shaped advantage
loss aggregation 长 response 在 per-response mean 中被稀释 DAPO, Dr. GRPO 改 token-level denominator 或常数长度预算,降低长度偏置
clip object PPO/GRPO 的 min 让越界 token 失去梯度 DAPO, CISPO DAPO 放宽正样本上界;CISPO 裁剪 IS weight 并保留 token 梯度
ratio granularity token ratio 高方差,长序列和 MoE routing 更脆弱 GSPO 用长度归一化 sequence ratio 做 off-policy correction 和 clip
sampling/filtering all-correct/all-wrong group 无可学习差异 DAPO Dynamic Sampling 保留组内 reward 非平凡的 prompt

因此,后面的算法可以按这条链读:PPO 把 trust region 做成 token-level clipped surrogate,并用 critic/GAE 获得 token-specific advantage;GRPO 去掉 critic,用 response-level group advantage 简化 RLVR;DAPO/Dr. GRPO 修 loss reduction 与长度偏置;CISPO 修 token update 被 clip 丢掉的问题;GSPO 修 response-level outcome signal 与 token-level ratio 的单位错配。

TRPO -> PPO:从约束优化到裁剪代理目标

目标与约束

TRPO 在平均 KL 约束内最大化旧策略分布下的新策略 surrogate objective。KL 半径控制策略分布变化,surrogate objective 决定这一步尽量沿 advantage 方向走多远:

\[\max_\theta \mathbb{E}_{s\sim\rho_{\theta_{old}},a\sim\pi_{\theta_{old}}} \left[ \frac{\pi_\theta(a \mid s)}{\pi_{\theta_{old}}(a \mid s)} A_{\theta_{old}}(s,a) \right]\] \[\text{s.t.}\quad \mathbb{E}_{s\sim\rho_{\theta_{old}}} \left[ D_{KL}\left(\pi_{\theta_{old}}(\cdot \mid s) \Vert \pi_\theta(\cdot \mid s)\right) \right]\le\delta.\]

KL 约束控制的对象

如果只最大化 ratio-weighted advantage,策略可以把某些动作概率推得过猛,采样分布和更新后分布迅速脱节;KL trust region 把“策略还能相信这批旧 rollout 多久”变成一个约束。

实现代价与 PPO 入口

TRPO 的工程代价来自解约束优化:线性化 surrogate objective,二阶近似 KL,使用 Fisher-vector product 和 conjugate gradient 近似自然梯度方向,再通过 line search 确认 surrogate 变好且 KL 未越界。推导见 TRPO trust-region 二阶近似

    # TRPO 的核心数据对象:旧策略 rollout、旧 logprob、advantage、KL 约束半径。
    ratio = torch.exp(new_logp - old_logp)
    surrogate = (ratio * advantages).mean()

    # 平均 KL 在 TRPO 中用于判定本次 step 是否留在 trust region 内。
    mean_kl = torch.distributions.kl_divergence(old_dist, new_dist).mean()

    # 真实 TRPO 会用 conjugate gradient 求近似自然梯度方向,
    # 再 line search 缩小 step,直到 surrogate 改善且 mean_kl <= target_kl。
    accept_step = (surrogate > old_surrogate) and (mean_kl <= target_kl)

PPO 的 clipped surrogate 是 TRPO 思想的一阶工程替代:省掉自然梯度和 line search,把 ratio 收益限制写进目标函数。代价是失去显式约束解法;收益是普通 SGD/Adam、多 epoch minibatch 和更简单的实现。

这条关系也是理解后续 GRPO/DAPO/CISPO/GSPO 的入口:旧策略采样的数据在多轮更新后还保留多少可信梯度。后续方法分别选择限制 token ratio、sequence ratio、IS 权重或 token update mask。

Proximal Policy Optimization (PPO)

目标函数:非 LLM 简化版本

\[\begin{aligned} J_{PPO}(\theta) &= \mathbb{E}\left[ \min\left(r_t(\theta) A_t,\mathrm{clip}(r_t(\theta),1-\epsilon,1+\epsilon)A_t\right) \right],\\ r_t(\theta) &= \frac{\pi_{\theta}(a \mid s)}{\pi_{old}(a \mid s)} = \exp(\log\pi_{\theta}(a \mid s)-\log\pi_{old}(a \mid s)). \end{aligned}\]

目标函数:LLM token-level 版本

RLHF 的全局目标常写成 reward 减 KL:

\[\mathcal{J}_{RLHF}(\theta)= \mathbb{E}_{x,y\sim\pi_\theta} \left[ R(x,y) -\beta D_{KL}(\pi_\theta(\cdot \mid x)\Vert\pi_{ref}(\cdot \mid x)) \right].\]

PPO 实现里经常先把这项展开成逐 token shaped reward。对第 $i$ 条 response:

\[r_{i,t}^{shaped} = \begin{cases} -\beta\left(\log\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})-\log\pi_{ref}(o_{i,t} \mid q,o_{i,\lt t})\right),& t\lt \lvert o_i\rvert\\ R(q,o_i)-\beta\left(\log\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})-\log\pi_{ref}(o_{i,t} \mid q,o_{i,\lt t})\right),& t=\lvert o_i\rvert \end{cases}\]

这里使用的是 sampled log-ratio KL penalty。若把当前策略记为采样分布 $q$、reference policy 记为 $p$,并定义 $\delta=p/q$,则每个 token 上的 KL penalty 对应 $-\log\delta$,也就是 k1 estimator。它简单、直接,但单样本值可以为负,方差也高于 k3;PPO/RLHF 中它通常先作为 reward shaping 信号参与 GAE,actor 更新阶段主要通过固定 advantage 与 PPO ratio 接收这部分影响。

然后用 value model 和 GAE 得到 token-specific advantage:

\[\hat A_{i,t}^{GAE} = \sum_{k=0}^{\lvert o_i\rvert-t}(\gamma\lambda)^k \left(r_{i,t+k}^{shaped}+\gamma V_\phi(s_{i,t+k+1})-V_\phi(s_{i,t+k})\right).\]

PPO 的 token-level clipped surrogate 再使用这个 advantage:

\[J_{PPO}(\theta) = \mathbb{E}_{q\sim \mathcal{D},o_i\sim \pi_{old}(\cdot \mid q)} \left[ \frac{1}{\lvert o_i\rvert}\sum_{t=1}^{\lvert o_i\rvert} \min\left(r_{i,t}\hat A_{i,t}, \mathrm{clip}(r_{i,t},1-\epsilon,1+\epsilon)\hat A_{i,t}\right) \right]\]

其中 $o$ 代表模型生成的一条序列, $o_i$ 代表第 $i$ 条序列, $o_{i,t}$ 代表第 $i$ 条序列的第 $t$ 个 token。这个写法先对一条序列内部 token 求平均,再对样本求平均;它能避免完整 sequence logprob 乘积让长序列天然占优,但当奖励主要是整段 outcome reward 时,也会带来长 response 的单 token 梯度被稀释的问题。这里的 KL 已经通过 shaped reward 进入 $\hat A_{i,t}^{GAE}$,因此它影响的是 advantage 和 value target。

粒度与实现对象

Token 级优势和 ratio 分别是:

\[\hat A_{i,t} \quad\text{and}\quad r_{i,t} = \frac{\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})} {\pi_{old}(o_{i,t} \mid q,o_{i,\lt t})}.\]

PPO 在 LLM-RLHF 中同时包含三种粒度:reward model 输出 response-level scalar reward;KL penalty 按 token 写入 shaped reward,并通过 value model/GAE 生成 token-specific advantage;policy loss 使用 token-level ratio 和 token-level clip,工程上常用 per-response mean 做 loss reduction。r_{i,t} > 1 表示新策略相对旧策略更倾向于输出该 token,反之则说明新策略正在降低该 token 的概率。

    # old_logp 是 rollout 采样时旧策略给动作/token 的 log probability。
    # new_logp 是当前正在更新的策略重新评估同一批动作/token 得到的 log probability。
    ratio = torch.exp(new_logp - old_logp)

    # advantage 的正负决定 clip 限制哪一边:
    # A > 0 时,ratio 过大代表把好动作推得太猛,上界会被截住;
    # A < 0 时,ratio 过小代表把坏动作压得太猛,下界会被截住。
    clipped_ratio = ratio.clamp(1.0 - clip_eps, 1.0 + clip_eps)
    surrogate = ratio * advantages
    clipped_surrogate = clipped_ratio * advantages

    # max objective 写成训练 loss 时要取负号;min 会选择更保守的一项。
    policy_loss = -torch.minimum(surrogate, clipped_surrogate)
    policy_loss = (policy_loss * action_or_token_mask).sum() / action_or_token_mask.sum()

Clip 与 Token-Masking

PPO 的 min 产生 advantage-sign-dependent 的单边裁剪。主线里只需要记住四个区域;完整梯度符号推导见 PPO clip 单边裁剪梯度符号

advantage ratio 区域 min 选择 梯度行为
高于上界 clipped 项 截断继续增大好 token 概率的梯度
低于下界 unclipped 项 保留梯度,把好 token 的 ratio 往上拉
低于下界 clipped 项 截断继续降低坏 token 概率的梯度
高于上界 unclipped 项 保留梯度,把坏 token 的 ratio 往下拉

这个表解释了 PPO clip 的单边性:沿 advantage 方向走太远时截断梯度;逆着 advantage 方向走太远时保留梯度,让 loss 把 ratio 拉回去。

Dual Clip

当更新方向与优势方向相反时,若 advantage 为负、旧策略概率很小且新策略概率很大,ratio 会急剧增大,让少数 token 主导梯度估计并放大方差。Dual Clip 对这类惩罚项设置 loss 上限,避免简单 mask 带来的训练信号损失。

参考:https://zhuanlan.zhihu.com/p/1950988412405417622

GAE 与 advantage

GAE 是 one-step TD error 和 MC return 之间的平滑插值, $\lambda$ 控制偏差与方差:

  • $\lambda = 0$, $A_t = \sum_{k=0}^{\infty} 0^{k} \delta_{t+k} = \delta_t$, $\delta_t = r_t + V(s_{t+1}) - V(s_t)$ is one-step TD,低方差高偏差
  • $\lambda = 1$, $A_t = \sum_{k=0}^{\infty} \gamma^{k} \delta_{t+k} = G_t - v(s_t)$, this can be proved by sum over $\delta_{t}$ expansion,低偏差、高方差
  • $0\lt\lambda\lt1$, as $\lambda$ increase, 指数衰减的权重 $(\gamma \lambda)^{k}$ 让远处的 TD Error 贡献逐渐减小

多轮更新与重要性采样

多轮更新的对象是同一批旧策略 rollout。每一轮参数更新都会拉开当前策略和采样策略的距离,因此需要 importance ratio 校正,并用 clip 控制方差和策略漂移。

  • on-policy or off-policy:PPO 算法整体属于 on-policy,但更新过程有 off-policy 的成分。
  • 采样:on-policy rollout,每个输出都是根据当前 policy 生成的。
  • 计算 log_prob:用当前 policy 和 ref policy 计算 log prob,然后计算权重 r。
  • 多轮 actor 更新:每一轮更新后 policy 会变,但数据依然是一开始采样的。新策略在学旧策略生成的数据,产生 off-policy 成分,因此需要用重要性采样比值 $r_t(\theta)=\pi_\theta/\pi_{old}$ 做校正,并用 clip 限制校正后方差和策略漂移。

非 LLM PPO 实现流程

非 LLM PPO 的数据流可以压缩成四步:

  1. 用旧策略采样 rollout,保存 action、old logprob、reward 和 value。
  2. 用 TD error 反向递推 GAE,得到 advantage 和 value target。
  3. 多个 PPO epoch 内反复重算 new logprob/value/entropy,并用 ratio 与 clip 计算 policy loss。
  4. 同时优化 policy loss、value loss 和 entropy bonus;每轮都监控 KL、clip fraction 和 advantage scale。

GRPO (from DeepSeekMath)

目标与对象定义

  • 对于模型 $\pi_\theta$ 给定一个问题 $q$ 采样多个回答 $\lbrace o_i \rbrace_{i=1}^{G}$, $G$ 是 group 数量,每个回答有不同的长度 $\lvert o_i\rvert$
  • $\pi_\theta(o_{i,t} \mid q, o_{i,\lt t})$ 是在 $q$ 的采样解答 $o_{i,t}$ 解码的第 $t$ 个词元的策略概率
  • KL 约束 $\pi_\theta$ 和 $\pi_{ref}$ 分布差异,使用 k3 estimator 作为 token-level regularizer

K3 estimator

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

这个式子对应 k3:若当前策略是采样分布 $q$,reference policy 是 $p$,并定义 $\delta=p/q$,则 k3 为 $\delta-1-\log\delta$。它保持无偏估计,同时比 k1 更稳定,并且单样本非负。GRPO 把它作为 token-level regularizer:每个 token 上独立计算,数值通常随 $t$ 改变;它不进入 response reward 的组内归一化,也不生成 GRPO 的 group advantage。

Group relative advantage

GRPO 相较于 PPO 的核心简化是去掉 value model。它对同一个 prompt $q$ 采样 $G$ 条回答 $o_1,\dots,o_G$,用 reward model 或 rule-based verifier 给每条回答一个 response-level reward $R_i=R(q,o_i)$,再做组内标准化:

\[\hat A_i = \frac{R_i-\frac{1}{G}\sum_{k=1}^{G}R_k} {\sqrt{\frac{1}{G}\sum_{k=1}^{G}\left(R_k-\frac{1}{G}\sum_{j=1}^{G}R_j\right)^2}+\epsilon}.\]

在实现中,这个 response-level advantage 会复制到第 $i$ 条 response 的每个 token,形成 token-shaped advantage tensor:

\[\hat A_{i,t}=\hat A_i,\quad t=1,\dots,\lvert o_i\rvert.\]

这个 broadcast 只把 response-level 方向铺到 token-level policy loss 上。GRPO 的 advantage tensor 可以写成 $\hat A_{i,t}$,但对固定的 $i$,它通常不随 $t$ 改变;ratio 和 clip 是 token-level,loss reduction 常是 per-response mean。

因此 GRPO 的目标里同时存在两类 token-level 对象:policy surrogate 使用广播后的 $\hat A_{i,t}=\hat A_i$,同一条 response 内 advantage 值相同;KL regularizer 使用 $\hat D_{KL}^{i,t}$,它按 token 计算,通常不相同。把二者分开看,才能避免把“GRPO 无 critic、advantage 广播”误读成“GRPO 的 token loss 每个位置都一样”。

目标函数与粒度

GRPO 的 token ratio 是:

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

带 KL penalty 的 clipped objective 常写成:

\[J_{\text{GRPO}}(\theta)= \mathbb{E} \left[ \frac{1}{G}\sum_{i=1}^{G}\frac{1}{\lvert o_i\rvert} \sum_{t=1}^{\lvert o_i\rvert} \left( \min\left(r_{i,t}\hat A_i, \mathrm{clip}(r_{i,t},1-\epsilon,1+\epsilon)\hat A_i\right) -\beta \hat D_{KL}^{i,t} \right) \right].\]

看这个式子的求和就能定位三个问题:

  1. $\hat A_i$ 不随 $t$ 变化,因此同一 response 内没有细粒度 credit assignment。
  2. $r_{i,t}$ 随 $t$ 变化,因此 off-policy correction 和 clip 在 token 粒度发生。
  3. 每条 response 前有 $1/\lvert o_i\rvert$,因此长 response 在样本等权聚合中被稀释。

与 PPO 的差异

PPO 用 critic/GAE 给每个 token/prefix 估计通常随位置变化的 $\hat A_{i,t}$;GRPO 用组内 reward 相对值替代 critic,降低训练成本,也更适合 RLVR 这种 outcome verifier 场景。代价是:如果一组回答全对或全错,组内方差接近 0,advantage 消失;如果回答很长,同一个 response-level advantage 会被许多无关 token 共享;如果 token ratio 波动很大,clip fraction 会迅速升高。

PPO/GRPO 的共同风险在 clip 机制。与反思、搜索或关键推理转折相关的 token 可能在 base model 中概率很低;一旦这些 token 获得正 advantage,ratio 很容易越过上界,PPO/GRPO 的 min 会让它们在有利方向上不再继续贡献梯度。DAPO 用 Clip-Higher 放宽正向上界,CISPO 改成 clipped IS-weight 以保留越界 token 的 $\log\pi_\theta$ 梯度。

实现流程

  1. 对每个 prompt 在线采样多个回答,得到一组样本 (batch) : $x_j \rightarrow \lbrace y_{j,1}, \dots, y_{j,G}\rbrace$, where $x_j$ is $j$-th prompt, , $G$ is group size, $y_{j,i}$ is $i$-th response under $j$-th prompt,
  2. 计算对应奖励 $r_{j,i} = R(x_j, y_{j,i})$。对于 GSM8K 这类数据集,每道题都有明确数值答案,可用规则 verifier 判断答案正确性;这就是 RLVR 中可验证奖励的典型来源。
  3. 计算组内均值、标准差和 response-level advantage:
\[\begin{aligned} \bar r_j &= \frac{1}{G}\sum_{i=1}^{G}r_{j,i},\\ s_j &= \sqrt{\frac{1}{G}\sum_{i=1}^{G}(r_{j,i}-\bar r_j)^{2}},\\ \hat A_{j,i} &= \frac{r_{j,i}-\bar r_j}{s_j+\epsilon}. \end{aligned}\]

如果标准差 $s_j\approx 0$,说明这组回答暂时没有可学习的差异,需设置 $\hat A_{j,i}=0$。做组内归一化有效的原因:

  • 难度归一化:不同题目的难度不同。简单题所有回答都正确(奖励均值很高),难题大部分回答都错误(奖励均值很低)。如果用绝对奖励,简单题的回答会获得更高的梯度信号,模型会把大部分精力花在简单题上。组内归一化消除了这种偏差,它只关注”这道题内部谁更好”,不受题目绝对难度的影响。
  • 相对比较更稳定:人类偏好标注通常采用成对比较(”A 比 B 好”),而非绝对分数(”A 得 87 分”)。GRPO 的组内比较沿用了这种相对评价形式。
  • 方差更低:同一组内的回答共享相同的 prompt,唯一的差异是模型生成的随机性。这种”控制变量”式的比较比跨样本的绝对评分更稳定。
  1. 用 token-level ratio 计算 clipped surrogate,并用 k3 estimator 计算 token KL:
\[\hat D_{KL} = \exp(\Delta)-\Delta-1, \quad \Delta=\log\pi_{ref}(y \mid x)-\log\pi_\theta(y \mid x).\]
        # rewards: [num_prompts, group_size],每行是一道题的多条 sampled responses。
        group_mean = rewards.mean(dim=1, keepdim=True)
        group_std = rewards.std(dim=1, keepdim=True).clamp_min(1e-6)
        response_adv = (rewards - group_mean) / group_std

        # response_mask: [num_prompts * group_size, max_response_len],只统计回答 token。
        # GRPO 的 advantage tensor 带 token 维度,但同一条 response 内所有 token 共享同一个数值。
        adv_tokens = response_adv.reshape(-1, 1).expand_as(response_mask)

        token_ratio = torch.exp(new_token_logp - old_token_logp)
        clipped_ratio = token_ratio.clamp(1.0 - clip_eps, 1.0 + clip_eps)
        token_objective = torch.minimum(token_ratio * adv_tokens, clipped_ratio * adv_tokens)

        # GRPO 原始形态通常先对每条 response 的 token 求平均,再对 response/group 求平均。
        per_response_objective = (token_objective * response_mask).sum(dim=-1) / response_mask.sum(dim=-1).clamp_min(1)

        # K3 estimator: delta = log pi_ref - log pi_theta, 以 token 方式估计 KL。
        delta = ref_token_logp - new_token_logp
        kl_k3 = torch.exp(delta) - delta - 1.0
        per_response_kl = (kl_k3 * response_mask).sum(dim=-1) / response_mask.sum(dim=-1).clamp_min(1)

        grpo_loss = -(per_response_objective - beta_kl * per_response_kl).mean()

实际问题与后续算法入口

GRPO 留下三条后续路线:

  1. 长度与 loss reduction。 Per-response mean 让每条 response 等权,长 response 的 token 贡献被 $1/\lvert o_i\rvert$ 稀释。DAPO 和 Dr. GRPO 都从这里切入。
  2. clip 与 token gradient。 PPO/GRPO 的 min 会让有利方向越界 token 失去梯度。DAPO 通过 Clip-Higher 缓解,CISPO 直接改变裁剪对象。
  3. ratio 粒度。 GRPO 对每个 token 做 importance ratio,而 reward/advantage 是整条 response 的 outcome 信号。GSPO 从这里切入,把 ratio 和 clip 提升到 sequence level。

训练 GRPO 时 loss 可以为负,也可以在训练中上升。原因是实现通常最小化 $-J+\beta\hat D_{KL}$;当正 advantage 的 clipped objective 大于 KL penalty 时,loss 为负。随着策略远离 reference,KL penalty 或 clip fraction 上升,loss 变大并不必然表示 reward 下降,必须同时看 reward、response length、KL、clip fraction、all-correct/all-wrong group 比例和评测分数。

DAPO (Seed, 2025)

目标函数

DAPO 的目标可以看成在 GRPO 基础上同时改四个对象:clip 上下界、prompt 采样、loss reduction 和过长样本 reward shaping。去掉显式 KL penalty 后,它优化:

\[\mathcal{L}_{DAPO}(\theta) = -\mathbb{E}_{q,a\sim\mathcal{D},\lbrace o_i \rbrace_{i=1}^{G}\sim\pi_{\theta_{old}}(\cdot \mid q)} \left[ \frac{1}{\sum_{i=1}^{G} \lvert o_i\rvert} \sum_{i=1}^{G} \sum_{t=1}^{\lvert o_i\rvert} \min(r_{i,t}\hat{A}_{i,t}, clip(r_{i,t}, 1-\epsilon_{low}, 1+\epsilon_{high})\hat{A}_{i,t}) \right]\]

其中 $r_{i,t}=\frac{\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})}{\pi_{old}(o_{i,t} \mid q,o_{i,\lt t})}$。DAPO 论文的核心改动是 Clip-Higher、动态采样、token-level policy gradient loss 和 overlong reward shaping;它移除了显式 KL penalty。

    # DAPO 仍然可以使用 response-level/group-level advantage,
    # 但 loss 聚合改成 token-level:所有有效 token 进入同一个分母。
    token_ratio = torch.exp(new_token_logp - old_token_logp)
    clipped_ratio = token_ratio.clamp(1.0 - clip_eps_low, 1.0 + clip_eps_high)

    # Clip-Higher 常见设置是放宽正向上界,让低概率但高奖励 token 有更大上升空间。
    token_objective = torch.minimum(token_ratio * adv_tokens, clipped_ratio * adv_tokens)

    # response_mask 的 1 表示真实回答 token,0 表示 padding 或 prompt token。
    # DAPO 使用 token 总数归一化,长 response 的 token 不再被 response 内平均稀释。
    dapo_loss = -(token_objective * response_mask).sum() / response_mask.sum().clamp_min(1)

s.t.

\[0 \lt \lvert\lbrace o_i \mid \text{equivalent}(a, o_i)\rbrace\rvert \lt G\]

关键改动

DAPO 分别处理 GRPO 的四个失真点:低概率好 token 被上界过早截断、全对/全错 prompt 没有梯度、长 response 的 token 被样本均值稀释、硬截断导致 reward noise。

Clip-Higher

PPO/GRPO 的默认 clip range 常是 $[1-\epsilon,1+\epsilon]$。如果旧策略下一个探索 token 的概率很低,即使 ratio 允许乘到 $1+\epsilon$,绝对概率提升仍很有限;高概率 token 的绝对概率提升更容易显著。结果是已有高概率模式继续被强化,低概率但可能带来高奖励的推理转折缺少上升空间。

DAPO 把上下界解耦:

\[\mathrm{clip}(r_{i,t},1-\epsilon_{low},1+\epsilon_{high}), \quad \epsilon_{high}\gt\epsilon_{low}.\]

上界放宽主要服务于正 advantage token:它允许低概率但高奖励的 token 在多轮 minibatch 更新里继续上升。下界不对称放宽,是因为负 advantage token 对应降低概率;过度放宽下界会更强地压缩采样空间,增加分布漂移和熵坍缩风险。

Dynamic Sampling

当某个 prompt 的 $G$ 条回答全对或全错时,组内 reward 没有差异,response-level advantage 全部接近 0。训练继续把这类 prompt 放进 batch,会让有效梯度样本数下降、梯度方差上升。

DAPO 的动态采样使用过采样和过滤,只保留组内准确率既不为 0 也不为 1 的 prompt:

\[0 \lt \sum_{i=1}^{G}\mathbb{1}[R(q,o_i)=1] \lt G.\]

这一步处理 sampling/filtering 粒度问题。保留下来的 prompt group 都有可比较的正负样本,group advantage 才有学习信号。

Token-Level Policy Gradient Loss

GRPO 的 sample-level reduction 是:

\[\frac{1}{G}\sum_i\frac{1}{\lvert o_i\rvert}\sum_t \ell_{i,t}.\]

DAPO 改成:

\[\frac{1}{\sum_i \lvert o_i\rvert}\sum_i\sum_t \ell_{i,t}.\]

这个改变要看分母:GRPO 让每条 response 等权,DAPO 让每个 token 更接近等权。对于高质量长 CoT,长 response 不再被 $1/\lvert o_i\rvert$ 系统性压小;对于低质量长 response,重复和无效 token 也不会因为 response 很长而被弱化惩罚。

Dr. GRPO 从同一类长度偏置出发,但做法不同。它指出 GRPO/PPO 的一些公开实现会在 masked mean 中引入 response-level length normalization,并且 group standard deviation normalization 会改变不同难度 prompt 的梯度尺度。Dr. GRPO 的修正是移除 length 和 std normalization,并用 generation budget 这样的常数分母替换 response length:

\[J_{\text{Dr.GRPO}} \approx \frac{1}{G}\sum_{i=1}^{G} \frac{1}{L_{\max}} \sum_{t=1}^{\lvert o_i\rvert}\ell_{i,t}, \quad \hat A_i = R_i-\frac{1}{G}\sum_{j=1}^{G}R_j.\]

因此,DAPO 和 Dr. GRPO 在“长 response 不应被样本均值稀释”上是一致方向;但 DAPO 采用 batch token denominator,并额外引入 Clip-Higher、Dynamic Sampling 与 Overlong Reward Shaping;Dr. GRPO 更强调无偏 policy gradient、长度归一化和组内标准差归一化带来的优化偏差。

Overlong Reward Shaping

长 CoT 训练里,硬截断会制造很强的 reward noise:一个推理过程可能只是略超长度,就被截断、无法抽取答案、直接得到惩罚。模型接收到的信号变成“接近长度边界时 reward 突然翻转”。

DAPO 的 Soft Overlong Punishment 把长度惩罚加到原始 rule-based reward 上。设期望最大长度为 $L_{target}$,软惩罚缓冲区为 $L_{cache}$,生成上限为 $L_{target}+L_{cache}$,response 长度为 $L_i$。惩罚项可以写成:

\[p_{len}(L_i)= \begin{cases} 0,& L_i\le L_{target}\\ \frac{L_{target}-L_i}{L_{cache}},& L_{target}\lt L_i\le L_{target}+L_{cache}\\ -1,& L_i\gt L_{target}+L_{cache} \end{cases}\]

最终 reward 是:

\[R_i^{shaped}=R_i^{rule}+p_{len}(L_i).\]

这仍然是 response-level reward shaping:惩罚先作用在整条 response 的 reward 上,再通过 group advantage 影响所有 token。它和 PPO/RLHF 的 token-level KL shaping 不同;DAPO 没有用 critic 把长度惩罚递推成 token-specific advantage。

    # rule_reward: [num_responses],例如答案正确为 1,错误为 0 或 -1。
    # response_len: [num_responses],只统计生成回答 token。
    over = response_len - target_len

    # 目标长度内不惩罚;缓冲区内线性降到 -1;超过缓冲区保持 -1。
    length_penalty = torch.zeros_like(rule_reward)
    in_cache = (over > 0) & (over <= cache_len)
    too_long = over > cache_len
    length_penalty[in_cache] = -over[in_cache].float() / float(cache_len)
    length_penalty[too_long] = -1.0

    shaped_reward = rule_reward + length_penalty

DAPO 还移除了显式 KL penalty。它的判断是:长 CoT 从 base policy 迁移到 reasoning policy 时,分布本来可能需要明显偏离 reference;强 KL 约束会压制这种迁移。去掉 KL 后,稳定性更多依赖 Clip-Higher、动态采样、长度 reward shaping、entropy/length 监控和学习率等工程设置。

CISPO (Minimax)

优化对象

CISPO (Clipped IS-weight Policy Optimization) 将 PPO/GRPO 的 clipped token update 改成 clipped importance sampling weight,并对该权重做 stop-gradient。所有 token 的 $\log \pi_\theta$ 梯度仍然参与训练,更新强度由 clipped IS weight 控制。

粒度定位

CISPO 仍然使用 token-level importance ratio:

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

CISPO 调整 clip object,保留 token-level ratio。PPO/GRPO/DAPO 的 clipped surrogate 在有利方向越界后会把对应 token 的梯度截掉;CISPO 让 token 继续通过 $\nabla_\theta\log\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})$ 参与训练,只把数值权重限制在 IS clip range 内。GSPO 调整 ratio granularity;CISPO 调整 token ratio 进入梯度的方式。

从 IS REINFORCE 到 CISPO 目标

从带 IS 修正的 REINFORCE 看,off-policy minibatch 更新可以写成:

\[J_{\text{REINFORCE}}(\theta)= \mathbb{E}_{(q,a)\sim\mathcal{D},o_i\sim\pi_{\theta_{old}}(\cdot \mid q)} \left[ \frac{1}{\lvert o_i\rvert}\sum_{t=1}^{\lvert o_i\rvert} sg(r_{i,t}(\theta))\hat{A}_{i,t} \log\pi_\theta(o_{i,t} \mid q,o_{i,\lt t}) \right],\]

其中

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

CISPO 在这个形式上引入 clipped IS weight,并采用 GRPO 的 group relative advantage 与 DAPO 的 token-level loss:

\[J_{CISPO}(\theta) = \mathbb{E}_{(q,a)\sim \mathcal{D},\lbrace o_i \rbrace_{i=1}^{G}\sim \pi_{\theta_{old}}(\cdot \mid q)} \left[ \frac{1}{\sum_{i=1}^{G}\lvert o_i\rvert} \sum_{i=1}^{G}\sum_{t=1}^{\lvert o_i\rvert} sg(\hat{r}_{i,t}(\theta))\hat{A}_{i,t} \log \pi_\theta(o_{i,t} \mid q,o_{i,\lt t}) \right],\] \[\hat{r}_{i,t}(\theta)=clip(r_{i,t}(\theta),1-\epsilon_{low}^{IS},1+\epsilon_{high}^{IS}).\]

代码实现

    # response_mask 只统计回答 token;adv_tokens 通常来自 group relative advantage。
    token_ratio = torch.exp(new_token_logp - old_token_logp)

    # MiniMax-M1 报告中强调裁剪 IS 权重,token update 仍通过 logprob 保留。
    # detach 对应公式中的 sg(.),权重只作为数值重加权,不承接梯度。
    clipped_is_weight = token_ratio.clamp(1.0 - eps_low_is, 1.0 + eps_high_is).detach()

    # new_token_logp 始终保留梯度;没有 PPO 的 min,也没有把越界 token 直接丢掉。
    token_objective = clipped_is_weight * adv_tokens * new_token_logp
    cispo_loss = -(token_objective * response_mask).sum() / response_mask.sum().clamp_min(1)

和 PPO/GRPO 的差异

  1. PPO/GRPO 的 min(unclipped, clipped) 是 advantage-sign-dependent 的单边保守目标;当 token ratio 在“有利方向”越界时,对应 token 可能不再贡献梯度。
  2. CISPO 的 $\hat r$ 被 detach,所以 $\nabla_\theta J$ 主要来自 $\nabla_\theta\log\pi_\theta$;越界 token 仍参与训练,只是梯度权重被压到边界。
  3. 如果不裁剪 IS weight,CISPO 退化为带 stop-gradient IS 权重的标准 policy gradient;裁剪会引入轻微偏差,但换来低方差和长 response 中更高的 token 利用率。

实际操作问题

  • 上界更关键。 MiniMax-M1 报告提到实验中主要调 $\epsilon^{IS}_{high}$,低界可设得较宽;因为他们更关心高 ratio token 的方差和爆炸风险。
  • 没有显式 KL penalty。 CISPO 和 DAPO/GSPO 一样,不把 reference KL 当主约束,稳定性更多依赖动态采样、长度惩罚、IS 权重范围和优化器设置。
  • 可能保留过多错误方向梯度。 当某些 token 已经在坏方向上显著偏离旧策略时,CISPO 仍保留其梯度,只是缩小权重;这比 PPO 更高效,但也要求更谨慎地监控 entropy、clip fraction、梯度范数和重复输出。

统一 mask 视角

MiniMax-M1 还给出一个带 token-wise mask 的统一写法,用来表示“何时完全丢掉 token 梯度”。若 $M_{i,t}=1$ 恒成立,就是纯 CISPO;若 $M_{i,t}$ 模拟 PPO 的单边截断,就可以回到更保守的 token update 过滤。

\[J_{\text{unify}}(\theta)= \mathbb{E}\left[ \frac{1}{\sum_i \lvert o_i\rvert} \sum_i\sum_t sg(\hat r_{i,t})\hat A_{i,t} \log\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})M_{i,t} \right]\] \[M_{i,t}= \begin{cases} 0,& \hat A_{i,t}\gt0\ \text{and}\ r_{i,t}(\theta)\gt1+\epsilon_{high}\\ 0,& \hat A_{i,t}\lt0\ \text{and}\ r_{i,t}(\theta)\lt1-\epsilon_{low}\\ 1,& \text{otherwise} \end{cases}\]

GSPO (Qwen, 2025)

优化对象

GSPO (Group Sequence Policy Optimization) 认为 GRPO 的 token-level importance ratio 用错了修正粒度:奖励和 group advantage 是整条 response 的 outcome signal,但 GRPO 在每个 token 上分别做 off-policy correction。GSPO 把 ratio、clip、rewarding、optimization 都提升到 sequence level,让似然比修正单位和 response-level outcome signal 对齐。

粒度定位

GSPO 的判断前提是:RLVR/RLHF 中的 outcome reward 往往是整条 response 的分数,尤其是数学答案 verifier 或 reward model 的 scalar score。PPO 为了 GAE 构造 token shaped reward;GRPO/GSPO 这种无 critic 目标里,组内优势 $\hat A_i$ 本身仍是 response-level scalar。

GSPO 调整 ratio granularity:response-level advantage 评价整条 response,因此旧策略数据的修正也使用整条 response 的 likelihood ratio,避免每个 token 的局部 ratio 独立放大或截断这条 response-level 信号。

目标函数

对同一个 prompt $x$ 采样 $G$ 条 response $\lbrace y_i \rbrace_{i=1}^{G}$,先做组内优势:

\[\hat A_i= \frac{r(x,y_i)-mean(\lbrace r(x,y_j) \rbrace_{j=1}^{G})} {std(\lbrace r(x,y_j) \rbrace_{j=1}^{G})}.\]

sequence-level ratio 使用长度归一化的 sequence likelihood ratio:

\[s_i(\theta)=\exp\left(\frac{1}{\lvert o_i\rvert}\sum_{t=1}^{\lvert o_i\rvert} \log\frac{\pi_\theta(o_{i,t} \mid q,o_{i,\lt t})}{\pi_{old}(o_{i,t} \mid q,o_{i,\lt t})}\right)\] \[J_{GSPO}(\theta)=\mathbb{E}\left[ \frac{1}{G}\sum_{i=1}^{G} \min(s_i(\theta)\hat{A}_i, clip(s_i(\theta),1-\epsilon,1+\epsilon)\hat{A}_i) \right]\]

长度归一化与代码实现

为什么要做长度归一化:完整 sequence likelihood 是所有 token 概率的乘积,长度越长越容易产生极端 ratio;取 $1/\lvert o_i\rvert$ 的几何平均后,不同长度 response 可以共享同一数量级的 clip range。

    # token_log_ratio: [batch_responses, max_response_len]
    token_log_ratio = (new_token_logp - old_token_logp) * response_mask
    response_len = response_mask.sum(dim=-1).clamp_min(1)

    # GSPO 把 token log-ratio 先做长度归一化,再得到 sequence-level ratio。
    seq_log_ratio = token_log_ratio.sum(dim=-1) / response_len
    seq_ratio = torch.exp(seq_log_ratio)
    clipped_seq_ratio = seq_ratio.clamp(1.0 - clip_eps, 1.0 + clip_eps)

    # response_adv 是组内 reward 标准化后的 response-level advantage。
    seq_objective = torch.minimum(seq_ratio * response_adv, clipped_seq_ratio * response_adv)

    # clip 判断以整条 response 为单位。
    gspo_loss = -seq_objective.mean()

梯度视角

忽略 clip 时,GSPO 梯度近似为:

\[\nabla_\theta J_{GSPO}(\theta)= \mathbb{E}\left[ \frac{1}{G}\sum_{i=1}^{G} s_i(\theta)\hat A_i \frac{1}{ \mid y_i \mid}\sum_{t=1}^{ \mid y_i \mid} \nabla_\theta \log\pi_\theta(y_{i,t} \mid x,y_{i,\lt t}) \right].\]

对比 GRPO:

\[\nabla_\theta J_{GRPO}(\theta)= \mathbb{E}\left[ \frac{1}{G}\sum_{i=1}^{G}\hat A_i \frac{1}{ \mid y_i \mid}\sum_{t=1}^{ \mid y_i \mid} \frac{\pi_\theta(y_{i,t} \mid x,y_{i,\lt t})}{\pi_{\theta_{old}}(y_{i,t} \mid x,y_{i,\lt t})} \nabla_\theta \log\pi_\theta(y_{i,t} \mid x,y_{i,\lt t}) \right].\]

GRPO 每个 token 被自己的 ratio 加权,长 response 中少数极端 token 会持续放大梯度噪声;GSPO 用整条 response 的同一个 $s_i$ 加权所有 token,降低 token-level ratio 方差。

GSPO-token

论文还给出 token-level variant,用 sequence-level $s_i$ 的数值控制 clip,但通过 stop-gradient 构造 token-level 可反传项:

\[s_{i,t}(\theta)=sg[s_i(\theta)]\cdot \frac{\pi_\theta(y_{i,t} \mid x,y_{i,\lt t})} {sg[\pi_\theta(y_{i,t} \mid x,y_{i,\lt t})]}.\]

数值上 $s_{i,t}=s_i$,但梯度来自当前 token 的 logprob;当一条 response 内所有 token 共享同一个 $\hat A_i$ 时,GSPO-token 与 GSPO 在目标、clip 条件和理论梯度上等价。它的价值在于:如果未来有 step-level 或 token-level advantage,可以在不回到 GRPO token ratio 的情况下加入细粒度 credit assignment。

    # seq_ratio.detach() 提供 sequence-level 数值权重;
    # exp(new_token_logp - new_token_logp.detach()) 数值为 1,但梯度等价于 new_token_logp。
    token_factor = torch.exp(new_token_logp - new_token_logp.detach())
    gspo_token_ratio = seq_ratio.detach()[:, None] * token_factor
    gspo_token_ratio = gspo_token_ratio * response_mask

    token_adv = response_adv[:, None].expand_as(response_mask)
    token_obj = torch.minimum(
        gspo_token_ratio * token_adv,
        gspo_token_ratio.clamp(1.0 - clip_eps, 1.0 + clip_eps) * token_adv,
    )
    gspo_token_loss = -(token_obj * response_mask).sum() / response_mask.sum().clamp_min(1)

实际操作问题

  • MoE routing mismatch。 GSPO 论文指出 token-level ratio 对 MoE expert routing 变化很敏感;同一 response 在更新后可能激活不同 expert,导致 token ratio 波动。GSPO 只依赖 sequence likelihood,对单个 token likelihood 的敏感度更低,因此可以减少对 routing replay 的依赖。
  • 推理/训练精度差异。 如果 rollout 由 vLLM/SGLang 等推理引擎生成,训练引擎重新算 token logprob 可能和推理时不完全一致。GSPO 使用 sequence-level likelihood,对这种细粒度差异更宽容。
  • 整段裁剪的取舍。 response-level clip 会把一整条 response 作为 off-policy 判断单位;这降低了 token ratio 噪声,但也意味着少数异常 token 可能影响整段样本是否被裁剪。实际监控应同时看 sequence clip fraction、长度分布、reward 分布和 entropy。

Reward Model:Bradley-Terry 偏好建模

目标和公式

目的:预测两个竞争者结果的概率模型,常用于处理成对比较的数据。 $p_i$ 是正实数分数,可以写成指数分数函数 $p_i=e^{\beta_i}$。

\[\begin{aligned} p(i\gt j) &= \frac{p_i}{p_i + p_j} \\ &= \frac{e^{\beta_i}}{e^{\beta_i} + e^{\beta_j}} \\ &= \frac{1}{1 + e^{-(\beta_i - \beta_j)}} \\ &= \sigma(\beta_i - \beta_j) \end{aligned}\]

MLE 目标

\[\mathrm{argmin}_{\beta} \sum_{i,j} -\log\sigma(\beta_i-\beta_j)\]

该目标鼓励 $\beta_i\gg\beta_j$。

训练数据和 BT likelihood

给定 prompt $x$ 根据人类偏好标注得到回答 $y_1 \succ y_2$,构建偏好数据集 $\mathcal{D} = \lbrace x^{(i)}, y_w^{(i)}, y_l^{(i)}\rbrace_{i=1}^{N}$,reward 模型需要预测出分数 $r^{\ast}(y, x)$。通过 BT 模型建模人类偏好分布:

\[p^{\ast}(y_1 \succ y_2 \mid x) = \frac{e^{r^{\ast}(x, y_1)}}{e^{r^{\ast}(x, y_1)} + e^{r^{\ast}(x, y_2)}} = \frac{1}{1 + e^{-(r^{\ast}(x, y_1) - r^{\ast}(x, y_2))}} = \sigma(r^{\ast}(x, y_1) - r^{\ast}(x, y_2))\]

MLE loss:

\[\mathcal{L}(r_\phi, \mathcal{D} ) = -\mathbb{E}_{x, y_w, y_l\sim \mathcal{D}}[\log \sigma(r_\phi(x, y_w) - r_\phi(x, y_l))]\]
        # reward_model 对 prompt+response 输出一个 response-level scalar reward。
        chosen_reward = reward_model(prompt_ids, chosen_response_ids)
        rejected_reward = reward_model(prompt_ids, rejected_response_ids)

        # Bradley-Terry: 只关心分数差,不关心两个 reward 的绝对平移。
        reward_margin = chosen_reward - rejected_reward
        reward_model_loss = -torch.nn.functional.logsigmoid(reward_margin).mean()

奖励颗粒度

Reward model 最常见的输出是 response-level scalar:完整 prompt+response 输入模型,最后得到 $r_\phi(x,y)$。这和语言模型训练里的 token logprob 不同;RM 不会天然告诉你第几个 token 贡献了偏好。

更细的 reward 粒度通常需要额外设计:

  1. response-level reward:整条回答一个分数,适合偏好标注、答案 verifier、格式 verifier,也是 PPO/RLHF 和 GRPO/RLVR 最常见的来源。
  2. step-level reward:按推理步骤打分,需要步骤切分、过程监督或 verifier 对中间结论的校验;它能改进 credit assignment,但标注与验证成本更高。
  3. token-level reward:每个 token 独立分数。人工偏好 RM 通常不天然输出这种信号;工程中更常见的做法是把 KL penalty 写成 token-level shaping。

后续 PPO 的 critic/GAE 可以把 response-level reward 传播到 token-specific advantage;GRPO/GSPO 通常直接把 response-level advantage 复制到 token-shaped objective 或 sequence objective。训练 loss 按 token 求和,不代表原始 reward 来自 token-level 标注。

实际操作注意

  • 数据切分:训练集和验证集共享同一个 prompt,甚至共享部分回答。这样得到的 eval accuracy 会偏乐观,更稳妥的做法是按 prompt 切分
  • RM 分数尺度:RM 训练只关心分数差,不关心绝对尺度,但 PPO 阶段感受到的奖励尺度完全不同,PPO之前需要校准,常见做法是在固定校准集上做标准化
  • reward hacking:PPO 的 actor 会主动搜索让 RM 给高分的输出分布。如果 RM 偏爱某种表面模式,Actor 会把这种模式推到极端,例如:偏爱长回答。Actor 可能学到:越写越长,尽管奖励不断上升,但是真实的信息密度下降。常见做法是在 PPO 前先做对抗性测试,如果“超长废话”比“正确但简短”分数高,先别跑 PPO

Reinforcement Learning from Human Feedback (RLHF)

SFT 目标

\[\mathcal{L}_{SFT} = -\mathbb{E}_{(x,y)\sim\mathcal{D}}[\log\pi_\theta(y \mid x)] \approx -\sum_{t=1}^{T} \log\pi_\theta(y_t \mid x,y_{\lt t})\]

RLHF 目标

\[\mathcal{J}_{RLHF} = \mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(\cdot \mid x)}[r_\phi(x,y)] - \beta D_{KL}(\pi_\theta(\cdot \mid x) \Vert \pi_{ref}(\cdot \mid x))\]

解释:让当前模型自己生成回答,用 RM 打分,再用 PPO 提高高分回答的概率,追求偏好奖励,同时别偏离 SFT 太远,用裁剪、优势估计和 KL 约束(k2 estimation)来稳定更新。

LLM-RLHF 的 reward shaping

Reward Model 往往只在完整回答 $y$ 结束后给一个分数 $r_\phi(x,y)$。PPO 训练需要 token-level policy update,因此工程上把逐 token KL penalty 和最后位置的 RM reward 合成 shaped reward,再交给 critic/GAE 计算 token-specific advantage。完整公式见 PPO 的 LLM token-level 目标

    # rm_reward: [batch],完整 response 的 response-level reward。
    # token_kl: [batch, max_len],每个生成 token 的 log pi - log pi_ref。
    shaped_reward = -beta_kl * token_kl

    # 只在最后一个有效 token 加上整段 RM reward。
    last_index = response_mask.sum(dim=-1).long() - 1
    shaped_reward[torch.arange(shaped_reward.size(0)), last_index] += rm_reward

    # shaped_reward 进入 critic/GAE;policy loss 仍按 token ratio 和 token advantage 更新。
    advantages = compute_gae(shaped_reward, values, response_mask, gamma, lam)

梯度颗粒度

PPO/RLHF 的 token-level 梯度来自 token-specific advantage 和 token ratio,RM 不直接给每个 token 打分。GRPO/GSPO 的 response-level 梯度方向来自 group advantage,再通过 token logprob 求和或 sequence-level ratio 进入参数更新。判断方法粒度时,同时检查 reward 来源、advantage 定义、ratio 定义和 loss 分母。

Direct Preference Optimization (DPO)

目标函数

\[\mathcal{L}_{DPO}(\pi_\theta;\pi_{ref}) = -\mathbb{E}_{x,y_w,y_l\sim \mathcal{D}}[\log \sigma(\beta\log\frac{\pi_\theta(y_w \mid x)}{\pi_{ref}(y_w \mid x)} - \beta\log\frac{\pi_\theta(y_l \mid x)}{\pi_{ref}(y_l \mid x)})]\]
    # chosen/rejected 都是整条回答的 log probability,
    # 通常由 token logprob 乘 response mask 后求和得到。
    chosen_logp = (chosen_token_logp * chosen_mask).sum(dim=-1)
    rejected_logp = (rejected_token_logp * rejected_mask).sum(dim=-1)
    ref_chosen_logp = (ref_chosen_token_logp * chosen_mask).sum(dim=-1)
    ref_rejected_logp = (ref_rejected_token_logp * rejected_mask).sum(dim=-1)

    chosen_logratio = chosen_logp - ref_chosen_logp
    rejected_logratio = rejected_logp - ref_rejected_logp

    # DPO 只看 chosen 相对 rejected 的 log-ratio 差值,不需要在线 rollout 或显式 RM。
    logits = beta * (chosen_logratio - rejected_logratio)
    dpo_loss = -torch.nn.functional.logsigmoid(logits).mean()

目标推导

从 RLHF 的目标开始:

\[\begin{aligned} \max_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(\cdot \mid x)}&[r_\phi(x,y)] - \beta D_{KL}(\pi_\theta(\cdot \mid x) \Vert \pi_{ref}(\cdot \mid x)) \\ &= \max_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(y \mid x)}[r(x,y) - \beta \log\frac{\pi_\theta(y \mid x)}{\pi_{ref}(y \mid x)}] \\ &= \min_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(y \mid x)}[\log\frac{\pi_\theta(y \mid x)}{\pi_{ref}(y \mid x)} - \frac{1}{\beta}r(x,y)] \\ &= \min_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(y \mid x)}[\log\frac{\pi_\theta(y \mid x)}{\pi_{ref}(y \mid x)} - \log\frac{1}{Z(x)} + \log\frac{1}{Z(x)} - \log e^{ \frac{1}{\beta}r(x,y)} + \log e^{ \frac{1}{\beta}r(x,y)} - \frac{1}{\beta}r(x,y)] \\ &= \min_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(y \mid x)}[\log\frac{\pi_\theta(y \mid x)}{\frac{1}{Z(x)}\pi_{ref}(y \mid x)e^{\frac{1}{\beta}r(x,y)}} + \log\frac{1}{Z(x)}] \\ &= \min_\theta\mathbb{E}_{x\sim \mathcal{D}, y\sim\pi_\theta(y \mid x)}[D_{KL}(\pi(y \mid x) \Vert \pi^{\ast}(y \mid x)) - \log Z(x)] \end{aligned}\]

推导动机

找到一个配分函数 $Z(x) = \sum_y \pi_{ref}(y \mid x)e^{\frac{1}{\beta}r(x,y)}$ 作为一个有效的概率分布的归一化系数:

\[\pi^{\ast}(y \mid x) = \frac{1}{Z(x)} \pi_{ref}(y \mid x)e^{\frac{1}{\beta}r(x,y)}\]

这样使得目标的第一项 $\log$ 的分母是一个有效的概率分布,将优化目标表达成 KL 散度。奖励函数 RM 可以用策略概率的比值来表示,不需要额外的 RM,策略模型自己就蕴含了奖励信号。推导结果:最小化 KL 项,得到求解策略 $\pi_\theta(y \mid x) = \pi^{\ast}(y \mid x)$。

替代目标中的奖励函数 $r(x,y) = \beta\log\frac{\pi^{\ast}(y \mid x)}{\pi_{ref}(y \mid x)} + \beta \log Z(x)$ 带入 BT model:

\[\begin{aligned} p^{\ast}(y_1 \succ y_2 \mid x) &= \frac{e^{r^{\ast}(x, y_1)}}{e^{r^{\ast}(x, y_1)} + e^{r^{\ast}(x, y_2)}} = \sigma(r^{\ast}(x, y_1) - r^{\ast}(x, y_2)) \\ &= \sigma(\beta \log\frac{\pi^{\ast}(y_1 \mid x)}{\pi_{ref}(y_1 \mid x)} - \beta \log\frac{\pi^{\ast}(y_2 \mid x)}{\pi_{ref}(y_2 \mid x)}) \end{aligned}\]

DPO 的退化风险与 PPO 对照

  • DPO的训练目标会导致过拟合,因为 rejected token 策略 $\pi_\theta(y_l \mid x)$ 会快速收敛到 0,导致 DPO sigmoid 概率不断接近 1,损失一直降低,但是没有对齐偏好。解决方案可以是 IPO,它把偏好概率拟合到一个固定 margin:
\[\log\frac{\pi^{\ast}(y_1 \mid x)}{\pi_{ref}(y_1 \mid x)} - \log\frac{\pi^{\ast}(y_2 \mid x)}{\pi_{ref}(y_2 \mid x)} \rightarrow \frac{\tau^{-1}}{2}\]
  • 在DPO的推导中,最优策略是基于BT-Model形式下能得到最大的reward,在非DPO的优化中,存在其他的策略能够使得DPO Loss更低
  • 参考:https://zhuanlan.zhihu.com/p/692991235

Training-Inference Mismatch

训练-推理不一致指训练阶段优化的分布、状态、奖励或系统实现,和最终推理/评测时模型真实面对的条件不一致。这类错位通常成组出现,并会互相放大。

发生场景

场景 训练时看到什么 推理/评测时面对什么 典型后果
SFT teacher forcing 每一步条件是 gold prefix $y^{\ast}_{\lt t}$ 每一步条件是模型自己生成的 prefix $\hat y_{\lt t}$ 早期错误改变后续状态分布,形成 exposure bias
Offline preference / DPO 固定偏好对来自人工数据或旧策略 当前策略会生成新的错误类型 拒绝样本概率被压得很低但真实偏好未必提升,容易过拟合偏好数据
Online RLHF / RLVR 当前策略 rollout + RM/verifier 打分 部署时面对更宽 prompt 分布和不同采样设置 能发现当前策略错误,但也可能 reward hacking 或 verifier hacking
Token loss vs response reward policy loss、KL 或 GAE 在 token 上计算 奖励通常只评价整段 response 或最终答案 reward shaping、loss aggregation 和 ratio granularity 若混用,会稀释关键 token 或放大 token ratio 噪声
训练长度 vs 推理长度 固定 max length、截断或长度惩罚 用户可能给更长上下文、要求更长 CoT 过长推理、重复循环、答案抽取失败、成本失控
推理引擎 vs 训练引擎 rollout 可能由 vLLM/SGLang 生成 训练端重算 logprob、MoE routing 或数值精度不同 token ratio 不稳定,clip fraction 异常,MoE 训练可能崩

SFT 的条件分布错位可以直接写成:

\[\mathcal{L}_{SFT} =-\sum_t\log\pi_\theta(y_t^{\ast} \mid x,y_{\lt t}^{\ast}), \quad \text{inference: } \hat y_t\sim\pi_\theta(\cdot \mid x,\hat y_{\lt t}).\]

训练目标没有覆盖 $\hat y_{\lt t}$ 这个“自己犯错后的状态”;一旦早期 token 偏了,后面的状态分布就会离开训练分布。teacher-forced token accuracy 因此不能代表真实生成质量。

问题分析

  • 状态分布错位会递归放大。 在 RL 记号里,策略改变会改变状态访问分布 $d^{\pi}(s)$;语言模型里状态就是 prefix。SFT/DPO 如果只在静态数据上训练,就很难覆盖当前策略生成的新 prefix。
  • 奖励粒度和优化粒度不一致。 整段 reward 只告诉模型“这条 response 好不好”,但训练目标还要决定 advantage 分到哪里、ratio 按什么单位修正、clip 截断哪个对象、loss 分母如何归一化。PPO 用 critic/GAE 把 response-level reward 与 token-level KL shaping 变成 token-specific advantage;GRPO 把 response-level advantage 复制成 token-shaped tensor;DAPO/Dr. GRPO 修 loss aggregation 的长度偏置;CISPO 修 clip object;GSPO 修 response-level outcome signal 与 token-level ratio 的单位错配。
  • 评测协议也是目标的一部分。 温度、top-p、max tokens、答案抽取规则、verifier 宽严度都会改变最终分数。如果训练时 reward extractor 和评测时 answer parser 不一致,模型可能优化到一个评测不认的输出格式。
  • 工程实现会制造隐形 off-policy。 用推理引擎生成 rollout,再用训练引擎重算 logprob;或者 MoE 模型更新后 routing 改变,都会让“同一个 token 的新旧概率比”不再只反映策略分布变化。GSPO 对 sequence likelihood 的依赖较低敏感度,就是在缓解这一类错位。
  • 越强的在线优化越需要防 reward hacking。 RLHF/RLVR 能让当前策略暴露真实错误,但策略也会主动搜索 reward/verifier 的漏洞。长回答偏好、格式投机、重复推理和“最终答案抽取”漏洞都属于这个范畴。

改善方向

  • SFT 阶段:让训练格式贴近推理格式。 保持 chat template、system prompt、工具调用格式、EOS/stop token 和推理时一致;必要时加入模型生成前缀上的纠错数据或 DAgger/scheduled-sampling 风格的数据聚合。
  • 偏好学习阶段:区分 offline alignment 和 online correction。 DPO 适合利用高质量固定偏好对,但要监控 rejected logprob 过快塌缩;PPO/GRPO/RLVR 适合暴露当前策略错误,但必须加入 KL/clip、长度约束、verifier 对抗测试和 prompt-level dynamic sampling。
  • RL 阶段:逐项检查 reward、advantage、ratio、clip 和 loss reduction。 若奖励是 response-level,response-level advantage 更自然;若继续使用 token-level ratio,需要监控 token ratio 方差和 clip fraction;若长 response 被样本均值稀释,要检查 loss denominator;若有 step-level verifier 或 process reward,再考虑 token/step advantage。
  • 长度控制:不要只靠硬截断。 硬截断会把接近边界的合理推理变成噪声样本。DAPO 的 soft overlong punishment 是更平滑的做法;实际训练还应监控 response length 分位数、重复 n-gram、EOS 率和答案抽取失败率。
  • 评测阶段:固定协议并复用 verifier。 同一模型在不同采样温度、max tokens、答案抽取规则下可能得到完全不同结论。训练日志和最终报告必须记录这些配置。
# 评测协议需要作为实验对象保存,避免关键设置散落在命令行参数里。
eval_protocol = {
    "temperature": 0.6,
    "top_p": 0.95,
    "max_new_tokens": 32768,
    "stop": ["</answer>"],
    "answer_extractor": "same_as_training_verifier",
}

for prompt in eval_prompts:
    response = policy.generate(prompt, **eval_protocol)
    answer = extract_answer(response, mode=eval_protocol["answer_extractor"])
    score = verifier(prompt, answer)

    log_eval_case(
        prompt_id=prompt.id,
        response_len=count_response_tokens(response),
        extracted_answer=answer,
        verifier_score=score,
    )

一个实用判断:如果训练 loss 变好但评测分数不动,先不要急着调学习率。优先检查这四件事:rollout prompt 分布是否覆盖评测分布;reward/verifier 是否和评测 extractor 一致;长度分布是否漂移;新旧 logprob/ratio 是否受推理-训练引擎差异污染。

Mathematical tools behind algorithms

Bellman expectation equation 推导

状态价值从定义出发:

\[v_\pi(s)=\mathbb{E}[G_t \mid S_t=s] =\mathbb{E}[R_{t+1}+\gamma G_{t+1} \mid S_t=s].\]

即时奖励项:

\[\begin{aligned} \mathbb{E}[R_{t+1} \mid S_t=s] &= \sum_r r p(r \mid s)\\ &= \sum_r r\sum_a p(r \mid s,a)p(a \mid s)\\ &= \sum_a \pi(a \mid s)\sum_r p(r \mid s,a)r. \end{aligned}\]

未来回报项用全期望公式和 Markov property 展开:

\[\begin{aligned} \mathbb{E}[G_{t+1} \mid S_t=s] &= \sum_{s^{\prime}}\mathbb{E}[G_{t+1} \mid S_t=s,S_{t+1}=s^{\prime}]p(s^{\prime} \mid s)\\ &= \sum_{s^{\prime}}\mathbb{E}[G_{t+1} \mid S_{t+1}=s^{\prime}]p(s^{\prime} \mid s)\\ &= \sum_{s^{\prime}}v_\pi(s^{\prime})\sum_a\pi(a \mid s)p(s^{\prime} \mid s,a). \end{aligned}\]

代回得到 element-wise Bellman expectation equation:

\[v_\pi(s)= \sum_a\pi(a \mid s) \left[ \sum_r p(r \mid s,a)r+\gamma\sum_{s^{\prime}}p(s^{\prime} \mid s,a)v_\pi(s^{\prime}) \right].\]

若定义

\[r_\pi(s)=\sum_a\pi(a \mid s)\sum_r p(r \mid s,a)r, \quad p_\pi(s^{\prime} \mid s)=\sum_a\pi(a \mid s)p(s^{\prime} \mid s,a),\]

则有矩阵形式:

\[v_\pi=r_\pi+\gamma P_\pi v_\pi.\]

当 $\gamma\lt1$ 且 $P_\pi$ 为随机矩阵时, $I-\gamma P_\pi$ 可逆,因此

\[v_\pi=(I-\gamma P_\pi)^{-1}r_\pi.\]

Bellman optimality contraction

Bellman optimality operator 定义为

\[(Tv)(s)=\max_a\left[r(s,a)+\gamma\sum_{s^{\prime}}p(s^{\prime} \mid s,a)v(s^{\prime})\right].\]

对任意两个 value function $u,v$:

\[\begin{aligned} \lvert (Tu)(s)-(Tv)(s) \rvert &\le \max_a \left\lvert \gamma\sum_{s^{\prime}}p(s^{\prime} \mid s,a)(u(s^{\prime})-v(s^{\prime})) \right\rvert \\ &\le \gamma\max_a\sum_{s^{\prime}}p(s^{\prime} \mid s,a)\lVert u-v\rVert_\infty\\ &= \gamma\lVert u-v\rVert_\infty. \end{aligned}\]

因此

\[\lVert Tu-Tv\rVert_\infty\le\gamma\lVert u-v\rVert_\infty.\]

当 $\gamma\lt1$ 时, $T$ 是 contraction mapping,所以存在唯一不动点:

\[v^{\ast}\]

value iteration $v_{k+1}=Tv_k$ 会收敛到这个不动点。

策略梯度定理证明

最常用的证明从整条轨迹 $\tau=(s_0,a_0,r_1,\dots,s_T)$ 的似然比开始。有限时域目标写作

\[J(\theta)=\mathbb{E}_{\tau\sim p_\theta(\tau)}[R(\tau)].\]

对参数求导:

\[\begin{aligned} \nabla_\theta J(\theta) &= \nabla_\theta \int p_\theta(\tau)R(\tau)d\tau \\ &= \int \nabla_\theta p_\theta(\tau)R(\tau)d\tau \\ &= \int p_\theta(\tau)\nabla_\theta \log p_\theta(\tau)R(\tau)d\tau \\ &= \mathbb{E}_{\tau\sim p_\theta(\tau)} \left[\nabla_\theta \log p_\theta(\tau)R(\tau)\right]. \end{aligned}\]

轨迹概率分解为

\[p_\theta(\tau)=\rho_0(s_0) \prod_{t=0}^{T-1} \pi_\theta(a_t \mid s_t)p(s_{t+1},r_{t+1} \mid s_t,a_t).\]

环境转移和奖励分布不含 $\theta$,所以

\[\nabla_\theta\log p_\theta(\tau) =\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t \mid s_t).\]

得到 trajectory 形式:

\[\nabla_\theta J(\theta) = \mathbb{E}_{\tau} \left[ \sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t \mid s_t)R(\tau) \right].\]

时刻 $t$ 的动作不影响过去奖励,所以可把整段回报换成 reward-to-go:

\[\nabla_\theta J(\theta) = \mathbb{E}_{\tau} \left[ \sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t \mid s_t)G_t \right], \quad G_t=\sum_{k=t}^{T-1}\gamma^{k-t}R_{k+1}.\]

再把 reward-to-go 换成条件期望,得到 action-value 形式:

\[\nabla_\theta J(\theta) = \mathbb{E}_{s_t,a_t} \left[ \nabla_\theta\log\pi_\theta(a_t \mid s_t)Q^{\pi}(s_t,a_t) \right].\]

baseline 不改变期望。对任意只依赖状态的 $b(s)$:

\[\begin{aligned} \mathbb{E}_{a\sim\pi_\theta(\cdot \mid s)} \left[\nabla_\theta\log\pi_\theta(a \mid s)b(s)\right] &= b(s)\sum_a\pi_\theta(a \mid s)\nabla_\theta\log\pi_\theta(a \mid s)\\ &= b(s)\sum_a\nabla_\theta\pi_\theta(a \mid s)\\ &=b(s)\nabla_\theta 1=0. \end{aligned}\]

因此可把 $Q^{\pi}(s,a)$ 换成 advantage:

\[\nabla_\theta J(\theta) = \mathbb{E}_{s_t,a_t} \left[ \nabla_\theta\log\pi_\theta(a_t \mid s_t)A^{\pi}(s_t,a_t) \right].\]

无限时域折扣设定常写成 discounted occupancy form:

\[\nabla_\theta J(\theta) = \frac{1}{1-\gamma} \mathbb{E}_{s\sim d_\gamma^{\pi},a\sim\pi_\theta(\cdot \mid s)} \left[ \nabla_\theta\log\pi_\theta(a \mid s)Q^{\pi}(s,a) \right],\]

其中

\[d_\gamma^{\pi}(s)=(1-\gamma)\sum_{t=0}^{\infty}\gamma^{t}P(S_t=s \mid \pi).\]

trajectory 形式更适合解释 REINFORCE/PPO 代码;discounted occupancy 形式更适合和 Bellman、actor-critic 的状态分布对齐。不同资料省略 $\frac{1}{1-\gamma}$ 时,通常是把常数吸收到学习率或采用未归一化 occupancy measure。

PPO clip 单边裁剪梯度符号

令单个 token/action 的当前 logprob 为:

\[z_t=\log\pi_\theta(a_t \mid s_t), \quad z_t^{old}=\log\pi_{old}(a_t \mid s_t), \quad r_t(\theta)=\exp(z_t-z_t^{old}).\]

旧策略 logprob 在本轮更新中是常数,因此:

\[\frac{\partial r_t}{\partial z_t}=r_t.\]

PPO 最大化单 token surrogate:

\[J_t(\theta)= \min\left( r_t A_t, \mathrm{clip}(r_t,1-\epsilon,1+\epsilon)A_t \right).\]

实际训练通常最小化 loss:

\[\ell_t(\theta)=-J_t(\theta).\]

当优势为正时,采样到的 token/action 比平均水平好,策略应提高它的概率。此时:

\[J_t(\theta)= \begin{cases} r_t A_t,& r_t\le 1+\epsilon\\ (1+\epsilon)A_t,& r_t\gt 1+\epsilon \end{cases}\]

对应的 loss 梯度是:

\[\frac{\partial \ell_t}{\partial z_t}= \begin{cases} -A_t r_t,& r_t\le 1+\epsilon\\ 0,& r_t\gt 1+\epsilon \end{cases}\]

在 $A_t\gt0$ 且 $r_t\lt1-\epsilon$ 的区域,新策略把好 token 的概率降得过多。此时梯度 $\frac{\partial \ell_t}{\partial z_t}=-A_t r_t\lt0$,梯度下降更新:

\[z_t \leftarrow z_t-\eta\frac{\partial \ell_t}{\partial z_t}\]

会增大 $z_t$,也就是增大 $\pi_\theta(a_t \mid s_t)$,把 ratio 往上拉回合理区间。这里的“惩罚”指错误方向的更新继续承担 loss 梯度;该梯度会把概率推回 advantage 指定的方向。

当优势为负时,采样到的 token/action 比平均水平差,策略应降低它的概率。此时:

\[J_t(\theta)= \begin{cases} (1-\epsilon)A_t,& r_t\lt 1-\epsilon\\ r_t A_t,& r_t\ge 1-\epsilon \end{cases}\]

对应的 loss 梯度是:

\[\frac{\partial \ell_t}{\partial z_t}= \begin{cases} 0,& r_t\lt 1-\epsilon\\ -A_t r_t,& r_t\ge 1-\epsilon \end{cases}\]

在 $A_t\lt0$ 且 $r_t\gt1+\epsilon$ 的区域,新策略把坏 token 的概率升得过多。此时 $\frac{\partial \ell_t}{\partial z_t}=-A_t r_t\gt0$,梯度下降会减小 $z_t$,也就是降低 $\pi_\theta(a_t \mid s_t)$,把 ratio 往下拉回合理区间。

TRPO trust-region 二阶近似

TRPO 的约束优化写成:

\[\max_\theta L_{\theta_{old}}(\theta) \quad \text{s.t.} \quad \bar D_{KL}(\theta_{old},\theta)\le\delta.\]

在 $\theta_{old}$ 附近对目标做一阶近似、对 KL 做二阶近似:

\[L_{\theta_{old}}(\theta)\approx L_{\theta_{old}}(\theta_{old})+g^{T}(\theta-\theta_{old}),\] \[\bar D_{KL}(\theta_{old},\theta)\approx \frac{1}{2}(\theta-\theta_{old})^{T}A(\theta-\theta_{old}),\]

其中 $A$ 是 KL Hessian,也就是 Fisher information matrix 的经验近似;一阶项为:

\[g= \left. \nabla_\theta L_{\theta_{old}}(\theta) \right\rvert_{\theta=\theta_{old}}.\]

于是局部问题变成:

\[\max_x g^{T}x \quad \text{s.t.} \quad \frac{1}{2}x^{T}Ax\le\delta.\]

其方向与自然梯度一致:

\[s\approx A^{-1}g.\]

大模型里通常不显式形成 $A^{-1}$;实现上用 conjugate gradient 和 Fisher-vector product 近似求解 $As=g$。步长由 KL 约束给出:

\[\beta=\sqrt{\frac{2\delta}{s^{T}As}}.\]

最后 TRPO 做 line search:从 $\theta_{old}+\beta s$ 开始逐步缩小步长,直到 surrogate objective 改善且真实平均 KL 不超过 $\delta$。没有这个 line search,二阶近似误差可能让一次更新跨出 trust region,造成性能崩塌。

Bradley-Terry preference model

Bradley-Terry model 用于建模 pairwise preference。给定两个候选项的分数,它把“A 优于 B”的概率写成两个正分数的归一化比例;DPO 和 reward model 训练都会用到这个比较式建模视角。

\[Pr(i\gt j) = \frac{p_i}{p_i + p_j} = \frac{e^{\beta_i}}{e^{\beta_i} + e^{\beta_j}} = \frac{1}{1 + e^{-(\beta_i - \beta_j)}} = \sigma(\beta_i - \beta_j),\]

$p_i$ 是 $i$ 的正实数分数, $p_i = e^{\beta_i}$ 是对应的指数分数函数

对应 loss 是:

\[y(x) = -\log \sigma(x) = -\log \sigma(\beta_i - \beta_j).\]

当分数差趋向正无穷时,loss 趋向 0;当分数差趋向负无穷时,loss 趋向正无穷。

KL divergence 的非对称性

设目标分布为 $p$,近似分布为 $q$。正向 KL 和反向 KL 权重不同,因此在多峰分布上会产生不同的覆盖行为。

正向 KL

  • 权重 $p(x)$
  • 在 $p(x)$ 大的地方,想让 KL 散度小,就需要 $q(x)$ 的值也尽量大;在 $p(x)$ 小的地方, $q(x)$ 对整体影响不大
  • 要想使正向 KL 散度最小,则要求在 $p(x)$ 不为 0 的地方, $q(x)$ 也尽量不为 0,所以正向 KL 散度被称为是 zero avoiding
  • 得到的分布 $q(x)$ 是一个比较 “宽” 的分布
\[q^{\ast} = \mathrm{argmin}_q D_{KL}(p \Vert q) = \mathrm{argmin}_q p(x) \log\frac{p(x)}{q(x)}\]

反向 KL

  • 权重 $q(x)$
  • 在 $p(x)$ 小的地方,想让 KL 散度小,就需要 $q(x)$ 的值也尽量小;在 $p(x)$ 大的地方,可以适当忽略
  • 要想使反向 KL 散度最小,则要求在 $p(x)$ 为 0 的地方, $q(x)$ 也尽量为 0,所以反向 KL 散度被称为是 zero forcing
  • 得到的分布 $q(x)$ 是一个比较 “窄” 的分布
\[q^{\ast} = \mathrm{argmin}_q D_{KL}(q \Vert p) = \mathrm{argmin}_q q(x) \log\frac{q(x)}{p(x)}\]

两峰混合分布例子

令真实分布 p 是两个高斯分布的混合,令近似分布 q 为单个高斯分布。两种 KL 的典型行为是:

  • 正向:更在意真实分布 p 中的常见事件,也就是两峰,需要让这些高概率区域在 q 中保持足够概率质量。当 p 具有多个峰时,q 倾向于覆盖多个峰,得到较宽的近似分布。
  • 反向:更在意 q 自己放置概率质量的位置,需要避免把质量放到 p 的低概率谷底。当 p 具有多个相隔较远的峰时,最小化反向 KL 常选择单个峰,得到较窄的近似分布。

KL divergence estimation

考虑反向 KL 散度。设当前采样分布为 $q$,参考分布为 $p$,样本 $x\sim q$,并定义:

\[\delta(x)=\frac{p(x)}{q(x)}.\]

则:

\[D_{KL}(q \Vert p) = \sum_x q(x)\log\frac{q(x)}{p(x)} = \mathbb{E}_{x\sim q} \left[ \log\frac{q(x)}{p(x)} \right]\]

也就是:

\[D_{KL}(q \Vert p)=\mathbb{E}_{x\sim q}[-\log\delta(x)].\]

常见 estimator 可以写成:

\[k_1(x)=-\log\delta(x).\] \[k_2(x)=\frac{1}{2}\left(\log\delta(x)\right)^2.\] \[k_3(x)=\delta(x)-1-\log\delta(x).\]
estimator 期望 单样本符号 方差/偏差 常见用途
k1 无偏估计 KL 可正可负 无偏但方差较高 PPO/RLHF 的 sampled log-ratio KL penalty;也可作为 KL 监控
k2 二阶近似 KL 非负 有偏,分布接近时偏差小,方差低 approximate KL、early stopping、诊断指标
k3 无偏估计 KL 非负 无偏且通常低方差 GRPO/DeepSeekMath 这类 token-level KL regularizer

k1 直接来自 KL 定义,因此无偏:

\[\begin{aligned} \mathbb{E}_{x\sim q}[k_1(x)] &= \mathbb{E}_{x\sim q}[-\log\delta(x)]\\ &= D_{KL}(q\Vert p). \end{aligned}\]

它的缺点是单样本值可以为负。KL 的期望非负,但某个 token 上如果参考策略概率高于当前策略概率,就会出现负样本值;这会增加方差。

k2 来自二阶近似。考虑 $f$-divergence:

\[D_f(p,q) = \mathbb{E}_{x\sim q} \left[ f\left(\frac{p(x)}{q(x)}\right) \right]\]

当 $q$ 接近 $p$ 时,不同 $f$-divergence 的二阶项都由 Fisher information 控制。对参数化分布 $p_\theta$:

\[D_f(p_0,p_\theta) = \frac{f^{\prime\prime}(1)}{2}\theta^{T}F\theta+O(\theta^{3}),\]

其中 $F$ 是 Fisher information matrix。KL 散度对应 $f(x)=-\log x$,k2 对应的二阶曲率相同,因此当两个分布很接近时:

\[k_2(x)=\frac{1}{2}\left(\log\delta(x)\right)^2\]

可以作为 KL 的低方差近似。它有偏,不适合需要无偏 KL regularizer 的地方;但因为非负、平滑、实现简单,常用于 approximate KL 或 early stopping。

k3k1 上加入 control variate:

\[k_3(x)=k_1(x)+\delta(x)-1.\]

新增项期望为 0:

\[\begin{aligned} \mathbb{E}_{x\sim q}[\delta(x)-1] &= \int q(x) \left(\frac{p(x)}{q(x)} - 1\right) dx \\ &= \int p(x) dx - \int q(x) dx \\ &=0. \end{aligned}\]

因此 k3 仍然无偏估计 KL。同时,由凸性不等式 $x-1-\log x\ge0$ 可知:

\[k_3(x)\ge0.\]

它同时具备无偏和单样本非负两个性质,方差通常也低于 k1。当 KL 项直接作为 token-level objective regularizer 时,k3 更适合稳定训练。

梯度和算法选择

PPO/RLHF 的 shaped reward 常用 k1 形式。对 token $y_t$,常见 KL penalty 是:

\[\log\pi_\theta(y_t \mid s_t)-\log\pi_{ref}(y_t \mid s_t).\]

把当前策略视为采样分布 $q$、reference 视为 $p$,这个 penalty 对应 $-\log\delta$。它通常先作为 reward shaping 数值进入 GAE,actor 更新时通过固定的 advantage 和 PPO ratio 起作用;很多实现不会把这项作为独立 KL loss 直接反传。k1 的优势是形式简单,并且和 KL-penalized RLHF 目标直接对齐;代价是 token 级样本值可负、方差较高。

GRPO/DeepSeekMath 的 KL 项在 objective 中作为 token-level regularizer 出现,常用 k3

\[\frac{\pi_{ref}(y_t \mid s_t)}{\pi_\theta(y_t \mid s_t)} - \log\frac{\pi_{ref}(y_t \mid s_t)}{\pi_\theta(y_t \mid s_t)} -1.\]

这里 KL 不进入 group reward 标准化,也不生成 group advantage。k3 的非负性和低方差更适合放在 token loss 中持续约束策略漂移。

k2 更常见于近似 KL 监控或 early stopping。它在新旧策略很接近时很好用,但有偏;如果训练目标需要精确的 KL regularizer,通常优先选 k1k3

Probability identities

Chain rule of conditional probability

\[\begin{aligned} p(x \mid a) &= \sum_b p(x, b \mid a) \quad \text{law of total (cond) prob}\\ &= \sum_b p(x \mid b,a)p(b \mid a) \quad \text{Def of cond prob} \end{aligned}\]

Law of total expectation

\[\begin{aligned} \mathbb{E}_a[X \mid A=a]p(a) &= \sum_a \left[\sum_x p(x \mid a) x\right] p(a) \quad \text{Def of cond Exp}\\ &= \sum_x\sum_a p(x \mid a) p(a) x \\ &= \sum_x p(x) x \quad \text{law of total prob} \\ &= E[X] \end{aligned}\]

Law of total conditional expectation

\[\begin{aligned} \mathbb{E}[X \mid A=a] &= \sum_x x p(x \mid a) \\ &= \sum_x x\left[\sum_b p(x \mid b,a)p(b \mid a)\right] \quad \text{chain rule of cond prob} \\ &= \sum_b \left[\sum_x xp(x \mid b,a)\right] p(b \mid a) \\ &= \sum_b \mathbb{E}[X \mid A=a,B=b] p(b \mid a) \quad \text{Def of cond Exp} \end{aligned}\]



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Google Gemini updates: Flash 1.5, Gemma 2 and Project Astra
  • Displaying External Posts on Your al-folio Blog
  • From nano-vLLM to vLLM: Scheduler, Paged KV Cache, Prefill/Decode, Tensor Parallelism, and Sampling
  • Distributed Training for Large Models: Collectives, FSDP/ZeRO, DeviceMesh, and Multi-Dimensional Parallelism
  • Modern Attention for LLMs: KV Cache, RoPE, MLA, FlashAttention, Sparse/Linear Attention, and MoE