Skip to content

Latest commit

 

History

History
615 lines (405 loc) · 30.6 KB

04.md

File metadata and controls

615 lines (405 loc) · 30.6 KB

四、策略梯度

到目前为止,我们已经看到了如何使用基于值的方法从值函数中派生隐式策略。 在这里,智能体将尝试直接学习策略。 做法是相似的,任何有经验的智能体都会在目睹之后更改策略。

值迭代,策略迭代和 Q 学习属于通过动态编程解决的基于值的方法,而策略优化方法则涉及策略梯度和该知识与策略迭代的结合,从而产生了行动者批判算法。

根据动态编程方法,存在一组自洽方程,可以满足QV值。 策略优化是不同的,策略学习直接进行,而不是从值函数中得出:

因此,基于值的方法学习了值函数,我们得出了一个隐式策略,但是使用基于策略的方法,就不会学习任何值函数,而直接学习了该策略。 由于我们同时学习了值函数和策略,而行为者批评方法更为先进,而网络学习值函数则充当了作为参与者的策略网络的批评者。 在本章中,我们将深入研究基于策略的方法。

我们将在本章介绍以下主题:

  • 策略优化方法
  • 为什么要采用策略优化方法?
  • 策略目标函数
  • 时差规则
  • 策略梯度
  • 使用策略梯度的智能体学习 Pong

策略优化方法

策略优化方法的目标是找到随机策略π[θ],它是针对给定状态的操作分布,该状态使期望的奖励总和最大化。 它旨在直接找到该策略。 基本概述是创建一个神经网络(即策略网络),该网络处理一些状态信息并输出智能体可能采取的行动的分布。

策略优化的两个主要组成部分是:

  • 神经网络的权重参数由θ向量定义,这也是我们控制策略的参数。 因此,我们的目标是训练权重参数以获得最佳策略。 由于我们将保单视为给定保单的预期奖励总和。 在此,对于θ的不同参数值,策略将有所不同,因此,最佳策略将是具有最大总体奖励的策略。 因此,具有最大预期奖励的θ参数将是最佳策略。 以下是预期奖励金额的公式:

那就是最大化期望的奖励总和。

这里, H地平线的时间步长,因此,如果开始时间步长t = 0,则总时间步长为H + 1

  • 随机策略类消除了策略优化问题,为我们提供了一组可以选择最佳策略的策略。 在网格世界环境中采用确定性策略的情况下,由于动作变化而导致的变化并不平滑,但是如果每个状态都有动作分布,我们可以稍微改变分布,而这只会稍微改变预期的总和。 奖励。 这是使用随机策略的优势,其中π[θ](a | s)给出给定状态s的动作a的概率。 因此,π[θ]给出了给定状态下动作的概率分布。

因此,由于随机策略,我们有一个平滑的优化问题,可以应用梯度下降来获得良好的局部最优,从而导致最优策略。

为什么要采用策略优化方法?

在本节中,我们将介绍策略优化方法相对于基于值的方法的优缺点。 优点如下:

  • 它们提供了更好的融合。
  • 在高维/连续状态动作空间的情况下,它们非常有效。 如果动作空间很大,则基于值的方法中的max函数将在计算上昂贵。 因此,基于策略的方法通过更改参数来直接更改策略,而不是在每个步骤中求解max函数。
  • 学习随机策略的能力。

与基于策略的方法相关的缺点如下:

  • 收敛到局部而不是全局最优
  • 策略评估效率低下且差异很大

我们将在本章后面讨论解决这些缺点的方法。 现在,让我们集中讨论对随机策略的需求。

为什么采用随机策略?

让我们看两个例子,这些例子将解释基于值方法将随机策略与接近确定性策略相结合的重要性。

示例 1-石头,剪刀,布

石头,剪刀,布是两人游戏,包含以下规则:

  • 石头打剪刀
  • 剪刀打布
  • 布打石头

因此,不可能有确定的策略来取胜。 说,如果有确定性的策略,那摇滚总是赢家,但是如果对手有剪刀,情况就是这样。 但是,当对手拿到纸时,石头就被击败了。 因此,在这种环境下无法确定解决方案。 解决此问题的唯一方法是使用本质上是随机的统一随机策略。

