本文将会快速从 RL 的基础理论讲起,介绍 RL Basis, Policy Gradients, Actor-Critic Methods 等 RL 中的基本概念,在这个基础上介绍最经典的一种强化学习算法 PPO
RL Basis#
对于一个统一的马尔可夫过程:M=(S,A,P,r,γ), 给定参数化策略 πθ(a∣s),我们给出的最终目标是:
θmaxJ(θ)=Eτ∼πθ[t=0∑Tγtr(st,at)]即从参数化策略中采样一个策略,我们希望这个策略的最终 reward 可以被最大化。
为了优化这个目标,我们引入如下函数和指标:
- Gt=∑k=0T−tγkrt+k: 从 t 时刻开始可以得到的全部 reward
- Vπ(s)=Eπ[Gt∣st=s]: 从 t 时刻开始,在当前状态 s 下采样运行策略 π,得到的 reward 的数学期望
- Qπ(s,a)=Eπ[Gt∣st=s,at=a]: 从 t 时刻开始,在当前状态 s 下运行 action a, 采样运行策略 π,得到的 reward 的数学期望
- Aπ(s,a)=Qπ(s,a)−Vπ(s): Advantage
- 因为对当前状态 s, 根据策略 π 采样出来的 Qπ(s,a) 的数学期望就是 Vπ(s).
Vπ(s)=Ea∼π(⋅∣s)[Qπ(s,a)]在 RL 算法中,存在两种优化方法:
- 如果我们能够建模出来 Qπ(s,a), 我们就可以根据这个函数对策略 π 进行优化
- 直接设置 π(a∣s)=1, 对于最大的 Q 对应的 action
- 这可以保证 π 的优化是递增的,即更新后的旧策略一定优于新策略
- 这种方式需要依赖对 Q Function 的很好的拟合 -> Value Based RL!
- 直接通过 reward 的梯度信号优化 policy (policy gradient)
- e.g. REINFORCE, PPO, GRPO
Policy Based RL (Policy Gradient)#
考虑一条轨迹: τ=(s0,a0,s1,a1,s2,a2,s3,...)
RL 优化的目标就是 sample 这样一条轨迹之后,这条轨迹的最终 reward 会被最大化。
首先,给出数学上的 Log-Derivative Trick(本质就是 log 导数的 trick,在这里省略证明):
∇θpθ(τ)=pθ(τ)∇θlogpθ(τ)对于一个离散的轨迹空间,期望的求和形式是:
J(θ)=τ∑pθ(τ)R(τ)基本的概率梯度形式#
对两边求 θ 的梯度:
∇θJ(θ)=∇θτ∑pθ(τ)R(τ)=τ∑R(τ)∇θpθ(τ)我们默认 R(τ) 的给出往往是环境的反馈等等,没有额外依赖 θ.
因此,代入公式:
∇θJ(θ)=τ∑R(τ)∇θpθ(τ)=τ∑R(τ)pθ(τ)∇θlogpθ(τ)=Eτ∼pθ[R(τ)∇θlogpθ(τ)]因此,我们需要求解的梯度,可以被写成一个针对旧策略采样的数学期望的形式。我们可以使用 MCMC 等方法进行 policy gradient 的估计。
轨迹概率分解#
接下来,我们继续攻关,尝试对 ∇θlogpθ(τ) 进行轨迹的概率分解:
考虑一个只有两个 Action 的轨迹, τ=(s0,a0,s1,a1,s2),完整的轨迹概率是:
pθ(τ)=ρ0(s0)×πθ(a0∣s0)×P(s1∣s0,a0)×πθ(a1∣s1)×P(s2∣s1,a1)我们取对数,可以计算:
logpθ(τ)=logρ0(s0)+logπθ(a0∣s0)+logP(s1∣s0,a0)+logπθ(a1∣s1)+logP(s2∣s1,a1)很显然,在这样子的累和项中,只有包含 πθ(a∣s) 的项,会产生梯度 (剩下的项只和环境有关,不会产生对模型参数的梯度)
∇θlogpθ(τ)=∇θlogπθ(a0∣s0)+∇θlogπθ(a1∣s1)将这个式子进行推广:
∇θlogpθ(τ)=t=0∑T−1∇θlogπθ(at∣st)因此,代入公式,我们得到:
∇θJ(θ)=Eτ[R(τ)t∑∇θlogπθ(at∣st)]From Reward to Reward-to-Go#
现在的梯度估计有个问题,轨迹级别的 reward 可能方差很大,可能导致梯度估计方差很高,而且不同 Action 的学习信号不够精细。
首先,我们的第一个优化是把 reward 换成 reward-to-go:
我们最终会优化成为的式子是:
∇θJ(θ)=Eτ[t=0∑T−1γtGt∇θlogπθ(at∣st)]对比一下这两个式子:
- Current: ∇θJ(θ)=Eτ[R(τ)∑t∇θlogπθ(at∣st)]
- Target: ∇θJ(θ)=Eτ[∑t=0T−1γtGt∇θlogπθ(at∣st)]
两者最核心的区别是,对于一条采样轨迹,每一步 Action 的梯度,在 current 中乘了 R(τ) (整条轨迹的 reward), 在 target 中乘了 reward-to-go: γtGt.
Reward to go: Gt=∑k=tT−1γk−trk
Reward: R(τ)=∑k=0T−1γkrk
因此,我们可以换个角度思考,我们只需要证明两者存在差异的部分是 0,我们展开原始式子,把 R(τ) 乘进去, 定义 gt=∇θlogπθ(at∣st):
∇θJ(θ)=Eτ[t=0∑T−1R(τ)gt]=Eτ[t=0∑T−1(k=0∑T−1γkrk)gt]我们将 reward 拆分成过去历史的 reward 和现在的 reward:
k=0∑T−1γkrk=过去的 Rewardk=0∑t−1γkrk+当前及未来的 Rewardk=t∑T−1γkrk我们考虑第一项 需要证明的是:
Eτ[t∑gtk<t∑γkrk]=0给定当前状态 st,对当前 Action 的所有可能取值求期望:
Eat∼πθ[gt∣st]=a∑πθ(a∣st)∇θlogπθ(a∣st)=a∑πθ(a∣st)πθ(a∣st)∇θπθ(a∣st)=a∑∇θπθ(a∣st)=∇θa∑πθ(a∣st)=∇θ1=0例如,我们想证明 Eτ[r0g1]=0, 在 Step 1 选择 Action 之前,r0 已经确定。用 H1 表示 Step 1 选择 Action 前的完整历史信息 (s0,a0,r1,s1)。利用条件期望:
Eτ[r0g1]=EH1[r0E[g1∣H1]]=EH1[r0×0]=0这里对 τ 轨迹的采样可以看作是两个步骤的采样,首先采样 s0,a0,r1,s1, 然后再这个条件下进一步采样 a1。数学上可以证明这样的采样顺序变化,最终的期望求解是等价的
同理,我们可以使用相同的方式证明: E[r0g2]=0.
Eτ[r0g2]=EH2[r0E[g2∣H2]]=EH2[r0×0]=0进一步归纳:
Eτ[rkgt](k<t)=EHt[rkE[gt∣Ht]]=EHt[rk×0]=0Eτ[gtk=0∑t−1γkrk]=0原命题证明成立。
因此,我们进一步优化了 Policy Gradient 的形式:
∇θJ(θ)=Eτ[t=0∑T−1γtGt∇θlogπθ(at∣st)]From Reward-to-Go to Advantages#
我们现在使用 Gt 来决定一个 action 的梯度应该被抑制还是鼓励。然而,绝对的 reward 的度量并不准确。因次,我们引入 baseline 和 advantage: At^=Gt−b(st)
同时,我们可以证明数学上的等价性:
∇θJ(θ)=Eτ[t=0∑T−1γt=Gt(Gt−b(st)+b(st))∇θlogπθ(at∣st)]考虑后一项 Eτ[∑t=0T−1γtb(st)∇θlogπθ(at∣st)]:
类似的方法,我们首先可以证明单个时间步下: Eτ[b(st)∇θlogπθ(at∣st)]=0:
Eτ[b(st)∇θlogπθ(at∣st)]=EHt[b(st)Eat∼πθ[∇θlogπθ(at∣st)]]=EHt[b(st)×0]=0因此,我们证明了后一项是 0,这个代表这梯度的等价性,与此同时,引入 gradient 可以降低整个梯度估计器 (Gt−b(st))∇θlogπθ(at∣st) 的方差,使得梯度估计可以更加稳定。
Actor-Critic 方法本质只是更好的估计 b(st), 一个只和 state 有关的量: b(st)=Vϕ(st).
我们可以挑选一个合适的度量来替换我们的 b(st), 我们这里选择: Aπ(st,at)=Qπ(st,at)−Vπ(st).
回顾条件期望的性质和 Q 的定义:
Eτ[Qπ(st,at)∇θlogπθ(at∣st)]=Eτ[Eπ[Gt∣st,at]∇θlogπθ(at∣st)]=Eτ[Gt∇θlogπθ(at∣st)]因此,最终,我们定义了 b(st) 的具体形式,写成了:
∇θJ(θ)=Eτ[t=0∑T−1γt∇θlogπθ(at∣st)Aπθ(st,at)]∇θJ(θ)∝Es,a∼πθ[∇θlogπθ(a∣s)Aπθ(s,a)]Summary#
总结一下,Policy Gradient 究竟在做什么? 关键在于求 J(θ) 的梯度:
为什么要求? J(θ) 是 RL Loss 的优化目标,需要进行梯度下降
为什么要这么求?
Step1: 定义形式
- Form: J(θ)=Eτ[R(τ)]
Step2: 梯度展开 && 求期望
- Form: ∇θJ=∑τR(τ)∇θpθ(τ)
- 存在问题: 离散采样不可微,无法求梯度
Step3: Log-Derivative Trick
- Form: ∇θJ=Eτ[R(τ)∇θlogpθ(τ)]
- 存在问题: 梯度项 pθ(τ) 由环境和策略共同决定
Step4: 轨迹概率分解
- Form: ∇θJ(θ)=Eτ[R(τ)∑t∇θlogπθ(at∣st)]
- 我们得到了第一个可求解的梯度形式! 但是我们还可以做更多优化!
Step5: Reward -> Reward to Go
- Form: ∇θJ(θ)=Eτ[∑t=0T−1γtGt∇θlogπθ(at∣st)]
- 使得整体方差更小,更稳定
Step6: Reward to Go -> Advantages
- Form: ∇θJ(θ)=Eτ[∑t=0T−1γt∇θlogπθ(at∣st)Aπθ(st,at)]
∇θJ∝Es,a[∇θlogπθ(a∣s)Aπ(s,a)]REINFORCE#
我们从理论角度出发,推导了 Policy Gradient 的数学形式:
∇θJ(θ)=Eτ[t=0∑T−1γt∇θlogπθ(at∣st)Aπθ(st,at)]这里面唯一的未知量就是 Aπθ, 在上文推导中,我们默认这个是一个已知量,在实际算法求解中,需要被估计计算。
REINFORCE 算法的梯度估计方式非常简单,通过蒙特卡洛采样的方式,直接放弃求解 Advantages,而是统计 Gt (Gt 可以通过蒙特卡罗采样的方式进行)
因此,REINFORCE 方法只是把外层的 E 换成了一个 MCMC,具体公式就是:
g^=N1i=1∑Nt=0∑Ti−1γtGi,t∇θlogπθ(ai,t∣si,t)接下来,根据梯度进行梯度上升(因为这里不是 loss,而是一个最大化目标)
θ←θ+ηg^Actor-Critic#
回到 REINFORCE 没有解决的那个问题: ∇θJ(θ)∝Es,a∼πθ[∇θlogπθ(a∣s)Aπθ(s,a)] 中 A^ 的估计是一个痛点。Actor-Critic 架构提出可以更新一个 V 网络作为可学习的 Value Function:
Vϕ(s)≈E[Gt∣st=s]=Vπ(s)结合 Value Function 的具体定义,Value Function 的作用就是评估当前状态的“价值”,类似于一个 teacher 的作用,提供打分监督。
在有一个近似的 Value Network 后(利用 rollout 的数据进行训练),就可以使用经典的近似算法来估计 At 了,比如:
- MCMC: A^t=Gt−Vϕ(st)
- TD Error: A^t=rt+γVϕ(st+1)−Vϕ(st)
具体的更新方式,在此处不做展开。
PPO#
PPO 的本质是对 Actor-Critic 网络的改进,因此其本身仍然适配在 Actor-Critic 的网络结构下,但是引入了对应的优化。
在每一次梯度更新是,算法依赖的是策略 πθ 对应的数据采样,但是每一次做完梯度更新后,旧策略的数据会被丢弃,无法继续使用。Actor-Critic 是一种 On Policy 的算法。
在实际应用中,数据收集的利用效率低下,因此可以加入重要性采样的手段,提升数据利用效率,同时避免 Off Policy 带来的问题。
重要性采样#
假设有一个函数 f(a), 计算期望:
Ea∼πθ[f(a)]=a∑πθ(a∣s)f(a)=a∑πθold(a∣s)πθold(a∣s)πθ(a∣s)f(a)因此:
Ea∼πθ[f(a)]=Ea∼πθold[πθold(a∣s)πθ(a∣s)f(a)]这个添加的比例就是重要性采样,也就是说,可以通过添加一个比例系数,来保证期望无偏性。
因此,在 PPO 中,我们定义 probability ratio 代表重要性采样:
ρt(θ)=πθold(at∣st)πθ(at∣st)定义代理目标函数,在旧策略的数据采样下进行:
LPG(θ)=Es,a∼πold[ρt(θ)A^t]∇θLPG=Eold[∇θρt(θ)A^t]=Eold[ρt(θ)∇θlogπθ(at∣st)A^t]当新旧策略相同时,代理目标函数的梯度就是真正 J(θ) 的梯度! 但是当两者偏移较远时,此时 ρt(θ) 会导致两者存在偏差。
Clipping#
在上面的框架下,我们没有做对新旧 Policy 差异的约束,如果模型在旧策略下拿到了很高的 A, 此时优化器会提高该 action 的激励(哪怕和现在的 policy 已经偏离)
因此,PPO 引入了一个 Clip 机制:
LCLIP(θ)=Et[min(ρtA^t,clip(ρt,1−ϵ,1+ϵ)A^t)]相比于之前的 LPG(θ)=Es,a∼πold[ρt(θ)A^t], 其主要的改进是后一项:
- clip(x,l,u) 代表的是将 x 的值限制约束在 [1−ϵ,1+ϵ] 中间
- 即,如果 IS 的值超过了 1+ϵ 或者低于 1−ϵ,代表此时针对这个动作新旧策略的概率分布差异太大,需要被 clip 掉
- 例如 ρt 过大,则被 clip 到最大值,此时的结果是 1+ϵ
- 例如 ρt 过小,被 clip 到最小值,但是此时 At^ 的预测值应该是一个负数 (做出了一个坏操作,对应概率被下调)
此外,PPO 作为经典的 Actor-Critic 架构,会使用 GAE 来估计 Advantage:
定义 TD_error:
δt=rt+γVϕ(st+1)−Vϕ(st)对应的估计是多阶 TD-Error 的加权结果。
A^tGAE=l=0∑T−t−1(γλ)lδt+lOff-Policy or On-Policy?#
我们具体梳理在工程实现中,PPO 的实现方式是什么:
- Iteration X:
- Rollout: 使用 Policy θ0 进行 rollout (运行 rollout batch sizes 次)
- PPO Update: for Epoch s:
- 对于每一个 mini-batch 聚合轨迹数据,计算梯度,进行梯度下降
- θ0 -> θ0,1 -> θ0,2 -> ...
- 注意,哪怕后续发生了多次偏移,在单个 iteration 中,所有的数据都使用 θ0 的数据进行更新,通过 IS 进行采样修复
- 最终,得到新的 Policy θ1
- Iteration X+1: ...
- 使用 θ1 进行轨迹数据 rollout(不再使用上一个 iteration 中的数据)
假设我们规定超参数:
- Rollout Batch Size = 1024 Responses
- Training Mini-batch Size = 256 Responses
- PPO Epoch = 4
则在单个 epoch 中 minibatches 的数量是: 1024/256 = 4, 因此在一个 iterations 内,需要做 16 次 gradient descent (epoch_num×mini_batch_size). 也就是说,可能在一个 iteration 中会有 16 个 policy checkpoint! 但是这些都使用相同的数据计算,只不过被赋予了不同的重要性采样。
因此,PPO 本质上是一种 On-Policy 的算法,但是为了提升数据复用利用效率,允许一部分数据的 Off-Policy 复用。