Skip to content

典型策略提升方法:TRPO+PPO+DPO+GRPO

📅 发表于 2025/09/01
🔄 更新于 2026/08/05
👁️ — 次访问
📝 12679 字
39 分钟
rl-theory
#重要性采样
#重要性采样策略梯度
#KL约束
#信任区域
#GAE
#n步优势估计
#TRPO
#PPO
#优势策略梯度
#PPO-Clip
#PPO-Penalty
#Reward Model
#Pairwise loss
#KL负奖励
#Critic学习目标
#Critic Loss
#TD Error
#Critic Value Clip
#踩坑经验
#DPO
#标准RLHF目标
#DPO显示最优解
#DPO Loss
#DPO缺点
#GRPO
#相对组优势

必备知识

重要性采样

基本概念

重要性采样

问题定义

  • 函数f(x),需从分布p(x)中采样,来计算期望值
  • 但现在很难从p(x)中采样

方法

  • 从另一个分布q(x)中采样(容易),间接达到从p(x)中采样的效果(困难)
Exp(x)[f(x)]=p(x)f(x) dx=q(x)p(x)q(x)f(x) dx=Exq(x)[p(x)q(x)f(x)]
  • 总结
Exp[f(x)]=Exq[p(x)q(x)f(x)]=1Nip(xi)q(xi)f(xi)

重要性权重

  • p(x)q(x)用来修正采样的偏差,即两个分布之间的差异

IS是特殊MC采样

  • 重要性采样也是一种特殊的MC采样
  • 允许从简单分布采样避免直接从困难分布采样的问题。

重要性采样的缺点

重要性采样缺点

方差大

  • q(x)p(x)差异大时方差很大,尽管期望相同。

依赖足够多的采样

  • 当q和p差异大时,需通过足够多的采样抵消差异对期望的影响
    • 如果采样次数不够多期望会有很大差异
      • Exp[f(x)]Exq[p(x)q(x)f(x)]有很大差异
    • 比如下图
      • Exp[f(x)]本身是负的
      • 但由于q和p差异大大部分q都只能采样到正的,导致期望不对
    • 需足够多的采样才能采到左边点,并给与其大权重,才能保证期望一致

采样具有随机性

  • 采样具有随机性,如果突然采样到方差大的样本,可能朝着错误方向更新
分布差异大、采样数量不够多怎么办?

核心思想

  • 增加约束信任条件

TRPO KL约束

  • KL约束(TRPO):πθπθold相似性 作为J(πθ)约束条件信任区域

PPO CLIP

  • CLIP(PPO):把相似性约束条件直接放回到目标函数J(πθ)中。

重要性采样在RL中的作用

重要性采样在RL中的作用

核心作用

  • 可实现off-policy,从而降低RL采样成本,解决采样效率问题,提升训练效率。
    • on-policy:采样策略和学习策略相同
      • 即产出数据的策略和用这批数据做更新的策略是同1个。
  • 更加谨慎地更新模型

使用方法

  • πold开始,πold和环境交互,得到一批回合数据
  • 把这批回合数据 重复使用k次去更新模型( off-policy过程)
    • 第1次,喂给:πoldπθ1
    • 第2次,喂给:πθ1πθ2
    • ...
    • 第k次,喂给:πθk1πθk
    • k次更新后πold=πθk

策略梯度发生变化

  • 原始策略梯度
J(θ)=E(st,at)πθ[Aπθ(st,at)alogpθ(atst)a]
  • 引入重要性采样后的梯度:τπθold训练数据是从旧策略采样出来的
J(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)alogpθ(atst)a]
  • 重要性权重

    rt(θ)=πθ(atst)πθold(atst)=πθ(ytx,y<t)πθold(ytx,y<t)ri,t(θ)=πθ(yi,tx,yi,<t)πθold(yi,tx,yi,<t)
  • 目标函数

argmaxπθJ(πθ)=Eτπold[πθ(atst)πθold(atst)AtGAE(γ,λ)(st,at)]

重要性采样策略梯度推导

策略梯度推导过程

重要性采样策略梯度推导

从定义到期望形式

J(θ)=τR(τ)pθ(τ)=τR(τ)pθ(τ)logpθ(τ)=Eτpθ(τ)[R(τ)logpθ(τ)]

转换成优势策略梯度

J(θ)=Eτpθ(τ)[R(τ)logpθ(τ)]=E(st,at)πθ[A(st,at)logπθ(atst)]

代入重要性采样

  • 推导过程
J(θ)=E(st,at)πθold[pθ(atst)pθold(atst)A(st,at)logpθ(atst)]=E(st,at)πθold[Aθold(st,at)pθ(atst)pθold(atst)1pθ(atst)pθ(atst)]=E(st,at)pθold[Aθold(st,at)1pθold(atst)pθ(atst)]=E(st,at)pθold[Aθold(st,at)pθ(atst)pθold(atst)]1Nn=1Nt=1TnAθold(st,at)pθ(atst)pθold(atst)
  • 推导结果
J(θ)1Nn=1Nt=1TnAθold(st,at)pθ(atst)pθold(atst)

除以旧策略概率的作用 pθ(atst)pθold(atst)

  • 1pθold(atst):为了加权梯度pθ(atst)
    • 初期:模型不自信,预测概率较小,加权大,
    • 模型自信后:就不怎么加权了。
  • 如果旧策略当前策略梯度 冲突较大,会造成过度优化训不动
  • PPO-CLIP信任域 可解

重要性采样和KL散度的区别

重要性权重 vs KL 散度

KL 散度

  • KL散度笔记

    • 第1个参数q:分子,真实分布参考分布旧策略,从分子采样
    • 第2个参数p:分母,近似分布模型分布新策略
    DKL(q||p)=Exq(x)[logq(x)p(x)]=xq(x)q(x)logq(x)p(x)=xq(x)logπold(oi,t|q,oi,<t)πθ(oi,t|q,oi,<t)Eπold[logπoldπθ]
  • 两种情况

    • 旧策略/当前策略旧策略 看作真实分布
    • ref策略/当前策略, ref策略 看作真实分布
  • KL值变大的含义

    • πold 认为概率高,但πθ认为概率低,模型发生巨大变化πθ看旧数据,令其惊讶。
    logπoldπθπold,πθ
  • KL 作用

    • 衡量2个分布之间的差异衡量距离,判断off-policy 数据 是否已到 需丢弃的程度

IS 权重

  • 衡量新旧策略更新幅度,自然是用 当前策略/旧策略,用于修正梯度ri,t(θ)=πθ(oi,t|q,oi,<t)πold(oi,t|q,oi,<t)

广义优势估计

TD(λ) 简介

TD(λ)

背景

  • MC:无偏估计低偏差高方差TD:有偏估计高偏差低方差
  • A2C引入优势函数缓解了方差但TD存在高偏差。需要平衡方差和偏差。

TD(λ)

  • 一个n步回报Gt:t+n采样n步再做自举估计
Gt:t+n=rt+1+γrt+2+γ2rt+3++γn1rt+n+γnV(st+n)
  • 多个n步回报估计量进行加权平均λ, 平衡了TD偏差和MC方差
    • λ接近1,接近MC估计,偏差小、方差大。
    • λ接近0,接近单步TD,偏差大、方差小。
  • Gtλ 定义
Gt:Tλ=(1λ)n=1Tt1λn1Gt:t+n+λTt1GtGtλ=(1λ)n=1λn1Gt:t+nV(st)V(st)+α(Gt:t+nV(st))V(st)V(st)+α((1λ)n=1λn1Gt:t+nλn,V(st))

GAE n步优势估计

GAE n步优势估计

1. 朴素 TD Error 定义

  • 时刻t、步长为1、步长为2TD Error定义
    • 注意:t时刻的即时奖励下标为t,这里rt和 前面文章 rt+1其实一样的
δt=rt+γV(st+1)V(st)δt+1=rt+1+γV(st+2)V(st+1)
  • 时刻t、步长为lTD Error 定义
δt+l=rt+l+γV(st+l+1)V(st+l)

2. n步优势估计 定义

At(1)=Gt:t+1V(st)=rt+γV(st+1)V(st)At(2)=Gt:t+2V(st)=rt+γrt+1+γ2V(st+2)V(st)At(3)=Gt:t+3V(st)=rt+γrt+1+γ2rt+2+γ3V(st+3)V(st)At(n)=Gt:t+nV(st)=rt+γrt+1+γ2rt+2+γnV(st+n)V(st)At()=Gt:t+V(st)=rt+γrt+1+γ2rt+2+γTrT+0+0+V(st)
  • n步优势估计 定义公式
    • 步长 n=
At()=Gt:t+V(st)=l=0γlrt+lV(st)

3. n步优势估计 迭代计算公式

  • 推导 At(2)
At(2)=rt+γrt+1+γ2V(st+2)V(st)=(rt+γV(st+1)V(st))+(γrt+1+γ2V(st+2)γV(st+1))=δt+γδt+1
  • n步优势估计 迭代计算公式

    • 步长2、3、4
    At(2)=δt+γδt+1At(3)=δt+γδt+1+γ2δt+2At(4)=δt+γδt+1+γ2δt+2+γ3δt+3
    • 步长为n
At(n)=l=0n1γlδt+lAt()=l=0γlδt+l

4. 总结 n步优势 定义及计算公式

At()=Gt:t+V(st)=l=0γlrt+lV(st)=l=0γlδt+lAt(n)=Gt:t+nV(st)=l=0n1γlrt+lV(st)=l=0n1γlδt+l

GAE 多个n步优势估计做加权平均

GAE 多个n步估计做加权

0. 背景

1. GAE 定义公式

  • 多个n步优势估计量,进行加权平均(步数从1到n到无穷),引入λ做方差、偏差平衡
AtGAE(γ,λ)(st,at)=(1λ)(λ0At(1)+λAt(2)+λ2At(3)+)AtGAE(γ,λ)(st,at)=(1λ)(λ0δt+λ(δt+γδt+1)+λ2(δt+γδt+1+γ2δt+2)+)

2. GAE 推导过程

AtGAE(γ,λ)(st,at)=(1λ)(λ0At(1)+λAt(2)+λ2At(3)+)=(1λ)(δt+λ(δt+γδt+1)+λ2(δt+γδt+1+γ2δt+2)+)=(1λ)(δt(1+λ+λ2+)+γδt+1(λ+λ2+)+γ2δt+2(λ2+λ3+)+)=(1λ)(δt11λ+γδt+1λ1λ+γ2δt+2λ21λ+)=δt+γλδt+1+γ2λ2δt+2+γ3λ3δt+3+=l=0(γλ)lδt+l=l=0(γλ)l(rt+l+γV(st+l+1)V(st+l))

3. GAE 推导结果

