04.md 33.2 KB
Newer Older
W
wizardforcel 已提交
1
# 策略梯度
W
wizardforcel 已提交
2

W
wizardforcel 已提交
3
到目前为止,我们已经看到了如何使用基于价值的方法从值函数中派生隐式策略。 在这里,代理将尝试直接学习策略。 做法是相似的,任何有经验的代理人都会在目睹之后更改策略。
W
wizardforcel 已提交
4 5 6

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

W
wizardforcel 已提交
7
根据动态编程方法,存在一组自洽方程,可以满足`Q``V`值。 策略优化是不同的,策略学习直接进行,而不是从值函数中得出:
W
wizardforcel 已提交
8 9 10

![](img/783c3d44-900b-4334-a5e6-b4a2a297a1a8.png)

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

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

W
wizardforcel 已提交
15 16
*   策略优化方法
*   为什么要采用策略优化方法?
W
wizardforcel 已提交
17
*   策略目标函数
W
wizardforcel 已提交
18
*   时差规则
W
wizardforcel 已提交
19
*   策略梯度
W
wizardforcel 已提交
20 21
*   使用策略梯度的 Agent 学习 Pong

W
wizardforcel 已提交
22
# 策略优化方法
W
wizardforcel 已提交
23

W
wizardforcel 已提交
24
策略优化方法的目标是找到随机策略![](img/e183d447-5314-4850-9e50-21a8888bf8c6.png),它是针对给定状态的操作分布,该状态使期望的奖励总和最大化。 它旨在直接找到该策略。 基本概述是创建一个神经网络(即策略网络),该网络处理一些状态信息并输出代理可能采取的行动的分布。
W
wizardforcel 已提交
25 26 27 28 29 30 31 32 33

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

*   神经网络的权重参数由![](img/28e571cd-ca92-4253-ae6c-3be13f0af326.png)向量定义,这也是我们控制策略的参数。 因此,我们的目标是训练权重参数以获得最佳策略。 由于我们将保单视为给定保单的预期奖励总和。 在此,对于![](img/28e571cd-ca92-4253-ae6c-3be13f0af326.png)的不同参数值,策略将有所不同,因此,最佳策略将是具有最大总体奖励的策略。 因此,具有最大预期奖励的![](img/28e571cd-ca92-4253-ae6c-3be13f0af326.png)参数将是最佳策略。 以下是预期奖励金额的公式:

![](img/b0592927-b05c-471e-a9f1-18b6c1bedaa4.png)

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

W
wizardforcel 已提交
34
这里, `H`地平线的时间步长,因此,如果开始时间步长`t = 0`,则总时间步长为`H + 1`
W
wizardforcel 已提交
35

W
wizardforcel 已提交
36
*   随机策略类消除了策略优化问题,为我们提供了一组可以选择最佳策略的策略。 在网格世界环境中采用确定性策略的情况下,由于动作变化而导致的变化并不平滑,但是如果每个州都有动作分布,我们可以稍微改变分布,而这只会稍微改变预期的总和。 奖励。 这是使用随机策略的优势,其中![](img/143e641a-8be1-411e-a866-01e470d80447.png)给出给定状态`s`的动作`a`的概率。 因此,![](img/342e31bf-6e76-40e8-a298-b03277733e73.png)给出了给定状态下动作的概率分布。
W
wizardforcel 已提交
37 38 39

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

W
wizardforcel 已提交
40
# 为什么要采用策略优化方法?
W
wizardforcel 已提交
41 42 43 44

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

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

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

*   收敛到局部而不是全局最优
W
wizardforcel 已提交
51
*   策略评估效率低下且差异很大
W
wizardforcel 已提交
52 53 54

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

W
wizardforcel 已提交
55
# 为什么采用随机策略?
W
wizardforcel 已提交
56 57 58

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

W
wizardforcel 已提交
59
# 示例 1-石头,剪刀,布
W
wizardforcel 已提交
60

