PG/PPO/DPO/GRPO/MDPO 公式推导

 ·  2025-02-26

<think> 这篇博客的主要目的是整理强化学习中几个XPO的优化目标,包括比较经典的PPO、DPO,KIMI1.5中的MDPO以及DeepseekMath(R1)的GRPO。

Policy Gradient

首先从策略梯度(Policy Gradient)说起,广义的强化学习优化目标如下
argmaxπθJ(πθ)=Eτπθ[R(τ)]=τR(τ)P(τ|πθ)
简单来说就是如果当前轨迹τ得到的奖励R(τ)越大,那就增大采样τ的概率。其梯度如下

对于LLM场景,πθ指的就是模型本身,τ则是它生成的一个句子。我们可以采样很多个句子τ来估计期望(蒙特卡洛采样)

J(πθ)=τR(τ)P(τ|πθ)=τR(τ)P(τ|πθ)P(τ|πθ)P(τ|πθ)=τR(τ)P(τ|πθ)logP(τ|πθ)=Eτπθ[R(τ)logP(τ|πθ)]

我们还可以对P(τ|πθ)做一定简化,因为τ=(s0,a0,s1,a1,...,st),所以
P(τ|πθ)=ρ0(s0)t=0T1P(st+1|st,at)πθ(at|st)
而初始状态s0和状态转移概率P(st+1|st,at)都和策略πθ无关,所以
J(πθ)=Eτπθ[R(τ)logP(τ|πθ)]=Eτπθ[R(τ)[logρ0(s0)+t=0T1logP(st+1|st,at)+t=0T1logP(at|st)]]=Eτπθ[R(τ)t=0T1logP(at|st)]
这个就是策略梯度的最终形态了,之后我们可以看到PPO/GRPO都可以用从这个式子出发

PPO

PPO首先改造的是R(τ),它将其分割到每一个时间步R(st,at)中,字面意思就是在st状态执行at的回报,相比于t时刻的奖励rt,这个回报如果能考虑未来的奖励情况就更好了,比如R(st,at)=k=tT1γktrk

刚刚提到的R(st,at)=k=tT1γktrk虽然考虑了实际的未来奖励值,但是每一个r都是随机变量,这会导致R(t)的方差很大。所以有没有可能用一个函数去估计R(st,at)呢?

于是这里引入了critic model和V(t)t时刻的平均(不管执行什么动作)回报叫做V(t),critic model的工作是估计V(t),而此时R(st,at)=rt+γV(t+1)V(t),这个形式其实就是TD Error,直观上理解,V(t)是t时刻的平均回报,rt+γV(t+1)是在t时刻执行动作at得到的奖励加上t+1时刻的折扣回报,也就是考虑了当前时间步的动作的总回报,那么R(st,at)则是当前t时刻,执行at动作得到的回报比平均回报多的部分。换而言之,R(st,at)也可以叫做优势。既然V(t)V(t+1)都是模型(critic model)估计的,那怎么设计它的损失函数呢?

critic model的损失函数其实就是R(st,at)本身,这里我们可以参考最早的R(st,at)=k=tT1γktrk,它满足R(st,at)=rt+γR(st+1,at+1),我们自然也希望V(t)也具备R(st,at)一样的性质。另外用一个模型去估计V,带来的方差会小一点(毕竟专门拿了一个模型来学V,它见过其他的轨迹τ,学习到的value方差也会小一点)

有人可能会觉得《critic model的损失函数其实就是R(st,at)本身》,那优势R(st,at)被优化到0了,我的策略模型岂不是没法更新了?事实上,如果R(st,at)如果是0,说明此时做什么动作都不会影响到最后的奖励期望,那这个时候已经是最优策略π了,自然也没有必要做策略提升

此时的R(st,at)强依赖于critic model估计的V(t),但是V(t)更新时只考虑到了当前轨迹当前动作at所带来的rt,偏差比较大。(这里解释偏差比较抽象,我的理解是学出来的V(t)虽然满足rt+γV(t+1)=V(t)这个相对关系约束,但是因为有t个未知数,t-1个方程,学出来的V不是确切解,可能存在偏差)

所以PPO最终采用的是GAE,即权衡了偏差和方差的最终版本Φ(st,at)。它是R(st,at)R(st,at)之间的trade off,通过一个λ超参调整之间的比例。
δt=rt+γV(t+1)V(t)Φst,at=k=0(γλ)kδt+k
λ=0Φ(t)退化成R(st,at);当λ=1Φ(t)退化成R(st,at)V(t)

R(st,at)V(t)R(st,at)的baselined版本,这里同样学了一个V(t),就不展开了