AtGAE(γ,λ)(st,at)=l=0(γλ)lδt+lAtGAE(γ,λ)(st,at)=l=0(γλ)l(rt+l+γV(st+l+1)V(st+l))AtGAE(γ,λ)(st,at)=l=0Tt1(γλ)l(rt+l+γV(st+l+1)V(st+l))

4. GAE估计 vs 单个n步估计

  • n步优势估计:采样n步,估计优势
At(n)=l=0n1(γ)lδt+l
  • GAE 优势估计:多个n步优势估计加权求平均A^tGAE=l=0Tt1(λγ)lδt+l

4. GAE 反向递推公式

  • 最后一个时间步开始反向遍历提高GAE计算效率
AtGAE(st,at)=δt+γλAt+1GAE(st+1,at+1)

5. λ=0时,退化单步TD估计

  • 高偏差低方差
AtGAE(γ,0)(st,at)=(10)(λ0At(1)+0At(2)+02At(3)+)AtGAE(γ,0)(st,at)=At(1)=Gt:t+1V(st)=rt+γV(st+1)V(st)AtGAE(γ,0)(st,at)=rt+γV(st+1)V(st)

6. λ=1时,退化完全MC采样估计

  • 低偏差高方差
AtGAE(γ,1)(st,at)=l=0γl(rt+l+γV(st+l+1)V(st+l))=(rt+γV(st+1)V(st))+γ(rt+1+γV(st+2)V(st+1))+γ2(rt+2+γV(st+3)V(st+2))+=rt+γrt+1+γ2rt+2++γnrt+n+V(st)=l=0γlrt+lV(st)=Gt:t+V(st)=At()(st,at)AtGAE(γ,1)(st,at)=rt+γrt+1+γ2rt+2++γnrt+n+V(st)

GAE中的奖励衰减(LLM)

奖励衰减

背景

  • 在LLM任务中
    • 对最后token,仅rT=rEOS0
    • 对前面的token,环境奖励rt=0均为0RM即时奖励

TD Error

  • 对中间步t<T

    δt=0+V(st+1)V(st)=V(st+1)V(st)
  • 对于最后一步t=T

δT=rT+V(sT+1)V(sT)=rTV(sT)

GAE 优势估计

  • 推导过程
A^t=l=0Tt(λγ)lδt+l=δt+(λγ)1δt+1+(λγ)2δt+2++(λγ)Tt1δT1+(λγ)TtδT=(λγ)Tt(rTV(sT))+(V(st+1)V(st))+(λγ)1(V(st+2)V(st+1))+(λγ)2(V(st+3)V(st+2))++(λγ)Tt1(V(sT)V(sT1))=(λγ)TtrT+(一堆只包含V(s)的项)
  • 推导结果
A^t=(λγ)TtrT+(一堆只包含V(s)的项)
  • λ=1,γ=1时,退回MC估计
A^t=rTV(st)

奖励衰减

  • 从公式可看出,真实外部奖励信号 rT 传播回第t个token时,会乘以权重 (λγ)Tt(λ)Tt
  • λ<1 且 T-t 很大
    • 前面token收不到任何有效奖励信号
    • 价值模型就无法学习到它们真正的贡献

λ=1 vs λ<1

  • λ<1
    • 传统RL任务,每一步都有奖励方差很大, 使用λ<1来降低方差,很有效
    • LLM任务奖励稀疏Vtarget 依赖自己自举
      • 如果一开始估计不准,就会导致错上加错训练不稳定
      • 带来的偏差危害(奖励信号衰减) 远远大于在降方差方面的好处。
  • λ=1
    • MC无偏估计Vtarget依赖环境奖励
    • 价值模型学习变成简单的监督学习非常稳定的梯度下降过程。

GAE 方差公式

GAE 方差公式

基础方差公式

Var[aX]=a2Var(X)Var[X+Y]=Var[X]+Var[Y]+2Cov(X,Y)

GAE 方差推导

A^tλ=λ0δt+λ1δt+1+λ2δt+2++λTt1δT1Var(A^tλ)=Var[l=0Tt1λlδt+l]=l=0Tt1λ2lVar[δt+l]+2i=0Tt1j=i+1Tt1λi+jCov(δt+i,δt+j)
  • 方差:由每一项自身方差项与项之间的协方差共同决定。
  • 减小λ会给这些项,更小的权重(尤其是后面的项),从而降低总方差

GAE 总结

GAE 总结

1. 时刻t、步长为lTD Error 定义

δt+l=rt+l+γV(st+l+1)V(st+l)

2. n步优势估计定义

At(n)=Gt:t+nV(st)=l=0n1γlrt+lV(st)=l=0n1γlδt+l

3. GAE定义

  • 对多个n步优势加权平均
AtGAE(γ,λ)(st,at)=(1λ)(λ0At(1)+λAt(2)+λ2At(3)+)AtGAE(γ,λ)(st,at)=(1λ)(λ0δt+λ(δt+γδt+1)+λ2(δt+γδt+1+γ2δt+2)+)

4. GAE 计算推导结果

AtGAE(γ,λ)(st,at)=l=0(γλ)lδt+lAtGAE(γ,λ)(st,at)=l=0(γλ)l(rt+l+γV(st+l+1)V(st+l))

5. GAE 反向递推公式 (实际代码计算用此公式)

AtGAE(st,at)=δt+γλAt+1GAE(st+1,at+1)

6. λ=0/1

  • λ=0时,GAE退化为单步TD估计
AtGAE(γ,0)(st,at)=rt+γV(st+1)V(st)
  • λ=1时,GAE退化完全MC采样
AtGAE(γ,1)(st,at)=rt+γrt+1+γ2rt+2++γnrt+n+V(st)
  • TD(λ)/TD(0)/TD(1)
    • λ越小偏差越大、方差越小 (TD)
    • λ越大偏差越小、方差越大 (MC)

GAE 作用

GAE 作用

优点/作用

  • 平衡单步优势估计中的MC-高方差TD-高偏差

RL 优化目标

J(θ)=1Nn=1Nt=0TnΨtlogpθ(atnstn)a
  • 引入GAE后的策略梯度
J(θ)=1Nn=1Nt=0TnAtGAE(γ,λ)(st,at)GAElogpθ(atnstn)a
  • 引入GAE + 重要性采样后的策略梯度
J(θ)=1Nn=1Nt=0Tnπθ(atst)πθold(atst)AtGAE(γ,λ)(st,at)GAElogpθ(atnstn)a
  • 优化目标
argmaxπθJ(πθ)=Eτπold[πθ(atst)πθold(atst)AtGAE(γ,λ)(st,at)]

GAE 实现代码

python
@register_adv_est(AdvantageEstimator.GAE) 
def compute_gae_advantage_return(
    token_level_rewards: torch.Tensor,
    values: torch.Tensor,
    response_mask: torch.Tensor,
    gamma: torch.Tensor,
    lam: torch.Tensor,
):
    """Adapted from https://github.com/huggingface/trl/blob/main/trl/trainer/ppo_trainer.py

    Args:
        token_level_rewards: `(torch.Tensor)`
            shape is (bs, response_length)
        values: `(torch.Tensor)`
            shape is (bs, response_length)
        response_mask: `(torch.Tensor)`
            shape is (bs, response_length). [EOS] mask. The token after [EOS] have mask zero.
        gamma is `(float)`
            discounted factor used in RL
        lam: `(float)`
            lambda value when computing Generalized Advantage Estimation (https://arxiv.org/abs/1506.02438)

    Returns:
        advantages: `(torch.Tensor)`
            shape: (bs, response_length)
        Returns: `(torch.Tensor)`
            shape: (bs, response_length)

    """
    with torch.no_grad():
        nextvalues = 0
        lastgaelam = 0
        advantages_reversed = []
        gen_len = token_level_rewards.shape[-1]

        for t in reversed(range(gen_len)):
            delta = token_level_rewards[:, t] + gamma * nextvalues - values[:, t]
            lastgaelam_ = delta + gamma * lam * lastgaelam

            # skip values and TD-error on observation tokens
            nextvalues = values[:, t] * response_mask[:, t] + (1 - response_mask[:, t]) * nextvalues
            lastgaelam = lastgaelam_ * response_mask[:, t] + (1 - response_mask[:, t]) * lastgaelam

            advantages_reversed.append(lastgaelam)
        advantages = torch.stack(advantages_reversed[::-1], dim=1)

        returns = advantages + values
        advantages = verl_F.masked_whiten(advantages, response_mask)
    return advantages, returns

TRPO

Trust region policy optimization

ActorCritic 缺点

ActorCritic思想

Actor-Critic 核心思想

  • 目标:找到θ=argmaxθJ(θ)沿θJ(θ)方向迭代更新策略参数
J(θ)=Es0[Vπθ(s0)]=Eπθ[t=0γtr(st,at)]J(θ)=1Nn=1Nt=0Tn(rtn+γVπ(st+1n)Vπ(stn)),logpθ(atnstn)a
  • 参数更新
θθ+αJ(θ)

Actor-Critic缺点

Actor-Critic 缺点

存在步长选择困难症

  • 学习率太大:导致策略更新幅度太大,可能使策略性能下降,甚至崩溃。
  • 学习率太小:导致策略更新速度太慢训练效率低下
  • 虽然简单直观,但训练不稳定
  • 解法:KL 约束

每次梯度更新都需对πθ做若干回合采样

  • 采样效率低训练过程比较慢
  • 采样具有随机性,可能偶然采样到方差大的样本;如果直接信任,可能朝着错误方向更新
  • 解法:重要性采样
    • 降低采样成本,提升训练效率
    • 同时更加谨慎的更新模型
  • 重要性采样需要两个分布差异不能太大
    • πθπold分布差异较大 且 采样轨迹数量不够大时J(θ)的估计不准
    • 解法:KL约束

TD Error 估计优势函数是有偏的

TRPO 提出背景
  • 解决步长选择困难症
    • 通过引入约束或限制,确保每次策略更新不会太大
    • 避免策略崩溃,且保证策略能持续提升
  • 引入GAE 平衡偏差和方差
  • 使用重要性采样 解决错误方向问题

信任区域

信任区域

信任区域作用理解

  • 策略空间中,策略的近似线性模型能够比较准确预测策略性能

    • 信任区域,可以信任策略梯度,进行策略更新
    • 离开信任区域,需重新评估策略性能,并调整更新方向
  • 解决重要性采样需要两个分布接近的缺点

    • πθπold 分布差异较大采样轨迹数量不够大时,对J(θ)估计不准
    • 使用信任区域做限制
  • 信任区域悟空给唐僧画的安全区

    • 在圈内,活动是绝对安全的。
    • 若要移动,需重新画圈圈确保每一步走的安全、稳健