示例 2-名为网格世界的状态

考虑以下别名为 grid-world 的状态:

在上图中,我们看到有八个状态,其中两个奖励为 -10 的状态是要避免的不良状态,并且有一个奖励为 10 的状态是良好状态,还有目标状态。 但是,我们主要担心的是灰色阴影状态,在该状态下,智能体无法区分这两个状态,因为它们具有相同的特征。

假设任何状态的特征都为φ(s, a),动作为北,东,西和南。

考虑到这些函数,让我们比较基于值的方法和基于策略的方法:

  • 基于值的强化学习将使用近似值函数Q(s, a) = f(φ(s, a), w)
  • 基于策略的强化学习将使用参数化策略π[θ](s, a) = g(φ(s, a), θ)

在此,w是值函数的参数,θ是策略的参数。 众所周知,灰色方块具有相同的特征,即在北部和南部都有墙。 因此,由于相同的特征,这导致状态混淆。 结果,基于值的强化学习方法学习了如下确定性策略:

  • 要么在两个灰色阴影状态下向西移动
  • 或在两个灰色阴影状态下向东移动

无论哪种方式,都极有可能被卡住或花费很长时间达到目​​标状态。

另一方面,在基于策略的方法的情况下,最优随机策略将随机选择处于灰色状态的东西方行为,因为这两种行为具有以下相同的概率:

  • (南北墙,行动=东)= 0.5
  • (南北墙,行动=西)= 0.5

结果,它将以更少的步骤达到目标状态,因为西方和东方都将具有相同的发生概率。 因此,与基于值的强化学习方法相比,不同的灰色阴影状态可能会随机发生不同的动作,从而导致目标状态更快。 因此,基于策略的强化学习可以学习最佳的随机策略。

因此,从前面的示例中,我们已经知道,每当发生状态别名时,随机策略都可以执行得更好。 因此,只要存在状态混叠的情况(即环境的表示),就会部分观察状态(例如,您处于部分可观察的马尔可夫决策过程中)或函数逼近器使用状态的特征,这会限制环境的整体视角,使用基于随机策略的基于策略的方法要比基于值的方法要好。

策略目标函数

现在让我们讨论如何优化策略。 在策略方法中,我们的主要目标是具有参数向量θ的给定策略J(θ)找到参数向量的最佳值。 为了测量哪个最好,我们针对参数向量θ的不同值测量J(θ)策略π[θ](s, a)的质量。

在讨论优化方法之前,让我们首先弄清楚度量策略π[θ](s, a)的质量的不同方法:

  • 如果是情景环境,则J(θ)可以是开始状态V[π[θ]](s[1])的值函数,也就是说,如果它从任何状态s[1]开始,则其值函数将是该状态开始时的预期奖励总和 。 因此,

  • 如果是连续环境,则J(θ)可以是状态的平均值函数。 因此,如果环境持续不断,那么策略质量的衡量标准可以是处于任何状态s的概率之和,该概率是d[π[θ]](s)乘以该状态的值,也就是说,从该状态开始的预期奖励。 因此,

  • 对于连续环境,J(θ)可以是每个时间步长的平均奖励,它是处于任何状态s的概率的总和,即d[π[θ]](s)乘以对该状态的不同动作的期望奖励E[R[s]^a] = Σ[a] π[θ](s, a) R[s]^a的总和。 因此:

在此,R[s]^a是在状态s采取行动a的奖励。

到目前为止,我们知道基于策略的强化学习是一个优化问题,目标是找到使J(θ)最大化的θ。 同样,在这里,我们将使用基于梯度的方法进行优化。 使用基于梯度的优化的原因是要获得更高的效率,因为与无梯度方法相比,梯度指向了更高效率的方向。

让衡量策略质量的J(θ)成为我们的策略目标函数。 因此,策略梯度算法通过相对于参数θ提升策略的梯度,在J(θ)中寻找局部最大值。 这是因为我们的目标是使J(θ)相对于θ最大化,因此我们进行了梯度上升,其中 为Δθ的参数的增量如下:

在这里,ᐁ[θ] J(θ)是策略梯度,α是学习率,也称为步长参数,步长参数决定该参数应在每个步长上偏移多少梯度。 策略梯度还可以用以下形式阐述:

策略梯度定理

假设给定策略π[θ](s, a)每当不为零时都是可微的,则给定策略相对于θ的梯度为ᐁ[θ] π[θ](s, a)。 因此,我们可以以似然比的形式进一步利用此梯度量,如下所示:

此处,ᐁ[θ] log π[θ](s, a)是得分函数,供将来参考。

现在,让我们考虑一个简单的一步式 MDP,即马尔可夫决策过程,其中:

  • 起始状态为s,发生的可能性为d[π[θ]](s)
  • 终止仅发生在获得奖励r = R[s]^a的一步之后

考虑到它是一个持续的环境,因此:

因此,策略梯度ᐁ[θ] J(θ)将如下所示:

在这里,我们证明了以下几点:

结果是:

因此,将该方法推广到多步马尔可夫决策过程将导致状态奖励 Q 值函数Q[π](s, a)代替瞬时奖励r。 这称为策略梯度定理。 该定理对前面讨论的其他类型的策略目标函数有效。 因此,对于任何这样的策略目标函数和任何可微分的π[θ](s, a),策略梯度如下:

时差规则

首先,时间差TD)是两个时间步之间的值估计值之差。 这与基于结果的蒙特卡洛方法不同,后者基于前瞻性的观点直到剧集结束才完成,以更新学习参数。 在时间差异学习的情况下,仅需完成一个步骤,而下一步的状态值估计将用于更新当前状态的值估计。 因此,学习参数会不断更新。 进行时差学习的不同规则是TD(1)TD(0)TD(λ)规则。 所有方法中的基本概念是,下一步的值估计用于更新当前状态的值估计。

TD(1)规则

TD(1)纳入了资格跟踪的概念。 让我们看一下该方法的伪代码,然后将详细讨论它:

Episode T
    For all s, At the start of the episode : e(s) = 0 and 
        After  : (at step t)

        For all s,

每个Episode T都以以下初始化开始:

  • 对于所有状态s,合格分数e(s) = 0
  • 对于所有状态s,给定Episode T中的状态值V[T](s)等于V[T-1](s)

在剧集的每个时间步,即当前步t,我们更新要离开的状态s[t-1]的资格,然后为所有状态更新以下内容:

  • 针对当前离开状态s[t-1](即r[t] + γ V[T-1](s[t]) + V[T-1](s[t-1]))和要更改其值的状态的合格分数e(s)使用时间差误差的状态值函数
  • 通过给定折扣系数进行折扣的资格分数

由于这些更新针对所有状态独立发生,因此可以针对所有状态并行执行这些操作。

在完成剧集的最后一步之后扩展每个状态的计算值估计值时,我们发现基于值的更新与基于结果的更新相同,例如在蒙特卡洛方法中,我们会进行全面的展望,直到剧集的结尾。 因此,我们需要一种更好的方法来更新我们的值函数估计值,而无需多做一步。 通过合并TD(0)规则,我们可以解决此问题。

TD(0)规则

如果无限重复重复有限数据,则TD(0)规则会找到值估计值,通常就是如果我们获取此有限数据并不断重复运行以下估计值更新规则。 然后,实际上我们正在平均每个转换。

因此,值函数由以下给出:

在基于结果的模型中,这是不正确的,在该模型中,我们不使用状态估计值V[T](s[t]),而是使用整个奖励序列,直到事件结束为止。 因此,在蒙特卡洛方法基于结果的模型的情况下,值函数由以下公式给出:

此外,在基于结果的方法中,我们只看到一个序列,重复该过程不会更改值函数的值。 但是,在TD(0)的情况下,每一步都会根据中间状态计算和完善值函数估计。

TD(0)TD(1)之间的区别是,在TD(1)情况下使用资格跟踪更新状态值函数,而在TD(0)情况下则不使用。