使用Φ(st,at)时,critic model的损失就得换成Φ(st,at)+V(t)V(t)=Φ(st,at),把广义优势当成损失

说完了R(t),这个时候回过头看J(πθ),他现在可以表示为
J(πθ)=Eτπθ[t=0T1Φ(t)logP(at|st)]
接下来再带入πθ经过on policy到off policy的转变(之前博客提到了),我们可以得到
J(πθ)=Eτπold[t=0T1Φ(t)πθ(at|st)πold(at|st)]
那么优化目标也就是
J(πθ)=Eτπold[t=0T1Φ(t)πθ(at|st)πold(at|st)]
这里πθ是要更新的model,而πold是拿来采样τ的model。off policy希望这两个model分布不要相差太大,所以我们可以再加一项KL散度约束(这里是反向的KL散度,可能之后再出一篇说)
J(πθ)=Eτπold[t=0T1Φ(t)πθ(at|st)πold(at|st)]βKL[πθ(|st)||πold(|st)]
以上就是PPO的Policy优化目标啦,这里省略了对优势的裁剪操作(训练critic model的时候也可以对V做裁剪)。

KL那一项如果拿出来,作为J(πθ)的约束条件,则是TRPO的做法

另外这里还省略了奖励模型的训练,rt的设置,可以参考上一篇博客

关于奖励模型的优化目标,请见下一章DPO

DPO

PPO首先要训一个奖励模型,再逐步更新actor/critic model,显得太繁琐了。DPO的想法就是绕过奖励模型。

PPO的训练目标还可以写成以下这种广义的形式
J(πθ)=maxπExD,yπ[r(x,y)]βDKL[πθ(y|x)||πref(y|x)]
第二项还是KL散度,而第一项在最大化采样句子τ=x+y的奖励期望,PPO在这里的做法是训了一个奖励模型来拟合r函数,同时为了和LLM next token prediction的token级别action对齐,把reward拆解成了多个时间步,并训练了一个critic model预测当前时间步的未来平均回报V

DPO则表示不急,还想继续推导一下J(πθ),于是有
J(πθ)=maxπExD,yπθ[r(x,y)]βDKL[πθ(y|x)||πref(y|x)]=maxπExD,yπθ[r(x,y)βlogπθ(y|x)πref(y|x)]=minπExD,yπθ[logπθ(y|x)πref(y|x)1βr(x,y)]=minπExD,yπθ[logπθ(y|x)πref(y|x)exp[1βr(x,y)]]=minπExD,yπθ[logπθ(y|x)1Z(x)πref(y|x)exp[1βr(x,y)]logZ(x)]
其中Z(x)=yπref(y|x)exp[1βr(x,y)],构造Z的原因是,DPO想把第一项写成KL散度的形式,那么分母也应该满足概率分布的条件,于是Z(x)就负责把它归一化到[0,1]

现在我们得到了一个新的概率分布π=1Z(x)πref(y|x)exp[1βr(x,y)]J(πθ)的目标是拉近πθ和它的距离。
J(πθ)=minπExD,yπθ[logπθ(y|x)1Z(x)πref(y|x)exp[1βr(x,y)]logZ(x)]=minπExD,yπθ[KL[πθ(x)||π(y|x)]logZ(x)]
另外logZ只和πref有关,所以只需要优化第一项即可。这个时候我们可以写出πθ的最优解!就是我们刚刚构造的π!(两个概率分布相等时KL散度为0)