信任区域定义 (KL约束条件)

  • 其实是定义了一个KL约束,策略空间中的一个KL球

  • 保证新策略不会偏离旧策略太远,从而保证策略的单调提升

    maxθ Lθk(θ),s.t.  Estρπθk[DKL(πθk(s),  πθ(s))]δ

目标函数理解 maxθ Lθk(θ)

  • 通过调整策略参数θ使目标最大化
    • θ:正在优化的新策略,是需要寻找的参数
    • θk:旧策略、已知的策略参数,第k次迭代
  • L 目标函数,代理优势函数,衡量了新策略πθ比旧策略πθk有多好
    • L 通过重要性采样计算,利用旧策略 πθk采样的数据,来评估新策略 πθ的表现
    • L > 0:说明新策略比旧策略好

约束条件理解

Estρπθk[DKL(πθk(s),  πθ(s))]δ
  • KL 散度 :衡量两个概率分布的差异
    • DKL(πθk,πθ)=0:两个策略在状态s下完全一样
    • DKL(πθk,πθ) 越大,说明新策略比旧策略变化越大
  • 所有状态st上的平均KL散度Estρπθkδ
    • 平均差异不能太大限制在半径为δ的小范围/信任区域
      • 如0.01,信赖域大小
    • stρπθk状态访问分布,访问各状态的概率是多少。
      • 根据旧策略访问这些状态的频率分布ρπθk来加权,关注重要状态的策略变化

策略目标

TRPO 策略目标
JTRPO(πθ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)],  KL(πold,πθ)δ
TRPO 策略目标推导过程

核心目标

  • 期望借助当前θ找到一个更优θ,使得J(θ)J(θ)

    • θθ旧策略新策略
    • θkθ旧策略新策略。两种符号表示。
  • 只要找到一个新策略,使EstvπθEaπθ(st)[Aπθ(st,at)]0,就能保证策略性能单调递增,推导过程见下文

J(θ)J(θ)=11λEstρπθEaπθ(st)[Aπθ(st,at)]Aπθ(st,at)=r(st,at)+γVπθ(st+1)Vπθ(st)

难点

  • 直接求解该式非常困难 Estρπθπθ需要求解的新策略
    • 既用新策略收集样本数据,把所有可能的新策略都拿来收集数据
    • 然后判断哪个新策略符合上述条件,显然是不现实的
  • 解法:直接使用旧策略πθ状态分布
    • 新旧策略接近时状态访问分布变化小近似是合理的
EstρπθEstρπθ

目标优化

  • 直接采用旧策略πθ的状态分布,忽略两个策略的状态访问分布
Lθ(θ)=J(θ)+11λEstρπθEaπθ(st)[Aπθ(st,at)]
  • 动作仍用新策略采样得到,用重要性采样做处理。
    • 这样就能基于旧策略πθ 采样出的数据来估计并优化 新策略πθ
Lθ(θ)=J(θ)+EstρπθEaπθ(st)[πθ(as)πθ(as)Aπθ(st,at)]

KL 约束 (上文信任域空间)

  • 增加KL约束保证新旧策略足够近
maxθ Lθ(θ),s.t.  Estvπθk[DKL(πθk(s),  πθ(s))]δ
  • 信任区域:不等式约束定义了策略空间中的一个KL球
  • 在信任区域中
    • 学习策略和环境交互的状态分布,与上一轮策略最后采样的状态分布一致
    • 可以基于一步行动的重要性采样使当前学习策略稳定提升

信任区域示意图:左侧无信任区域,梯度更新可能导致性能骤降;右侧有信任区域,每次梯度更新都能带来稳定提升。

目标推导过程

J(θ) 另一种形式

J(θ)=Es0[Vπθ(s0)]=Eπθ[t=0γtVπθ(st)t=1γtVπθ(st)]=Eπθ[t=0γt(γVπθ(st+1)Vπθ(st))]

J(θ)J(θ)推导过程

J(θ)J(θ)=Es0[Vπθ(s0)]Es0[Vπθ(s0)]=Eπθ[t=0γtr(st,at)]+Eπθ[t=0γt(γVπθ(st+1)Vπθ(st))]=Eπθ[t=0γt(r(st,at)+γVπθ(st+1)Vπθ(st))]=Eπθ[t=0γtAπθ(st,at)]=t=0γtEstvπθEaπθ(st)[Aπθ(st,at)]=11λEstvπθEaπθ(st)[Aπθ(st,at)]

广义优势估计

GAE 笔记

GAE
  • 对不同TD步数的优势估计进行指数加权平均,平衡方差和偏差
δt+l=rt+l+γV(st+l+1)V(st+l)AtGAE(γ,λ)(st,at)=l=0(γλ)lδt+lAtGAE(γ,λ)(st,at)=l=0(γλ)l(rt+l+γV(st+l+1)V(st+l))
python
def compute_advantage(gamma, lmbda, td_delta):
    td_delta = td_delta.detach().numpy()
    advantage_list = []
    advantage = 0.0
    for delta in td_delta[::-1]:
        advantage = gamma * lmbda * advantage + delta
        advantage_list.append(advantage)
    advantage_list.reverse()
    return torch.tensor(advantage_list, dtype=torch.float)

PPO

核心思想

PPO 背景

背景

  • TRPO计算复杂, 每步更新运算量非常大
  • PPO基于TRPO思想,但实现更简单。能学的一样好、甚至更快。
PPO核心思想

1.引入GAE

  • 解决单步优势方差-偏差平衡问题

2.引入重要性采样

  • 使用重要性权重 修正分布差异
  • 达成可使用off-Policy提高采样效率解决效率问题

3.引入Clip或Penalty

  • 解决采样方差大& 重要性采样分布差异大+采样数量不足面临的问题
  • 使用Clip或Penalty 增强训练稳定性
  • πθπθold相似性 作为J(πθ)约束条件
    • TRPO:用KL约束做一个信任区域
    • PPO:把约束条件放到J(πθ)中做优化,CLIP 或 Penalty。

PPO-Clip

Clip 核心思想

PPO-Clip 背景

引入IS和GAE后的优化目标

argmaxπθJ(πθ)=Eτπold[πθ(atst)πθold(atst)AϕGAE(γ,λ)(st,at)]

为什么需要CLIP

  • 考虑采样不足的情况下,πθπθold 分布差异不能太大

  • 因此πθ(atst)πθold(atst)有上限和下限的,需保证πθ(atst)πθold(atst) 在信任域内

  • 不能一味轻信 AϕGAE(γ,λ)(st,at)来提升或降低 πθ(atst)

PPO Clip

CLIP 核心思想

  • 通过CLIP裁剪+MIN函数限制策略更新幅度,来保证训练稳定性
  • 限制重要性权重在一个信任域内,超出信任域就裁切
    • 约束新旧策略πθπθold尽可能接近相似限制更新幅度不要太大,保证训练稳定性
    • 希望采样策略学习策略差距不要太大

CLIP 信任域

  • [1ϵ,1+ϵ]
1ϵrt(θ)=πθ(atst)πθold(atst)1+ϵ

优化目标

  • 不做KL散度约束,直接把CLIP 信任域放到目标函数
JPPOCLIP(πθ)=Eτπθold[min(rt(θ)Aϕπθold(st,at),clip(rt(θ),1ϵ,1+ϵ)Aϕπθold(st,at))]JPPOCLIP(πθ)=st,atmin(πθ(atst)πθold(atst)Aϕπθold(st,at),clip(πθ(atst)πθold(atst),1ϵ,1+ϵ)Aϕπθold(st,at))

Clip 到底做了什么

CLIP 到底做了什么

有无CLIP公式对比

  • 无限制的策略梯度目标:rt(θ)A^t
  • 有限制的策略梯度目标:clip(rt(θ),1ϵ,1+ϵ)A^t,IS权重裁剪[1ϵ,1+ϵ]
Jclip(θ)=Et[min(rt(θ)A^t,clip(rt(θ),1ϵ,1+ϵ)A^t)]
  • 比例rt(θ)一旦超出范围变量就变为一个常数,对常数求导为0导致梯度为0

对于好动作 A^t>0

  • 目标:提高概率,即增大rt(θ)

  • rt(θ)1+ϵ时:一切正常

  • rt(θ)>1+ϵ:变成(1+ϵ)A^t

    min(rt(θ)A^t,(1+ϵ)A^t)=(1+ϵ)A^t
  • (1+ϵ)A^t没有梯度

    • 旧策略计算出的常数,和当前优化参数θ 无关
    • 意味着IS差距大的token 梯度为0无法进行梯度更新该token被硬丢弃

对于差动作 A^t<0

  • 目标:降低概率,即减小rt(θ)

  • rt(θ)<1ϵ:变成(1ϵ)A^t

    min(rt(θ)A^t,(1ϵ)A^t)=(1ϵ)A^t
  • 同理,(1ϵ)A^t 没有梯度

    • IS差异大的token无法进行梯度更新该token被硬丢弃
从梯度公式来理解

默认无clip

  • 策略梯度
θLppo=Et[rt(θ)A^t(st,at)logπ(atst)]=Et[rt(θ)A^tϕ(st,at)]
  • 推导梯度项
logπ(atst)=log(efθ(st,at)befθ(st,b))=logefθ(st,at)log(bAefθ(st,b))=fθ(st,at)1bAefθ(st,b)bAefθ(st,b)fθ(st,b)θ=fθ(st,at)θ1bAefθ(st,b)bAefθ(st,b)fθ(st,b)θ=fθ(st,at)θbAefθ(st,b)bAefθ(st,b)fθ(st,b)θ=fθ(st,at)θbAπθ(b|st)fθ(st,b)θ
  • 项1:正向推力提高atlogit分数
  • 项2:反向抑制按概率加权 降低其他动作的logit分数

带clip的策略梯度

  • 比例rt(θ)一旦超出范围,变量就变为一个常数,对常数求导为0导致梯度为0

  • 在clip区域之外所有梯度均为0

    • At>0,在clip区域范围外不会做提升
    • At<0,在clip区域范围外不会做抑制

PPO-CLIP 梯度简洁写法