TD(0)规则的伪代码如下:

Episode T
    For all s, At the start of the episode : 
        After  : (at step t)
        For s = ,

因此,这里我们仅使用时间差误差r[t] + γ V[T-1](s[t]) + V[T-1](s[t-1])更新当前离开状态s[t-1]的值函数。

TD(λ)规则

TD(1)TD(0)规则产生一个通用规则,即TD(λ),因此对于λ ∈ [0, 1]并应满足以下条件:

  • 如果λ = 0,则TD(λ)趋于TD(0)
  • 如果λ = 1,则TD(λ)趋于TD(1)

TD(0)TD(1)都基于时间连续预测之间的差异进行更新。

因此,TD(λ)的伪代码如下:

Episode T
    For all s, At the start of the episode : e(s) = 0 and 
        After  : (at step t)

        For all s,

这满足前面两个条件,并且可以合并λ ∈ [0, 1]的任何值。

策略梯度

根据策略梯度定理,对于先前指定的策略目标函数和任何可微分策略π[θ](s, a),策略梯度如下:

下一节显示了使用基于蒙特卡洛策略梯度的方法更新参数的步骤。

蒙特卡洛策略梯度

蒙特卡洛策略梯度方法中,我们使用随机梯度上升方法更新参数,并按照策略梯度定理进行更新,并使用v[t]作为Q[π[θ]](s[t], a[t])的无偏样本。 在此,v[t]是从该时间步开始的累计奖励。

蒙特卡洛策略梯度法如下:

Initialize  arbitrarily
for each episode as per the current policy  do
    for step t=1 to T-1 do

    end for
end for

Output: final 

演员评论家算法

先前使用蒙特卡洛策略梯度方法进行的策略优化导致较大的差异。 为了解决此问题,我们使用评论家来估计状态作用值函数,如下所示:

这产生了著名的演员评论家算法。 顾名思义,演员评论家算法出于以下目的维护两个网络:

  • 一个网络充当评论者,它更新状态动作函数逼近器的权重w参数向量
  • 其他网络充当演员,它根据批评者给出的方向更新策略参数向量θ

下图代表了演员评论家算法:

因此,在执行者批评算法的情况下,实际策略梯度公式中的真实状态作用值函数Q[π[θ]](s, a)被替换为近似状态作用值函数Q[w](s, a)。 因此:

并且:

因此,为了估计状态作用值函数,评论者网络使用TD(0)(先前讨论)来更新权重参数w,并更新策略参数向量θ演员网络使用策略梯度。 演员评论家算法的一种简单方法如下所示:

Initialize s, 
for each episode
    Sample  as per the current policy     
    for each step do 
        Take action  and observe reward  and next state 
        Sample action  as per the current policy 

    end for
end for

Output : final 

因此,我们可以看到参与者评论家既具有基于值的优化又具有基于策略的优化。 因此,在采用蒙特卡洛策略梯度法的情况下,策略改进会贪婪地进行。 但是在演员批评家中,演员通过按照批评家的方向采取措施来更新策略参数,以便制定更好的策略。

使用基线减少方差

除了我们最初使用行为准则的方法来减少方差之外,我们还可以通过从策略梯度中减去基线函数 来减少方差。 这将减少方差而不影响期望值,如下所示:

有许多选择基线函数的选项,但是状态值函数被认为是很好的基线函数。 因此:

因此,我们可以通过减去基线函数来重写策略梯度公式,如下所示:

在这里,Q[π[θ]](s, a) - A[π[θ]](s)被称为优势函数A[π[θ]](s, a)。 因此,策略梯度公式变为:

因此,通过使用基线函数,期望值受到方差降低的控制,而方向没有任何变化。

原始策略梯度

在常规策略梯度方法中,目标是使用策略梯度估计和更好的基线估计来更新策略。

以下是实现原始策略梯度以找到最佳策略的伪代码:

Initialize: Policy parameter , and baseline b
for iteration = 1,2,......N   do
        Collect a set of trajectories using the current policy
        At each time step t in each trajectory, compute the following:
            returns ,and
            advantage estimate 
        Refit the baseline function 

