【学习强化学习】七、DQN算法的改进

本文深入探讨了深度强化学习中的DQN算法及其改进方法,包括DoubleDQN解决Q值高估问题、DuelingDQN的网络架构调整、优先经验回放、平衡MC和TD学习、NoisyNet的随机性探索以及DistributionalQ-function对奖励分布的建模。这些技术通过优化网络结构和学习策略,提升了DQN算法的性能和效率。
摘要由CSDN通过智能技术生成

参考资料

  1. https://datawhalechina.github.io/easy-rl/#/chapter7/chapter7
  2. Dueling DQN
  3. 优先经验回放
  4. Distrbutional DQN
  5. Distrbutional DQN:C51

算法实现见github仓库

1. Double DQN

  • 传统的DQN方法Q值往往被高估(over-estimated)。
  • 虽然一般的 DQN 的 Q-network 高估了自己会得到的 reward,但实际上它得到的 reward 是比较低的。

Q: 为什么 Q 值总是被高估了呢?

A: 因为实际上在做的时候,是要让左边这个式子跟右边这个目标越接近越好。你会发现目标的值很容易一不小心就被设得太高。因为在算这个目标的时候,我们实际上在做的事情是,看哪一个a 可以得到最大的 Q 值,就把它加上去,就变成我们的目标。所以假设有某一个动作得到的值是被高估的。
在这里插入图片描述

1.1 怎么解决Q值高估的问题?

在 Double DQN 里面,选动作的 Q-function 跟算目标Q值的 Q-function 不是同一个。在原来的 DQN 里面,你穷举所有的 a,把每一个 a 都带进去, 看哪一个 a 可以给你的 Q 值最高,那你就把那个 Q 值加上 r t r_t rt​。但是在 Double DQN 里面,有两个 Q-network:

  • 第一个 Q-network Q 决定哪一个动作的 Q 值最大(把所有的 a 带入 Q 中,看看哪一个 Q 值最大)。
  • 决定你的动作以后, Q 值是用第二个Q网络 Q ′ Q' Q 算出来的。

假设我们有两个 Q-function,

  • 假设第一个 Q-function 高估了它现在选出来的动作 a,只要第二个 Q-function Q ′ Q' Q没有高估这个动作 a 的值,那算出来的就还是正常的值。

  • 假设 Q ′ Q' Q 高估了某一个动作的值,只要前面这Q 不要选那个动作出来就没事了,这个就是 Double DQN 神奇的地方。

  • 在实现上,有两个 Q-network:目标的 Q-network 和更新的 Q-network。所以在 Double DQN 里面,拿会更新参数的Q-network 去选动作,然后拿目标网络(固定住不动的网络)去算值。

  • Double DQN 相较于原来的 DQN 的更改是最少的,它几乎没有增加任何的运算量,连新的网络都不用,因为原来就有两个网络了。你唯一要做的事情只有,原本在找 Q 值最大的 a 的时候,你是用目标网络来算,现在改成用另外一个会更新的 Q-network 来算,然后把a带入目标网络得到目标Q值。可以理解为一个网络提议案,另外一个网络进行执行。即:
    a = arg max ⁡ Q ( s t + 1 , ) y = r t + Q t a r g e t ( s t + 1 ∣ a ) a=\argmax Q(s_{t+1},)\\ y= r_t+Q_{target}(s_{t+1}|a) a=argmaxQ(st+1,)y=rt+Qtarget(st+1a)

2. Dueling DQN

  • Dueling DQN相较于原来的 DQN,唯一的差别是改了网络的架构。
    在这里插入图片描述

2.1 Dueling DQN 如何更改了网络的架构?

本来的 DQN 就是直接输出 Q 值的值。现在 dueling 的 DQN,它不直接输出 Q 值的值,它分成两条路径去运算:

  • 第一条路径会输出一个 scalar,这个 scalar 叫做 V ( s ) V(s) V(s)。因为它跟输入 s 是有关系,所以叫做 V ( s ) V(s) V(s) V ( s ) V(s) V(s) 是一个 scalar。

  • 第二条路径会输出一个 vector,这个 vector 叫做 A ( s , a ) A(s,a) A(s,a)。每一个动作它都有一个值。

  • 再把这两部分加起来就可以得到Q 值。

