强化学习 -Part 2:Modern Methods

上一篇 强化学习-Part 1:From MDP to DQN 我们介绍了强化学习的基本问题,MDP 建模方法,以及 value-based 的强化学习方法。这些方法我归类为传统方案,其中 DQN 方法在 2014 年在雅达利游戏中超过人类选手。本文介绍的 Policy based 以及 Actor-Critic 方法是现在强化学习的主流方法。当然这些方法也大量使用了 value-based 的想法,以及我们上一篇文章介绍的 MC、TD-Learning 等随机近似的方法。
本篇文章,我们会先讨论基于 Policy 的 Policy gradient 方法,REINFORCE。然后讨论 policy 和 value 结合的 actor-critic 方法。基于此,我们会进一步讨论 TRPO 和 PPO 这些现代方法。

我们首先回顾一下,在 MDP 模型的设置下,我们使用了贝尔曼公式和贝尔曼最优公式描述了 state、 action value 的关系。为了估计 value 的值,使用 MC 方法进行估计,或者使用 TD-Learning 来渐进式的估计 value,最后引入 value function 刻画连续状态下的 value 值。利用神经网络强大的泛化性来拟合 value。所有的一切围绕讨论如何求解 value,我们期望求得 action value q(s,a),在此基础上求得 policy(ε-greedy / max greedy)。

Policy-based 方法的基本想法是:我们能不能直接求得策略 Policy,而不是通过先求 action value,再求 policy。
如何直接获得 policy 呢?非常类似优化 value function 的思路,我们还是使用梯度下降的想法。首先定义一个基于 policy 的损失函数(也叫 metrics),然后优化(最大化)这个 metrics,当遇到未知变量的时候,我们尝试用“近似值”替代。

Policy Gradient

为了直接求解 policy,我们定义 policy 为下面的式子,不同于之前的定义 π(a|s),新增了 θ 表示策略的参数:

π(a|s,θ)

这里的策略可以用一个神经网络来表示,他的输入是状态,输出是 action,模型的参数是 θ, 也可以表示为 πθ(a|s),或者 πθ(a,s)

在上一篇文章中策略定义为 π(a|s),之所以没有参数 θ, 是因为我们的策略不需要参数,他要不是从 q(s,a) 里面 greedy 求出,要不是结合 ε-greedy 策略给出。

我们定义,和策略相关的 metric,目的是“只要优化 metrics,是得 metrics 最大,我们就能得到最优的策略”

Metrics

Metric 1:Average state value

v¯π=sSd(s)vπ(s) J(θ)=E[t=0γtRt+1]