这时候我们可以得到给定r可以训练得到的最优πθ
πθ=1Z(x)πref(y|x)exp[1βr(x,y)]
变换一下可以得到rπθ之间的关系,那么下一步是不是意味着我们在训练奖励模型的时候用等式右边替换,就可以把优化对象从奖励模型r切换到πθ了?
r(x,y)=βlogπθ(y|x)πref(y|x)+βlogZ(x)
接下来回顾一下奖励模型的优化目标是什么,OpenAI的RLHF-PPO的做法和这里一样(应该是DPO和PPO一样)
Jr(r,D)=maxE(x,yw,yl)D[logP(yw>yl|x)]
这里用Bradley-Terry刻画了概率P(yw>yl|x)=eλ1eλ1+eλ2,其中λ1,λ2yw,yl的强度参数,我们可以用奖励值代替,那么优化目标就变成
Jr(r,D)=maxE(x,yw,yl)D[logP(yw>yl|x)]=maxE(x,yw,yl)D[loger(x,yw)er(x,yw)+er(x,yl)]=maxE(x,yw,yl)D[log11+e[r(x,yw)r(x,yl)]]=maxE(x,yw,yl)D[logσ[r(x,yw)r(x,yl)]
其中σ是sigmoid函数,这个形式和InstructGPT就一样了。理解也很直接:好的句子的reward比坏的句子的reward高就行。

这个优化目标只要求两者之间的相对关系,所以DPO训练的时候有可能出现两个句子采样概率都变低了,但是因为坏句子采样概率降低的更快,所以.......

OK,推导这一步,我们只需要把刚刚求的r带入到这个优化目标中,就可以得到DPO最终的优化目标了
Jr(r,D)=maxE(x,yw,yl)D[logσ[βlogπθ(yw|x)πref(yw|x)βlogπθ(yl|x)πref(yl|x)]
注意这里的几个π分布都是句子级别的,所以在代码实现时,会把所有token的logprobs之差都加起来。

GRPO

DeepSeek R1的Iterative GRPO最近关注度非常高,也有很多开源项目在follow。但是GRPO本身复现也有些争议,所以这里只简单介绍一下DeepseekMath里提到的公式。

说回最早的策略梯度, R(τ)的设计百花争鸣,有多次采样未来奖励的形式、也有用critic model估计优势的形式、还有两者结合的GAE,有时还需要加上裁剪、KL散度,这些设计无疑都比较繁琐。(这些设计,包括前段时间的MCTS,都是过程奖励模型)
J(πθ)=Eτπθ[R(τ)t=0T1logP(at|st)]
GRPO则探索了另一个方向,首先设计容易验证的问题和答案,使用ruled-based的奖励模型(结果奖励模型)。

举个例子,我希望模型输出的内容包括思维链和最终答案,思维链被tag \<think> \<\think>包裹,如果模型生成的句子有这两个tag,就给一定的奖励。

现在奖励来源搞定了,但是怎么体现“优势”呢(之前讨论PPO的优势时我们还提到一个baseline的版本,一个相对奖励会更好优化些),GRPO的做法是采样多条路径o=(o1,...,og)为一组,每组计算归一化后的奖励(假设一组采样g次)
Ai,t=ri=rimean(r)std(r),r=(r1,r2,...rg)
那么优化的目标就是
J(πθ)=E(o1,o2,...,ogπθ)[t=0T1Ai,tlogπθ(at|st)]=1Gi=1G1Tt=0T1Ai,tlogπθ(at|st)

细心的小伙伴会发现这里多了一个1/T,这其实等效于Ai,t的值除以当前这个句子的长度,GRPO为什么要这么做呢?因为我们设计Ai,t的时候一个句子每个token(t)位置的奖励都是整个句子的奖励ri,所以这里可以认为是把整体奖励平均分给每个token

我们再加上PPO里也用上的重要性采样,以及KL散度,就可以得到论文里的公式了
J(πθ)=1Gi=1G1Tt=0T1{min[πθ(oi,t|q,oi,<t)πold(oi,t|q,oi,<t)Ai,t,clip(πθ(oi,t|q,oi,<t)πold(oi,t|q,oi,<t),1ϵ,1+ϵ)Ai,t]βDKL[πθ||πref]}
trl也实现了GRPOTrainer,但是实现和上面的式子不太一样,比如上式是off policy,而实现时用的是on policy,于是可以去掉clip,因为比值是1(但是这里为什么不直接用策略梯度的logπθ还没有定论)

对源码感兴趣的同学可以参考GRPO Trainer

另外,R1用的实际上是Iterative GRPO,πref也会逐步更新,这里就不展开了

再补充一点,KL散度的计算采用了Schulman估计,之后可能会展开讲,估计的好处是方差比较小(尽管直接算logqp是无偏的)

MDPO-K1.5

MDPO是KIMI k1.5用到的RL方式,来自Mirror Descent Policy Optimization。它其实和GRPO有点相似,但是理论基础更多一点。

首先K1.5也使用ruled-based的奖励模型(结果奖励模型),简化了r的设计。

其次我们在DPO推导出了r函数和最优策略πθ的关系
r(x,y)=βlogπθ(y|x)πref(y|x)+βlogZ(x)
目前r已知,Z(x)=yπref(y|x)exp[1βr(x,y)];我们构造一个代理损失来优化πθ
L(θ)=(r(x,y)βlogπθ(y|x)πref(y|x)βlogZ(x))2
我们稍微规范一下符号(与论文中对齐),x为quesiton,y为ref model采样的responsey为标准答案,D为数据集,KL散度因子用βτ。我们可以得到
L(θ)=E(x,y)D[E(y,z)πθi[(r(x,y,y)τlogZ(x)τlogπθ(y|x)πθi(y|x))2]]

注意πref换成了πθi,这是因为这里的算法也是Iterative的,但是我们先只看一次迭代

另外注意这里采样句子的是πθi(ref model),而不是πθ或之前提到的重要性采样模型πold,我的理解是它这里从ref model采样句子是为了估计Z(x)同时也是因为这个原因,ref model也需要迭代式的更新,来保证采样的句子和我们最后要的πθ生成的句子分布接近

继续考虑Z的估计,假设从πθi采样了(y1,z1),(y2,z2),...,(yk,zk) ,那么Z(x)1ki=1kexp[r(x,yi,y)/τ]。(zi指的是思维链,我们可以先把它和yi一起考虑)

接下来重点来了,实际应用时τlogZ(x)可以直接用r¯=mean(r(x,y1,y),..,r(x,yk,y))来表示。这是因为采样次数足够多时,
τlogZ(x)τlog1ki=1kexp[r(x,yi,y)/τ]τlog1kkexp[r¯(x,yi,y)/τ]r¯(x,yi,y)
OK,最后我们得到了
L(θ)=E(x,y)D[E(y,z)πθi[(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))2]]
开始求梯度!(先忽略掉两个期望值)
L(θ)=[(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))2]=2(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))=2(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))(τlogπθ(y|x)πθi(y|x))=2τ(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))(logπθ(y|x)πθi(y|x))=2τ(r(x,y,y)r¯τlogπθ(y|x)πθi(y|x))logπθ(y|x)=2τ(θlogπθ(y|x)[r(x,y,y)r¯]τlogπθ(y|x)πθi(y|x)logπθ(y|x))=2τ(θlogπθ(y|x)[r(x,y,y)r¯]τ2θ(logπθ(y|x)πθi(y|x))2)=2τki=1k(θlogπθ(yi,zi|x)[r(x,yi,y)r¯]τ2θ(logπθ(yi,zi|x)πθi(yi,zi|x))2)
最后一步考虑了E(y,z)πθi,另外把输出y拆解成了输出y和思维链z,可以看到这个式子和论文中的只差了常数项2τ,这应该是论文漏写了

