为了更好地理解 PPO,看看这篇论文的主要贡献是有帮助的,它们是:(1) Clipped Surrogate Objective 和 (2) the使用“随机梯度上升的多个时期来执行每个策略更新”。
来自原PPO paper:
我们引入了 [PPO],这是一系列策略优化方法,它使用多个随机梯度上升时期来执行每个策略更新。这些方法具有 trust-region [TRPO] 方法的稳定性和可靠性,但实现起来要简单得多,只需更改几行代码即可实现普通策略梯度,适用于更普遍设置(例如,当为策略和价值函数使用联合架构时),并具有更好的整体性能。
1.裁剪的代理目标
Clipped Surrogate Objective 是策略梯度目标的直接替代品,旨在通过限制您在每个步骤中对策略所做的更改来提高训练稳定性。
对于普通策略梯度(例如,REINFORCE)——您应该熟悉,或者在阅读本文之前familiarize yourself with --- 用于优化神经网络的目标如下所示:
这是您将在 Sutton book 和 other resources 中看到的标准公式,其中 A-hat 可以是折扣回报(如 REINFORCE)或优势函数(如 @987654328 @) 例如。通过相对于网络参数对这种损失采取梯度上升步骤,您将激励导致更高回报的行动。
普通策略梯度方法使用您的操作的对数概率 (log π(a | s)) 来跟踪操作的影响,但您可以想象使用另一个函数来执行此操作。在this paper 中引入的另一个此类函数使用当前策略 下的动作概率 (π(a|s)) 除以先前策略下的动作概率 (π_old(a|s))。如果你熟悉的话,这看起来有点类似于重要性抽样:
当您的当前政策比您的旧政策更可能执行此操作时,此 r(θ) 将大于 1政策;当您当前的政策不太可能采取行动时,它将介于 0 和 1 之间。
现在用这个 r(θ) 构建一个目标函数,我们可以简单地将它换成 log π(a|s) 项。这就是 TRPO 中所做的:
但是,如果您的行动对于您当前的策略来说更有可能(比如 100 倍以上),会发生什么情况? r(θ) 往往会非常大,并导致采取较大的梯度步骤,可能会破坏您的政策。为了解决这个问题和其他问题,TRPO 添加了一些额外的花里胡哨(例如,KL Divergence 约束)来限制策略可以更改的数量并帮助保证它是单调改进的。
与其添加所有这些额外的花里胡哨,不如将这些稳定属性构建到目标函数中呢?正如您可能猜到的,这就是 PPO 所做的。它获得了与 TRPO 相同的性能优势,并通过优化这个简单(但看起来有点滑稽)的 Clipped Surrogate 目标避免了复杂性:
最小化中的第一项(蓝色)与我们在 TRPO 目标中看到的 (r(θ)A) 项相同。第二项(红色)是 (r(θ)) 被限制在 (1 - e, 1 + e) 之间的版本。 (在论文中,他们指出 e 的良好值约为 0.2,因此 r 可以在 ~(0.8, 1.2) 之间变化)。然后,最后,对这两个项进行最小化(绿色)。
花点时间仔细查看方程式,确保您知道所有符号的含义,以及数学上正在发生的事情。查看代码也可能有所帮助;这是 OpenAI baselines 和 anyrl-py 实现中的相关部分。
太棒了。
接下来,让我们看看 L 剪辑功能会产生什么效果。这是论文中的图表,它绘制了优势为正和负时的剪辑目标值:
在图表的左半部分,其中 (A > 0),这是行动对结果产生积极影响的估计位置。在图的右半部分,(A
注意在左半边,如果 r 值太高,它会被剪掉。如果在当前政策下采取的行动比在旧政策下更有可能发生,就会发生这种情况。当这种情况发生时,我们不想贪婪而走得太远(因为这只是我们策略的局部近似和样本,所以如果我们走得太远将不准确),因此我们将目标裁剪为防止它从成长。 (这会在反向传播中起到阻挡渐变的效果---导致渐变为0的平线)。
在图表的右侧,动作对结果产生了估计的负面影响,我们看到剪辑在 0 附近激活,在当前策略下的动作不太可能发生。在我们刚刚迈出了一大步降低动作的可能性之后,这个剪辑区域同样会阻止我们更新太多以降低动作的可能性。
因此,我们看到这两个裁剪区域都可以防止我们变得过于贪婪并尝试一次更新太多,从而离开该样本提供良好估计的区域。
但是为什么我们让 r(θ) 在图的最右侧无限增长呢?这看起来很奇怪,但是在这种情况下,什么会导致 r(θ) 变得非常大? r(θ) 在这个区域的增长将是由使我们的操作很多的梯度步骤引起的更有可能,结果证明我们的政策更糟。如果是这种情况,我们希望能够撤消该梯度步骤。碰巧 L 剪辑功能允许这样做。这里的函数是负数,所以梯度会告诉我们往另一个方向走,并且按照与我们搞砸的程度成正比的程度降低动作的可能性。 (请注意,图的最左侧有一个类似的区域,该区域的动作很好,但我们不小心降低了它的可能性。)
这些“撤销”区域解释了为什么我们必须在目标函数中包含奇怪的最小化项。它们对应于未剪辑的 r(θ)A,其值低于剪辑版本并通过最小化返回。这是因为它们是朝错误方向迈出的一步(例如,动作很好,但我们不小心降低了它的可能性)。如果我们没有在目标函数中包含最小值,这些区域将是平坦的(梯度 = 0),我们将无法修复错误。
这是一个总结的图表:
这就是它的要点。 Clipped Surrogate Objective 只是您可以在 vanilla 策略梯度中使用的替代品。剪裁限制了您可以在每个步骤中进行的有效更改以提高稳定性,并且最小化使我们能够纠正我们的错误,以防我们搞砸了。我没有讨论的一件事是 PPO 目标是什么意思,形成了论文中讨论的“下限”。有关更多信息,我建议this part 作者的讲座。
2.策略更新的多个时期
与普通策略梯度方法不同,并且由于裁剪代理目标函数,PPO 允许您在样本上运行多个梯度上升时期,而不会导致破坏性的大策略更新。这使您可以从数据中提取更多信息并减少样本效率低下的情况。
PPO 使用 N 个并行参与者运行策略,每个参与者收集数据,然后它对这些数据的小批量进行采样,以使用 Clipped Surrogate Objective 函数训练 K 个 epoch .请参阅下面的完整算法(近似参数值为:K = 3-15, M = 64-4096, T (horizon) = 128 -2048):
parallel actor部分被A3C paper普及,已经成为一种相当标准的数据收集方式。
较新的部分是他们能够在轨迹样本上运行 K 个梯度上升时期。正如他们在论文中所说,对数据进行多次传递的普通策略梯度优化会很好,这样您就可以从每个样本中了解更多信息。然而,这在实践中对于普通方法通常会失败,因为它们对本地样本采取了太大的步骤,这会破坏策略。另一方面,PPO 具有防止过多更新的内置机制。
对于每次迭代,在使用 π_old 对环境进行采样后(第 3 行)以及当我们开始运行优化(第 6 行)时,我们的策略 π 将完全等于 π_old。所以一开始,我们的更新都不会被剪裁,我们保证从这些例子中学到一些东西。然而,当我们使用多个 epoch 更新 π 时,目标将开始达到裁剪限制,这些样本的梯度将变为 0,训练将逐渐停止……直到我们继续进行下一次迭代并收集新样本.
....
这就是现在的全部内容。如果您有兴趣获得更好的理解,我建议您深入研究original paper,尝试自己实现它,或者深入研究baselines implementation 并使用代码。
[编辑:2019/01/27]:为了更好地了解背景以及 PPO 与其他 RL 算法的关系,我还强烈建议查看 OpenAI 的 Spinning Up resources and implementations。