2.2 更改网络架构的好处

在这里插入图片描述

假设原来的 Q ( s , a ) Q(s,a) Q(s,a)就是一个表格。为了说明方便,我们假设只有 4 个不同的状态,只有 3 个不同的动作

我们知道:
Q ( s , a ) = V ( s ) + A ( s , a ) Q(s,a) = V(s) + A(s,a) Q(s,a)=V(s)+A(s,a)

其中

  • V ( s ) V(s) V(s) 是对不同的状态 它都有一个值。
  • A ( s , a ) A(s,a) A(s,a) 是对不同的状态,不同的动作都有一个值。

如上图所示,假设在训练网络的时候,目标是希望这一个值变成 4,另一个值变成 0。但是实际上能更改的并不是 Q 的值,网络更改的是 V 跟 A 的值。根据网络的参数,V 跟 A 的值输出以后,就直接把它们加起来,所以其实不是更动 Q 的值。

然后在学习网络的时候,假设希望这边的值,3 增加 1 变成 4, -1 增加 1 变成 0。最后在训练网络的时候,网络 可能不更新 A 的值,而是更新 V 的值,把 V 的值从 0 变成 1。把 0 变成 1 有什么好处呢?本来只想动这两个部分的值,但这个第三个值也动了,-2 变成 -1。所以有可能在某一个状态,你只 sample 到 2 个动作,没 sample 到第三个动作,但是你其实也可以更改第三个动作的 Q 值。这样的好处就是不需要把所有的 state-action pair 都 sample 过,也可以用比较高效的方式去估计 Q 值出来。更新 V ( s ) V(s) V(s)的时候,只要一改,所有的值就会跟着改。这是一个比较有效率的方法去使用数据,这是 Dueling DQN 可以带给我们的好处。

2.2.1 网络可能学到 V 永远都是 0的情况处理

网络学到 V 永远都是 0,然后A 就等于 Q,那就没有得到任何 Dueling DQN 可以带来的好处, 就变成跟原来的 DQN 一模一样。为了避免这个问题,实际上要给 A 一些约束,让网络觉得更新 A 比较麻烦,让网络倾向于会想要去用 V 来解问题。

  • 举例来说,在原始的文献中,它有不同的约束 。一个最直觉的约束是必须要让 A 的每一列的和都是 0,如上图举的例子。如果这边列的和都是 0,这边 V 的值,就可以想成是上面 Q 的每一列的平均值。这个平均值,加上A值才会变成Q 的 值。所以假设在更新参数的时候,要让整个列一起被更新,你不会想要更新 A 这个矩阵。因为 A 这个矩阵的每一列的和都要是 0,所以没有办法说,让A的值通通都 +1,因为它的约束就是和永远都是要 0,所以不可以都 +1。这时候就会强迫网络去更新 V 的值。

在这里插入图片描述

  • 实现时,要给这个 A 一个约束。举个例子,假设有 3 个动作,然后输出的 vector 是 [ 7 , 3 , 2 ] T [7,3,2]^{\mathrm{T}} [7,3,2]T,把 A 跟 V 加起来之前,先加一个归一化(normalization),比如层归一化( layer normalization)。这个归一化做的事情就是把7+3+2 加起来等于 1212/3 = 4。然后把这边通通减掉 4,变成 3, -1, 2。再把 3, -1, 2 加上 1.0,得到最后的 Q 值。

  • 这个归一化的步骤就是网络的一部分,在训练的时候,也是从这里一路 back propagate 回来的,只是归一化是没有参数的,它只是一个归一化的操作。把它放到网络里面,跟网络的其他部分 jointly trained,这样 A 就会有比较大的约束。这样网络就会给它一些好处,倾向于去更新 V 的值。

  • 实际在实现时,依据的下面的公式:

在这里插入图片描述