注意,换个角度理解,这个损失函数可以看作是所有路径 trajectory 的 discounted Return 的加权和(即,期望 E[G(τ)]

Metric 2:Average one-step reward

r¯πsSdπ(s)rπ(s)=E[rπ(S)], limn1nE[Rt+1+Rt+2++Rt+n|St=s0]=limn1nE[k=1nRt+k|St=s0]=limn1nE[k=1nRt+k]=sdπ(s)rπ(s)=r¯π

两个 metrics 可以相互转换

r¯π=(1γ)v¯π.

求梯度

我们再回忆一下我们的目标:希望找到一个策略使得上面的 metric 最大化。

基本思路:下面的推导思路与我们上一篇文章中的 value 的函数近似类似。在 metric/损失函数的基础上求导,进行梯度上升/下降。我们会把求梯度后的形式转化为期望的形式(Expection, E[...]),然后使用 RM 算法迭代求期望的近似解(近似的梯度为 0 时的解 θ 的值)。同时当表达式里面有未知量(这里分别state value vπ(s) 或者 action value qπ(s,a))的时候,再次使用近似算法(MC 或者 TD)求解。
基于上面的基本思路,我们观察上面的 metric 公式,有一个“小问题”,上面 metric 的定义都是基于 Reword,我们需要把他们展开为 value(vπ(s), qπ(s,a)) 和 policy (π(as,θ)) 相关函数。

可以对对比 value 的函数近似那里直接就是 state Value,可以直接应该 rm,这里就需要对公式镜像展开化简。

对上面的 metric 求梯度,直接给出一个通用的解如下所示(他适用于上面所有的 metric):

θJ(θ)=sSη(s)aAθπ(a|s,θ)qπ(s,a)=E[θlnπ(A|S,θ)qπ(S,A)]

上面第一行到第二行的推导里面这里使用到的一个 log 的导数的公式,我们通过他把梯度最终转化为了“期望”的形式。

θlnπ(a|s,θ)=θπ(a|s,θ)π(a|s,θ)

这一步推导如下(简而言之,就是从公式里面提取出 state s, action a 对应的概率到 Expection 里面):

θJ=sd(s)aθπ(as,θ)qπ(s,a)=sd(s)aπ(as,θ)θlnπ(as,θ)qπ(s,a)=Esd[aπ(as,θ)θlnπ(as,θ)qπ(s,a)]=Esd,aπ[θlnπ(as,θ)qπ(s,a)]=E[θlnπ(AS,θ)qπ(S,A)]

上面我们直接给出了梯度的结论,他是如何导出的呢?下面内容作为参考:
针对 metric E[t=0γtRt+1] 这可以有两种表述,他们是等价的:

  1. 训练一个 Policy π(as,θ) 例如神经网络,在所有的 Trajectory 中,得到 Return 的期望最大。E(R(τ))τPθ(τ)=τR(τ)Pθ(τ)
  2. 寻找一个 Policy π(as,θ) 例如神经网络,在所有状态 S 下,给出相应的 Action,得到 Return 的期望最大。
    为了把把公式转化为包含策略 π 的形式 我们需要把上面的“1”转化为 “2”:
  3. 求梯度: θEτPθ[R(τ)]=τR(τ)θPθ(τ)=EτPθ[R(τ)θlnPθ(τ)]
  4. 轨迹概率 Pθ(τ) 可分解为初始状态分布和策略的乘积: Pθ(τ)=p(s0)t=0T1π(at|st,θ)p(st+1|st,at)
  5. 求 2 中的轨迹概率的梯度,θlnPθ(τ)=t=0T1θlnπ(at|st,θ)
  6. 3 代入 1 中:θE[R(τ)]=EτPθ[R(τ)t=0T1θlnπ(at|st,θ)]
  7. 重点理解这里的 R(τ) 表示的是一个轨迹 Trajectory 的奖励之和 k=0T1γkrk,他是长期累计奖励(Discounted Reward)随机变量 Gt 的一个采样(Sample)
  8. 由于 k=0T1γkrk 只是一个采样,所以可能非常不稳定,variance 非常大,
  9. 实践中,我们一步只要考虑时间 t 之后的 reward 就行,t 之前的 reward 应该对当前 action 没有影响。即 R(τ) 修改为 k=tT1γktrk
  10. θE[R(τ)]=EτPθ[t=0T1θlnπ(at|st,θ)k=tT1γktrk]
  11. 考虑 R(τ) 在这里非常的不稳定,是使用 E[Gt]) 即轨迹 return 的期望,而不是轨迹 return 的采样来作为 R(τ)E[GtSt=s,At=a] 就是 qπ(st,at) 的定义!
  12. 最终我们得到了上面的公式 θJ=Esd,aπ[θlnπ(as,θ)qπ(s,a)]

基于上面的梯度公式的期望形式,使用 RM 算法迭代估计求解 θ

θt+1=θt+αθlnπ(at|st,θt)qt(st,at)

根据这个迭代公式,只要我们有后面的采样值就能一步一步的求解出 θ, 其中 θlnπ(at|st,θt) 已知(如果是个神经网络,直接 autograd 既可求出),后面的 qt(st,at) 不知道。

理解 gradient

分析上面公式的 intuition,首先我们尝试理解里面的 ln 的作用,这可以从两个不同的角度看,然后从 exploit-explore 的角度分析策略梯度的含有。

角度一:展开 θlnπ(at|st,θt),我们发现他是一个策略梯度除以策略的形式:

θt+1=θt+αqt(st,at)θπ(at|st,θt)π(at|st,θt)