W
wizardforcel 已提交
61
石头,剪刀,布是两人游戏,包含以下规则:
W
wizardforcel 已提交
62 63 64 65 66 67 68

*   摇滚剪刀
*   剪刀打纸
*   纸拍摇滚

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

W
wizardforcel 已提交
69
# 示例 2-名为网格世界的状态
W
wizardforcel 已提交
70 71 72 73 74

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

![](img/c3a614ea-6981-49ca-b3a3-65614cdb7db6.png)

W
wizardforcel 已提交
75
在上图中,我们看到有八个状态,其中两个奖励为 -10 的状态是要避免的不良状态,并且有一个奖励为 10 的状态是良好状态,还有目标状态。 但是,我们主要担心的是灰色阴影状态,在该状态下,代理人无法区分这两个状态,因为它们具有相同的特征。
W
wizardforcel 已提交
76 77 78 79 80 81 82 83

假设任何状态的特征都为![](img/a0e8241f-a4a4-4bbc-a9b8-8912eb94ef2a.png),动作为北,东,西和南。

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

*   基于值的强化学习将使用近似值函数![](img/bc43afc9-6edf-43f7-9d3c-1a25a10aca56.png)
*   基于策略的强化学习将使用参数化策略![](img/f0d57666-8c89-494e-9345-9b2784a5ddbc.png)

W
wizardforcel 已提交
84
在此,`w`是值函数的参数,![](img/cbfbfe03-7b6c-438f-acd5-3b0a29950004.png)是策略的参数。 众所周知,灰色方块具有相同的特征,即在北部和南部都有墙。 因此,由于相同的特征,这导致状态混淆。 结果,基于价值的强化学习方法学习了如下确定性策略:
W
wizardforcel 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

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

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

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

*   ![](img/6a5d3643-6236-4ad0-beb6-3a15a52416aa.png)(南北墙,行动=东)= 0.5
*   ![](img/ba7a9786-5034-4fb6-9c46-7f35d5ce2caf.png)(南北墙,行动=西)= 0.5

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

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

W
wizardforcel 已提交
100
# 策略目标函数
W
wizardforcel 已提交
101 102 103 104 105 106 107 108 109

现在让我们讨论如何优化策略。 在策略方法中,我们的主要目标是具有参数向量![](img/7f80ae4c-023b-41eb-afe0-4adc03aeaa6f.png)的给定策略![](img/fba31d95-dfc8-484d-89a8-3f18a2a052a1.png)找到参数向量的最佳值。 为了测量哪个最好,我们针对参数向量![](img/1d265c8a-58fb-47ad-a899-332ce8ed4b57.png)的不同值测量![](img/f7d09ac3-d177-4d26-be11-40d62ddd2498.png)策略![](img/7eff98de-883b-4dc2-91b2-bcf5345e6d21.png)的质量。

在讨论优化方法之前,让我们首先弄清楚度量策略![](img/a87b9882-1171-43a5-9a30-cb96ac7792f1.png)的质量的不同方法:

*   如果是情景环境,则![](img/399546eb-fa7e-4286-a286-0bbc7b7075a9.png)可以是开始状态![](img/a8ed5154-6128-47af-9e75-c430390a98e0.png)的值函数,也就是说,如果它从任何状态![](img/224c25b9-df64-40a0-8d0a-cf927ef00be0.png)开始,则其值函数将是该状态开始时的预期奖励总和 。 因此,

![](img/01578517-3d8f-4227-a234-94a8e6fc9985.png)

W
wizardforcel 已提交
110
*   如果是连续环境,则![](img/67a2605d-5b85-4ef8-8345-23f88e04c7aa.png)可以是状态的平均值函数。 因此,如果环境持续不断,那么策略质量的衡量标准可以是处于任何状态`s`的概率之和,该概率是![](img/a112f968-41ba-4324-8aea-9a7362cd57dc.png)乘以该状态的值 也就是说,从该状态开始的预期奖励。 因此,
W
wizardforcel 已提交
111 112 113