后记

至此PPO/DPO/GRPO/MDPO-K1.5所有的公式推导基本都放在这里了,还有一些重要性采样(上篇博客介绍了),裁剪、Iterative的操作这里为了简洁就省略了。

回顾这几个算法的设计,可以看到从PRM到ORM的转变,从一个复杂的reward/critic model到ruled-based model,从policy-base和value-base结合的ppo到纯policy-base的grpo,整个强化学习的pipeline是不断在简化的。(又让我想起来经典的The bitter lesson)

KIMI1.5论文里介绍了PRM到ORM转变的原因:通过value去估计某个action的优势,可能会导致有些不那么错的action采样概率降低(比如st状态下,一个action a通向正确的结果,而另一个action b通向了差一点点就正确的结果,那么动作a会被鼓励而动作b会被抑制),这降低了模型去trial and error的可能性,也就是所谓的“aha moment”。从这个角度看ORM可能会好一点,但是ORM奖励并不是token/action级别的,现在几个算法都是直接平均分摊,可能这个点还可以做一下?

不管怎么讲,这篇博客到这就该结束了。这几天追热点确实很过瘾,但也愈发觉得自己的渺小,只能写点文字聊以慰籍,留下一些痕迹。

博客又何尝不是一种思维链呢(突然想起来之前博客被人爬了,会不会有某个LLM记得JJJYmmm🤣)

</think>

附录

Qingbin大佬指出PPO的J(πθ)可能不太严谨,但数值上相差不大(附上他提供的cs285 slides)
J(πθ)=J(πθ)J(πθ)=Eτπθ[t=0T1Φ(t)logP(at|st)]=Eτπθ[t=0T1Φπθ(t)logπθ(at|st)]

image-20250226205318237

image-20250226205333958

image-20250226204626012

评论
1

期待反向KL散度和正向KL散度的下一篇

JJJYmmm

好!可能下周写(等我搞搞明白

无伤大雅的错误:)
\tau = {s_0, a_0, \dots, s_T, a_T} 哎呀~jjjymmm得了MVP🙌🏾🤪

JJJYmmm

最后一个s_T不需要做action了,所以没有a_T🙌🏾🤪

jingxz

有一个疑问,PPO中,当λ=0的时候,这个时候k=0当作00=1处理的吗?所以退化为R(st,at)

JJJYmmm

是的

JJJYmmm's Blog. All Rights Reserved. Theme Jasmine by Kent Liao.