end for

使用策略梯度的学习 Pong 的智能体

在本节中,我们将创建一个策略网络,该策略网络将使用来自 pong 环境的原始像素(来自 OpenAI Gym 的 pong-v0)作为输入。 策略网络是一个单独的隐藏层神经网络,它全连接到输入层上 pong 的原始像素,还全连接到包含单个节点的输出层,该单个节点返回了桨上升的可能性。 我要感谢 Andrej Karpathy 提出了一种使智能体使用策略梯度进行学习的解决方案。 我们将尝试实现类似的方法。

灰度大小为80 * 80的像素图像(我们将不使用 RGB,即80 * 80 * 3)。 因此,我们有一个80 * 80的二进制网格,它告诉我们桨和球的位置,并将其作为输入输入到神经网络。 因此,神经网络将包含以下内容:

  • 输入层(X:将80 * 80压缩为6400 * 1,即 6400 个节点
  • 隐藏层:200 个节点
  • 输出层:1 个节点

因此,总参数如下:

  • 连接输入层和隐藏层的权重和偏置6400 * 200(权重)+ 200(偏置)参数
  • 连接隐藏层和输出层的权重和偏置200 * 1(权重)+ 1(偏置)参数

因此,总参数将约为 130 万。

这是巨大的,因此训练需要几天的时间才能见证您的经纪人流畅地打乒乓球。

不能从静态帧播放 Pong,因此,需要捕获某种运动信息,可以通过连接两个这样的帧或新帧与前一帧之间的差异来完成。 因为我们没有使用卷积神经网络,所以除了 6400 个像素值在 0 和 1 之间翻转之外,没有可用的空间信息。 而不是桨和球的位置。

训练 130 万个参数的有效计算方法是使用策略梯度。 您可以将其与监督学习相关联,其中针对每个状态都提到了一个动作标签。 因此,数据和训练如下:

但是,实际上我们没有标签。 因此,我们将实现强化学习,在其中我们将尝试许多任务并记下观察结果。 然后,更频繁地执行表现更好的任务。

在输入 Python 代码之前,让我们放下步骤。 它们如下:

  1. 初始化随机策略。
  2. 对于给定的当前策略,我们将通过以下方式收集不同的样本轨迹(展示):
    1. 运行游戏的一个剧集并捕获该剧集的轨迹。
    2. 同样,收集一批轨迹,如下所示:
轨迹 游戏结果 轨迹好/坏
上,下,上,上,下,下,下,上
下,上,上,下,上,上
上,上,下,下,下,下,上
下,上,上,下,上,上

因此,我们能够创建示例数据,在这些示例中,我们认为赢得的案例是该操作的正确标签。 因此,我们将增加这些动作的对数概率,即log p(y[i], x[i]),并且每个动作失败的情况将被视为错误标签。 因此,在这些情况下,我们将减少这些操作的对数概率。

因此,在收集了一批轨迹之后,我们将最大化优势与对数概率的乘积,即Σ[i] A[i] x log p(y[i], x[i])

在此,A[i]是与状态操作对关联的优势。 优势是一个标量,它量化了操作最终的效果。 如果我们想在将来鼓励给定的行动,则A[i]会很高,而如果我们想阻止该行动,则A[i]会很低。 正优势使该状态的将来更有可能发生该行为,而负优势使该状态的将来不太可能发生该行为。

首先,我们将导入所需的重要依赖项,如下所示:

#import dependencies
import numpy as np #for matrix math
import cPickle as pickle #to save/load model
import gym
  • 超参数初始化:由于我们正在使用RMSProp优化器进行梯度下降,因此超参数(例如隐藏层节点的数量,批量大小,学习率,折扣系数gamma,衰减率)。 我们将使用以下代码进行初始化:
#hyperparameters
H = 200 #number of nodes in the hidden layer
batch_size = 10 
learning_rate = 1e-4 
gamma = 0.99 #discount factor
decay_rate = 0.99 #for RMSProp Optimizer for Gradient Descent
resume = False #to resume from previous checkpoint or not
  • 策略神经网络模型初始化:策略神经网络的权重参数的初始化。 在这里,我们使用一个隐藏层神经网络。 我们将使用以下代码进行初始化:
#initialize : init model
D = 80*80 #input dimension
if resume:
    model = pickle.load(open('model.v','rb'))
else:
    model = {}
    #xavier initialisation of weights
    model['W1'] = np.random.randn(H,D)*np.sqrt(2.0/D)
    model['W2'] = np.random.randn(H)*np.sqrt(2.0/H)
    grad_buffer = {k: np.zeros_like(v) for k,v in model.iteritems()} #to store our gradients which can be summed up over a batch
    rmsprop_cache = {k: np.zeros_like(v) for k,v in model.iteritems()} #to store the value of rms prop formula
  • 激活函数sigmoid(x)relu(x)分别指执行 Sigmoid 和 ReLU 激活计算的函数。 我们将使用以下代码定义函数:
#activation function
def sigmoid(x):
    return 1.0/(1.0+np.exp(-x)) #adding non linearing + squashing

def relu(x):
    x[x<0] = 0
    return x
  • 预处理函数preprocess(image)函数将图像像素作为参数,并通过裁剪,下采样,使其成为灰度,擦除背景并将图像展平为一维向量来对其进行预处理。 我们将使用以下代码定义函数:
#preprocessing function
def preprocess(image): #where image is the single frame of the game as the input
    """ take 210x160x3 frame and returns 6400 (80x80) 1D float vector """
    #the following values have been precomputed through trail and error by OpenAI team members
    image = image[35:195] #cropping the image frame to an extent where it contains on the paddles and ball and area between them
    immage = image[::2,::2,0] #downsample by the factor of 2 and take only the R of the RGB channel.Therefore, now 2D frame
    image[image==144] = 0 #erase background type 1
    image[image==109] = 0 #erase background type 2
    image[image!=0] = 1 #everything else(other than paddles and ball) set to 1
    return image.astype('float').ravel() #flattening to 1D
  • 折扣奖励discount_rewards(r)函数将与不同时间步长对应的奖励列表r作为参数,并返回与不同时间步长对应的折扣奖励列表,如以下代码所示 :
def discount_rewards(r):
    """ take 1D float array of rewards and compute discounted reward """
    discount_r = np.zeros_like(r)
    running_add = 0 #addition of rewards
    for t in reversed(xrange(0,r.size)):
        if r[t] != 0: #episode ends
            running_add = 0
        running_add = gamma*running_add+r[t]
        discount_r[t] = running_add
    return discount_r
  • 正向传播policy_forward(x)函数接收预处理的图像向量x,返回动作概率为UP,并且向量包含隐藏状态节点的值,例如以下代码:
def policy_forward(x):
    h = np.dot(model['W1'],x) 
    h = relu(h) 
    logit = np.dot(model['W2'],h)
    p = sigmoid(logit)
    return p,h #probability of action 2(that is UP) and hidden layer state that is hidden state
  • 反向传播policy_backward(arr_hidden_state, gradient_logp, observation_values)函数采用隐藏状态值,误差gradient_logp和观测值来针对不同权重参数计算导数,如以下代码所示:
def policy_backward(arr_hidden_state,gradient_logp,observation_values):
    """ backward pass """
    #arr_hidden_state is array of intermediate hidden states shape [200x1]
    #gradient_logp is the loss value [1x1]
    dW2 = np.dot(arr_hidden_state.T,gradient_logp).ravel() 
    # [200x1].[1x1] => [200x1] =>flatten=>[1x200]
    dh = np.outer(gradient_logp,model['W2']) # [1x1]outer[1x200] => [1x200]
    dh = relu(dh) #[1x200]
    dW1 = np.dot(dh.T,observation_values) #[200x1].[1x6400] => [200x6400]
    return {'W1':dW1,'W2':dW2}

创建环境并结合先前的函数以使智能体逐步学习多个剧集的最终任务如下:

#implementation details
env = gym.make('Pong-v0')
observation = env.reset()
prev_x = None 
#prev frame value in order to compute the difference between current and previous frame
#as discussed frames are static and the difference is used to capture the motion
#Intially None because there's no previous frame if the current frame is the 1st frame of the game
episode_hidden_layer_values, episode_observations, episode_gradient_log_ps, episode_rewards = [], [], [], []
running_reward = None
reward_sum = 0
episode_number = 0

#begin training
while True:
    env.render()
    #get the input and preprocess it
    cur_x = preprocess(observation)
    #get the frame difference which would be the input to the network
    if prev_x is None:
        prev_x = np.zeros(D)
    x = cur_x - prev_x
    prev_x = cur_x

    #forward propagation of the policy network
    #sample an action from the returned probability
    aprob, h = policy_forward(x)
    #stochastic part
    if np.random.uniform() < aprob:
        action = 2
    else:
        action = 3

    episode_observations.append(x) #record observation
    episode_hidden_layer_values.append(h) #record hidden state
    if action == 2:
        y = 1
    else:
        y = 0

    episode_gradient_log_ps.append(y-aprob) #record the gradient

    #new step in the environment
    observation,reward,done,info = env.step(action)
    reward_sum+=reward #for advantage purpose
    episode_rewards.append(reward) #record the reward

    if done: #if the episode is over
        episode_number+=1

        #stack inputs,hidden_states,actions,gradients_logp,rewards for the episode
        arr_hidden_state = np.vstack(episode_hidden_layer_values)
        gradient_logp = np.vstack(episode_gradient_log_ps)
        observation_values = np.vstack(episode_observations)
        reward_values = np.vstack(episode_rewards)

        #reset the memory arrays
        episode_hidden_layer_values, episode_observations, episode_gradient_log_ps, episode_rewards = [], [], [], []

        #discounted reward computation
        discounted_episoderewards = discount_rewards(reward_values)
        #normalize discounted_episoderewards
        discounted_episoderewards = (discounted_episoderewards - np.mean(discounted_episoderewards))/np.std(discounted_episoderewards) #advantage

        #modulate the gradient with the advantage
        gradient_logp *= discounted_episoderewards

        grad = policy_backward(arr_hidden_state,gradient_logp,observation_values)

        #summing the gradients over the batch size
        for layer in model:
            grad_buffer[layer]+=grad[layer]

        #perform RMSProp to update weights after every 10 episodes
        if episode_number % batch_size == 0:
            epsilon = 1e-5
            for weight in model.keys():
                g = grad_buffer[weight] #gradient
                rmsprop_cache[weight] = decay_rate*rmsprop_cache[weight]+(1-decay_rate)`g`2
                model[weight]+=learning_rate*g/(np.sqrt(rmsprop_cache[weight]) + epsilon)
                grad_buffer[weight] = np.zeros_like(model[weight])

        if running_reward is None:
            running_reward = reward_sum
        else:
            running_reward = running_reward*learning_rate+reward_sum*(1-learning_rate)

        print('Episode Reward : {}, Running Mean Award : {}'.format(reward_sum,running_reward))
        if episode_number % 100 == 0:
            pickle.dump(model,open('model.v','wb'))

        reward_sum = 0
        prev_x = None
        observation = env.reset() #resetting the environment since episode has ended

    if reward != 0: #if reward is either +1 or -1 that is an episode has ended
        print("Episode {} ended with reward {}".format(episode_number,reward))

智能体玩的游戏的屏幕截图:

如果您在笔记本电脑上运行先前的代码,则融合可能需要几天的时间。 尝试使用 GPU 驱动的云实例在大约 5-6 个小时内获得更好的结果。

总结

在本章中,我们介绍了强化学习中最著名的算法,策略梯度和参与者批评算法。 在制定策略梯度以强化学习中更好的基准测试方面,正在进行大量研究。 策略梯度的进一步研究包括信任区域策略优化TRPO),自然策略梯度深度依赖策略梯度DDPG),这些内容不在本书的讨论范围之内。

在下一章中,我们将研究 Q 学习的基础知识,应用深度神经网络以及更多技术。