θLPPOclip=Et[Itrt(θ)A^tϕ(st,at)]It={1,rt(θ)A^tclip(rt(θ),1ϵ,1+ϵ)A^t0,其他

Clip 改进工作

PPO-Penalty

PPO-Penalty 背景

背景

  • 直接把限制条件加入优化目标中,解决TRPO优化复杂的问题
  • 限制条件被称为KL penalty

相关笔记

KL惩罚、自适应参数、优化目标

KL 惩罚约束行为距离

  • 使用KL散度 约束行为上的距离而非参数上的距离,因此无法用L12范数等距离法。
JPPOπθold(θ)=Jπθold(πθ)βDKL(πθ,πθold)
  • KL散度设置阈值 [KLmin,KLmax]

自适应KL惩罚beta参数

  • 超参β的调整策略:自动调节自适应KL散度
  • KL(πθ,πθold)KLmax
    • πθ 新策略偏离旧策略太远 ,应该增大β把分布拉回来
  • KL(πθ,πθold)KLmin
    • 新旧策略相近,可能只优化KL散度不去优化优势相关的项。
    • 应该减小β降低KL散度对目标的影响

优化目标

  • 原始优化目标
argmaxπθJ(πθ)=Eτπold[πθ(atst)πθold(atst)AϕGAE(γ,λ)(st,at)]
  • 引入KL 惩罚后的优化目标
argmaxπθJPPOKL(πθ)=Eτπold[πθ(atst)πθold(atst)Aϕπold(st,at)βKL(πθold(st),πθ(st))]JPPOKL(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aϕπθold(st,at)]βKL(πold,πθ)

Actor

策略目标

普通优势策略目标和TRPO策略目标

普通优势策略目标

J(πθ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)]

TRPO策略目标

JTRPO(πθ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)],  KL(πold,πθ)δ
PPO-CLIP Seq-Level

PPO-Clip Seq-Level 策略目标

JPPOCLIP(πθ)=Eτπθold[min(rt(θ)Aϕπθold(st,at),clip(rt(θ),1ϵ,1+ϵ)Aϕπθold(st,at))]JPPOCLIP(πθ)=st,atmin(πθ(atst)πθold(atst)Aϕπθold(st,at),clip(πθ(atst)πθold(atst),1ϵ,1+ϵ)Aϕπθold(st,at))JPPOCLIP(πθ)=Eq,oπθold1|o|t=1|o|min(πθ(otq,o<t)πθold(otq,o<t)At,clip(πθ(otq,o<t)πθold(otq,o<t),1ϵ,1+ϵ)At)

PPO-Clip Seq-level Loss

Lppo(θ)=1Gi=1G1|oi|t=1|ot|序列内平均min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1ϵ,1+ϵ)A^i,t)
PPO-Clip, Token-Level

相关笔记

PPO-Clip Token-level 策略目标

JDAPO(θ)=E(q,a)D,{oi}i=1Gπθold(q)[1i=1G|oi|i=1Gt=1|ot|所有Token直接做平均min(ri,t(θ)A^i,t,clip(ri,t(θ),1ϵlow,1+ϵhigh)A^i,t)]

PPO-Clip Token-level Loss

  • 直接对所有Token做平均每个token权重相同,不论来自长或短序列。
LDAPO(θ)=1i=1G|oi|i=1Gt=1|ot|所有Token直接做平均min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1ϵlow,1+ϵhigh)A^i,t)
PPO-KL-Penalty 策略目标
JPPOKL(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aϕπθold(st,at)]βKL(πold,πθ)argmaxπθJPPOKL(πθ)=Eτπold[πθ(atst)πθold(atst)Aϕπold(st,at)βKL(πθold(st),πθ(st))]

PPO Loss

Actor在PPO epoch中,使用同一批数据做迭代更新的。

PPO Loss

重要性权重/比率做Clip

  • 为了稳定性,会对重要性权重CLIP截断
rt(θ)=πθ(atst)πθold(atst)rt(θ)=clip(rt(θ),min_r,max_r)
  • negative_approx_kl = log_prob - old_log_prob
  • negative_approx_kl = torch.clamp(negative_approx_kl, min=-20.0, max=20.0)

PPO Loss

LtPPOstd=min(πθ(atst)πθold(atst)Aϕπθold(st,at),clip(πθ(atst)πθold(atst),1ϵ,1+ϵ)Aϕπθold(st,at))Lppo(θ)=1Gi=1G1|oi|t=1|ot|序列内平均min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1ϵ,1+ϵ)A^i,t)

PPO Dual-Clip Loss

Dual-Clip Loss

负优势IS大权重时CLIP失效

  • At<0rt>1+ϵhigh

  • MIN机制选择更小的负数,Loss变成绝对值巨大的负数,产生巨大梯度,导致训练不稳定

    L=min(rtAt,clip(rt,1ϵ,1+ϵ)At)
  • 负优势+IS权重大CLIP机制失效惩罚太大 梯度无限制。如rt=10,At=1

    L=min(10,clip(10,10.2,1+0.2)(1))=10

Dual-Clip Loss

  • 在优势At<0时,额外增加一个裁剪
  • 负优势+IS权重偏差很大限制惩罚力度
  • 这个token的loss,最大不能超过优势绝对值*clip_ratio_c=3
LtDual-Clip={min(rtAt,clip(rt,1ϵ,1+ϵ)At)At0min(rtAt,cAt)At<0

熵奖励

熵奖励

相关笔记

背景

  • 熵是信息量的期望,衡量不确定性的程度。熵越大,不确定性越大
  • RL容易陷入局部最优,停止探索。为了鼓励探索,增加熵奖励

计算方法

  • 熵系数entropy_coef + 熵lossentropy_lossresponse每个生成token熵的平均值
  • agg_loss(loss_mat=entropy, loss_mask=response_mask, loss_agg_mode=x)
  • 熵奖励:entropy_coeff * entropy_loss
Ltotal=LppoβHLentropy
python
if calculate_entropy:
  	entropy = output["entropy"][:, -response_length - 1 : -1].contiguous()
    entropy_loss = agg_loss(loss_mat=entropy, loss_mask=response_mask, ...)  
    entropy_coeff = meta_info["entropy_coeff"]
    # 核心:从PPO损失中减去熵损失(乘以一个系数)
    policy_loss = pg_loss - entropy_coeff * entropy_loss  

KL 惩罚

KL Loss 背景

背景

  • RLHF中通常有一个SFT或基座的πref模型,有一定能力
  • Reward Hacking:如果不约束πθ,模型可能会走捷径骗过RM,来获取高奖励

KL Loss 正则化手段

KL Loss 惩罚

KL Loss

KLloss=βDKL(πθ,πθref)

自适应KL系数(PPO原论文)

  • 计算平均KL散度d,设置目标值dtarg

  • KL散度小于目标值降低beta;否则,增大beta

    β={β/2,d<dtarg/1.5β×2,d>dtarg×1.5

K1

DKLt(πθ,πθref)=logπθ(oi,tq,oi,<t)πref(oi,tq,oi,<t)

K3

DKLt(πθ,πθref)=πref(oi,tq,oi,<t)πθ(oi,tq,oi,<t)logπref(oi,tq,oi,<t)πθ(oi,tq,oi,<t)1
python
if self.config.use_kl_loss:
    ref_log_prob = data["ref_log_prob"]
    # compute kl loss
    kld = kl_penalty(logprob=log_prob, ref_logprob=ref_log_prob, kl_penalty=self.config.kl_loss_type) 
    kl_loss = agg_loss(loss_mat=kld, loss_mask=response_mask, loss_agg_mode=self.config.loss_agg_mode) 
		# 核心:将KL损失(乘以一个系数)加到总损失上
    policy_loss = policy_loss + kl_loss * self.config.kl_loss_coef 
python
def kl_penalty(logprob: torch.FloatTensor, ref_logprob: torch.FloatTensor, kl_penalty) -> torch.FloatTensor:
    """Compute KL divergence given logprob and ref_logprob. Optionally using straight through to bind k2 on other
    kl penalty compute method for unbiased KL gradient estimation.
    See more description in http://joschu.net/blog/kl-approx.html

    Args:
        logprob:
        ref_logprob:

    Returns:
        kl_estimate
    """
    forward_score = kl_penalty_forward(logprob, ref_logprob, kl_penalty) 
    if not kl_penalty.endswith("+") or kl_penalty in ("mse", "k2"):
        return forward_score

    """
    The expectation of k1 and k3 estimator is the expected value of KL, but the expected gradient of k1 and k3
    estimator is not the expected gradient of KL. On the other hand k2 estimator gives right gradient estimator, 
    so we use a straight through trick here if the kl_penalty method ends with '+', e.g., k3+. 
    """
    backward_score = 0.5 * (logprob - ref_logprob).square()

    return backward_score - backward_score.detach() + forward_score.detach()
python
def kl_penalty_forward(logprob: torch.FloatTensor, ref_logprob: torch.FloatTensor, kl_penalty) -> torch.FloatTensor:
    """Compute KL divergence given logprob and ref_logprob.
    Copied from https://github.com/huggingface/trl/blob/main/trl/trainer/ppo_trainer.py#L1104
    See more description in http://joschu.net/blog/kl-approx.html

    Args:
        logprob:
        ref_logprob:

    Returns:
        kl_estimate
    """
    if kl_penalty in ("kl", "k1"):
        return logprob - ref_logprob  

    if kl_penalty == "abs":
        return (logprob - ref_logprob).abs()

    if kl_penalty in ("mse", "k2"):
        return 0.5 * (logprob - ref_logprob).square()  

    # J. Schulman. Approximating kl divergence, 2020.
    # # URL http://joschu.net/blog/kl-approx.html.
    if kl_penalty in ("low_var_kl", "k3"):
        kl = ref_logprob - logprob 
        # For numerical stability
        kl = torch.clamp(kl, min=-20, max=20)
        ratio = torch.exp(kl)
        kld = (ratio - kl - 1).contiguous()
        return torch.clamp(kld, min=-10, max=10)

    if kl_penalty == "full":
        # so, here logprob and ref_logprob should contain the logits for every token in vocabulary
        raise NotImplementedError

    raise NotImplementedError

PG Loss 代码及实现过程

PPO PG Loss 核心部件

核心思想

  • 优势 * 重要性权重PPO-ClipPPO-Dual-Clip
  • Loss 聚合类型token-meanseq-mean-token-mean 等。
  • 入参:old_log_problog_probadvantagesresponse_mask、loss_agg_mode等

相关笔记

PG Loss 计算过程

1. 重要性权重

  • IS ratio=torch.exp(log_prob - old_log_prob)ri,t(θ)=πθ(oi,t|q,oi,<t)πold(oi,t|q,oi,<t)

2. 新旧策略PPO_KL监控指标

  • -(log_prob - old_log_prob),近似KL,作为观测指标

  • 数据采样策略πold当前学习策略πθ。Response做Mask,求mean

    DKL(πold||πθ)=Exπold[logπold(oi,tq,oi,<t)πθ(oi,tq,oi,<t)]

3. 朴素无clip的 PG Loss

  • pg_losses1 = -advantages * ratioJ(πθ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)]

4. PPO-CLIP PG Loss 计算

  • 根据clip_range(low和high),对IS权重做clip,再乘以优势,计算pg_losses2

    • pg_losses2= -advantages * torch.clamp(ratio, 1 - cliprange_low, 1 + cliprange_high)
  • pg_losses1和pg_losses2 选大的,loss已有负号应选大的

    • clip_pg_losses1 = torch.maximum(pg_losses1, pg_losses2)
    LDAPO(θ)=1i=1G|oi|i=1Gt=1|ot|所有Token直接做平均min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1ϵlow,1+ϵhigh)A^i,t)
  • 计算pg_clipfrac比例,监控指标,有多少比例的token 被clip掉

    • pg_clipfrac = verl_F.masked_mean(torch.gt(pg_losses2, pg_losses1).float(), response_mask)

