From 22c47988e365a0bec143fb36b7dad793bd15a6ef Mon Sep 17 00:00:00 2001 From: wizardforcel <562826179@qq.com> Date: Fri, 25 Dec 2020 17:03:36 +0800 Subject: [PATCH] 2020-12-25 17:03:36 --- new/handson-rl-py/08.md | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/new/handson-rl-py/08.md b/new/handson-rl-py/08.md index 1159d7a8..d0002f2d 100644 --- a/new/handson-rl-py/08.md +++ b/new/handson-rl-py/08.md @@ -16,17 +16,19 @@ 在继续之前,首先让我们回顾一下 Q 函数。 什么是 Q 函数? Q 函数(也称为状态动作值函数)指定`a`在`s`状态下的状态。 因此,我们将每个状态下所有可能动作的值存储在一个称为 Q 表的表中,并选择一个状态下具有最大值的动作作为最佳动作。 还记得我们是如何学习这个 Q 函数的吗? 我们使用了 Q 学习,这是一种非策略性的时差学习算法,用于估算 Q 函数。 我们在第 5 章“时间差异学习”中对此进行了研究。 -到目前为止,我们已经看到了状态数量有限且动作有限的环境,并且我们对所有可能的状态动作对进行了详尽搜索,以找到最佳 Q 值。 想想一个环境,我们有很多状态,并且在每个状态下,我们都有很多动作可以尝试。 仔细检查每个状态下的所有操作将非常耗时。 更好的方法是使用某些参数![](img/00240.jpeg)将`Q`函数近似为![](img/00241.jpeg)。 我们可以使用权重为![](img/00242.jpeg)的神经网络来估计每种状态下所有可能动作的`Q`值。 当我们使用神经网络来近似`Q`函数时,我们可以称其为 Q 网络。 好的,但是我们如何训练网络,我们的目标功能是什么? 回顾我们的 Q 学习更新规则: +到目前为止,我们已经看到了状态数量有限且动作有限的环境,并且我们对所有可能的状态动作对进行了详尽搜索,以找到最佳 Q 值。 想想一个环境,我们有很多状态,并且在每个状态下,我们都有很多动作可以尝试。 仔细检查每个状态下的所有操作将非常耗时。 更好的方法是使用某些参数`θ`将`Q`函数近似为`Q(s, a; θ) ≈ Q*(s, a)`。 我们可以使用权重为`θ`的神经网络来估计每种状态下所有可能动作的`Q`值。 当我们使用神经网络来近似`Q`函数时,我们可以称其为 Q 网络。 好的,但是我们如何训练网络,我们的目标功能是什么? 回顾我们的 Q 学习更新规则: ![](img/00243.jpeg)。 -![](img/00244.jpeg)是目标值,![](img/00245.jpeg)是预测值; 我们试图通过学习正确的策略来最大程度地降低这一价值。 +`r + r maxQ(s', a)`是目标值,`Q(s, a)`是预测值; 我们试图通过学习正确的策略来最大程度地降低这一价值。 -同样,在 DQN 中,我们可以将损失函数定义为目标值和预测值之间的平方差,并且我们还将尝试通过更新权重![](img/00246.jpeg)来最大程度地减少损失: +同样,在 DQN 中,我们可以将损失函数定义为目标值和预测值之间的平方差,并且我们还将尝试通过更新权重`θ`来最大程度地减少损失: ![](img/00247.jpeg) -其中![](img/00248.jpeg)。 +其中: + +![](img/00248.jpeg) 我们更新权重,并通过梯度下降使损失最小化。 简而言之,在 DQN 中,我们使用神经网络作为函数逼近器来逼近`Q`函数,并且通过梯度下降使误差最小化。 @@ -50,7 +52,7 @@ DQN 的第一层是卷积网络,网络的输入将是游戏屏幕的原始帧 # 经验回放 -我们知道,在 RL 环境中,我们通过执行某些操作`a`,从一个状态`s`转移到下一状态`s'`,并获得奖励`r`。 我们将此转移信息作为![](img/00250.jpeg)保存在称为回放缓冲区或经验回放的缓冲区中。 这些转移称为代理的经验。 +我们知道,在 RL 环境中,我们通过执行某些操作`a`,从一个状态`s`转移到下一状态`s'`,并获得奖励`r`。 我们将此转移信息作为``保存在称为回放缓冲区或经验回放的缓冲区中。 这些转移称为代理的经验。 经验回放的关键思想是,我们使用从回放缓冲区采样的转移来训练深度 Q 网络,而不是使用最后的转移进行训练。 智能体的经历一次相关,因此从回放缓冲区中随机选择一批训练样本将减少智能体的经历之间的相关性,并有助于智能体更好地从广泛的经验中学习。 @@ -64,13 +66,13 @@ DQN 的第一层是卷积网络,网络的输入将是游戏屏幕的原始帧 ![](img/00252.jpeg) -我们使用相同的 Q 函数来计算目标值和预测值。 在前面的公式中,您可以看到相同的权重![](img/00253.jpeg)用于目标`Q`和预测的`Q`。 由于同一网络正在计算预测值和目标值,因此两者之间可能会有很大差异。 +我们使用相同的 Q 函数来计算目标值和预测值。 在前面的公式中,您可以看到相同的权重`θ`用于目标`Q`和预测的`Q`。 由于同一网络正在计算预测值和目标值,因此两者之间可能会有很大差异。 为避免此问题,我们使用称为目标网络的单独网络来计算目标值。 因此,我们的损失函数变为: ![](img/00254.jpeg) -您可能会注意到目标`Q`的参数是![](img/00255.jpeg)而不是![](img/00256.jpeg)。 我们的实际 Q 网络用于预测`Q`值,它通过使用梯度下降来学习![](img/00257.jpeg)的正确权重。 将目标网络冻结几个时间步,然后通过从实际 Q 网络复制权重来更新目标网络权重。 冻结目标网络一段时间,然后使用实际的 Q 网络权重更新其权重,以稳定训练。 +您可能会注意到目标`Q`的参数是`θ'`而不是`θ`。 我们的实际 Q 网络用于预测`Q`值,它通过使用梯度下降来学习`θ`的正确权重。 将目标网络冻结几个时间步,然后通过从实际 Q 网络复制权重来更新目标网络权重。 冻结目标网络一段时间,然后使用实际的 Q 网络权重更新其权重,以稳定训练。 # 削减奖励 @@ -81,13 +83,15 @@ DQN 的第一层是卷积网络,网络的输入将是游戏屏幕的原始帧 现在,我们将了解 DQN 的整体工作方式。 DQN 涉及的步骤如下: 1. 首先,我们预处理游戏屏幕(状态`s`)并将其馈送到 DQN,DQN 将返回该状态下所有可能动作的`Q`值。 -2. 现在,我们使用`ε`贪婪策略选择一个动作:对于概率`epsilon`,我们选择一个随机动作`a`;对于概率为 1 `epsilon`,我们选择一个具有最大`Q`的动作值,例如![](img/00258.jpeg)。 +2. 现在,我们使用`ε`贪婪策略选择一个动作:对于概率`epsilon`,我们选择一个随机动作`a`;对于概率为 1 `epsilon`,我们选择一个具有最大`Q`的动作值,例如`a = argmax(Q(s, a; θ))`。 3. 在选择动作`a`之后,我们在`s`状态下执行此动作,然后移至新的`s'`状态并获得奖励。 下一个状态`s'`是下一个游戏屏幕的预处理图像。 4. 我们将此转移存储在``的回放缓冲区中。 5. 接下来,我们从回放缓冲区中抽取一些随机的转移批次并计算损失。 -6. 我们知道![](img/00259.jpeg)就像目标`Q`与预测的`Q`之间的平方差一样。 -7. 我们针对实际网络参数![](img/00260.jpeg)执行梯度下降,以最大程度地减少这种损失。 -8. 在每个`k`个步骤之后,我们将实际网络权重![](img/00261.jpeg)复制到目标网络权重![](img/00262.jpeg)。 +6. 我们知道损失就像目标`Q`与预测的`Q`之间的平方差一样。 + + ![](img/00259.jpeg) +7. 我们针对实际网络参数`θ`执行梯度下降,以最大程度地减少这种损失。 +8. 在每个`k`个步骤之后,我们将实际网络权重`θ`复制到目标网络权重`θ'`。 9. 对于`M`个情节,我们重复这些步骤。 # 建立代理来玩 Atari 游戏 @@ -402,7 +406,7 @@ with tf.Session() as sess: ![](img/00269.jpeg) -在前面的公式中,我们有两个`Q`函数,每个函数具有不同的权重。 因此,权重为![](img/00270.jpeg)的`Q`函数用于选择操作,权重为![](img/00271.jpeg)的其他`Q`函数用于评估操作。 我们还可以切换这两个`Q`功能的角色。 +在前面的公式中,我们有两个`Q`函数,每个函数具有不同的权重。 因此,权重为`θ'`的`Q`函数用于选择操作,权重为`θ-`的其他`Q`函数用于评估操作。 我们还可以切换这两个`Q`功能的角色。 # 优先经验回放 @@ -416,7 +420,7 @@ with tf.Session() as sess: ![](img/00273.jpeg) -![](img/00274.jpeg)是转换的优先级`i`,![](img/00275.jpeg)是转换的 TD 误差`i`,而![](img/00276.jpeg)只是一些正常数,可确保每次转换 具有非零优先级。 当![](img/00277.jpeg)为零时,添加![](img/00278.jpeg)将使转换具有优先级而不是零优先级。 但是,转换的优先级要比![](img/00279.jpeg)不为零的转换低。 指数![](img/00280.jpeg)表示使用的优先级数量。 当![](img/00281.jpeg)为零时,则仅是均匀情况。 +`p[i]`是转换的优先级`i`,`δ[i]`是转换的 TD 误差`i`,而`ε`只是一些正常数,可确保每次转换 具有非零优先级。 当`δ`为零时,添加`ε`将使转换具有优先级而不是零优先级。 但是,转换的优先级要比`δ`不为零的转换低。 指数`α`表示使用的优先级数量。 当`α`为零时,则仅是均匀情况。 现在,我们可以使用以下公式将此优先级转换为概率: @@ -426,13 +430,15 @@ with tf.Session() as sess: ![](img/00283.jpeg) -`rank(i)`指定转移`i`在回放缓冲区中的位置,在该位置中,转移从高 TD 错误到低 TD 错误被分类。 计算优先级后,我们可以使用相同的公式![](img/00284.jpeg)将优先级转换为概率。 +`rank(i)`指定转移`i`在回放缓冲区中的位置,在该位置中,转移从高 TD 错误到低 TD 错误被分类。 计算优先级后,我们可以使用相同的公式将优先级转换为概率: + +![](img/00284.jpeg) # 决斗网络架构 我们知道`Q`函数指定代理在状态`s`下执行动作`a`有多好,而值函数则指定使代理处于`s`状态有多好。 现在,我们引入一个称为优势函数的新函数,该函数可以定义为值函数和优势函数之间的差。 优势功能指定与其他动作相比,代理执行一个动作`a`有多好。 -因此,值函数指定状态的优劣,而优势函数指定动作的优劣。 如果我们将价值功能和优势功能结合起来会发生什么? 这将告诉我们代理在状态`s`实际上是我们的`Q`功能下执行动作`a`有多好。 因此,我们可以像![](img/00285.jpeg)中那样将`Q`函数定义为值函数和优势函数的和。 +因此,值函数指定状态的优劣,而优势函数指定动作的优劣。 如果我们将价值功能和优势功能结合起来会发生什么? 这将告诉我们代理在状态`s`实际上是我们的`Q`功能下执行动作`a`有多好。 因此,我们可以像`Q(s, a) = V(s) + A(a)`中那样将`Q`函数定义为值函数和优势函数的和。 现在,我们将看到决斗网络架构是如何工作的。 下图显示了决斗 DQN 的架构: -- GitLab