3. Prioritized Experience Replay

在这里插入图片描述

  • 原来在 sample 数据去训练 Q-network 的时候,我们是均匀地从 experience buffer 里面去 sample 数据。假设有一些数据,之前有 sample 过,发现这些数据的 TD error 特别大(TD error 就是网络的输出跟目标之间的差距),那这些数据代表在训练网络的时候, 训练是比较不好的。既然比较训练不好, 那就应该给它比较大的概率被 sample 到,即给它 priority,这样在训练的时候才会多考虑那些训练不好的训练数据。实际上在做 prioritized experience replay 的时候,你不仅会更改 sampling 的 过程,你还会更改更新参数的方法。所以 prioritized experience replay 不仅改变了 sample 数据的分布,还改变了训练过程

4. Balance between MC and TD

在这里插入图片描述

  • 另外一个tips是 balance MC 跟 TD(即多步TD)。MC 跟 TD 的方法各自有优劣,怎么在 MC 跟 TD 里面取得一个平衡呢?我们的做法是这样,在 TD 里面,在某一个状态 s t s_t st​ 采取某一个动作 a t a_t at​ 得到 reward r t r_t rt​,接下来跳到下一个状态 s t + 1 s_{t+1} st+1​。但是我们可以不要只存一个步骤的数据,我们存 N 个步骤的数据。

  • 我们记录在 s t s_t st​ 采取 a t a_t at​,得到 r t r_t rt​,会跳到什么样的 s t + 1 s_{t+1} st+1​。一直纪录到在第 N 个步骤以后,在 s t + N s_{t+N} st+N采取 a t + N a_{t+N} at+N​ 得到 reward r t + N r_{t+N} rt+N,跳到 s t + N + 1 s_{t+N+1} st+N+1​ 的这个经验,通通把它存下来。实际上你今天在做 Q-network learning 的时候,你的 learning 的方法会是这样,你 learning 的时候,要让 Q ( s t , a t ) Q(s_t,a_t) Q(st,at)跟你的目标值越接近越好。 Q ^ \hat{Q} Q^​ 所计算的不是 s t + 1 s_{t+1} st+1​,而是 s t + N + 1 s_{t+N+1} st+N+1的。你会把 N 个步骤以后的状态 丢进来,去计算 N 个步骤以后,你会得到的 reward。要算目标值的话,要再加上多步(multi-step) 的 reward ∑ t ′ = t t + N r t ′ \sum_{t^{\prime}=t}^{t+N} r_{t^{\prime}} t=tt+Nrt​ ,多步的 reward 是从时间 t 一直到 t+N 的 N 个 reward 的和。然后希望 Q ( s t , a t ) Q(s_t,a_t) Q(st,at) 和目标值越接近越好。

  • 显然它有 MC 的好处跟坏处,也有 TD 的好处跟坏处。如果看它的这个好处的话,因为我们现在 sample 了比较多的步骤,之前是只 sample 了一个步骤, 所以某一个步骤得到的数据是 real 的,接下来都是 Q 值估测出来的。现在 sample 比较多步骤,sample N 个步骤才估测值,所以估测的部分所造成的影响就会比较小。当然它的坏处就跟 MC 的坏处一样,因为 r 比较多项,把 N 项的 r 加起来,方差就会比较大。但是可以去调这N 的值,在 方差 跟不精确的 Q 之间取得一个平衡。N 就是一个 hyperparameter

5. Noisy Net