如果我们不用 θlnπ(at|st,θt),而是直接 θπ(at|st,θt),这可能会导致对于出现次数多的 action 的偏好。分母部分充当了一个 normalize 的作用。例如,有一个 action 序列 s1,a1,s2,a2,s3,a2,s4,a2, 假设他们的 action value 相同,且都是大于 0,使用这个 trajectory 来 update θ,多导致我们多次 update action a2, 会增大这个 action a2 的概率,然而可能不是说因为这个 action 本身价值大,只是因为他出现的次数多。

角度二:如果再仔细观察策略梯度的更新公式

θt+1=θt+αθlnπ(at|st,θt)qt(st,at)

其实再 ML 中,我们还有一个常见的任务,多分类的交叉熵包含 ln

L=i=1CyilogpiθθαθL

对于某个样本而言,只有一个 yi 为 1,其他为 0,此时

θθαθlog(pi)

我们可以把学习的策略也看作一个多分类问题(classification task),于是策略梯度的公式可以解释为使用 action value 加权的多分类 loss

角度三:另外一个现实意义的 intuition 是,我们稍微变形一下:

θt+1=θt+α(qt(st,at)π(at|st,θt))βtθπ(at|st,θt)

如此整理后,这个方程可以看成是对策略 π(at|st,θt) 进行梯度上升:随着迭代的进行,在状态 st 下,策略对动作 at 给予更大概率,我们把 βt 看作影响梯度更新的常数:

REINFORCE

回忆上一小结,我们通过对 metrics 的参数 θ 求导得到了梯度的期望形式,然后通过 RM 近似算法得到了对策略参数 θ 的更新公式

θt+1=θt+αθlnπ(at|st,θt)qt(st,at)

在这个公式中,我们对 qt(st,at) 的值是不知道,因此无法实际使用,显然根据前面的 Value 函数近似一节中估计 vπ(s) 思想,这里也可以对 qt(st,at) 进行近似估计。思路也是两个

image.png

Actor-Critic 算法

上一节我们提到也可以使用 TD Learning 的方法来估计 qπ(st,at),TD 方法的一个好处是我们可以 sample 一步(不需要完整的 episode)就可以 apply 来估计 action value,换言之,变成了一个 online 的方法(incremental)。结合了 TD 方法后我们也叫这种方法为 Actor-Critic 算法,至于为什么这么叫,可以看我们下面的分析,还是一个十分形象的叫法。再次回忆 policy gradient 的更新公式

θt+1=θt+αθlnπ(at|st,θt)qt(st,at)

QAC

最简单的 Actor-Critic(QAC) 算法也很直接,就是同步使用 SARSA 算法估计 quality qt(st,at) 和 update policy
image.png

A2C

引入 Advantage 的概念,其核心是在我们的策略梯度的定义中(Expection 形式)引入了 baseline 的概念

θJ(θ)=ESη,Aπ[θlnπ(A|S,θt)qπ(S,A)]=ESη,Aπ[θlnπ(A|S,θt)(qπ(S,A)b(S))]

上面公式中的 b(S) 就是我们新加入的 baseline,他的存在不会影响上面策略梯度定义中的 Expection 的值。他只会影响里面随机变量的 bias。通过减去这个 baseline,我们 sample 的部分可以有更小的方差,也就是我们会有更稳定的结果。
Baseline 的选择,最优的 baseline 比较复杂,我们忽略,一般选择 state value,即

b(s)=EAπ[q(s,A)]=vπ(s)

因此,我们有了一个更直观的解释:这里的 Critic 的评估标准是:一个 action 的 quality(qπ(s,a))是不是是这个状态的平均质量 (vπ(s)) 高?

简单的代入 baseline,参数的梯度上升公式:

θt+1=θt+αE[θlnπ(A|S,θt)[qπ(S,A)vπ(S)]]θt+αE[θlnπ(A|S,θt)δπ(S,A)]

其中,我们定义

δπ(S,A)qπ(S,A)vπ(S)

是 Advantage Function。(优势函数)
使用随机近似的梯度更新的公式如下:

θt+1=θt+αθlnπ(at|st,θt)[qt(st,at)vt(st)]=θt+αθlnπ(at|st,θt)δt(st,at)

