PPO(Proximal Policy Optimization) — 近端策略优化
Important
一、引言:从“会说话”到“说对话”——强化学习对齐的提出
1.1 大模型训练的三阶段
- 预训练(Pre-training) :在海量文本上学习“预测下一个词”,让模型获得语言能力和世界知识。这个阶段模型学会了“怎么说话”。
- 监督微调(SFT,Supervised Fine-Tuning) :在人工标注的“指令-答案”对上学习,让模型学会遵循指令、回答问题。这个阶段模型学会了“回答的格式”。
- 基于人类反馈的强化学习(RLHF,Reinforcement Learning from Human Feedback) :让模型在开放生成中学会符合人类复杂偏好(如有益、诚实、无害)的回应。
1.2 强化学习对齐提出背景
SFT的局限性在于:它本质上是“模仿学习” 。模型学得再好,也只能达到数据集中标注者的水平。它只知道“标准答案长什么样”,却不知道“什么样的回答更好”——尤其是在面对“哪个回答更有帮助?”“哪个回复更富有同情心?”这类涉及主观偏好和复杂权衡的问题时,SFT的损失函数只关心“和标准答案像不像”,对此无能为力。
更关键的是,互联网数据质量参差不齐,大模型在预训练中不可避免地接触了大量低质量甚至有害内容。如果不加干预,模型可能会生成虚构事实、偏见内容甚至有害信息。这正是对齐(Alignment)问题的核心:模型的能力与人类的意图和价值观(Alignment) 出现了偏差。
强化学习对齐正是在这个背景下应运而生。它引入 “奖励”信号 ——这个奖励可以来自一个训练好的奖励模型(学习人类偏好),也可以来自一套规则——让模型通过尝试不同的回答获得奖励反馈,学会最大化期望奖励。这就好比让学生从“死记硬背标准答案”变成了“理解评分标准并自由发挥”。
而PPO(Proximal Policy Optimization,近端策略优化) ,正是这个过程中最核心、最经典的策略优化算法。
二、PPO的核心思想
2.1 从策略梯度到PPO:为什么要“近端”?
- 策略梯度(Policy Gradient):这是强化学习中最朴素的优化思路,其核心公式——策略梯度定理——给出的优化方向是:
∇θJ(θ)=Eτ∼πθ[∑t=0T∇θlogπθ(at∣st)⋅Ψt]
其中 Ψt 可以是累积奖励、优势函数等。 这个公式在数学上是无偏的,但在实际使用中,我们通常只能通过采样来近似这个期望。由于采样数据的分布依赖于当前的策略 πθ,一旦策略发生更新,旧数据就不能再用了。这导致了On-Policy算法的低样本效率——每次更新都要重新与环境交互采样。
- 重要性采样(Importance Sampling):为了解决样本效率问题,研究者引入了重要性采样(Importance Sampling) ,使得我们可以用旧策略 πθold 采样的数据来估计新策略 πθ 的期望梯度:
∇θJ(θ)=Eτ∼πθold[πθold(at∣st)πθ(at∣st)∇θlogπθ(at∣st)⋅At]
这里 πθoldπθ 就是概率比(Probability Ratio),记作 rt(θ)。 重要性采样让我们能更高效地利用数据,但也引入了一个风险:如果 rt(θ) 过大(比如远大于1),说明新旧策略差异巨大,此时重要性采样的方差会急剧增大,导致估计严重失真。
-
PPO近端约束的动机:我们希望利用重要性采样带来的效率提升,但必须通过显式约束来抑制 rt(θ) 的剧烈波动。这个约束就是PPO中裁剪(Clipping)机制的设计原点。
-
从算法演进的角度看,PPO之前的TRPO(Trust Region Policy Optimization) 已经意识到了这个问题,它通过KL散度约束来严格限制更新步长,但TRPO需要计算二阶梯度(Fisher信息矩阵),计算开销极大。PPO的创新在于:用一种计算量极小的“裁剪”操作,近似实现了TRPO的信任域约束效果,使得算法既稳定又高效。
2.2 RLHF中的四大模型角色
在深入PPO的数学原理之前,需要先理解RLHF训练中同时存在的四个模型:
| 模型 | 功能定位 | 训练状态 | 核心作用 |
|---|---|---|---|
| Actor 策略网络 | 待优化主生成模型 | 可训练 (LoRA/全参) | 策略优化主体。接收逐Token状态,输出动作概率分布;通过裁剪机制在约束幅度内提升高奖励Token的生成概率,直接驱动模型向人类偏好调整。 |
| Critic 价值网络 | 状态价值估计器 | 可训练 (常共享主干) | 方差调控器。逐状态评估价值,生成基线以计算优势函数,显著降低策略梯度的估计方差,保障训练稳定性。 |
| Reward Model 奖励模型 | 人类偏好量化器 | 完全冻结 (仅前向) | 目标信号源头。输入完整生成轨迹,输出单一全局奖励分数,该分数注入后续优势估计,从根本上决定更新方向;不参与梯度回传。 |
| Reference 参考模型 | 分布约束基准 | 完全冻结 (固定SFT权重) | 遗忘防火墙。逐Token比较Actor与自身的输出分布差异,施加惩罚以约束Actor,防止过度优化奖励而牺牲语言流畅性和生成多样性。 |
这四个模型同时在显存中周转,这也是PPO训练资源消耗巨大的根源。
Tip在PPO训练的动态闭环中,Reward Model(RM)扮演着“人类意图的静态锚点”与“稀疏全局驱动力”的双重角色。
它本质上是一个在离线偏好数据上训练好的、参数完全冻结的判别式模型,其最核心的技术特征在于**“全局性”与“滞后性”** —— 它不参与逐Token的实时引导,而是在Actor完整走完一条生成轨迹(Prompt + 完整Response)后,才输出一个单一的、绝对的标量分数 r。这个分数是整条轨迹上唯一携带人类偏好信息的监督信号,直接决定了后续优势估计(GAE)中累积回报 R^t 的基准水平。
由于RM仅提供“最终结果好坏”的宏观评价,而无法告知“哪个中间Token导致了高分”,它必须依赖Critic网络在逐Token层面进行“信用分配”(将全局r拆解为每个时间步的优势值)。同时,RM的绝对分数若不经约束极易失控,因此它生成的奖励必须与Reference Model施加的逐Token KL惩罚(rfinal=rRM−β⋅KL)进行实时动态抵消,从而在“迎合人类偏好”与“保留原始语言能力”之间找到精细的平衡。正是这种“全局打分、冻结推理”的机制,使得RM成为RLHF中价值对齐的“北极星”,也是导致四模型同载时显存压力骤增(因RM体积常与Actor相当)的主要瓶颈之一。
2.3 PPO的核心目标函数
PPO的核心目标函数——即实际用于梯度更新的损失——实际上包含三个部分。理解这个完整目标函数的结构,是理解PPO如何同时兼顾“奖励追求”、“更新稳健”和“能力保持”三者的关键。
LPPO(θ)=−策略优化LCLIP(θ)+价值函数损失c1⋅LVF(θ)−熵奖励c2⋅S[πθ]其中,策略损失 LCLIP(θ) 是PPO最具标志性的部分:
LCLIP(θ)=E(st,at)[min(rt(θ)⋅At, clip(rt(θ),1−ϵ,1+ϵ)⋅At)]
逐一拆解这个公式的深层含义:
(1)概率比 rt(θ)
rt(θ)=πθold(at∣st)πθ(at∣st)
这是新策略(当前正在训练的模型)与旧策略(更新前的模型)在同样状态下采取同样动作的概率之比。如果 rt(θ)>1,说明新模型更倾向于生成这个回答;如果 rt(θ)<1,说明新模型不太愿意生成这个回答。
(2)优势函数 At
At=Q(st,at)−V(st)
优势函数衡量的是“当前这个动作相比平均水平好多少”。如果 At>0,说明这个回答比平均水平好,我们应该增加它的概率;如果 At<0,说明这个回答不如平均水平,应该降低它的概率。
基线(Baseline)通常由Critic网络(价值网络)估计,用于减少方差、稳定训练。
(3)裁剪机制 clip() 的深层设计逻辑
clip(rt(θ),1−ϵ,1+ϵ)
这是PPO最核心的创新点。ϵ 通常取0.1 ~ 0.3。
为了更直观地理解裁剪,分两种情况分析目标函数的形状:
-
当 At>0(好动作)时:我们想要最大化 rt(θ)⋅At,即希望增加该动作的概率。目标函数变为 min(rt(θ),1+ϵ)⋅At。这意味着当 rt(θ)>1+ϵ 时,梯度变为0,裁剪函数会“踩刹车”,强制停止在该方向上的推进。这种非对称的梯度截断,有效防止了策略因一次侥幸的高奖励而过度膨胀。
-
当 At<0(坏动作)时:我们想要最小化 rt(θ)⋅At(即降低概率),目标函数变为 max(rt(θ),1−ϵ)⋅At。当 rt(θ)<1−ϵ 时,梯度同样被截断,防止模型因为一次坏样本而过度惩罚某个动作,导致策略坍缩。
(4)min操作:保守更新
min(rt(θ)⋅At, clip(rt(θ),1−ϵ,1+ϵ)⋅At)
取两者的最小值,意味着PPO总是选择更保守的那个更新方向——这相当于给目标函数设置了一个上界 ,限制了单步更新的最大收益预期。这种“宁可少赚,不可激进”的设计哲学,是PPO在大模型训练中稳健性的根本保证。