![](img/2cfba9ad-f36c-4239-80f2-8c4acd2b5738.png)

W
wizardforcel 已提交
114
*   对于连续环境,![](img/d7daa239-124e-489d-8dee-dac4ce0c67da.png)可以是每个时间步长的平均奖励,它是处于任何状态`s`的概率的总和,即![](img/ff38860c-55d7-48cb-b711-96730be55ee6.png)乘以对该状态的不同动作的期望奖励![](img/ab734c3a-740c-4d05-bee7-9fee1d71a8ec.png)的总和。 因此:
W
wizardforcel 已提交
115 116 117

![](img/d42506b9-9710-4ec3-93a3-50c62b3b2991.png)

W
wizardforcel 已提交
118
在此,![](img/76bb83ab-8783-441c-b93f-9cb852adea36.png)是在状态`s`采取行动`a`的奖励。
W
wizardforcel 已提交
119 120 121

到目前为止,我们知道基于策略的强化学习是一个优化问题,目标是找到使![](img/29b8bcc8-8899-4036-915c-da44b0572d00.png)最大化的![](img/ebff45ff-12c2-44e0-bda5-21cde9d251b6.png)。 同样,在这里,我们将使用基于梯度的方法进行优化。 使用基于梯度的优化的原因是要获得更高的效率,因为与无梯度方法相比,梯度指向了更高效率的方向。

W
wizardforcel 已提交
122
让衡量策略质量的![](img/e692d5f7-a0f4-429d-88b9-76841097db58.png)成为我们的策略目标函数。 因此,策略梯度算法通过相对于参数![](img/ea8c20d8-5c4c-48ed-92eb-d67c4fce01c2.png)提升策略的梯度,在![](img/2db17489-4871-4766-aecf-8ceb59e3588f.png)中寻找局部最大值。 这是因为我们的目标是使![](img/8fa96eec-d05a-4d08-823a-c94a2f12d1f2.png)相对于![](img/a785ed7b-74a1-4b8c-a661-44cbe24676b7.png)最大化,因此我们进行了梯度上升,其中
W
wizardforcel 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
为![](img/029690bc-9836-48b8-b4c6-2106aa3a2a32.png)的参数的增量如下:

![](img/9ff648e7-9f6f-4a44-a52f-7d749cb6e1cf.png)

在这里,![](img/a0ed8041-0913-44e4-8e75-4a4575f6a43e.png)是策略梯度,![](img/08199fd7-dc55-41ad-b165-1986e4b9b3f0.png)是学习率,也称为**步长参数**,步长参数决定该参数应在每个步长上偏移多少梯度。 策略梯度还可以用以下形式阐述:

![](img/0d918775-9864-4b04-9b05-f59c0941e222.png)

# 策略梯度定理

假设给定策略![](img/e3d26803-9858-4ea2-bd79-3e0b45a09f99.png)每当不为零时都是可微的,则给定策略相对于![](img/1ac193f4-8848-497e-b421-fcc2c4f3be6b.png)的梯度为![](img/bdb911f2-ef69-4a03-ad39-6d2c15e520ba.png)。 因此,我们可以以似然比的形式进一步利用此梯度量,如下所示:

![](img/0af8a486-8579-4e97-8e22-ec4b276714f5.png)

此处,![](img/d7dd0cd7-842e-41fb-9d73-bf9ffa1d8df6.png)是得分函数,供将来参考。

W
wizardforcel 已提交
139
现在,让我们考虑一个简单的一步式 MDP,即马尔可夫决策过程,其中:
W
wizardforcel 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

*   起始状态为,发生的可能性为![](img/a366eee2-685d-4db4-8eb6-bb12f82762cf.png)
*   终止仅在获得奖励![](img/564de4ef-e5c9-433a-b305-f5727f768af8.png)的情况下执行一次

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