理解 Gradient 同样的方法,我们也可以像下面这样理解这个更新公式

θt+1=θt+αθlnπ(at|st,θt)δt(st,at)=θt+αθπ(at|st,θt)π(at|st,θt)δt(st,at)=θt+α(δt(st,at)π(at|st,θt))step sizeθπ(at|st,θt)

可以看到这里的 stepsize 理解也是从 exploit-explore 框架入手,这里 Advantage function 扮演了 exploit 的角色

最后一个问题,由于上面的 Advantage function 有即有 action value q(s,a) 又有 state value v(s), 近似估计起来不是很方便,我们可以利用他们的定义来简单的变形:

δt=qt(st,at)vt(st)rt+1+γvt(st+1)vt(st)

我们可以只依赖 state value v(s) 的近似估计就可以完成 Advantage 的计算了。

image.png

Importance Sample

上面的 policy graident算法都是 on-policy,因为我们再推导策略梯度时候需要满足 Esd,aπ[θlnπ(as,θ)qπ(s,a)] 这个公式,要求我们的 action 从策略 π sample。即生成数据的 behavior policy 和训练的 target policy 是相同,这限制了我们数据的来源,使用当前策略生成的数据往往是低效(不能使用旧数据训练)。

EXp0[X]=xp0(x)x=xp1(x)p0(x)p1(x)xf(x)=EXp1[f(X)] EXp0[X]f¯=1ni=1nf(xi)=1ni=1np0(xi)p1(xi)xi

一个常见的疑问是:上面的公式中我们需要知道 p0(x), 如果我已经他的概率为什么不能直接用 E[X]=p0(x)x 直接求出期望?核心的原因是我们只知道他的概率值,而不知道他的总体分布(即不知道他的分布表达式,无法就和或者求积分),典型的例子是 x 是神经网络的输出值,只知道他的概率,例如策略 π(θk)

基于上面 Importance sample 原理,我们给出使用重要性采样的策略梯度

θJ(θ)=ESρ,Aβ[π(A|S,θ)β(A|S)θlnπ(A|S,θ)qπ(S,A)]

引入 Baseline 的版本的梯度是:

θJ(θ)=E[π(A|S,θ)β(A|S)θlnπ(A|S,θ)(qπ(S,A)vπ(S))]

这里的 β(A|S) 就是 behavior policy,我们数据采样的分布
Baseline 版本的公式还能进一步化简,把下面的 update 公式

θt+1=θt+αθπ(at|st,θt)β(at|st)θlnπ(at|st,θt)δt(st,at)

展开 θlnπ(at|st) 约掉分子部分

θt+1=θt+αθ(δt(st,at)β(at|st))θπ(at|st,θt)

同样的我们理解这个更新公式:

最终的 off policy 版本的 A2C 算法的版本如下:
image.png
这个算法中

一个补充,上面我们假设我们的策略是有限个的 action 输出,即 π(at|st,θt) 例如一个多分类的神经网络,我们有 n 个策略,且我们要求这次 action 的概率全部都大于 0(不能等于 0)。
还有一种情况是,Policy 是一个固定的输出,表示连续的动作空间,即 Deterministic Actor,用 a=μ(s,θ)μ(s) 表示,他只有一个输出 action,就是我们要执行的动作是什么(其他的动作的概率是 0),此时我们策略梯度的公式的形式有些不同,参考 DPGDDPG 的算法。
PS:这里所说的连续动作,常用在机器人控制领域,就是如果选择了某个动作,其他的动作概率就是 0。比如动作空间是 0-30 角度的连续值,我们无法给每个值指定概率,只能输出一个具体的角度值。

Actor-Critic 优化算法

前面,我们讨论基于 Policy Gradient 的 Actor-Critic 算法(A2C),尤其是我们引入了 Importance sample 算法,得到了 off-policy A2C 算法。虽然理论上 off-policy 提高了数据的利用率, 然而 off-policy 算法在实际使用是还是会存在不稳定的问题,例如“离线数据”与当前策略相差过大,重要性采样导致了高的方差,这些问题的存在可能导致总体上并没有提升有效数据利用率,反而降低了效率。因此,在现代强化学习中,还是大量使用的一些“精心设计”的 on-policy 算法,例如 TRPO,PPO。他们通过结合一些 off-policy 的思想,达成了更强的性能。
一些优化点包括:

TRPO && PPO

之前 On-Policy 版本的 A2C 方法,样本效率很低,我们每次 sample 完一个 episode 后只能更新一次策略参数 θ,然后又得重新采样。有没有一种方法能一次 sample 多个 episode 然后多次 update 策略呢?这其实就是把上面我们提出的 Importance Sample 引入 On-Policy 方法中。

为什么不能直接在 On-Policy 中采样多个 episode,然后 update 多次参数呢?
因为 update 参数之后,策略参数的分布就变了,如果多次更新,旧的 episode 和新的策略就不一致了。其实这个处理方法和 off-policy 一样。

回忆我们学习的 A2C 方法, on-policy 版本策略参数的更新公式如下:

θt+1=θt+αθδtθlnπ(at|st,θt)

Off-policy 版本策略参数的更新公式如下:

θt+1=θt+αθπ(at|st,θt)β(at|st)δtθlnπ(at|st,θt)

其中 δt 是 Advantage function(优势函数,在很多文章中也用 At 表示),下面我们就是把这个 off-policy 版本的更新公式加入到在线策略中。

PPO/TRPO 算法流程如下:

  1. 初始化策略参数 θ0
  2. 在每一轮迭代 k 中
    1. 使用 θk 与环境交互,收集训练数据集,多个 episode 的集合 {st,at}
    2. 使用 θk 计算所有的 Advantage function Aθk(st,at)
    3. 使用策略梯度多次迭代优化目标函数 Jθk(θ)(当前 update 的参数是 θ,旧的参数是 θk

上面 Jθk(θ) 的目标函数引入重要性采样,定义如下
我们假设每一轮迭代的当前目标策略参数是 θ, 上一轮的旧策略参数是 θ

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

PS:如果转化为参数的 update 公式,其实和off-policy 的 A2C 的更新公式一致。

下面我们从策略梯度开始推导,加入重要性采样, 最后反推出原始的目标函数 Jθk(θ)

  1. 不含 Importance Sample 的策略梯度: E(st,at)πθ[Aθ(st,at)logπθ(atn|stn)]
  2. 加入 importance Sample: E(st,at)πθ[Pθ(st,at)Pθ(st,at)Aθ(st,at)logπθ(atn|stn)]
  3. 用条件概率展开 weight, E(st,at)πθ[πθ(at|st)πθ(at|st)pθ(st)pθ(st)Aθ(st,at)logπθ(atn|stn)]
  4. 这里假设了 pθ(st)pθ(st) 相等,即在不同的策略下,状态出现的概率相同。
  5. 我们展开 log 的梯度,然后约掉相同的项:E(st,at)πθ[πθ(at|st)πθ(at|st)Aθ(st,at)]
  6. 这里是梯度,去掉求导符号反推出原始的 cost function 是 E(st,at)πθ[πθ(at|st)πθ(at|st)Aθ(st,at)]

如果我们对参数 θ 的更新的太大(步长太长),可能会显著的导致策略变差。TRPO 方法中通过引入约束 KL 散度限制 θ 变化的范围来缓解这个问题:

JTRPOθk(θ)=Jθk(θ)st.KL(θ,θk)<ξ

上面的约束入如同在更新时找到一块信任区域(trust region),在这个区域上更新策略时能够得到某种策略性能的安全性保证,这就是信任区域策略优化(trust region policy optim)。TRPO 就变成了一个带约束条件的优化问题,这个问题一般使用拉格朗日法来求解。实际计算比较复杂,很难优化,实际上我们还是用 PPO 比较多,经验证明,PPO 对比 TRPO 能取得类似的效果。
PPO 则是直接在 J(θ) 中加入 KL 散度作为 Metric:

JPPOθk(θ)=Jθk(θ)βKL(θ,θk) JPPO2θk(θ)(St,at)min(πθ(at|st)πθk(at|st)Aθk(st,at),clip(πθ(at|st)πθk(at|st),1ε,1+ε)Aθk(st,at))

对这个公式理解是他通过控制优势的权重的大小来控制策略参数 θ 的范围:

image.png

上图中 x 轴是我们通过 Importance Sample 计算出来的权重, y 轴是变化后的权重(也可以看作 Metric 大小,就是再乘以 A),红色的线是上面公式的结果,可以简单理解为控制 Metric 的范围。可以看到

上面的红线直接看所 metric 函数,就是我们的优化目标,这个目标我们要控制好,不能让他过高(左图,上面的情况一),或者过低(右图,上面的情况 2)

补充 PPO 收集数据过程:

GAE(Generalized Advantage Estimation)

在上面的 Actor-Critic、PPO 算法中,使用 value function 或者 Advantage function 充当 baseline(Critic),回忆Advantage function 的定义如下:

δt=qt(st,at)vt(st)rt+1+γvt(st+1)vt(st)

在实际应用到时候,我们训练网络计算(直接回归)state value (v(st)),然后使用 Advantage function 的公式就可以计算出“优势”。
观察上面的公式,可以看出这是对优势函数的一步估计,即我们只使用了一步的 reward rt+1 展开了公式来近似估计 action value。这里存在的问题是虽然估计的方差较小,但是可能偏差较大。类似我们之前学习的 n-step sample,这里我们也可以了使用多步采样,甚至直接 MC 出这个值来。一种更为“先进”的方法是:我们对从 1 步采样的 Advantage 到 n 步的采样的 Advantage 求一个加权平均,这就是 GAE 的思想。

从时间 t 开始,定义 1 步,2 步估计等的 Advantage function 如下:

Aθ1(st,a)=rt+γVθ(st+1)Vθ(st)Aθ2(st,a)=rt+γrt+1+γ2Vθ(st+2)Vθ(st)Aθ3(st,a)=rt+γrt+1+γ2rt+2+γ3Vθ(st+3)Vθ(st)

每个时间步的 1 步估计的的 Advantage function 公式:

δtV=rt+γVθ(st+1)Vθ(st)δt+1V=rt+1+γVθ(st+2)Vθ(st+1)

使用上面的 1 步估计来表示多步估计的公式:

Aθ1(st,a)=δtVAθ2(st,a)=δtV+γδt+1VAθ3(st,a)=δtV+γδt+1V+γ2δt+2V

GAE 就是上面多步估计的加权

AθGAE(st,a)=(1λ)(Aθ1+λAθ2+λ2Aθ3+)

实际在应该的时候我们怎么计算这个 GAE AθGAE(st,a) 呢?

本质上,GAE 就是对 advantage function 的值的估计的优化,希望在方差和偏差上去得 balance,实际中,这个方法也非常有效,GAE 基本是现代 PPO 方法标配

总结

让我们自上而下的梳理本篇文章,如果要理解现代强化学习中最常用的 PPO 方法,需要我们有一些背景知识。PPO 是一种 On-Policy 的 Actor-Critic 方法,他改进自 TRPO,简化了对策略分布约束的方法。TRPO/PPO 这类方法的核心 Policy Gradient,同时结合了 Importance Sample 实现了在 on-policy 条件下更高的样本效率。此外,这类 AC 方法又要依赖我们上一篇文章中介绍的 Value Function Estimation 来实现 Critic。针对 Value 估计的改进引入了 GAE 方法。

graph TD
    A["PPO(Proximal Policy Optimization)"] --> B["TRPO"]
    A --> B1["GAE"]
    A --> B2["KL形式损失"]
    A --> B3["CLIP形式损失:PPO2"]
    B --> C["Actor-Critic"]
    B --> C1["Importance Sampling"]
    B --> C2["KL 散度约束"]
    C --> D["On-Policy Policy Gradient"]
    C --> D1["BaseLine:优势函数"]
    D --> E["Metric 定义"]
    D --> F["理解 Gradient表达式"]
    D1 --> H["Value Estimation"]
    
    B1 --> D1
    B2 --> C2
   
    
   
    
    
    style A fill:#f9f,stroke:#333
    style D fill:#bbf,stroke:#333
    style C1 fill:#bbf,stroke:#333