文章

RL 基础

本文目录 9

背景

Markov

马尔可夫链和马尔可夫决策过程

markov决策过程是st→atst+1,rts_t\xrightarrow{a_t}s_{t+1},\quad r_t,

典型的场景有:

  • 游戏决策
  • 机器人控制
  • 自动驾驶

而这些问题的共同特征都是当前动作会在影响下一个动作的同时,也会影响更远的未来;所以RL的出现原本是为了能够学习这种连续决策的能力


RL的过程

简单来说就是有一个state sts_t,在某个environment中选择了action aa之后,得到了一个新的state st+1s_{t+1} ;这个过程会被环境评分得到一个reward rtr_t。而RL的目标就是通过这个奖励的值,回去更新决策的模型

一些二级定义:

  • Q(s,a)Q(s,a): 在s的情况下,选择了a的动作,最终将带来的reward

  • τ=(s0.a0,r0,⋯ )\tau=(s_0.a_0,r_0,\cdots): 一条经过多个步骤的trajectory

  • GtG_t: 从t时刻之后的长期的收益,=(rt+γrt+1+γ2rt+2+⋯ )=(r_t+ \gamma r_{t+1} + \gamma^2 r_{t+2} + \cdots),γ\gamma是折扣因子,因为越远的奖励对当前的决策的影响越小


RL的三大分类

对于想要从强化学习中得到什么,主要分为三大类:

  • Value-based
  • Policy-based
  • Actor-Critic

Value-based

训练的是一个评分的模型,也就是输入s和a之后能得到Q的模型;这个奖励的过程是一个有意思的bootstrap 自举

流程如下:

action-model

比如我这里对s_t情况下,发生动作a_t进行了了一个长期reward的评估

所以它监督的信号也是一个长期reward;这里的目标值yty_t使用的是yt=rt+γmax⁡a′Q(st+1,a′)y_t = r_t+\gamma\max_{a'}Q(s_{t+1},a')

也就是长期累计的reward等于当前的reward(由环境决定,是决定正确的)加上估计的未来的累计reward(由Q模型自己估计)

所以这里是一个自举的训练,或者说是“从后向前”的训练,因为最后一步的yTerminatey_{Terminate}就是rTerminater_{Terminate}


Policy-based

学习是一个策略的模型

最经典的算法是Policy Gradient,目标是增加输出“好”的action的概率,流程图如下

policy-model

在跑完一个trajectory之后,根据这条路径得到的结果去更新策略

这里比较tricky的就是这个更新的过程,我们的目标是J(θ)=E[G]J(\theta) = E[G],E[G]E[G]是跑多条路径之后得到的奖励期望

我们的目标始终是:

J(θ)=Eτ∼Pθ[G(τ)]J(\theta) = \mathbb E_{\tau\sim P_\theta}[G(\tau)]

其中:

  • θ\theta:policy 参数
  • Pθ(τ)=∏πP_\theta(\tau) = \prod\pi:当前 policy 产生轨迹 τ\tau 的概率
  • G(τ)G(\tau):这条轨迹最终得到的 Return(累计回报)

如果直接展开期望,得到

J(θ)=Eτ∼Pθ[G(τ)]=∑τPθ(τ)G(τ)J(\theta) = \mathbb E_{\tau\sim P_\theta}[G(\tau)] = \sum_\tau P_\theta(\tau)G(\tau)

问题在于期望的定义是对所有的情况做精确的加权求和,在训练里显然无法覆盖无穷无尽的情况,所以需要做一个sampling

这里选取Monte Carlo Estimation来逼近期望,他的公式是E[f(x)]≈1N∑if(xi)\mathbb E[f(x)] \approx \frac1N\sum_i f(x_i),随着N的增加,他的误差按O(1N)O(\frac{1}{\sqrt{N}})下降

这个近似之所以没有概率的存在,是因为采样的频率,也就是样本出现的次数,充当了这个概率权重的作用

把这个带入到J(θ)J(\theta)里,得到的是J=1N∑iG(τi)J= \frac{1}{N} \sum_i G(\tau_i),这是很坏的。因为G是由环境打出来的分数,他不是连续的计算,和模型之间是没有梯度的,求导的结果永远是0,也就无法更新参数

所以为了在做近似的同时,能够保护这个概率PP,需要用到一个trick,就是∇log⁡f(x)=∇f(x)f(x)\nabla \log f(x) = \frac{\nabla f(x)}{f(x)}。如果能先做梯度的计算,就能把里面变成P∇logPP \nabla logP的形式,这样在P被采样消耗掉之后,还能保留logP的梯度,避免了梯度的消失

也就是

∇θJ(θ)=∇θ∑yPθ(y)G(y)\nabla_\theta J(\theta) = \nabla_\theta \sum_{y} P_\theta(y) G(y)

因为G关于θ\theta不可导,把∇\nabla拿到求和里面之后,得到

\nabla_\theta J(\theta) = \sum_{y} G(y) \nabla_\theta P_\theta(y)\tag{1}

利用梯度的等式,

\nabla_\theta J(\theta) = \sum_{y} G(y) \cdot P_\theta(y) \nabla_\theta \log P_\theta(y) \tag{3}

这时候再应用一下采样,得到最终的梯度

∇θJ(θ)≈1N∑i=1NG(yi)∇θlog⁡Pθ(yi)\nabla_\theta J(\theta) \approx \frac{1}{N} \sum_{i=1}^{N} G(y_i) \nabla_\theta \log P_\theta(y_i)