![](img/a8296a39-e2c7-4a1e-a8c4-02e15df4fd4e.png)

因此,策略梯度![](img/b7b329f8-340c-472e-afcd-cacd7ff3a1d5.png)将如下所示:

![](img/ba08ca33-c4b3-4d33-85f9-cd7ee7413342.png)

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

![](img/0c0c9dc6-9641-4931-855c-216477a3a009.png)

结果是:

![](img/b6666854-9607-4fcd-9536-6ad2779a7ffd.png)

W
wizardforcel 已提交
160
因此,将该方法推广到多步马尔可夫决策过程将导致状态奖励 Q 值函数![](img/5610aab6-6f91-4840-b4dc-dbb44f9ed700.png)代替瞬时奖励`r`。 这称为**策略梯度定理**。 该定理对前面讨论的其他类型的策略目标函数有效。 因此,对于任何这样的策略目标函数和任何可区分的![](img/e3d26803-9858-4ea2-bd79-3e0b45a09f99.png),策略梯度如下:
W
wizardforcel 已提交
161 162 163 164 165

![](img/22aa628a-e90d-49c5-ae2d-c8f5e168393c.png)

# 时差规则

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

W
wizardforcel 已提交
168
# `TD(1)`规则
W
wizardforcel 已提交
169

W
wizardforcel 已提交
170
`TD(1)`纳入了资格跟踪的概念。 让我们看一下该方法的伪代码,然后将详细讨论它:
W
wizardforcel 已提交
171 172 173 174 175 176 177 178 179 180 181 182

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

        For all s,

```

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

W
wizardforcel 已提交
183
*   对于所有状态`s`,合格分数`e(s) = 0`
W
wizardforcel 已提交
184
*   对于所有状态`s`,给定`Episode T`中的状态值![](img/96757d13-12cc-4ae2-b27b-1b8383db5a88.png)等于![](img/4ba99034-9dea-402d-871b-ac5949e7b310.png)
W
wizardforcel 已提交
185

W
wizardforcel 已提交
186
在情节的每个时间步,即当前步`t`,我们更新要离开的状态![](img/93bfad9d-15d6-48dc-8f47-8f9aef8070ba.png)的资格,然后为所有状态更新以下内容:
W
wizardforcel 已提交
187 188 189 190 191 192

*   针对当前离开状态![](img/3c8ca4ff-4fda-4e46-bf29-46dd17cbb4de.png)(即![](img/a11db6ce-2582-4ac7-89d7-d7c972b0ec78.png))和要更改其值的状态的合格分数![](img/9d156535-7cde-4d47-827f-877259ece162.png)使用时间差误差的状态值函数
*   通过给定折现系数进行折现的资格分数

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

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

W
wizardforcel 已提交
195
# `TD(0)`规则
W
wizardforcel 已提交
196

W
wizardforcel 已提交
197
如果无限重复重复有限数据,则`TD(0)`规则会找到值估计值,通常就是如果我们获取此有限数据并不断重复运行以下估计值更新规则。 然后,实际上我们正在平均每个转换。
W
wizardforcel 已提交
198 199 200 201 202 203 204 205 206 207 208

![](img/262fb91d-f5d6-4d42-97fc-710d525ac99f.png)

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

![](img/49b93224-b17b-4deb-b5cf-bf76e9eb19db.png)

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

![](img/24c5dac2-f8c8-45a1-b87c-bf33254da2aa.png)

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

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

W
wizardforcel 已提交
213
`TD(0)`规则的伪代码如下:
W
wizardforcel 已提交
214 215 216 217 218 219 220 221 222 223 224

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

```

因此,这里我们仅使用时间差误差![](img/bbe74c85-c403-4b25-bf57-53e9fd7a9692.png)更新当前离开状态![](img/187fe806-bcca-4c11-8794-13c5058b5cf7.png)的值函数。