(5)辅助项
除了策略裁剪损失,完整目标函数还包括两个辅助项:
-
价值函数损失 LVF(θ)=E[(Vθ(st)−Vttarget)2]:用于训练 Critic网络(价值网络),使其对状态价值的估计更准确。通常采用Huber损失或裁剪后的MSE损失来增强稳定性。
-
熵奖励 S[πθ]=E[−∑aπθ(a∣st)logπθ(a∣st)]:鼓励策略保持一定的探索性,防止模型过早地退化为确定性策略(输出坍缩到单一模式)。
2.4 KL散度约束
除了裁剪机制,PPO在实际RLHF实现中通常还会在奖励信号中直接加入KL惩罚项,而不是仅在损失函数中。这意味着奖励模型给出的原始得分会被修正为:
Rtotal(s,a)=RRM(s,a)−β⋅KL(πθ(⋅∣s)∣∣πref(⋅∣s))
其中 KL(πθ∣∣πref)=Ea∼πθ[logπref(a∣s)πθ(a∣s)]。β 是一个动态调整的超参数,控制约束的强度。

这种设计的精妙之处在于:它将约束直接作用于奖励信号层面,意味着模型在生成每个token时都会受到KL惩罚的影响,而非仅在最终更新时施加。这确保了模型在追求高奖励(对齐) 的同时,不会完全丢失SFT阶段学到的良好语言能力,实现了更细粒度的约束。
2.5 GAE优势估计
在实际实现中,PPO通常使用GAE(Generalized Advantage Estimation,广义优势估计) 来计算优势函数。GAE的核心是一个截断的λ-回报递归定义:
δt=rt+γV(st+1)−V(st)
AtGAE(γ,λ)=∑l=0∞(γλ)lδt+l
这个公式的物理含义是:GAE通过参数 λ 在时序差分(TD)估计(λ=0,低方差、高偏差)和蒙特卡洛估计(λ=1,高方差、无偏)之间进行平滑插值。在LLM对齐实践中,λ 通常取0.95~0.97,倾向于保留更多的蒙特卡洛信息,因为奖励模型给出的分数往往是对整个完整回答的全局评价,而非每个token的即时奖励。
三、PPO的训练流程
3.1 算法流程步骤
- 初始化:加载SFT模型作为Actor πθ 和Reference πref;初始化Critic网络 Vϕ 和奖励模型(RM)。
- 数据收集(Rollout Phase):对于每个迭代轮次,Actor根据一组prompt生成固定长度(如2048个token)的响应轨迹。同时,Critic计算每个token状态的价值 Vϕ(st)。
- 计算奖励(Reward Scoring Phase):利用RM对完整响应打分,并结合与 πref 的逐token KL散度计算最终奖励 rt。同时,使用GAE计算出每个token的优势 At 和目标价值 V^ttarget。
- 策略优化(Update Phase):将收集到的数据存入经验池。对经验池数据进行多次(如10-15次)随机采样,形成小批量进行梯度更新。
- 计算新的概率比 rt(θ)。
- 计算裁剪后的PPO目标函数 LCLIP。
- 计算价值损失 LVF。
- 反向传播更新Actor和Critic网络。
- 迭代:清空经验池,用更新后的策略进入下一轮收集。
3.2 核心伪代码
典型的PPO-based RLHF训练流程构成了一个迭代的经验收集与策略优化闭环。
1# ==================== 初始化阶段 ====================2actor = Actor(init_from="SFT_model") # 策略模型(待训练)3ref = Reference(init_from="SFT_model") # 参考模型(冻结)4critic = Critic(init_from="RM_value_head") # 价值网络(待训练)5rm = RewardModel(load="reward_model") # 奖励模型(冻结)6
7# 超参数配置8EPSILON = 0.2 # 裁剪范围9GAMMA = 1.0 # 折扣因子(LLM通常设为1,因为任务为episodic)10LAMBDA = 0.95 # GAE平滑系数11KL_BETA = 0.01 # KL惩罚系数12EPOCHS = 10 # 每批数据的复用轮数13BATCH_SIZE = 512 # 小批量大小14
15# ==================== 主训练循环 ====================16for iteration in range(total_iterations):17
18 # ---------- Step 1: 经验采样 (Rollout) ----------19 # 根据当前策略生成一批对话,收集完整轨迹20 trajectories = []21 for prompt in prompts_batch:22 # 自回归生成完整回答23 tokens, log_probs, values = actor.generate_with_values(prompt)24 # 计算参考模型下的log概率(用于KL计算)25 ref_log_probs = ref.compute_log_probs(tokens)26 # 奖励模型打分27 reward_score = rm.score(tokens)28 trajectories.append({29 "tokens": tokens,30 "log_probs": log_probs, # 旧策略下的log概率31 "ref_log_probs": ref_log_probs,32 "values": values, # 每个token位置的Critic估值33 "reward": reward_score # 最终奖励(稀疏)34 })35
36 # ---------- Step 2: 优势计算 (GAE) ----------37 for traj in trajectories:38 # 计算token级别的即时奖励:最终奖励 + KL惩罚(每个token)39 token_rewards = []40 kl_divs = traj["log_probs"] - traj["ref_log_probs"]41 for t in range(len(traj["tokens"])):42 # 仅在最后一个token处获得RM得分,其余位置为043 r = KL_BETA * kl_divs[t] # 每个token施加KL惩罚44 if t == len(traj["tokens"]) - 1:45 r += traj["reward"] # 最终奖励施加在最后一个token上46 token_rewards.append(r)47
48 # 计算GAE优势 (反向递推)49 advantages = []50 gae = 0.051 for t in reversed(range(len(token_rewards))):52 # 注意:LLM中GAMMA通常为1,不进行折扣53 delta = token_rewards[t] + GAMMA * traj["values"][t+1] - traj["values"][t] if t+1 < len(traj["values"]) else token_rewards[t] - traj["values"][t]54 gae = delta + GAMMA * LAMBDA * gae55 advantages.insert(0, gae)56
57 traj["advantages"] = advantages58 traj["returns"] = [adv + val for adv, val in zip(advantages, traj["values"])]59
60 # ---------- Step 3: 策略更新 (多个epoch) ----------61 # 将所有轨迹拼接为一个大数据集62 dataset = flatten(trajectories)63
64 for epoch in range(EPOCHS):65 # 随机打乱并分批次更新66 for batch in sample_batches(dataset, BATCH_SIZE):67 # 计算当前策略下的概率比 r_t(θ)68 new_log_probs = actor.compute_log_probs(batch["tokens"])69 ratio = torch.exp(new_log_probs - batch["log_probs"])70
71 # ---------- 策略损失 (Clipped Surrogate Objective) ----------72 adv = batch["advantages"]73 # 正向/反向裁剪74 surr1 = ratio * adv75 surr2 = torch.clamp(ratio, 1 - EPSILON, 1 + EPSILON) * adv76 policy_loss = -torch.min(surr1, surr2).mean() # 负号因为要梯度上升77
78 # ---------- 价值损失 (Value Function Loss) ----------79 # 使用裁剪后的value目标,防止价值网络更新过激80 value_pred = critic(batch["states"])81 value_clipped = batch["values"] + torch.clamp(value_pred - batch["values"], -EPSILON, EPSILON)82 vf_loss1 = (value_pred - batch["returns"]) ** 283 vf_loss2 = (value_clipped - batch["returns"]) ** 284 value_loss = 0.5 * torch.max(vf_loss1, vf_loss2).mean()85
86 # ---------- 熵奖励 (Entropy Bonus) ----------87 entropy = actor.compute_entropy(batch["states"]).mean()88 entropy_loss = -entropy # 最大化熵 = 最小化 -熵89
90 # ---------- 总损失 ----------91 loss = policy_loss + 0.5 * value_loss + 0.01 * entropy_loss92
93 # 梯度更新94 optimizer.zero_grad()95 loss.backward()96 # 梯度裁剪 (防止梯度爆炸)97 torch.nn.utils.clip_grad_norm_(actor.parameters(), max_norm=1.0)98 optimizer.step()99
100 # ---------- Step 4: 迭代结束,旧策略更新为新策略 ----------101 # 下一轮迭代中,actor即为当前的最新策略,用于采样要点总结:
- 经验收集(Rollout) 和 参数更新(Update) 是严格分离的两个阶段,这正是PPO作为Off-Policy(但基于重要性采样的近似On-Policy) 算法的体现。
- 价值网络的更新采用了与策略网络类似的裁剪机制,这并非原论文的标准形式,而是后续实现中证实有效的工程改进,可以显著提升Critic训练的稳定性。
- 多个Epoch的重复利用是PPO样本效率的核心来源。但需要注意的是,过高的EPOCHS值会导致分布漂移过大,从而使重要性采样失效。实践中通常取10~15轮。
四、PPO的适用场景、优势与局限、演进方向
4.1 适应场景
- 初始模型质量较高的场景:PPO需要在一个已经经过充分SFT的模型基础上进行优化。如果SFT模型本身质量不佳,PPO容易陷入“低质量区域”的局部最优。
- 需要精细控制策略更新的任务:如对话系统的安全性强化、内容生成偏好控制等。PPO的信任域约束使其能精准控制优化幅度。
- 模型规模较大的场景:通常适合 >70B 参数的大模型,某云厂商的千亿参数模型训练显示,PPO可使有害内容生成率降低82%。
- 已有奖励模型或可获取大量用户反馈的场景:如推荐系统、客服对话优化等。PPO能够高效利用这些偏好信号。
- 追求理论完备性和收敛性保证的场景:PPO有严格的数学证明支撑,在连续动作空间任务中也有良好表现。
4.2 核心优势
| 优势 | 说明 |
|---|---|
| 理论完备 | 有严格的收敛性证明,且与TRPO的信任域理论一脉相承 |
| 训练稳定 | 裁剪机制+KL约束防止策略崩溃,适用于大模型微调 |
| 样本效率高 | 支持多轮epoch重复利用数据,比传统On-Policy算法效率高数倍 |
| 实现简洁 | 相比TRPO无需计算二阶梯度,工程实现友好 |
| 灵活性高 | 支持离散/连续动作空间,可适配多种奖励模型架构 |
4.3 核心局限
| 局限 | 说明 |
|---|---|
| 资源消耗巨大 | 需同时维护Actor/Critic/Reward/Reference四个大模型,GPU显存压力极大 |
| 超参数敏感 | ϵ、β、λ、学习率等需精细调优,不同规模模型的最佳配置差异显著 |
| Critic网络训练困难 | 价值函数估计误差会传导至策略更新,大模型场景下Critic容易过拟合,且价值网络与策略网络共享参数时存在优化冲突 |
| 奖励模型质量决定上限 | 如果奖励模型本身不能准确反映人类偏好,PPO的效果将大打折扣——所谓”Garbage in, garbage out” |
| 训练不稳定风险 | 尽管已有改进,PPO仍可能出现奖励震荡(Reward Spiking)、熵崩溃(Entropy Collapse)、策略发散等问题,需要大量工程trick来稳定 |
4.4 演进方向
- 问题一:Critic网络成为瓶颈。 PPO需要同时训练Actor和Critic两个网络,Critic的价值估计误差会直接影响策略更新的质量。而价值网络在大规模语言模型上的训练本身就极其困难,容易过拟合。这催生了GRPO(Group Relative Policy Optimization)——由DeepSeek提出,通过组内相对优势估计替代绝对价值估计,完全去除了Critic网络,显著降低了显存占用和训练复杂度。
- 问题二:奖励模型的标定问题。 传统RLHF依赖Bradley-Terry模型将成对偏好转化为标量奖励,但这种奖励在不同prompt之间缺乏标定——同样的分数在不同语境下意义不同。这催生了Pairwise PPO(P3O)和统一配对框架(Unified Pairwise Framework)——直接在成对比较上操作,绕过标量奖励近似的局限,实现了更精确的偏好建模。
- 问题三:训练效率低下。 四个大模型的顺序执行导致大量GPU资源闲置,Actor生成样本时Critic和RM等模型处于空闲状态。这催生了OPPO(Pipeline Overlap PPO)——通过流水线重叠技术将训练和推理阶段并行化,实现了1.8倍的端到端训练加速。
- 问题四:KL约束的动态调整。 固定系数的KL惩罚无法适应训练过程中策略漂移的非平稳性。自适应KL控制(Adaptive KL Control)技术通过实时监控KL散度并动态调整β系数,已成为现代RLHF工程实践的标准配置。
NotePPO之所以能成为大模型强化学习对齐的基石,核心在于它回答了一个根本问题:如何在追求目标(最大化奖励)的同时,确保过程是稳定和可控的?
它通过两个精妙的设计回答了这个问题:
- 裁剪机制:在数学层面限制了策略更新的最大幅度,防止重要性采样的方差爆炸
- KL散度约束:在语义层面确保模型不会“忘本”,维持生成质量的下限
这两个机制共同构成了PPO的“信任域”,让大模型能够在“保持自我”的前提下,稳步地向人类偏好方向进化。
从ChatGPT到GPT-4,从Claude到各类开源对话模型,PPO都是其实现与人类价值观对齐的核心技术基石。理解PPO,不仅需要看懂它的公式,更需要理解它的设计动机——为什么需要裁剪?为什么需要KL约束?为什么需要GAE?这些问题背后的答案,共同构成了现代大模型“从会说话到说对话”这一蜕变的核心密码。
Some information may be outdated