总结一下就是:

不能先把期望通过 sampling 化成单纯的 reward 平均再求导;而是先对期望求导,把参数化概率分布的梯度显式提取出来,再对这个梯度期望进行 Monte Carlo 估计

我们再带入pθ(τ)=∏tπθ(at∣st),τ=(a1,s1,…,at,st)p_θ(τ)=\prod_{t}\pi_θ(a_t∣s_t), \tau =(a_1,s_1,\dots,a_t,s_t)

得到多轮rollout之后N条trajectory的梯度就是:

∇θJ(θ)≈1N∑i=1N(∑t=0T∇θlog⁡πθ(ai,t∣si,t))⋅G(τi)\nabla_\theta J(\theta) \approx \frac{1}{N} \sum_{i=1}^{N} \left( \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta(a_{i,t} | s_{i,t}) \right) \cdot G(\tau_i)

注:

这里使用的是整条轨迹后更新,是trajectory-level的;REINFORCE通常是这种方式

另外一种更新方式是step-wise的,下面在Actor-Critic里会介绍到


Actor-Critic

              state
                │
       ┌────────┴────────┐
       ↓                 ↓
     Actor             Critic
       ↓                 ↓
   选择 action         评价局势
       │                 │
       └──────┬──────────┘
              ↓
         更新 Actor

策略梯度的问题是会不稳定;同时因为它使用的是总分R,可能会让某些已经表现的比较好的trajectory获得更多的训练,同时它因环境的变化可能导致比较大的方差

因此使用一个相对的分数AA=实际奖励-期望奖励更好

于是引入了Value Function状态价值函数V(st)V(s_t),这个就是critic model的职责

Vπ(st)=E[Gt∣st]\boxed{V^\pi(s_t) = \mathbb E[G_t|s_t]}

然后得到一个Advantage,At=Gt−V(st)\boxed{ A_t = G_t-V(s_t) }

当我们有了value function之后,就可以像最开始的Value-based一样,通过一个bootstrap的估计来进行一个自举,只不过这里要得到的对象是GtG_t,把他替换成G^t=rt+γV(st+1)\hat G_t = r_t + \gamma V(s_{t+1})

于是也得到了一个Advantage的估计A^t=rt+γV(st+1)−V(st)\hat A_t = r_t+\gamma V(s_{t+1})-V(s_t),给他一个新的名字TD Error,Temporal-Difference Error,时序差分误差

这样,我们在第t步的时候就能得到这个TD error δt\boxed{\delta_t},无需等待轨迹结束便可进行反向传播,每一步都执行更新Lactor=−A^tlog⁡π(at∣st)L_{\text{actor}} = -\hat A_t\log\pi(a_t|s_t)

同理,也可以参照Q-learning的方法,继续构造yt=rt+γVϕ(st+1)\boxed{ y_t = r_t+\gamma V_\phi(s_{t+1})}来更新Critic的权重

critic 相当于生成评分的模型,actor相当于生成policy的模型


RL和LLM的结合

有人说语言也是具有markov性质的一串字符,而LLM本身天然就是一个Policy,它做的事情就是P(tokent∣token<t)P(token_t \mid token_{<t})

所以二者可以直接对应

RL                         LLM

state s             =     当前上下文
action a            =     下一个 token
policy π(a|s)       =     LLM 的 next-token distribution
trajectory          =     一整段生成文本

当我们对LLM的要求越来越高,我们希望它能:

  • 解决更多的问题
  • 更加安全
  • 能推理出正确的答案
  • 让代码通过测试

这些目标往往难以通过传统的监督学习达到一个很好的效果,这也是后来的RLHF的核心思想

PPO

Proximal Policy Optimization

基本上还是Actor-Critic,但是限制每次的policy不要更新太猛

他出现的原因就是普通的策略梯度容易在一步的更新中更新过头,所以有必要限制一下每次更新的幅度

定义一个ratio

rt(θ)=πθ(at∣st)πold(at∣st)r_t(\theta) = \frac{ \pi_\theta(a_t|s_t) }{ \pi_{\text{old}}(a_t|s_t) }

再加一个clippingclip⁡(rt,0.8,1.2)\operatorname{clip}(r_t,0.8,1.2)

最后的loss是LPPO=E[min⁡(rtAt,clip⁡(rt,1−ϵ,1+ϵ)At)]L_{\text{PPO}} = \mathbb E\left[ \min\left( r_tA_t, \operatorname{clip}(r_t,1-\epsilon,1+\epsilon)A_t \right) \right]

展开min里面的一个来看看,得到

rt(θ)At=πθ(at∣st)πold(at∣st)At\boxed{ r_t(\theta)A_t = \frac{\pi_\theta(a_t|s_t)} {\pi_{\text{old}}(a_t|s_t)} A_t }

可以看到和actor-critic也就差了一个系数,Lactor=−A^tlog⁡π(at∣st)L_{\text{actor}} = -\hat A_t\log\pi(a_t|s_t)

GRPO

Group Relative Policy Optimization,用组内的相对值来替代Critic的输出

可以看成是PPO-style policy update + group-relative advantage - Critic

对于一组的rollout,他的一组的rollout的最终的Reward的平均值为μ\mu,那么Advantage可以认为就是R−μR-\mu;

注意这里用的是最终的Reward,而不是G

如果用G的话,GRPO也能做,不过可能比较难算G