W
wizardforcel 已提交
225
# TD 规则
W
wizardforcel 已提交
226

W
wizardforcel 已提交
227
`TD(1)``TD(0)`规则产生一个通用规则,即`TD(λ)`,因此对于![](img/4b1123cb-72a4-481e-81e9-6835853ffc68.png)并应满足以下条件:
W
wizardforcel 已提交
228

W
wizardforcel 已提交
229 230
*   如果![](img/d6400b9d-6c9e-4370-b506-ff40da00344d.png) = 0,则`TD(λ)`趋于`TD(0)`
*   如果![](img/d6400b9d-6c9e-4370-b506-ff40da00344d.png) = 1,则`TD(λ)`趋于`TD(1)`
W
wizardforcel 已提交
231

W
wizardforcel 已提交
232
`TD(0)``TD(1)`都基于时间连续预测之间的差异进行更新。
W
wizardforcel 已提交
233

W
wizardforcel 已提交
234
因此,`TD(λ)`的伪代码如下:
W
wizardforcel 已提交
235 236 237 238 239 240 241 242 243 244 245 246

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

        For all s,

```

这满足前面两个条件,并且可以合并![](img/4b1123cb-72a4-481e-81e9-6835853ffc68.png)的任何值。

W
wizardforcel 已提交
247
# 策略梯度
W
wizardforcel 已提交
248 249 250 251 252 253 254

根据策略梯度定理,对于先前指定的策略目标函数和任何可微分策略![](img/20afea81-2790-4090-9aa2-1760249c17fd.png),策略梯度如下:

![](img/406f3ccb-146a-485c-b05a-89a8f4d935cd.png)

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

W
wizardforcel 已提交
255
# 蒙特卡洛策略梯度
W
wizardforcel 已提交
256 257 258

**蒙特卡洛策略梯度**方法中,我们使用随机梯度上升方法更新参数,并按照策略梯度定理进行更新,并使用![](img/1181ceb5-bd76-4d0f-9b7c-d232ea3145ff.png)作为![](img/7b469909-8042-48f5-a02f-8b3131c036b6.png)的无偏样本。 在此,![](img/ac53328a-b0d7-4305-a938-3e4c23fc3c85.png)是从该时间步开始的累计奖励。

W
wizardforcel 已提交
259
蒙特卡洛策略梯度法如下:
W
wizardforcel 已提交
260 261 262 263 264 265 266 267 268 269 270 271

```py
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
wizardforcel 已提交
272
# 评论家算法
W
wizardforcel 已提交
273 274 275 276 277

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

![](img/bdee56e7-7167-4d77-a478-710505461008.png)

W
wizardforcel 已提交
278
这产生了著名的**演员评论家算法**。 顾名思义,演员评论家算法出于以下目的维护两个网络:
W
wizardforcel 已提交
279

W
wizardforcel 已提交
280
*   一个网络充当评论者,它更新状态动作函数逼近器的权重`w`参数向量
W
wizardforcel 已提交
281
*   其他网络充当演员,它根据批评者给出的方向更新策略参数向量![](img/49aece0d-9f5a-4d27-8ccc-13b01329f2de.png)
W
wizardforcel 已提交
282

W
wizardforcel 已提交
283
下图代表了演员评论家算法:
W
wizardforcel 已提交
284 285 286 287 288 289 290 291 292

![](img/ca78b5e5-1459-4f34-ad61-de744f663054.png)

因此,在执行者批评算法的情况下,实际策略梯度公式中的真实状态作用值函数![](img/091617b0-180f-4323-8f54-6ccc8001c015.png)被替换为近似状态作用值函数![](img/a764a644-e5f7-46ab-88f8-999b59a38cc6.png)。 因此:

![](img/d8b7251d-91aa-4183-add1-5a5a0f9f8d0c.png)

![](img/d9896c48-a57d-45e1-974e-3d9bed7c4af3.png)

