近端策略优化(PPO)算法是OpenAI在2017提出的一种强化学习算法,被认为是目前强化学习领域的SOTA方法,也是适用性最广的算法之一。本文将从PPO算法的基础入手,理解从传统策略梯度算法(例如REIFORCE算法)、自然策略梯度算法、信赖域策略优化算法(TRPO)直到PPO算法的演进过程,以及算法迭代过程中的优化细节。整体框图如下图所示。
强化学习算法可以分为两大类:基于值函数的强化学习和基于策略的强化学习。
基于值函数的强化学习通过递归地求解贝尔曼方程来维护Q值函数(可以是离散的列表,也可以是神经网络),每次选择动作时会选择该状态下对应Q值最大的动作,使得未来积累的期望奖励值最大。经典的基于值函数的强化学习算法有Q-Learning、SARSA、DQN算法等。这些算法在学习后的Q值函数不再发生变化,每次做出的策略也是一定的,可以理解为确定性策略。基于策略的强化学习不再通过价值函数来确定选择动作的策略,而是直接学习策略本身,通过一组参数 对策略进行参数化,并通过神经网络方法优化 。
基于策略的强化学习用参数化概率分布代替了基于值函数的强化学习中的确定性策略,在返回的动作概率列表中对不同的动作进行抽样选择。
基于参数化策略的思想,我们的目标就是找到那些可能获得更多奖励的动作,使它们对应的概率更大,从而策略就更有可能选择这些动作。为此,我们定义的最大化目标函数 如下:其中 是agent与环境交互产生的状态-动作轨迹 ,对 求和代表的是与环境交互可能产生的所有情况。我们的目标是通过调整 ,使得获得更大奖励的轨迹出现的概率更高。
其中,轨迹 在策略 下发生的概率定义为:
表示为状态转移概率和动作选择概率的乘积,因为状态和动作决定轨迹。
与神经网络的优化思路相同,为了通过参数 优化目标函数,我们需要计算目标函数 对 的导数:推导过程中使用了对数导数技巧,将 表示为对数的形式,从而可以方便的重写为:
其中第一步中第一项的状态转移概率只与环境有关,而与 无关。
然而,到目前为止的计算还需要对所有可能的轨迹进行求和,这在实际的RL问题中是难以处理的,我们需要利用轨迹样本进行梯度近似,表达式如下:
现在的表达式是完全可计算的,现在只需要给出策略 的明确定义,就可以计算得到 ,从而用策略梯度更新规则: 来对 进行调整优化,从而不断迭代至最优策略。
这里给出两种常见的策略示例及其对应梯度。
- Softmax策略
对于离散动作空间,多使用Softmax策略。其定义如下:对应的策略梯度为: 梯度的结果可以解释为观察到的特征向量减去所有动作的平均特征向量。因此,如果奖励信号很高并且观察到的向量与平均向量相差很大,就会有增加该动作概率的强烈趋势。
- 高斯策略
对于连续动作空间,多使用高斯策略。其定义如下其中正态分布的均值 。
对应的策略梯度为:
同样地,在高回报的情况下,远离均值的动作会触发强烈的更新信号。由于概率总和必须为 1,因此增加某些轨迹的概率也意味着减少其他轨迹的概率。
在实际任务中,我们没有必要手动计算偏导数,使用深度学习框架的自动求导就好了。为了实现自动求导,我们只需要根据之前策略梯度的推导结果,定义损失函数如下:
就可以让计算机解决所有的推导。
Williams提出的REINFORCE算法[1]是经典的策略梯度算法之一。其伪代码如下所示:
算法思路简介明了,是最简单的基于似然比的策略梯度强化学习算法。接下来我们将介绍如何对REINFORCE算法进行一步步的优化,直到发展为强大的PPO算法的过程。
自然策略梯度算法[2]揭露了传统策略梯度算法的缺点以及补救的方法,尽管自然梯度已被TRPO和PPO等算法超越,但掌握它的基本原理对于理解这些当代RL算法至关重要。
对自然梯度的完整讨论需要具备较强的数学功底,需要许多冗长的推导。我们的讨论将主要关注推理和直觉,为更深入的推导提供外部参考。
在传统的策略梯度算法中,我们根据目标函数梯度 和步长 更新策略权重 ,这样的更新过程可能会出现两个常见的问题:
- 过冲(Overshooting):更新错过了奖励峰值并落入了次优策略区域
- 下冲(Undershooting):在梯度方向上采取过小的更新步长会导致收敛缓慢
在监督学习问题中,overshooting并不是什么大问题,因为数据是固定的,我们可以在下一个epoch中重新纠正,但在强化学习问题中,如果因为overshooting陷入了一个较差的策略区域,则未来的样本批次可能不会提供太多有意义的信息,用较差的数据样本再去更新策略,从而陷入了糟糕的正反馈中无法恢复。较小的学习率可能会解决这个问题,但会导致收敛速度变慢的undershooting问题。
为了避免overshooting带来的严重后果,一种直觉方法是限制每次更新步长的上限:其中 代表更新前后策略权重的欧式距离。
尽管听起来很合理,但实际效果并不是像我们预期的那样,原因是不同的分布对参数变化的敏感度是不同的。比如在下图中,我们都让策略权重变化了1个单位的欧式距离,但是对左图的影响是远大于右图的。所以,只限制参数是不合理的,更应该考虑分布对参数变化的敏感度,传统的策略梯度算法无法考虑到这种曲率变化,我们需要引入二阶导数,这正是自然策略梯度相较于传统策略梯度算法的区别。
我们需要表示策略(分布)之间的差异,而不是参数本身的差异。计算两个概率分布之间的差异,最常见的是KL散度[3],也称为相对熵,描述了两个概率分布之间的距离:
调整后的策略更新限制为: 通过计算这个表达式,我们可以确保在参数空间中执行大更新的同时,保证策略本身的改变不超过阈值。然而,计算KL散度需要遍历所有的状态-动作对,因此我们需要一些化简来处理现实的RL问题。
接下来的数学部分,可以在Katerina Fragkiadaki(CMU)关于自然策略梯度的PPT[4]中找到详细的证明推导。
首先,我们使用拉格朗日松弛将原表达式的发散约束转化为惩罚项,得到一个更容易求解的表达式:
由于计算KL散度需要遍历所有的状态-动作对,我们必须用近似方法来化简。通过泰勒展开:
目标函数近似于一阶泰勒展开(与散度相比,二阶展开可以忽略不计),KL散度近似于二阶泰勒展开(零阶和一阶差分的计算结果为0)。我们可以进一步化简,通过
- 用费舍尔信息矩阵(Fisher information matrix)替换二阶KL导数
- 删除所有不依赖于 的项
可以得到:用费舍尔信息矩阵代替二阶导数的原因,除了符号紧凑性外,还可以大大减少计算开销。原先的Hessian矩阵是一个 的矩阵,每个元素都是二阶导数,完整的计算可能非常麻烦,而对于Fisher信息矩阵,有一个替代表达式: 可以表示为策略梯度的外积,在局部等效于Hessian,同时计算效率更高(因为传统策略梯度的这些值 本身也是我们需要的,无需再重复计算,同时期望意味着可以使用样本近似)。
对于近似简化后的表达式,可以通过将关于 的梯度设置为0,来找到最优的权重更新 :
其中, 是一个常数,可以吸收到学习率 中。根据 ,我们可以推出动态学习率:
可以确保每次更新的KL散度(近似)等于 。
最后,我们提取自然策略梯度,它是针对流形曲率校正的梯度:
这种自然策略梯度在距离约束内给出了黎曼空间中最陡的下降方向,而不是传统上假设的欧几里德空间中的最陡下降方向。与传统的策略梯度相比,唯一的区别是与逆Fisher矩阵相乘。
最终的权重更新方案为:
该方案的强大之处在于,无论分布的表示如何,它总是以相同的幅度改变策略。
自然策略梯度算法的完整概述伪代码[5]如下。其中策略梯度和Fisher矩阵在实际计算时都是使用样本估计的。
最终结果在两个方面不同于传统的策略梯度算法:
- 考虑到策略对局部变化的敏感性,策略梯度由逆Fisher矩阵校正,而传统的梯度方法假定更新为欧几里得距离。
- 更新步长 具有适应梯度和局部敏感性的动态表达式,确保无论参数化如何,策略变化幅度为 。在传统方法中, 通常设置为一些标准值,如0.1或0.01。
Trust region policy optimization(TPRO)算法[6]是现代强化学习的基础,它以自然策略梯度优化为基础,迅速获得普及,成为主流强化学习算法,因为它在经验上比自然策略梯度算法表现得更好、更稳定。尽管此后它已被近端策略优化 (PPO) 超越,但它的仍然具有重要的意义。
我们将讨论TRPO背后的单调改进定理(关注直觉)以及将其与自然策略梯度区分开的三个变化。
- 近似值可能会违反KL约束,从而导致分析得出的步长过大,超出限制要求
- 矩阵 的计算时间太长,是 复杂度的运算
- 我们没有检查更新是否真的改进了策略。由于存在大量的近似过程,策略可能并没有优化
针对自然策略梯度算法的问题,我们希望可以对策略的优化进行量化,从而保证每次的更新一定是优化作用的。为此,我们需要计算两种策略之间预期回报的差异。这里采用的是原策略预期回报添加新策略预期优势的方式[7]。该表达式在原策略下计算优势函数,无需重新采样:其中优势函数的定义为:
在给定的策略和状态下,计算特定动作$a$的期望累积奖励与总体期望值的差值,描述了该动作的相对吸引力。
由于时间范围是无限的,引入状态的折扣分布 ,原差异表达式可重新表示为: 我们无法在不对更新策略进行采样的情况下知道对应于更新策略的状态分布,故引入近似误差,使用当前策略近似: 接下来,我们将状态分布求和替换为期望,方便实际计算时使用蒙特卡洛模拟进行采样,同时将动作求和替换为重要性采样。通过重要性采样,可以有效利用当前策略的行动期望,并针对新策略下的概率进行了修正:
描述更新策略相对于原策略的预期优势称为替代优势(surrogate advantage): 之前产生的近似误差可以用两种策略之间最坏情况的KL散度表示: 论文中推导出 的值以及目标函数改进的下限。如果我们改进右侧,可以保证左侧也得到改进。本质上,如果替代优势 超过最坏情况下的近似误差 ,我们一定会改进目标。
这就是单调改进定理。相应的过程是最小化最大化算法(MM)。即如果我们改进下限,我们也会将目标改进至少相同的量。
在实际的算法实现方面,TRPO和自然策略梯度算法没有太大的区别。TRPO主要有三个改进,每个改进都解决了原始算法中的一个问题。TRPO的核心是利用单调改进定理,验证更新是否真正改进了我们的策略。
3.2.1 共轭梯度法(conjugate gradient method)
在自然策略梯度算法中,计算逆Fisher矩阵是一个耗时且数值不稳定的过程,特别是对于神经网络,参数矩阵可以变得非常大, 的时间复杂度将无法计算。
好消息是,我们对逆矩阵本身并不感兴趣。观察自然策略梯度的方程式,如果我们可以直接得到乘积 ,就不再需要逆。
引入共轭梯度法,这是一个近似上式乘积的数值过程,这样我们就可以避免计算逆矩阵。共轭梯度通常在 步内收敛,从而可以处理大矩阵。
共轭梯度法并不是TRPO中独有的,例如在Truncated Natural Policy Gradient[^9]中也部署了相同的方法,但它仍然是算法中的一个重要组成部分。
3.2.2 线搜索(line search)
虽然自然梯度策略中提供了给定KL散度约束的最佳步长,但由于存在较多的近似值,实际上可能不满足该约束。
TRPO 通过执行线搜索来解决此问题,通过不断地迭代减小更新的大小,直到第一个不违反约束的更新。这个过程可以看作是不断缩小信任区域,即我们相信更新可以实际改进目标的区域。
更新迭代减小的方式是使用指数衰减率 , 随迭代的进行而增加。同时,在约束条件的判断中,我们看到KL散度约束不是唯一满足的约束,它还保证了替代优势 非负,这就是接下来介绍的改进检查。
3.2.3 改进检查
在TRPO中,我们并没有假设更新会提高替代优势 ,而是真正检查了它。尽管实际计算时需要根据旧策略计算优势,以及使用重要性抽样来调整概率,会花费一些时间,但验证更新是否真正改进了策略是有必要的。
3.2.4 算法完整框架
TRPO执行了共轭梯度算法、约束样本KL散度的线搜索和检查改进替代优势,相较于自然策略梯度算法有了较大的改进,代表了自然策略梯度发展的一个重要里程碑。
TRPO算法解决了许多与自然策略梯度相关的问题,并获得了RL社区的广泛采用。但是,TRPO仍然存在一些缺点,特别是:
- 无法处理大参数矩阵:尽管使用了共轭梯度法,TRPO仍然难以处理大的 Fisher矩阵,即使它们不需要求逆
- 二阶优化很慢:TRPO的实际实现是基于约束的,需要计算上述Fisher矩阵,这大大减慢了更新过程。此外,我们不能利用一阶随机梯度优化器,例如ADAM
- TRPO 很复杂:TRPO很难解释、实现和调试。当训练没有产生预期的结果时,确定如何提高性能可能会很麻烦
在TRPO的基础上,Schulman等人引入了近端策略优化算法PPO(Proximal Policy Optimization)[8]。有两种主要的PPO变体需要讨论(均在17年的论文中介绍):PPO Penalty和PPO Clip。我们首先从PPO Penalty入手,它在概念上最接近TRPO。
TRPO在理论分析上推导出与KL散度相乘的惩罚项,但在实践中,这种惩罚往往过于严格,只产生非常小的更新。因此,问题是如何可靠地确定缩放参数β ,同时避免overshooting:
难点是很难确定适用于多个问题的某个 值。事实上,即使是同一个问题,随着时间的推移,特征也可能发生变化。我们既不希望 过大,与TRPO一样只产生较小的更新,也不希望 过大,容易出现overshooting问题。
PPO通过设置目标散度 的方式解决了这个问题,希望我们的每次更新都位于目标散度附近的某个地方。目标散度应该大到足以显著改变策略,但又应该小到足以使更新稳定。
每次更新后,PPO都会检查更新的大小。如果最终更新的散度超过目标散度的 1.5倍,则下一次迭代我们将加倍 来更加重惩罚。相反,如果更新太小,我们将 减半,从而有效地扩大信任区域。迭代更新的思路与TRPO线搜索有一些相似之处,但PPO搜索是在两个方向上都有效的,而TRPO是单向减小的。
这里基于超过目标值的1.5倍将 加倍或减半并不是数学证明的结果,而是基于启发式确定的。我们会不时违反约束条件,但通过调整 可以很快地纠正它。根据经验,PPO对数值设置是非常不敏感的。总之,我们牺牲了一些数学上的严谨性来使实际的效果更好。
与自然策略梯度和TRPO算法相比,PPO更容易实现。同时,我们可以使用流行的随机梯度下降算法(如ADAM等)执行更新,并在更新太大或太小时调整惩罚。
总之,PPO比TRPO更容易使用,同时不失竞争力。PPO的第二种变体PPO Clip将会做的比PPO Penalty更好。
Clipped PPO是目前最流行的PPO的变体,也是我们说PPO时默认的变体。PPO Clip相比于PPO Penalty效果更好,也更容易实现。
与PPO Penalty不同,与其费心随着时间的推移改变惩罚,PPO Clip直接限制策略可以改变的范围。我们重新定义了替代优势:
其中, 为重要性采样:
clip为截断函数,当重要性采样超出规定的上或下限后,函数会返回对应的上或下限。
项 和 不依赖于 ,产生的梯度为0。因此,可信区域之外的样本被有效地抛出,避免过大的更新。我们没有明确地限制策略更新本身,只是简单地忽略了过度偏离策略所带来的优势。和PPO Penalty一样,我们可以使用像ADAM等优化器来执行更新。
PPO Clip中根据优势的正负性以及重要性采样的范围,可以分为六种可能的案例,在下图中对六种案例进行了总结[9]。
为了实现想要达到的效果,我们应该调整 ,作为对KL散度的隐式限制。根据经验, 和 是实际效果较好的值。尽管这些值与自然策略梯度的理论基础有些偏差(该理论建立在假设 的局部近似值之上),但在实际运行时的效果较好。
PPO2是Open AI发布的算法更新版本,是矢量化环境的PPO算法实现,针对 GPU 进行了优化,更好地支持并行训练。它与PPO也有许多实际实现的差异,例如优势被自动归一化、价值函数被裁剪等,但与本文概述的PPO具有相同的数学基础。如果需要直接使用OpenAI实现的PPO算法,则应该使用PPO2。
从传统策略梯度算法,到自然策略梯度算法,再到TRPO算法,以及最终的PPO算法,经过不断的优化迭代,PPO算法已经成为强化学习领域最主流的算法。不论是学术界中的各大顶会文章,还是工业界中例如chatgpt的背后强化学习部分的实现,都离不开PPO算法的身影。
纵向来看,对策略梯度算法的改进,主要针对的就是限制参数迭代的这一步。自然策略梯度算法引入了KL散度约束,TRPO利用线搜索和改进检查来保证限制下的可行性,PPO则通过clip函数限制了策略可以改变的范围等。
相比于自然梯度和TRPO所具有的理论保证和数学技巧,PPO放弃了一些数学上的严谨性,但往往能比其竞争对手更快更好地收敛。看来PPO在速度、严谨性和可用性之间取得了正确的平衡,在未来几年来依旧会保有属于它的竞争力。