在这里插入图片描述

  • Epsilon Greedy 的探索是在动作的空间上面加噪声,但是有一个更好的方法叫做Noisy Net它是在参数的空间上面加噪声
  • Noisy Net 的意思是说,每一次在一个 episode 开始的时候,在跟环境互动的时候,在Q网络的每一个参数上面加上一个高斯噪声(Gaussian noise),那就把原来的 Q-function 变成 Q ~ \tilde{Q} Q~​ ,就得到一个新的网络叫做 Q ~ \tilde{Q} Q~​。
  • 这边要注意在每个 episode 开始的时候,开始跟环境互动之前,我们就 sample 网络。接下来用这个固定住的 noisy网络去玩这个游戏,直到游戏结束,才重新再去 sample 新的噪声。OpenAI 跟 DeepMind 又在同时间提出了一模一样的方法,不一样的地方是,他们用不同的方法,去加噪声。OpenAI 直接加一个高斯噪声就结束了,就你把每一个参数,每一个 weight 都加一个高斯噪声就结束了。DeepMind 比较复杂,他们的噪声是由一组参数控制的,也就是说网络可以自己决定那个噪声要加多大。总之就是把Q网络加上一些噪声,把它变得跟原来的 Q-function 不一样,然后拿去跟环境做互动。这个参数虽然会加噪声,但在同一个 episode 里面参数就是固定的。玩第二场新的游戏的时候,才会重新 sample 噪声。在同一场游戏里面就是同一个 noisy Q-network 在玩那一场游戏,这件事非常重要。为什么这件事非常重要呢?因为这是导致了 Noisy Net 跟原来的 Epsilon Greedy 或其它在动作做 sample 方法的本质上的差异。

5.1 Noisy Net 跟 Epsilon Greedy 等方法的本质上的差异。

  • 在原来 sample 的方法,比如说 Epsilon Greedy 里面,就算是给同样的状态,你的 agent 采取的动作也不一定是一样的。因为你是用 sample 决定的,给定同一个状态,要根据 Q-function 的网络,你会得到一个动作,你 sample 到 random,你会采取另外一个 动作。但实际上在一个真实世界的策略,给同样的状态,他应该会有同样的回应。如果你是在 Q-function 上面去加噪声的话,那在整个互动的过程中,在同一个 episode 里面,它的网络的参数总是固定的,所以看到同样的状态,就会采取同样的动作。在 paper 里面有说,这个叫做 state-dependent exploration,也就是说你虽然会做探索这件事, 但是你的探索是跟状态有关系的,看到同样的状态, 你就会采取同样的探索的方式,即有系统地在尝试。而 Epsilon Greedy的动作只是随机乱试。

在这里插入图片描述

6. Distributional Q-function

在这里插入图片描述

  • 还有一个技巧叫做 Distributional Q-function。Q-function 是累积奖励的期望值,所以我们算出来的 Q 值其实是一个期望值。因为环境是有随机性的,在某一个状态 采取某一个动作的时候,我们把所有的 reward 玩到游戏结束的时候所有的 reward 进行一个统计,其实得到的是一个分布。也许在 reward 得到 0 的机率很高,在 -10 的概率比较低,在 +10 的概率比较低,但是它是一个分布。我们对这一个分布算它的平均值才是这个 Q 值,我们算出来是累积奖励的期望。但不同的分布,它们其实可以有同样的平均值。也许真正的分布是图中右边的分布。假设我们只用 Q 值的期望来代表整个 reward 的话,其实可能会丢失一些信息,你没有办法 model reward分布

在这里插入图片描述

  • Distributional Q-function 想要做的事情是对分布(distribution)建模,怎么做呢?在原来的 Q-function 里面,假设你只能够采取 a 1 a_1 a1​, a 2 a_2 a2​, a 3 a_3 a3 3 个动作,那你就是输入一个状态,输出 3 个值。3 个值分别代表 3 个动作的 Q 值,但是这个 Q 值是一个分布的期望值。所以 Distributional Q-function 的想法就是何不直接输出那个分布

  • 实际上的做法是, 假设分布的值就分布在某一个 range 里面,比如说 -10 到 10,那把 -10 到 10 中间拆成一个一个的 bin,拆成一个一个的长条图。 Q-function 的输出是要预测你在某一个状态,采取某一个动作,你得到的 reward,落在某一个 bin 里面的概率。

  • 实际上在做测试的时候, 我们还是要选某一个动作去执行,那选哪一个动作呢?还是选平均值最大的那个动作去执行。

  • 但假设我们可以对 distribution 建模的话,除了选平均值最大的以外,也许在未来你可以有更多其他的运用。举例来说,你可以考虑它的分布长什么样子。如果分布方差很大,代表说采取这个动作虽然平均值可能平均而言很不错,但也许风险很高,你可以训练一个网络它是可以规避风险的。就在 2 个动作平均值都差不多的情况下,也许可以选一个风险比较小的动作来执行,这是 Distributional Q-function 的好处。