5. PPO-Dual CLIP Loss 计算

  • clip_pg_losses2:针对负优势,使用clip_ratio_c=3.0做clip。
  • pg_losses3 = -advantages * clip_ratio_c
  • clip_pg_losses2 = torch.min(pg_losses3, clip_pg_losses1)

6. 最终clip_pg_losses

  • 优势小于0的token,选择clip_pg_losses2其余仍选择clip_pg_losses1
    • pg_losses = torch.where(advantages < 0, clip_pg_losses2, clip_pg_losses1)
  • 根据loss_agg_modeloss聚合
python
@register_policy_loss("vanilla")  # type: ignore[arg-type]
def compute_policy_loss_vanilla(
    old_log_prob: torch.Tensor,
    log_prob: torch.Tensor,
    advantages: torch.Tensor,
    response_mask: torch.Tensor,
    loss_agg_mode: str = "token-mean",
    config: Optional[DictConfig | AlgoConfig] = None,
    rollout_is_weights: torch.Tensor | None = None,
) -> tuple[torch.Tensor, dict[str, Any]]:
    """
    Compute the clipped policy objective and related metrics for PPO.

    Adapted from
    https://github.com/huggingface/trl/blob/main/trl/trainer/ppo_trainer.py#L1122

    Args:
        old_log_prob (torch.Tensor):
            Log-probabilities of actions under the old policy, shape (batch_size, response_length).
        log_prob (torch.Tensor):
            Log-probabilities of actions under the current policy, shape (batch_size, response_length).
        advantages (torch.Tensor):
            Advantage estimates for each action, shape (batch_size, response_length).
        response_mask (torch.Tensor):
            Mask indicating which tokens to include in the loss, shape (batch_size, response_length).
        loss_agg_mode (str, optional):
            Aggregation mode for `agg_loss`. Defaults to "token-mean".
        config: `(verl.trainer.config.ActorConfig)`:
            config for the actor.
        rollout_log_probs: `(torch.Tensor)`:
            log probabilities of actions under the rollout policy, shape (batch_size, response_length).
    """

    assert config is not None
    assert not isinstance(config, AlgoConfig)
    clip_ratio = config.clip_ratio  # Clipping parameter ε for standard PPO. See https://arxiv.org/abs/1707.06347.
    clip_ratio_low = config.clip_ratio_low if config.clip_ratio_low is not None else clip_ratio
    clip_ratio_high = config.clip_ratio_high if config.clip_ratio_high is not None else clip_ratio
    clip_ratio_c = config.get(  # Lower bound of the ratio for dual-clip PPO. See https://arxiv.org/pdf/1912.09729.
        "clip_ratio_c", 3.0
    )

    cliprange = clip_ratio
    cliprange_low = clip_ratio_low
    cliprange_high = clip_ratio_high

    assert clip_ratio_c > 1.0, (
        "The lower bound of the clip_ratio_c for dual-clip PPO should be greater than 1.0,"
        + f" but get the value: {clip_ratio_c}."
    )
    negative_approx_kl = log_prob - old_log_prob
    # KL做CLIP
    negative_approx_kl = torch.clamp(negative_approx_kl, min=-20.0, max=20.0)
    # IS 重要性权重
    ratio = torch.exp(negative_approx_kl) 
    # old_logprob-logprob,old-采样,logprob-学习,PPO_KL近似KL散度,监控指标
    ppo_kl = verl_F.masked_mean(-negative_approx_kl, response_mask)
    # 朴素无clip的pg_loss,-优势*重要性权重
    pg_losses1 = -advantages * ratio  
    if cliprange_low is None:
        cliprange_low = cliprange
    if cliprange_high is None:
        cliprange_high = cliprange
    # ppo-clip 第二项,对ratio做clip,乘以advantages
    pg_losses2 = -advantages * torch.clamp(ratio, 1 - cliprange_low, 1 + cliprange_high)  # - clip(ratio, 1-cliprange, 1+cliprange) * A  #
    # max(-ratio * A, -clip(ratio, 1-cliprange, 1+cliprange) * A)
    # ppo clip loss
    clip_pg_losses1 = torch.maximum(pg_losses1, pg_losses2)    
    # ppo clip 比例,有多少loss2 > loss1的
    pg_clipfrac = verl_F.masked_mean(torch.gt(pg_losses2, pg_losses1).float(), response_mask)
    
    # dual ppo clip,在优势小于0时,额外增加clip
    pg_losses3 = -advantages * clip_ratio_c 
    clip_pg_losses2 = torch.min(pg_losses3, clip_pg_losses1) 
    # dual ppo clip 比例
    pg_clipfrac_lower = verl_F.masked_mean(
        torch.gt(clip_pg_losses1, pg_losses3) * (advantages < 0).float(), response_mask
    )
    # dual ppo clip,在优势小于0时,额外增加一个裁剪
    pg_losses = torch.where(advantages < 0, clip_pg_losses2, clip_pg_losses1)  

    # Apply rollout correction weights if provided
    if rollout_is_weights is not None:
        pg_losses = pg_losses * rollout_is_weights

    pg_loss = agg_loss(loss_mat=pg_losses, loss_mask=response_mask, loss_agg_mode=loss_agg_mode)  

    pg_metrics = {
        "actor/pg_clipfrac": pg_clipfrac.detach().item(),
        "actor/ppo_kl": ppo_kl.detach().item(),
        "actor/pg_clipfrac_lower": pg_clipfrac_lower.detach().item(),
    }
    return pg_loss, pg_metrics

总Policy Loss 及代码

总Policy Loss

相关笔记

核心思想

  • Policy loss = PPO损失 - 熵奖励 + KL 惩罚

  • policy_loss = pg_loss - entropy_coeff * entropy_loss + kl_loss_coef * kl_loss

Policy Loss 增加 Entropy和KL loss

python
policy_loss = pg_loss

if calculate_entropy:
  entropy = output["entropy"][:, -response_length - 1 : -1].contiguous()
  if not forward_only:
      entropy_loss = agg_loss(loss_mat=entropy, loss_mask=response_mask, loss_agg_mode=loss_agg_mode)
      entropy_coeff = meta_info["entropy_coeff"]
      policy_loss = pg_loss - entropy_coeff * entropy_loss 
  else:
      ret_entropy = entropy

if forward_only:
  policy_loss = torch.tensor(1.0, device=device)
else:
  if self.config.use_kl_loss:
      ref_log_prob = data["ref_log_prob"]
      # compute kl loss
      kld = kl_penalty(logprob=log_prob, ref_logprob=ref_log_prob, kl_penalty=self.config.kl_loss_type)
      kl_loss = agg_loss(loss_mat=kld, loss_mask=response_mask, loss_agg_mode=self.config.loss_agg_mode)

      policy_loss = policy_loss + kl_loss * self.config.kl_loss_coef
      metrics["actor/kl_loss"] = kl_loss.detach().item()
      metrics["actor/kl_coef"] = self.config.kl_loss_coef

Verl 训练观测指标

监控指标

pg_loss

  • 优势*权重+PPO-Clip+PPO-Dual-Clip后的最终pg_lossLDAPO(θ)=1i=1G|oi|i=1Gt=1|ot|所有Token直接做平均min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1ϵlow,1+ϵhigh)A^i,t)

ppo_kl

  • 采样策略πold学习策略πθ之间的KL距离DKL(πold||πθ)=Exπold[logπold(oi,tq,oi,<t)πθ(oi,tq,oi,<t)]

