ppo、trpo、grpo均属于actor-critic类算法
PPO
ppo和a2c的整理流程与思想基本一致:
- 与环境交互,收集经验(当前状态、执行的action、得到的reward)
- 更新价值网络(裁判员):目的是为了更加准确评估当前执行动作的得分
- 更新策略网络(运动员):目的是在给定状态下,执行更好的动作,从而获取更高的得分
- 一致迭代上面的操作直到收敛
ppo关键的改动是第3步策略网络的损失函数(目标函数)。存在两种常用的目标函数:1️⃣ppo剪切法;2️⃣ppo自适应KL惩罚。我们一个一个看
ppo-clip(剪切法)
直接上策略网络的目标函数,推导略(比较复杂),我们知道这个是ppo的目标函数即可,对这个函数做梯度上升,收敛之后得到的策略网络就是ppo算法找到的最优网络:
LCLIP(θ)=E^t[min(rt(θ)A^t,clip(rt(θ),1−ϵ,1+ϵ)A^t)]
L^{CLIP}(\theta)=\hat{E}_t[\min(r_t(\theta)\hat{A}_t,\text{clip}(r_t(\theta),1 - \epsilon,1+\epsilon)\hat{A}_t)]
LCLIP(θ)=E^t[min(rt(θ)A^t,clip(rt(θ),1−ϵ,1+ϵ)A^t)]
- rt(θ)=πθ(at∣st)πθold(at∣st)r_t(\theta)=\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}rt(θ)=πθold(at∣st)πθ(at∣st),表示概率比,其中 πθold\pi_{\theta_{old}}πθold 是旧策略
- ϵ\epsilonϵ 是剪辑超参数,用于限制策略更新的幅度
解释一下这个公式的含义:
当rt(θ)r_t(\theta)rt(θ)处于1−ϵ~1+ϵ1-\epsilon~1+\epsilon1−ϵ~1+ϵ之间,目标函数为rt(θ)A^tr_t(\theta)\hat{A}_trt(θ)A^t;否则将rt(θ)r_t(\theta)rt(θ)截断到1−ϵ~1+ϵ1-\epsilon~1+\epsilon1−ϵ~1+ϵ之间。
这样做是为了避免单次更新的新旧网络差异过大。
再看这个公式,我们已知ϵ\epsilonϵ,还剩下rt(θ)r_t(\theta)rt(θ)和A^t\hat{A}_tA^t需要确定,就只剩下θ\thetaθ这个自变量。
- 对于rt(θ)=πθ(at∣st)πθold(at∣st)r_t(\theta)=\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}rt(θ)=πθold(at∣st)πθ(at∣st)
- 上面的含义是当前策略下在状态s下选择a的概率,下面表示旧策略在状态s下选择a的概率
- 我们知道,在与环境交互时,需要通过策略网络选择动作。实际上策略网络返回的只是每个动作的概率,我们在返回的概率分布下进行抽样才得到了动作,这时会存储状态、执行的动作、动作的概率、reward到记忆缓冲区,这个动作的概率就是πθold(at∣st){\pi_{\theta_{old}}(a_t|s_t)}πθold(at∣st)
- 接着,使用记忆缓冲区的数据对策略网络训练并更新。假如进行K次训练和更新,那每更新一次网络,我们都会重新获取状态S下执行A的概率值(状态S输入最新的策略网络得到的动作概率),这个概率就是πθ(at∣st)\pi_{\theta}(a_t|s_t)πθ(at∣st)
- 这样rt(θ)r_t(\theta)rt(θ)的数据就成功获取
- 对于A^t\hat{A}_tA^t
- 它的公式为A(st,at)=Q(st,at)−V(st)A(s_t,a_t)=Q(s_t,a_t) - V(s_t)A(st,at)=Q(st,at)−V(st),实际上也是td_error
- V(s)V(s)V(s)是当前的状态价值,可以通过价值网络获得
- Q(s,a)Q(s,a)Q(s,a)通过蒙特卡洛近似得到,蒙特卡洛近似是一种通过抽样数据来近似真实期望的方式,那么抽样数据在哪里?答案就是记忆缓冲区
- 回顾上面,我们实际上是按照顺序把一整个轨迹的数据存放到缓冲区(代码中通过list.append()实现
- 那么我们只需要遍历缓冲区中的数据,通过Q(st,at)=˙rt+1+γrt+2+⋯=∑k=0∞γkrt+k+1
Q(s_t,a_t) \dot{=} r_{t+1} + \gamma r_{t+2} + \cdots = \sum_{k=0}^{\infty} \gamma^k r_{t+k+1}
Q(st,at)=˙rt+1+γrt+2+⋯=k=0∑∞γkrt+k+1
即可计算得到Q(st,at)Q(s_t,a_t)Q(st,at)的蒙特卡洛估计,这里γ\gammaγ表示折扣率,是预设的超参数; rt+1r_{t+1}rt+1表示状态sts_tstt时刻下执行动作a获得的reward,这在缓冲区已经存储,是已知值
- 因此A(st,at)A(s_t,a_t)A(st,at)也可以计算得到
现在目标函数就是一个关于θ\thetaθ这个单变量的函数,使用梯度上升(实际往往是在函数前加负号用梯度下降)来优化网络。
ppo-自适应KL惩罚
还是直接看目标函数:
LKL(θ)=E^t[πθ(at∣st)πθold(at∣st)A^t−β⋅KL[πθold,πθ]]
L^{KL}(\theta) = \mathbb{\hat{E}}_t \left[ \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)} \hat{A}_t - \beta \cdot \text{KL}[\pi_{\theta_{\text{old}}}, \pi_\theta] \right]
LKL(θ)=E^t[πθold(at∣st)πθ(at∣st)A^t−β⋅KL[πθold,πθ]]
- πθ(at∣st)πθold(at∣st)A^t\frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)} \hat{A}_tπθold(at∣st)πθ(at∣st)A^t和上面clip计算方式相同,不再赘述
- β\betaβ是超参数,预先设定好
- KL[πθold,πθ]\text{KL}[\pi_{\theta_{\text{old}}}, \pi_\theta]KL[πθold,πθ]表示πθold\pi_{\theta_{\text{old}}}πθold和πθ\pi_\thetaπθ的KL散度
- πθold\pi_{\theta_{\text{old}}}πθold和πθ\pi_\thetaπθ是旧策略和新策略执行不同动作的概率分布
- KL散度表示两个概率分布的相似度,完全一致则为0,差异越大,KL散度越大
- KL散度的计算依赖于概率分布值
- 而旧策略和新策略的概率分布clip中也已经说过,即,与环境交互时,存储策略网络的输出为旧策略概率分布;训练与更新策略网络时,实时获取当前策略网络的输出为新概率分布。
- 可以看到当两个网络差异越大,KL散度越大,目标函数就越小。
- 而我们的目的是梯度上升最大化目标函数,因此更新时会限制新旧网络分布差异过大,这与clip中截取的目的相同
计算出除自变量θ\thetaθ所有参数值之后,这就再次变成一个简单的梯度上升问题。
TRPO
对于策略网络类的算法,核心思想就是找到合适的目标函数,当最大化目标函数后,这个策略网络给出的动作就是最优的
置信域算法
首先补充一个前置知识:置信域算法。
对于目标函数J(θ)J(\theta)J(θ),它的梯度上升公式为:
θnew←θold+α⋅∇J(θ)\theta_{\text{new}} \leftarrow \theta_{\text{old}} + \alpha \cdot \nabla J(\theta)θnew←θold+α⋅∇J(θ)
但是有时J(θ)J(\theta)J(θ)的梯度并不好求,那么我们就寻找一个简单的L(θ)L(\theta)L(θ),它在θold\theta_{old}θold的某个邻域内接近J(θ)J(\theta)J(θ),此时我们只需要对L(θ)L(\theta)L(θ)做梯度上升寻找θnew\theta_{new}θnew
常见的L(θ)L(\theta)L(θ)比如J(θ)J(\theta)J(θ)的泰勒展开,蒙特卡洛近似。
θold\theta_{old}θold的这个邻域称为置信域
如图所示,我们使用紫线来近似绿线,找到了θnew\theta_{new}θnew。这个θnew\theta_{new}θnew必须要在置信域内部。
接着以这个θnew\theta_{new}θnew作为新一轮的θold\theta_{old}θold,并再次进行函数近似+最大化,这样循环迭代一直到找到最优解。
因此置信域算法可以总结为以下两个步骤的重复:
- 近似:给定θold\theta_{old}θold,在它的邻域内对J(θ)J(\theta)J(θ)做近似得到L(θ)L(\theta)L(θ)
- 最大化:使用梯度上升最大化L(θ)L(\theta)L(θ),得到θnew\theta_{new}θnew
TRPO
TRPO实际上就是对以上两步的实践
step1:近似
直接看目标函数
J(θ)=Et[πθ(at∣st)πθold(at∣st)⋅Qt(S,A)]
J(\theta) =\mathbb{{E}}_t \left[ \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)} \cdot Q_{t}(S, A) \right]
J(θ)=Et[πθold(at∣st)πθ(at∣st)⋅Qt(S,A)]
它需要对所有状态与所有动作求期望,同时还需要真实的动作价值,我们需要对这3个部分做近似从而得到L(θ)L(\theta)L(θ)
对于状态与动作的期望,使用蒙特卡洛近似。
同上文PPO一样,我们与环境交互时,会存储一个轨迹下的状态、reward、执行动作、动作概率到记忆缓冲区。
存储的动作概率就是πθold(at∣st)\pi_{\theta_{\text{old}}}(a_t|s_t)πθold(at∣st)
对于Qt(S,A)Q_{t}(S, A)Qt(S,A),遍历整个轨迹,通过以下公式计算
Q(st,at)=˙rt+1+γrt+2+⋯=∑k=0∞γkrt+k+1
Q(s_t,a_t) \dot{=} r_{t+1} + \gamma r_{t+2} + \cdots = \sum_{k=0}^{\infty} \gamma^k r_{t+k+1}
Q(st,at)=˙rt+1+γrt+2+⋯=k=0∑∞γkrt+k+1
πθ(at∣st)\pi_\theta(a_t|s_t)πθ(at∣st)是在训练过程中,通过实时输入状态到最新的策略网络得到动作的概率分布。
通过上面的操作我们得到J(θ)J(\theta)J(θ)的近似
L(θ)=1n∑i=1n[πθ(ai∣si)πθold(ai∣si)⋅Qt(si,ai)]
L(\theta) =\frac{1}{n} \sum_{i=1}^{n} \left[ \frac{\pi_\theta(a_i|s_i)}{\pi_{\theta_{\text{old}}}(a_i|s_i)} \cdot Q_{t}(s_i, a_i) \right]
L(θ)=n1i=1∑n[πθold(ai∣si)πθ(ai∣si)⋅Qt(si,ai)]
对L(θ)L(\theta)L(θ)
step2:最大化
θnew←argmaxθL(θ∣θold);s.t.θ∈N(θold). \theta_{\text{new}} \leftarrow \underset{\theta}{\arg\max} {L}(\theta \mid \theta_{\text{old}}); \quad \text{s.t.} \quad \theta \in \mathcal{N}(\theta_{\text{old}}). θnew←θargmaxL(θ∣θold);s.t.θ∈N(θold).
- θ∈N(θold)\theta \in \mathcal{N}(\theta_{\text{old}})θ∈N(θold)表示需要保证θ\thetaθ在置信域内
控制置信域有两种方式:
- ∥θ−θold∥<Δ.\|\theta - \theta_{\text{old}}\| < \Delta.∥θ−θold∥<Δ.直接限制一个范围
- 在同一状态下,新策略与旧策略输出的动作概率分布的KL散度不能相差太大
1n∑i=1nKL[πθold(⋅∣si) ∥ πθ(⋅∣si)]<Δ \frac{1}{n} \sum_{i=1}^{n} \text{KL} \left[ \pi_{\theta_{old}}(\cdot \mid s_i) \, \| \, \pi_{\theta}(\cdot \mid s_i) \right] < \Delta n1i=1∑nKL[πθold(⋅∣si)∥πθ(⋅∣si)]<Δ
GRPO
GRPO是在PPO的基础上进行改动。
当我们把PPO用于大模型时,需要额外为大模型训练一个reward模型,这个reward模型,用于给大模型的答案进行打分。
但是PPO算法中训练状态价值网络时,需要每一个token(最小分词)的得分,reward模型是无法对每个token进行打分的。
GRPO的处理方式是
使用一个模型生成多个答案,分别对每个答案进行打分,不同的答案作为一个action,再把每个答案的得分分到每个token