6.1 Distributional DQN 本质上不会高估 reward

  • 当用 Distributional DQN 的时候,本质上不会高估 reward。为什么做 Distributional DQN,不会高估 reward,反而会低估 reward 呢?因为这个 Distributional DQN 的输出的是一个分布的范围,输出的范围不可能是无限宽的,你一定是设一个范围, 比如说最大输出范围就是从 -10 到 10。假设今天得到的 reward 超过 10 怎么办?是 100 怎么办,就当作没看到这件事。所以 reward 很极端的值,很大的值其实是会被丢掉的, 所以用 Distributional DQN 的时候,你不会有高估的现象,反而会低估。

6.2 算法伪代码

在这里插入图片描述

具体可查看参考资料:Distrbutional DQN:C51

7. Rainbow

在这里插入图片描述

  • 最后一个技巧叫做 rainbow,把刚才所有的方法都综合起来就变成 rainbow 。给每一个方法一种自己的颜色,把所有的颜色通通都合起来,就变成 rainbow,它把原来的 DQN 也算是一种方法,故有 7 色。
  • A3C 其实是 Actor-Critic 的方法。单纯的 A3C 看起来是比 DQN 强的。这边没有多步的方法(多步的方法就是平衡 TD 跟 MC),可能是因为 A3C 本身内部就有做多步的方法,所以可能觉得实现 A3C 就是实现多步的方法。所以可以把这个 A3C 的结果想成是多步方法的结果。

8. 练习

8.1 简述double DQN原理?

答:DQN由于总是选择当前值函数最大的动作值函数来更新当前的动作值函数,因此存在着过估计问题(估计的值函数大于真实的值函数)。

原本在找 Q 值最大的 a 的时候,是用目标网络来算,现在double DQN改成用另外一个会更新的 Q-network 来算,然后把a带入目标网络得到目标Q值。可以理解为一个网络提议案,另外一个网络进行执行
即:
a = arg max ⁡ Q ( s t + 1 , ) y = r t + Q t a r g e t ( s t + 1 ∣ a ) a=\argmax Q(s_{t+1},)\\ y= r_t+Q_{target}(s_{t+1}|a) a=argmaxQ(st+1,)y=rt+Qtarget(st+1a)

8.2 请问Dueling DQN模型有什么优势呢?

答:对于我们的 Q ( s , a ) Q(s,a) Q(s,a) 其对应的state由于为table的形式,所以是离散的,而实际中的state不是离散的。对于 Q ( s , a ) Q(s,a) Q(s,a)的计算公式, Q ( s , a ) = V ( s ) + A ( s , a ) Q(s,a)=V(s)+A(s,a) Q(s,a)=V(s)+A(s,a) 。其中的 V ( s ) V(s) V(s) 是对于不同的state都有值,对于 A ( s , a ) A(s,a) A(s,a) 对于不同的state都有不同的action对应的值。所以本质上来说,我们最终的矩阵 Q ( s , a ) Q(s,a) Q(s,a)的结果是将每一个 V ( s ) V(s) V(s) 加到矩阵 A ( s , a ) A(s,a) A(s,a) 中得到的。从模型的角度考虑,我们的network直接改变的 Q ( s , a ) Q(s,a) Q(s,a) 而是更改的 V 、 A V、A VA 。但是有时我们update时不一定会将 V ( s ) V(s) V(s) Q ( s , a ) Q(s,a) Q(s,a)都更新。我们将其分成两个path后,我们就不需要将所有的state-action pair都sample一遍,我们可以使用更高效的estimate Q value方法将最终的 Q ( s , a ) Q(s,a) Q(s,a)计算出来。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CHH3213

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值