pg_clipfrac

  • IS权重PPO-Clip区间 [1ϵlow,1+ϵhigh] `裁剪的比例

pg_clipfrac_lower

  • PPO-Clip后,被PPO-Dual-Clip针对负优势裁剪的比例LtDual-Clip={LtPPOstdAt0min(LtPPOstd,cAt)At<0

Reward

Reward Model 训练

Reward Model 训练

目标

  • (Prompt, Response) 打分,输出1个标量

偏好数据收集

  • 1个Prompt,输出多个Response,人类排序
  • 偏好数据:(prompt, chosen_response, rejected_response)

训练目标

  • 好回复的分数差回复的分数
RM(prompt,chosen_response)>RM(prompt,rejected_response)

Pairwise Loss

  • scorechosenscorereject:原始分数差;目标:最大化原始分数差
  • Sigmoid:模型认为 Chosen比Reject分数好的概率;目标:把概率推向1
  • log交叉熵loss,对错误概率进行惩罚;目标:最小化惩罚
loss=log(σ(R(ycx)R(yrx)))loss=log(σ(scorechosenscorereject))

Reward Model 即时奖励

Reward

RM 打分

  • 在NLP中,RM仅对整个Response1个分,仅最后一个token才有奖励rT,其余设为0。

    • 下文Critic目标之一:使最后一个token的回报 接近RM给的奖励 rTVϕ(sT)rT
  • 打分模型:训练过的Reward Model 或者 Rule-Based FuncLLM as Judge 等。

  • 充当环境的作用,给每一步 即时奖励

环境奖励信号

  • 环境奖励rtenv={00tT1rTt=T最终奖励

最终奖励

  • 最终每一步的奖励 = 环境奖励 -KL约束,KL 奖励约束见下文
rttotal=rtenvβDKLt(πθ,πref)=rtenvβlogπθ(otq,o<t)πref(otq,o<t)
  • 由于KL约束非负,除rT其余token的奖励rt 要么是0要么是负数

奖励加入KL散度项

奖励加入KL散度

目的

  • 确保 PolicyModel 不会偏离 ReferenceModel 太远
  • 如果偏离越大负的KL散度奖励对策略的抑制也越大

核心思想

  • 对Policy和Reference模型的token预测分布,加入KL项。
  • KL 负奖励
DKLt(πθ,πref)=logπθ(otq,o<t)πref(otq,o<t)

最终奖励

  • 最终奖励 = 环境奖励 - KL约束
rttotal=rtenvβDKLt(πθ,πref)=rtenvβlogπθ(otq,o<t)πref(otq,o<t)rt=rφ(q,ot)βlogπθ(otq,o<t)πref(otq,o<t)r(x,y)=rϕ(x,y)β(logπθ(yx)logπref(yx))
  • 由于KL约束非负,除rT其余token的奖励rt 要么是0要么是负数

Critic

Critic 目标

Critic 目标

Critic 核心目标

  • 评估策略效果,Actor更新后,需新的Critic来衡量新策略的价值。

  • 优化价值函数V(s)学习真实目标值

    • V(s)预测 尽可能更接近真实的未来总回报类比TD Error 定义
      • 预测当前策略,从状态s出发,未来总回报的期望值
      • 是状态st的价值不是即时奖励rt
  • 但我们并不知上帝视角真实目标值

    • 只能通过MC采样轨迹来估计,也就是Target ValueVtarget,t
  • 使最后一个token的回报 接近RM给的奖励 rT

Critic 核心作用

  • 通过不断“预测-验证-修正”的过程,Critic 的价值评估能力 越来越强
  • 从而能为 Actor 提供 更准确、更稳定的优势信号,最终引导 Actor 学会更好的策略

稀疏的监督信号

  • 在LLM RL中,仅最后一个token 有RM给的奖励。
  • 其他token 奖励都为0其他token缺乏合适的奖励信号
  • 导致Critic Model非常难以训练 ‼️。

Critic 学习过程

Critic 学习过程

标准的监督学习

  • 输入:状态sst
  • 预测:Vϕ(s)Vθ(st)V(st)Vnew(st)
    • Critic网络 在时间步t对状态st价值预测
    • ϕ是Critic 网络参数
  • 目标:VtargetVtarget,tRt
    • 在时间步t根据实际获得奖励对真实回报估计值
    • 这是最核心内容,在下文详细介绍计算。
  • Loss预测值目标值之间的差距MSE loss

算法流程

  • 采样数据

    • Actor和环境交互,收集1个batch的轨迹数据
  • 计算旧价值预测 Vold(st)

    • 使用当前Critic每一个状态st 预测价值,得到Vold(st),后面作为固定值
  • 计算 TD Error

    • 每个时间步t,计算TD Error
    δt=rt+1+γVπ(st+1)Vπ(st)
    • rt+1 是环境给的即时奖励,可通过Reward Model 或 Reward Func给出
  • 计算 GAE 优势估计

    • GAE 公式

      AtGAE(γ,λ)(st,at)=l=0(γλ)lδt+l
    • 最后一个时间步开始反向遍历提高GAE计算效率

      AtGAE(st,at)=δt+γλAt+1GAE(st+1,at+1)
  • 计算 Critic 目标值:利用GAE优势 + 旧价值预测 Vold(st)

Vtarget,t=AtGAE(γ,λ)(st,at)+Vold(st)
  • 计算 Critic Loss (见下文详细说明)

    • PPO多个优化子周期(epoch)里,对batch中每个数据点 (st,Vold(st))

      • st输入到正在更新的Critic网络,得到新预测值 Vϕ(st)

      • 利用Critic 目标值Critic 最新预测值,计算 MSE Loss

        Lcritic=(Vϕ(st)Vtarget,t)2
      • 根据Critic Loss调整Critic网络争取下次预测的更准

Critic Loss

Critic Loss

Loss函数

  • 实际训练中,从收集到的数据,取batch,计算batch上所有时间步的平均loss
Lcritic=(Vtarget,tVθ(st))2Lcritic=1Nt=1N(Vtarget,tVϕ(st))2δt=rt+1+γV(st+1)V(st)Lcritic=(Vtarget,tVnew(st))2Lcritic=(RtVθ(st))2

Critic目标值/真实回报目标值计算 Vtarget,tRt

  • 最核心部分, Vtarget,t 计算方法直接影响Critic的学习效率和稳定性

  • 优势函数计算

  • Vtarget,t 计算 ‼️

    • 目标回报Q值 = 优势值 + V值

      Aπ(st,at)=Qπ(st,at)Vπ(st)Qπ(st,at)=Aπ(st,at)+Vπ(st)
    • Critic 学习目标真实回报,可以看作Qt的一个估计,得到

      Vtarget,t=AtGAE(st,at)+Vold(st)
    • 请注意

      • Vold(st):用当时旧的Critic网络预测并记录下来旧的、固定的值,在GAE之前

        • 当做常数,不参与梯度计算。
      • AtGAE(γ,λ)(st,at)Vold值计算出来的。

    • Vtarget,t理解

      • 基于旧价值函数的估计 + 这个估计的修正量(优势值) = 得到 更精确的回报估计

Critic Loss 深入理解

Critic Loss TD Error 类比

TD Error

δt=rt+1+γV(st+1)V(st)

Critic Loss

Lcritic=(Vtarget,tVnew(st))2

TD Error 类比

Lcritic=(RtVθ(st))2
  • Vtarget,tRt :类比 TD 目标值

  • Vnew(st)Vϕ(st):类比TD Error中的需要优化的价值函数当前网络的预测值

  • Loss 类比 TD Error

Critic Loss 再深入理解

GAE 优势 推导

  • 反向递推公式
AtGAE(st,at)=δt+γλAt+1GAE(st+1,at+1)=rt+1+γVold(st+1)Vold(st)+γλAt+1GAE(st+1,at+1)
  • 推导结果
AtGAE(st,at)=rt+1+γVold(st+1)Vold(st)+γλAt+1GAE(st+1,at+1)

目标回报值 推导

  • R = A + V
Rt=Vtarget,t=AtGAE(st,at)+Vold(st)=rt+1+γVold(st+1)Vold(st)+γλAt+1GAE(st+1,at+1)+Vold(st)=rt+1+γVold(st+1)+γλAt+1GAE(st+1,at+1)Rt=Vtarget,t=rt+1+γVold(st+1)+γλAt+1GAE(st+1,at+1)

代入计算Loss

Lcritic=(RtVnew(st))2=(rt+1+γVold(st+1)+γλAt+1GAE(st+1,at+1)TDGAEVnew(st))2Lcritic=(rt+1+γVold(st+1)+γλAt+1GAE(st+1,at+1)TDGAEVnew(st))2

Critic Value Clip

Value Function Clip

背景

  • 稳定训练技巧防止Critic网络更新过大,对新价值预测裁剪

价值更新裁剪

  • ϵ是超参 例如(0.2),和Actor Loss 裁剪范围通常相同。Vclipped(st)=clip(Vθ(st),Vold(st)ϵ,Vold(st)+ϵ)

计算未裁剪和裁剪后的2个loss

  • 未裁剪

    Lunclipped=(Vnew(st)Vtarget,t)2
  • 裁剪后

Lclipped=(Vclipped(st)Vtarget,t)2

最终Critic Loss 取较大者

Lcritic=max(Lunclipped,Lclipped)

具体稳定训练过程思考

  • 建立信任区域

    • 围绕旧值Vold(st)建立信任区域,相信旧价值预测大体上是正确的

      [Vold(st)ϵ,Vold(st)+ϵ]
    • 确保新价值预测Vnew(st)不会离旧价值预测Vold(st) 太远

    • 预测价值本该朝向目标回报靠近,但若预测价值超出信任区域,则应该Clip。

      Vnew(st)Rt
  • 防止因目标值不准而过度更新

    • Vtarget,t 是由GAE计算出来的,是估计值,存在方差
  • 保持 Actor和Critic 更新步调一致

    • PPO核心是限制策略更新幅度,为Actor提供指导信号的Critic也应该限制更新幅度。
    • 防止Critic剧烈变化导致下一轮优势估计出现波动,导致Actor训练不稳定。

重要性采样

PPO 重要性采样

策略梯度

  • 交互策略πθold:与环境交互,采集大量数据来训练πθ
  • 学习策略πθ:要训练学习的网络
  • πθ更新多次后,再去更新πθold
J(θ)=Eτpθold(τ)[pθ(τ)pθold(τ)R(τ)logpθ(τ)]

优势策略梯度

  • 优势作权重
J(θ)=E(st,at)πθ[Aπθ(st,at)alogπθ(atst)a]
  • 引入重要性采样
J(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθ(st,at)alogπθ(atst)a]
  • 优势应是演员和环境交互 计算出来的
J(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)alogpθ(atst)a]

目标函数

J(θ)=E(st,at)πθold[πθ(atst)πθold(atst)Aπθold(st,at)a]

优点

  • 可通过重要性采样把同策略换成异策略

GAE

GAE 笔记

GAE
  • 对不同步数的TD优势估计进行指数加权平均,平衡方差和偏差
δt+l=rt+l+γV(st+l+1)V(st+l)AtGAE(γ,λ)(st,at)=l=0(γλ)lδt+lAtGAE(γ,λ)(st,at)=l=0(γλ)l(rt+l+γV(st+l+1)V(st+l))

算法流程

算法流程

PPO算法流程

  • 初始策略参数θ0
  • 每次迭代
    • 旧策略θk 和环境交互采样大量(s,a)
    • 根据θk交互结果,估计Aπθk(st,at)
    • 采样到这组数据后,最大化目标函数
    • 可以让θ更新很多次
JPPOθk(θ)=Jθk(θ)βKL(θ,θk)

PPO 调参踩坑经验

PPO 主要注意点

主要坑点

  • Critic初始化
    • 要用预训练权重, 随机初始化基本gg
  • KL散度监控
    • 超过0.02就要降学习率,不然策略会崩
  • 内存管理
    • 内存需求爆炸,双网络+梯度存储
  • 超参数敏感
    • 学习率、裁切范围,都很敏感

部分参数

  • learning_rate:3e-4直接爆炸,降到1.5e-5才稳定
  • batch_size:小于128,训练震荡严重
  • clip_range:跳到0.4后,策略变化太激进

来自 知乎 PPO vs GRPO

json
# 稳定的PPO配置(13B模型)
ppo_config = {
    "learning_rate": 1.5e-5,  # 别用太大,容易崩
    "clip_range": 0.2,        # 经典值,基本不用改
    "batch_size": 256,        # 越大越稳定
    "gae_lambda": 0.95,       # GAE参数
    "value_loss_coef": 0.5,   # 价值损失权重
    "entropy_coef": 0.01,     # 探索系数
    "max_grad_norm": 1.0,     # 梯度剪切
    "n_epochs": 4,            # 数据重用次数
}

缺点不足

PPO不足

GAE带来的计算开销大、训练不稳定

  • GAE 主要依赖于单步时序误差
δ=rt+γV(st+1)V(st)
  • 计算TDError之前,需为每个token计算奖励价值
    • 每个token的价值需由独立的Critic模型计算得到
    • Critic通常和策略模型同架构和大小,Critic计算开销非常大,且训练不稳定导致 无法提供准确的价值信号

DPO

标准RLHF目标

标准RLHF目标

标准RLHF目标-tradeoff

  • 最大化奖励πθ 生成的回答y从奖励模型尽可能获得高分
  • 不要偏离太远:约束策略πθ和参考策略πref 保持一定相似性πsft
maxπθExD,yπθ(yx)[rϕ(x,y)βDKL(πθ(yx),πref(yx))]
  • 奖励函数
r(x,y)=rϕ(x,y)β(logπθ(yx)logπref(yx))

标准RLHF训练流程

  • 先训rewad model

    maxrϕE(x,yw,yl)D[logσ(rϕ(x,yw)rϕ(x,yl))]
  • 再通过PPO训Actor Model

    maxπθExD,yπθ(yx)[rϕ(x,y)βDKL(πθ(yx),πref(yx))]

PPO缺点 & DPO动机

PPO缺点 & DPO动机

PPO 缺点

  • 计算复杂、成本高
    • Actor、CriticModel(估计价值,降低梯度估计中的方差)、RewardModel(奖励信号)、SFTModel (KL散度)
  • 训练不稳定
    • 奖励稀疏梯度更新不稳定收敛困难参数敏感
  • Reward Hacking
    • RM从有限的人类偏好数据中学习的,不可避免存在缺陷和偏差
    • 策略在优化过程中,发现并利用RM的漏洞获得高分 但实际不符合人类预期的输出。
    • 复杂抽象的人类价值观压缩成简单的标量信号,是很困难的。

DPO 动机

  • 把带有KL约束最大化奖励目标,等价替换成简单的直接在偏好数据上进行优化的分类问题
  • 对齐问题重定义为最大似然估计问题简单二元交叉熵loss直接对偏好Pair数据优化
  • 完全绕过 显示奖励模型训练复杂RL训练。这两个恰好是RLHF中最贵和不稳定的环节
  • 并非性能上超越RLHF,而是工程上的成功更稳定更轻量更容易实现

理论基础

显示最优解

显示最优解推导过程

PPO式子理论存在显示最优解

  • 理论最优解:通过完美奖励函数计算出完美策略模型不需要迭代式的强化学习
  • 最优策略参考策略奖励函数之间的确定性关系
πr(yx)=1Z(x)πref(yx)exp(1βr(x,y))
  • Z(x)归一化因子、分配函数,确保给定x,所有y概率加起来等于1
Z(x)=yπref(yx)exp(1βr(x,y))

显示最优解推导过程

显示最优解推导过程

显示最优解推导过程

  • 推导1
maxπθJ(θ)=maxπθExD,yπθ(yx)[rϕ(x,y)βDKL(πθ(yx),πref(yx))]=maxπθExD,yπθ(yx)[rϕ(x,y)βlogπθ(yx)πref(yx)]=minπθExD,yπθ(yx)[logπθ(yx)πref(yx)1βrϕ(x,y)]=minπθExD,yπθ(yx)[logπθ(yx)πref(yx)logerϕ(x,y)β]=minπθExD,yπθ(yx)[logπθ(yx)πref(yx)erϕ(x,y)/β]
  • 归一化分母,构建Z(x),以及新的概率分布π(yx)

    Z(x)=yπref(yx)erϕ(x,y)/βπ(yx)=πref(yx)erϕ(x,y)/βZ(x)
  • 代入目标式子,得到KL散度

maxπθJ(θ)=minπθExD,yπθ(yx)[logπθ(yx)πref(yx)erϕ(x,y)/βZ(x)Z(x)]=minπθExD,yπθ(yx)[logπθ(yx)π(yx)logZ(x)πθ]=minπθExD,yπθ(yx)[logπθ(yx)π(yx)]=minπθExDDKL(πθ(yx),π(yx))
  • KL散度在2个分布相等时取最小值,因此RLHF训练希望得到的最优概率分布就是π(yx)
π(yx)=πref(yx)erϕ(x,y)/βZ(x)

反解奖励函数

反解奖励函数

反解奖励函数

  • 直接转换π(yx)定义,反解出隐式奖励函数rϕ(x,y)
π(yx)πref(yx)Z(x)=erϕ(x,y)/ββlogπ(yx)πref(yx)Z(x)=rϕ(x,y)rϕ(x,y)=βlogπ(yx)πref(yx)+βlogZ(x)

DPO和RM目标loss一致

RM&DPO 目标loss一致

奖励函数带入奖励loss

  • RewardModel 训练目标 和 DPO 训练目标一致
JRM=maxrϕE(x,yw,yl)D[logσ(rϕ(x,yw)rϕ(x,yl))]=maxπE(x,yw,yl)D[logσ(βlogπ(ywx)πref(ywx)+βlogZ(x)βlogπ(ylx)πref(ylx)βlogZ(x))]=maxπE(x,yw,yl)D[logσ(βlogπ(ywx)πref(ywx)βlogπ(ylx)πref(ylx))]=JDPO

DPO目标和Reward Model一致

  • DPO对标的是RewardModel
    • 训练数据一致loss函数一致局限性也一致
JDPO=JRM

DPO和RM不同点

  • 架构不同
    • RM:有单独的Value Head,输出分值
    • DPO:无Value Head,直接优化token概率
  • 优化手段/目标不同
    • RM:优化偏序打分目标
    • DPO:优化生成目标。

DPO和RM 联系

  • RM可以给DPO扩充数据
  • 理论上,RM也可以做生成,DPO也可以做打分,只是没这么试过。

DPO 核心思想

DPO 核心思想

通过πθ,πold反解出奖励函数

  • 逆向运用理论最优解关系。
  • 不再采用老策略:先学习奖励函数、再利用奖励函数优化策略。
  • 假设LLM隐式定义一个奖励函数,从策略πθ参考策略πref反解出隐式奖励函数
rϕ(x,y)=βlogπθ(yx)πref(yx)+βlogZ(x)

偏好建模

  • winner > loser, chosen > reject
  • 人类偏好yw而不是yl的概率 p(yw>ylx)
p(yw>ylx)=σ(r(x,yw)r(x,yl))=σ(βlog(πθ(ywx)πref(ywx))+βlog(Z(x))βlog(πθ(ylx)πref(ylx))βlog(Z(x)))=σ(βlog(πθ(ywx)πref(ywx))βlog(πθ(ylx)πref(ylx)))

DPO 目标函数

  • 最小化目标函数

    • log交叉熵loss,对错误概率进行惩罚;目标:最小化惩罚
    LDPO(πθ;πref)=E(x,yw,yl)D[logσ(βlog(πθ(ywx)πref(ywx))βlog(πθ(ylx)πref(ylx)))]
  • 最大化以下目标

    • 生成正样本的概率 比参考模型高生成负样本的概率 比参考模型低
maxθlogσ(βlogπθ(ywx)πref(ywx)βlogπθ(ylx)πref(ylx))

从loss理解其弊端

  • Loss转换过程
maxθJDPO(θ)=maxθlogσ(βlogπθ(ywx)πref(ywx)βlogπθ(ylx)πref(ylx))=maxθlogσ(βlogπθ(ywx)βlogπref(ywx)βlogπθ(ylx)+βlogπref(ylx))=maxθlogσ(βlogπθ(ywx)πθ(ylx) βlogπref(ywx)πref(ylx))
  • Loss转换结果

    • 生成正负样本的比例,要目标策略的比例参考策略的比例 loss就可以下降
    maxθlogσ(βlogπθ(ywx)πθ(ylx)βlogπref(ywx)πref(ylx))
    • 比如参考策略0.50.25=2,目标策略 0.30.1=3

      • 虽然loss下降负样本概率下降,但是正样本概率也下降了。
      • 正负样本概率都下降,自然一些奇奇怪怪的输出概率就提高了。
      πref:0.50.25=2πθ:0.30.1=3

梯度更新

θLDPO(πθ;πref)=βE(x,yw,yl)D[σ(r^θ(x,yl)r^θ(x,yw))(θlogπ(ywx)θlogπ(ylx))ywyl]r^θ(x,y)=βlogπθ(yx)πref(yx)

算法机制

  • 数据:离线静态的偏好数据
  • 参考模型作用:πθπref=πsft不要偏离太远
  • 超参数β:控制2部分权重
    • 一是:最大化chosen和reject之间的概率差
    • 二是:保持与参考模型的相似性

DPO 缺点

简洁性是其最大优点,但也是其最大缺点

DPO 缺陷

1. 离线模式缺乏在线采样数据

  • 策略模型在进化,但静态偏好数据一成不变

    • 数据集无法代表 新策略潜在的失败模式导致模型无法从新的错误中学习

    • DPO离线特性限制了模型的探索能力

      • 只有evaluate,没有generate
    • PPO/GRPO 一直和环境交互采样数据,用当前策略采样新数据学习提升

      • generate + evaluate + generate + evaluate + ...

2. DPO Loss 导致优化过程不稳定

maxθlogσ(βlogπθ(ywx)πθ(ylx)βlogπref(ywx)πref(ylx))
  • 正样本概率负样本概率 都可能会下降。 回答抑制模式,正负似然都下降。

  • 奇怪输出概率会上升,特别在遇见未见内容时。

  • 负样本概率下降正样本概率提升 快得多

    • 大力惩罚已知坏样本,擅长学习不做什么,而非做什么。
    • 不是探索奖励好样本
  • 过拟合/RewardHacking

    • Loss对所有偏好对一视同仁,不会做权重区分,强行拉开他们的概率差距
    • 缺乏鲁棒性:可能拟合数据噪声,而非真实人类偏好。

3. 依赖SFT模型和数据质量

  • 对SFT模型质量很敏感
    • 最终性能取决于初始化SFT模型
    • 起点差了,就很难摆脱。而在线学习能通过采样自我学习迭代来摆脱。
  • 数据质量敏感
    • 需要高质量偏好数据
    • 可能学习多数群体的偏好、而忽略少数群体的观点,引入偏见。

GRPO

PPO缺点&GRPO动机

PPO 缺点 & GRPO 动机

PPO 核心思想

  • Actor Model
JPPOCLIP(πθ)=Eq,oπθold1|o|t=1|o|min(πθ(otq,o<t)πθold(otq,o<t)At,clip(πθ(otq,o<t)πθold(otq,o<t),1ϵ,1+ϵ)At)
  • Critic Model
Lcritic=(rt+1+γVold(st+1)+γλAt+1GAE(st+1,at+1)TDGAEVnew(st))2
  • Reward Model (不参与训练,或 Rule Based Reward)
rttotal=rtenvKLt(πθ,πref)=rtenvβlogπθ(otq,o<t)πref(otq,o<t)

PPO 缺点

  • 资源开销大
    • 需要训Critic Model(通常和Actor同尺寸),增加了额外的内存计算开销
    • 每个Token都需要由Critic 去估计价值, At 依赖Critic
  • 训练复杂/不好训

GRPO 动机

  • 解决PPO Critic资源开销大训练复杂的问题。

GRPO核心思想

GRPO 核心思想

核心思想

  • 抛弃Critic Model降低资源开销训练复杂度

  • 分组采样:每个Prompt采样1组答案(G=64)。

  • 组内计算优势

    • 好的答案,加大权重;差的答案,降低权重。
    • 使用组内平均分作为基线
    • 每个答案得分减去平均分,作为自身优势,作为策略梯度优化信号。
  • 自适应加权的对比学习

MC采样思想

  • REINOFRCE 算法挺像,主要依赖MC采样,不用TD估计优势。
  • 但MC采样方差大,没有TD去平衡方差,怎么解呢?
    • 使用组内标准化奖励,一定程度降低了策略梯度估计方差。

组内相对优势

优势计算

分组采样

  • 对每个query,采样1组输出RewardModel每个输出打分,给出奖励
qo={o1,o2,,oG}r={r1,r2,,rG}
  • 组内基线计算:组内平均奖励/奖励标准差
mean(r),std(r)

相对组优势计算

  • 为每个输出oi,计算组内的相对得分,作为组内的相对优势
r^i=rimean(r)std(r)A^i=r^iA^i,t=A^i=r^i=rimean(r)std(r)

GRPO策略目标

GRPO 策略目标

优化目标-PPO核心差异

  • 使用组内优势来替代GAE优势
  • πθπθrefKL约束放入目标函数
    • PPO是放在每个Token的即时奖励信号 rt里的
      • rttotal=rtenvβDKLt(πθ,πref)
  • 同PPO一样,使用CLIP信任域来保证新旧策略分布差异不太大。

GRPO 优化目标公式

JGRPO(πθ)=Eq,{oi}i=1Gπθold1Gi=1G1|oi|t=1|oi|(min(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t)A^i,t,clip(πθ(oi,tq,oi,<t)πθold(oi,tq,oi,<t),1+ϵ,1ϵ)A^i,t)βDKL(πθ,πθref))θJGRPO(θ)=ExD,{yi}i=1Gπθold(|x)[1Gi=1G1|yi|t=1|yi|πθ(yi,t|x,yi,<t)πθold(yi,t|x,yi,<t)token重要性权重A^i,ttoken优势θlogπθ(yi,t|x,yi,<t)token梯度]

GRPO ref KL 约束

  • K3 KL无偏且低方差
DKLt(πθ,πθref)=πref(oi,tq,oi,<t)πθ(oi,tq,oi,<t)logπref(oi,tq,oi,<t)πθ(oi,tq,oi,<t)1

GRPO调参踩坑经验

GRPO 关键点

主要坑点

  • 采样基础设施:需高效的推理系统,SGLANG/VLLM
  • Group大小太小(<32)统计不稳定,太大计算贵
  • Beta调参非常关键,需要仔细调
  • 奖励设计:需要奖励信号有足够的区分度
GRPO 关键参数

Beta 参数

  • 0.05:学习太慢、收敛慢
  • 0.1大多数任务的甜点
  • 0.2:有时候会过拟合
  • 0.3+:基本上会发散

Group_size

  • 16:统计不稳定、方差大
  • 32:勉强能用
  • 64:比较稳定的选择
  • 128:更稳定、但计算成本高

GRPO 标准配置

json
# 我的GRPO标准配置
grpo_config = {
    "learning_rate": 8e-7,    # 比PPO小很多
    "beta": 0.1,              # KL系数,最关键
    "group_size": 64,         # 群体大小
    "temperature": 0.7,       # 生成多样性
    "top_p": 0.9,             # 核采样
    "max_length": 2048,       # 最大长度
}

PPO vs GRPO

GRPO算法和PPO算法本质区别是什么

核心目标思想差异

PPO vs GRPO 核心目标

PPO

  • 找到一个最大化奖励的最优策略。
  • 解决问题:策略更新的稳定性

GRPO

  • 找到一组高质量且多样化的策略。
  • 解决问题:策略发现的多样性
PPO vs GRPO 核心思想

PPO

  • 拥有历史数据库的教练,追求绝对最优,学习绝对期望值
  • 过程
    • 策略模型(1个运动员)完成1次表现,奖励模型给出最终成绩。
    • 价值模型基于历史数据,在运动员跑到中间点时,预测最终成绩
  • 优势
    • 最终成绩-历史预测成绩超预期,就获得正向奖励
    • 参照物:过去的自己,πθold。超越昨天的自己。
  • 学习信号/优势信号

GRPO

  • 组织小组赛的教练,追求相对领先,直接使用相对的、动态的平均值
  • 过程
    • 策略模型(1组运动员)同时完成表现,生成G个回答。奖励模型为每位运动员给出最终成绩。
    • 没有历史数据,直接算出这组运动员的平均成绩
  • 优势
    • 组内相对优势个人成绩-小组平均成绩超平均水平,就获得正向奖励
    • 参照物:团队平均策略,π¯。超越团队平均。
  • 学习信号/优势信号
    • Response-LevelTrajectory-Level
    • 轨迹级优势直接应用到序列的每个token作为token-level优势

技术实现差异

PPO vs GRPO 技术实现差异

核心目标

  • PPO:找到一个最大化累积奖励的单一最优策略。解决策略更新的稳定性问题。
  • GRPO:找到一组高质量且具备多样性的策略。解决策略发现的多样性效率问题。

优化参照物

  • PPO:过去的自己πθold。通过和上一轮策略比较,在信任域内小步快跑,争取超过昨天的自己。
  • GRPO:小组的平均策略π¯。超过平均水平,则获得正向激励。

算法架构

  • PPO
    • Actor-Critic架构:Actor+Critic+RewardModel。
    • Critic 估计状态价值V(s)、用于GAE计算优势。
    • MC 采样 + TD估计。
  • GRPO
    • 纯策略梯度:Actor+RewardModel。
    • 无Critic,价值基线通过统计得出。
    • MC 采样。

优势

  • PPO
    • GAE依赖价值模型V(s)基于模型预测、学习的方法。
      • 对多个n步优势估计,加权平均,引入λ平衡方差和偏差
      • 结合了多步MC回报+Critic价值预测,MC采样+TD估计。
      • 依赖准确估计的Critic,这个往往是PPO的难点。
    • 优势获得条件
      • 实际得分比历史预测好,才获得正向奖励。
      • 基于绝对奖励+价值函数预测
    • 优势信号特点
      • 仅最后一个token有环境奖励其余token为0
      • 所有token都有KL惩罚奖励。
  • GRPO
    • 组相对优势不依赖价值模型 基于群体投票、统计的方法。
    • 优势获得条件
      • 个人比组平均成绩好,才获得正向奖励。
      • 组内相对排名和分数
    • 优势信号特点
      • 一条轨迹上所有token共享相同的优势值,都为A^i,t

奖励信号利用

  • PPO

    • Token-Level
    • 间接利用。
      • 环境奖励用来训Critic;再由依赖Critic计算的GAE优势,指导Actor更新优化。
    • 有奖励KL惩罚。
    • 绝对奖励信号。
  • GRPO

    • Response-level
    • 直接利用。
      • 奖励信号直接用于计算相对优势,直接用于Actor优化。
    • 无奖励KL惩罚。
    • 标准化组相对奖励。

资源开销和训练复杂度差异

PPO vs GRPO

1. 资源开销

  • PPO
    • 资源需求高Actor和Critic 2个模型
    • 内存需求:基础模型*3倍
      • Actor *1, Critc *1, 梯度+优化器 *1旧策略缓存:部分参数。
      • 实际和bs、序列长度有关。
  • GRPO
    • 资源需求低仅Actor模型
    • 内存需求:基础模型*1.5倍
      • Actor *1梯度+优化器 *0.5(单网络)。
      • 实际和bs、序列长度有关。
    • 无Critic,与PPO相比,显存需求降低25%。若使用规则,不用RewardModel,降低50%。

2. 训练复杂性

  • PPO
    • 复杂性:高。
    • 需同时训Actor和Critic,难度大。超参数敏感。
    • Critic本身难训练,尤其在奖励稀疏语言模型中,Critic难收敛,导致优势估计不准
  • GRPO:
    • 复杂性:低。
    • 只需训练Actor,调参更容易。
    • 基线是直接从组内得分统计出来的而非学习来的。过程更简单、稳定

3. 训练稳定性

  • PPO
    • 相对稳定。
    • 通过CLIP信任域机制,限制策略更新幅度,防止“学崩”,保证训练稳定性。
    • GAE在Critic训练良好的情况下,能有效平衡降低方差和偏差。Critic若收敛,训练更稳定。
  • GRPO
    • 非常稳定。
    • 组内相对优势,天然对奖励绝对值不敏感,只关心排序有效降低了方差
    • 目标函数通样有KL约束,保证策略更新的稳定性。

优缺点对比

PPO vs GRPO 优缺点

优点

  • PPO

    • 通用性强。
    • 当样本更新对噪声容忍度较高。
  • GRPO

    • 高效轻量。无Critic模型,资源消耗低、训练快。
    • 稳定易用。训练过程更稳定,参数好调。
    • 与偏好奖励模型 (Reward Model) 的相对比较机制完美契合

缺点

  • PPO

    • 计算成本高。
    • 训练困难。
    • 对奖励缩放敏感。优势估计受奖励绝对值影响。
  • ·GRPO

    • 采样开销可能较高,每次更新需要采样G个输出。G太小,方差大。
    • 对G值敏感:会影响性能开销平衡。
    • 依赖组内质量多样性组内样本高度相似情况下,如标准差为0优势估计会失效,导致梯度为0,更新失效。
为什么GRPO能work

为什么GRPO在LLM下可能更优/能work

  • Critic 在LLM 稀疏奖励情况下(仅最后token有奖励信号),非常难以训练
  • GRPO 完美规避了Critic训练难题。
  • GRPO和RewardModel很搭配
    • RewardModel通过比较谁更好来训练,最擅长做出相对判断;
    • GRPO通过组内选出更好的,而非绝对分数。
    • 机制上契合,使得奖励信号利用更加高效
  • 隐式课程学习
    • 同一个问题,组内样本质量有高有低。
    • 模型通过比较,可以同时学到好的和差的,学习信号更加丰富。
  • 高效且稳定。

适用场景对比

PPO vs GRPO 适用场景

PPO

  • 通用RL,机器人控制、游戏AI等。
  • 主观评价。
  • 内存、计算资源充足。
  • 追求极致性能提升
  • 支持连续和离散动作空间。

GRPO

  • 针对LLM的RLHF:GRPO完美契合人类偏好训练的RewardModel。
  • 内存、计算资源有限。极致性价比。
  • 快速迭代。
  • 多样性任务。
  • 高效稳定。
总访客数:— · 总访问量:—
PLM's Blog @ 2016 - 2026