W
wizardforcel 已提交
293
因此,为了估计状态作用值函数,评论者网络使用`TD(0)`(先前讨论)来更新权重参数`w`,并更新策略参数向量![](img/86eb3024-7437-442e-b21a-1b2c1ccffbfc.png) 演员网络使用策略梯度。 演员评论家算法的一种简单方法如下所示:
W
wizardforcel 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

```py
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 
```

W
wizardforcel 已提交
309
因此,我们可以看到参与者评论家既具有基于价值的优化又具有基于策略的优化。 因此,在采用蒙特卡洛策略梯度法的情况下,策略改进会贪婪地进行。 但是在演员批评家中,演员通过按照批评家的方向采取措施来更新策略参数,以便制定更好的策略。
W
wizardforcel 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330

# 使用基线减少差异

除了我们最初使用行为准则的方法来减少方差之外,我们还可以通过从策略梯度中减去**基线函数** ![](img/57466ce5-670a-4989-9de6-c43208771e1b.png)来减少方差。 这将减少方差而不影响期望值,如下所示:

![](img/3564b3a4-9d0f-4cc2-87a6-a3ae59c46f7e.png)

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

![](img/b0a2160a-823c-437d-a1a1-64413a9be3cc.png)

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

![](img/e4d88794-1d88-4b34-89cb-b726ea224273.png)

在这里,![](img/f9d82ccb-5cc8-4e13-aee3-09e4de688a27.png)被称为**优势函数** ![](img/9431ca65-6206-44c7-960b-d75003b7db7f.png)。 因此,策略梯度公式变为:

![](img/5b410fc8-1d5b-4a36-9250-730d1a651b86.png)

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

W
wizardforcel 已提交
331
# 原始策略梯度
W
wizardforcel 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348

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

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

```py
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
```

W
wizardforcel 已提交
349
# 使用策略梯度的学习 Pong 的智能体
W
wizardforcel 已提交
350

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

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

W
wizardforcel 已提交
355
*   **输入层(`X`)**:将`80 * 80`压缩为`6400 * 1`,即 6400 个节点
W
wizardforcel 已提交
356 357 358 359 360
*   **隐藏层**:200 个节点
*   **输出层**:1 个节点

因此,总参数如下:

W
wizardforcel 已提交
361 362
*   **连接输入层和隐藏层的权重和偏置**`6400 * 200`(权重)`+ 200`(偏置)参数
*   **连接隐藏层和输出层的权重和偏置**`200 * 1`(权重)`+ 1`(偏置)参数
W
wizardforcel 已提交
363 364 365

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

W
wizardforcel 已提交
366
这是巨大的,因此训练需要几天的时间才能见证您的经纪人流畅地打乒乓球。
W
wizardforcel 已提交
367 368 369

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

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

![](img/297c6703-97ca-4ba2-8e19-70dabec7b4a1.png)

W
wizardforcel 已提交
374
但是,实际上我们没有标签。 因此,我们将实现强化学习,在其中我们将尝试许多任务并记下观察结果。 然后,更频繁地执行性能更好的任务。
W
wizardforcel 已提交
375 376 377 378

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

1.  初始化随机策略。
W
wizardforcel 已提交
379
2.  对于给定的当前策略,我们将通过以下方式收集不同的样本轨迹(展示):
W
wizardforcel 已提交
380 381 382 383
    1.  运行游戏的一个情节并捕获该情节的轨迹。
    2.  同样,收集一批轨迹,如下所示:

| **轨迹** | **游戏结果** | **轨迹好/坏** |
W
wizardforcel 已提交
384 385 386 387 388
| --- | --- | --- |
| 上,下,上,上,下,下,下,上 | 输 | 坏 |
| 下,上,上,下,上,上 | 赢 | 好 |
| 上,上,下,下,下,下,上 | 输 | 坏 |
| 下,上,上,下,上,上 | 赢 | 好 |
W
wizardforcel 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

因此,我们能够创建示例数据,在这些示例中,我们认为赢得的案例是该操作的正确标签。 因此,我们将增加这些动作的对数概率,即![](img/9870b991-5c5f-4c6f-9154-14acf670dbc1.png),并且丢失每个动作的情况将被视为错误标签。 因此,在这些情况下,我们将减少这些操作的对数概率。

因此,在收集了一批轨迹之后,我们将最大化优势与对数概率的乘积,即![](img/33fcf07a-587f-4876-a81d-6d77f467c7f7.png)

在此,![](img/67380edd-b86f-448f-a76c-9ac522a1c13b.png)是与状态操作对关联的优势。 优势是一个标量,它量化了操作最终的效果。 如果我们想在将来鼓励给定的行动,则![](img/33f8b677-10bd-421d-aa20-94676af257a6.png)会很高,而如果我们想阻止该行动,则![](img/33f8b677-10bd-421d-aa20-94676af257a6.png)会很低。 正优势使该状态的将来更有可能发生该行为,而负优势使该状态的将来不太可能发生该行为。

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

```py
#import dependencies
import numpy as np #for matrix math
import cPickle as pickle #to save/load model
import gym
```

W
wizardforcel 已提交
405
*   **超参数初始化**:由于我们正在使用`RMSProp`优化器进行梯度下降,因此超参数(例如隐藏层节点的数量,批量大小,学习率,折现系数`gamma`,衰减率)。 我们将使用以下代码进行初始化:
W
wizardforcel 已提交
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432

```py
#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
```

*   **策略神经网络模型初始化**:策略神经网络的权重参数的初始化。 在这里,我们使用一个隐藏层神经网络。 我们将使用以下代码进行初始化:

```py
#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
```

W
wizardforcel 已提交
433
*   **激活函数**`sigmoid(x)``relu(x)`分别指执行 Sigmoid 和 ReLU 激活计算的函数。 我们将使用以下代码定义函数:
W
wizardforcel 已提交
434 435 436 437 438 439 440 441 442 443 444

```py
#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
```

W
wizardforcel 已提交
445
*   **预处理函数**`preprocess(image)`功能将图像像素作为参数,并通过裁剪,下采样,使其成为灰度,擦除背景并将图像展平为一维向量来对其进行预处理。 我们将使用以下代码定义函数:
W
wizardforcel 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459

```py
#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
```

W
wizardforcel 已提交
460
*   **折扣奖励**`discount_rewards(r)`函数将与不同时间步长对应的奖励列表`r`作为参数,并返回与不同时间步长对应的折扣奖励列表,如以下代码所示 :
W
wizardforcel 已提交
461 462 463 464 465 466 467 468 469 470 471 472 473 474

```py
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
```

W
wizardforcel 已提交
475
*   **正向传播**`policy_forward(x)`函数接收预处理的图像向量`x`,返回动作概率为`UP`,并且向量包含隐藏状态节点的值,如 以下代码:
W
wizardforcel 已提交
476 477 478 479 480 481 482 483 484 485

```py
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
```

W
wizardforcel 已提交
486
*   **反向传播**`policy_backward(arr_hidden_state, gradient_logp, observation_values)`函数采用隐藏状态值,错误`gradient_logp`和观测值来针对不同权重参数计算导数,如以下代码所示:
W
wizardforcel 已提交
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580

```py
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}
```

创建环境并结合先前的功能以使代理逐步学习多个情节的最终任务如下:

```py
#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
W
wizardforcel 已提交
581
                rmsprop_cache[weight] = decay_rate*rmsprop_cache[weight]+(1-decay_rate)`g`2
W
wizardforcel 已提交
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
                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))

```

代理商玩的游戏的屏幕截图:

![](img/a93603fa-c7c9-450d-9df9-5549bb6fb056.png)

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

W
wizardforcel 已提交
609
# 总结
W
wizardforcel 已提交
610

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

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