Shortcuts

Rainbow

概述

Rainbow 是在 Rainbow: Combining Improvements in Deep Reinforcement Learning. 它将许多独立的改进方法应用于DQN,包括: Double DQN, priority, dueling head, multi-step TD-loss, C51 (distributional RL) 和 noisy net。

要点摘要

  1. Rainbow 是一种 无模型(model-free)基于值(value-based) 的强化学习算法。

  2. Rainbow 仅支持 离散动作空间

  3. Rainbow 是一种 异策略(off-policy) 算法。

  4. Usually, Rainbow 使用 eps-greedy多项式采样 或者 noisy net 进行探索。

  5. Rainbow 可以与循环神经网络 (RNN) 结合使用。

  6. Rainbow 的 DI-engine 实现支持 多离散(multi-discrete) 动作空间。

关键方程或关键图表

Double DQN

Double DQN, 是在 Deep Reinforcement Learning with Double Q-learning 中提出的一种常见的 DQN 变体。传统的DQN维护一个目标Q网络,该网络周期性地使用当前的Q网络进行更新。双重DQN通过解耦解决了Q值的过高估计问题。它使用当前的Q网络选择动作,但使用目标网络估计Q值,具体而言:

\[\left(R_{t+1}+\gamma_{t+1} q_{\bar{\theta}}\left(S_{t+1}, \underset{a^{\prime}}{\operatorname{argmax}} q_{\theta}\left(S_{t+1}, a^{\prime}\right)\right)-q_{\theta}\left(S_{t}, A_{t}\right)\right)^{2}\]

Prioritized Experience Replay(PER)

DQN 从经验回放缓冲区均匀地进行采样。理想情况下,我们希望更频繁地采样那些有更多可学习内容的 transition。作为评估学习潜力的一种替代方法,优先级经验回放会根据最新的绝对 TD 误差转化得到的概率来采样对应的transition,具体而言:

\[p_{t} \propto\left|R_{t+1}+\gamma_{t+1} \max _{a^{\prime}} q_{\bar{\theta}}\left(S_{t+1}, a^{\prime}\right)-q_{\theta}\left(S_{t}, A_{t}\right)\right|^{\omega}\]

在优先级经验回放(PER)的原始论文中,作者展示了在57个Atari游戏中,PER在大多数游戏上都取得了改进,特别是在 Gopher, Atlantis, James Bond 007, Space Invaders 等游戏中。

Dueling Network

Ddueling network 是一种为基于值的强化学习算法设计的网络架构。它包含两个计算流,一个用于状态值函数 \(V\) ,另一个用于状态相关的动作优势函数 \(A\) 。 这两个流共享一个公共的卷积编码器,并通过一个特殊的聚合器合并,产生状态-动作值函数Q的估计,如图所示。

../_images/DuelingDQN.png

给定 \(Q\) ,我们无法唯一地恢复 \(V\)\(A\) 。因此,我们通过以下的动作值分解方式来强制使优势函数为零:

\[q_{\theta}(s, a)=v_{\eta}\left(f_{\xi}(s)\right)+a_{\psi}\left(f_{\xi}(s), a\right)-\frac{\sum_{a^{\prime}} a_{\psi}\left(f_{\xi}(s), a^{\prime}\right)}{N_{\text {actions }}}\]

通过这种方式,可以解决可识别性问题,并增加优化过程的稳定性。Rainbow的网络架构是一种针对回报分布进行调整的 dueling network 网络架构。

Multi-step Learning

DQN的多步变体通过最小化替代损失来定义,具体如下:

\[\left(R_{t}^{(n)}+\gamma_{t}^{(n)} \max _{a^{\prime}} q_{\bar{\theta}}\left(S_{t+n}, a^{\prime}\right)-q_{\theta}\left(S_{t}, A_{t}\right)\right)^{2}\]

其中,截断的n步回报定义为:

\[R_{t}^{(n)} \equiv \sum_{k=0}^{n-1} \gamma_{t}^{(k)} R_{t+k+1}\]

在文章 Revisiting Fundamentals of Experience Replay, 作者分析认为,当使用多步学习时,更大容量的回放缓冲区显著提高了性能,并且他们认为原因是多步学习带来了更大的方差,而这一方差可以通过更大的回放缓冲区来进行补偿。

Distributional RL

Distributional RL 最初是在 A Distributional Perspective on Reinforcement Learning 中提出的。它通过使用离散分布来学习逼近回报的分布,而不是期望回报。它的分布由一个向量 \(\boldsymbol{z}\) 支持, 即 \(z^{i}=v_{\min }+(i-1) \frac{v_{\max }-v_{\min }}{N_{\text {atoms }}-1}\) ,其中 \(i \in\left\{1, \ldots, N_{\text {atoms }}\right\}\), \(N_{\text {atoms }} \in \mathbb{N}^{+}atoms\) 。 它在t时刻的近似分布 \(d_{t}\) 在这个支持向量上被定义, 在每个原子 \(i\) 上的概率为 \(p_{\theta}^{i}\left(S_{t}, A_{t}\right)\) 最终的分布可以表示为 \(d_{t}=\left(z, p_{\theta}\left(S_{t}, A_{t}\right)\right)\) 。 然后,通过最小化分布 \(d_{t}\) 和目标分布之间的Kullback-Leibler散度,得到了一种 Q-learning 的 distributional variant 。

\[D_{\mathrm{KL}}\left(\Phi_{\boldsymbol{z}} d_{t}^{\prime} \| d_{t}\right)\]

在这里, \(\Phi_{\boldsymbol{z}}\) 是目标分布在固定支持 \(\boldsymbol{z}\) 上的L2投影。

Noisy Net

Noisy Nets使用一个噪声线性层,它结合了确定性和噪声流:

\[\boldsymbol{y}=(\boldsymbol{b}+\mathbf{W} \boldsymbol{x})+\left(\boldsymbol{b}_{\text {noisy }} \odot \epsilon^{b}+\left(\mathbf{W}_{\text {noisy }} \odot \epsilon^{w}\right) \boldsymbol{x}\right)\]

随着时间的推移,网络可以学习忽略噪声流,但在状态空间的不同部分以不同的速率进行学习,从而实现一种自适应的状态条件探索,即一种自退火机制。当动作空间很大时,例如在 Montezuma’s Revenge 等游戏中噪声网络通常比 \(\epsilon\)-greedy 方法取得更好的改进效果,这是由于 \(\epsilon\)-greedy 往往会在收集足够数量的动作奖励之前迅速收敛到一个 one hot 分布。 在我们的实现中,噪声在每次前向传播时都会重新采样,无论是在数据收集还是训练过程中。当使用双重Q学习时,目标网络也会在每次前向传播之前重新采样噪声。噪声采样过程中,噪声首先从 \(N(0,1)\) 中进行采样,然后通过一个保持符号的平方根函数进行调节,即 \(x \rightarrow x.sign() * x.sqrt()\).

Intergrated Method

首先,我们将一步的 distributional loss 替换为多步损失:

\[\begin{split}\begin{split} D_{\mathrm{KL}}\left(\Phi_{\boldsymbol{z}} d_{t}^{(n)} \| d_{t}\right) \\ d_{t}^{(n)}=\left(R_{t}^{(n)}+\gamma_{t}^{(n)} z,\quad p_{\bar{\theta}}\left(S_{t+n}, a_{t+n}^{*}\right)\right) \end{split}\end{split}\]

然后,我们将多步 distributional loss 与 Double DQN相结合,通过使用在线网络选择贪婪动作,并使用目标网络评估该动作。KL损失也被用来优先选择转换:

\[p_{t} \propto\left(D_{\mathrm{KL}}\left(\Phi_{z} d_{t}^{(n)} \| d_{t}\right)\right)^{\omega}\]

网络有共享的表征层, 之后将其输入到 \(N_{atoms}\) 输出的值流 \(v_\eta\) 中,以及  \(N_{atoms} \times N_{actions}\) 输出的优势函数流 \(a_{\psi}\), 在这里 \(a_{\psi}^i(a)\) 表示与原子i和动作a对应的输出。对于每个原子 \(z_i\) , 值流和优势流被聚合,类似于 Dueling DQN,然后通过softmax层进行处理,以获得用于估计回报分布的归一化参数化分布:

\[\begin{split}\begin{split} p_{\theta}^{i}(s, a)=\frac{\exp \left(v_{\eta}^{i}(\phi)+a_{\psi}^{i}(\phi, a)-\bar{a}_{\psi}^{i}(s)\right)}{\sum_{j} \exp \left(v_{\eta}^{j}(\phi)+a_{\psi}^{j}(\phi, a)-\bar{a}_{\psi}^{j}(s)\right)} \\ \text { where } \phi=f_{\xi}(s) \text { and } \bar{a}_{\psi}^{i}(s)=\frac{1}{N_{\text {actions }}} \sum_{a^{\prime}} a_{\psi}^{i}\left(\phi, a^{\prime}\right) \end{split}\end{split}\]

扩展

  • Rainbow 可以与以下技术相结合使用:

    • 循环神经网络 (RNN)

实现

Rainbow 默认参数如下:

class ding.policy.rainbow.RainbowDQNPolicy(cfg: EasyDict, model: Module | None = None, enable_field: List[str] | None = None)[source]
Overview:
Rainbow DQN contain several improvements upon DQN, including:
  • target network

  • dueling architecture

  • prioritized experience replay

  • n_step return

  • noise net

  • distribution net

Therefore, the RainbowDQNPolicy class inherit upon DQNPolicy class

Config:

ID

Symbol

Type

Default Value

Description

Other(Shape)

1

type

str

rainbow

RL policy register name, refer to
registry POLICY_REGISTRY
this arg is optional,
a placeholder

2

cuda

bool

False

Whether to use cuda for network
this arg can be diff-
erent from modes

3

on_policy

bool

False

Whether the RL algorithm is on-policy
or off-policy

4

priority

bool

True

Whether use priority(PER)
priority sample,
update priority

5

model.v_min

float

-10

Value of the smallest atom
in the support set.

6

model.v_max

float

10

Value of the largest atom
in the support set.

7

model.n_atom

int

51

Number of atoms in the support set
of the value distribution.

8

other.eps
.start

float

0.05

Start value for epsilon decay. It’s
small because rainbow use noisy net.

9

other.eps
.end

float

0.05

End value for epsilon decay.

10

discount_
factor

float

0.97, [0.95, 0.999]

Reward’s future discount factor, aka.
gamma
may be 1 when sparse
reward env

11

nstep

int

3, [3, 5]

N-step reward discount sum for target
q_value estimation

12

learn.update
per_collect

int

3

How many updates(iterations) to train
after collector’s one collection. Only
valid in serial training
this args can be vary
from envs. Bigger val
means more off-policy

Rainbow使用的网络接口被定义如下:

class ding.model.template.q_learning.RainbowDQN(obs_shape: int | SequenceType, action_shape: int | SequenceType, encoder_hidden_size_list: SequenceType = [128, 128, 64], head_hidden_size: int | None = None, head_layer_num: int = 1, activation: Module | None = ReLU(), norm_type: str | None = None, v_min: float | None = -10, v_max: float | None = 10, n_atom: int | None = 51)[source]
Overview:

The neural network structure and computation graph of RainbowDQN, which combines distributional RL and DQN. You can refer to paper Rainbow: Combining Improvements in Deep Reinforcement Learning https://arxiv.org/pdf/1710.02298.pdf for more details.

Interfaces:

__init__, forward

Note

RainbowDQN contains dueling architecture by default.

forward(x: Tensor) Dict[source]
Overview:

Use observation tensor to predict Rainbow output. Parameter updates with Rainbow’s MLPs forward setup.

Arguments:
  • x (torch.Tensor):

    The encoded embedding tensor with (B, N=hidden_size).

Returns:
  • outputs (Dict):

    Run MLP with RainbowHead setups and return the result prediction dictionary.

ReturnsKeys:
  • logit (torch.Tensor): Logit tensor with same size as input x.

  • distribution (torch.Tensor): Distribution tensor of size (B, N, n_atom)

Shapes:
  • x (torch.Tensor): \((B, N)\), where B is batch size and N is head_hidden_size.

  • logit (torch.FloatTensor): \((B, M)\), where M is action_shape.

  • distribution(torch.FloatTensor): \((B, M, P)\), where P is n_atom.

Examples:
>>> model = RainbowDQN(64, 64) # arguments: 'obs_shape' and 'action_shape'
>>> inputs = torch.randn(4, 64)
>>> outputs = model(inputs)
>>> assert isinstance(outputs, dict)
>>> assert outputs['logit'].shape == torch.Size([4, 64])
>>> # default n_atom: int =51
>>> assert outputs['distribution'].shape == torch.Size([4, 64, 51])

基准

environment

best mean reward

evaluation results

config link

comparison

Pong

(PongNoFrameskip-v4)

21

../_images/pong_rainbow.png

config_link_p

Tianshou(21)

Qbert

(QbertNoFrameskip-v4)

20600

../_images/qbert_rainbow.png

config_link_q

Tianshou(16192.5)

SpaceInvaders

(SpaceInvadersNoFrame skip-v4)

2168

../_images/spaceinvaders_rainbow.png

config_link_s

Tianshou(1794.5)

P.S.:

  1. 上述结果是通过在五个不同的随机种子 (0, 1, 2, 3, 4)上运行相同的配置获得的。

  2. 对于离散动作空间算法,通常使用 Atari 环境集进行测试(包括子环境 Pong ) ,而 Atari 环境通常通过训练10M个环境步骤的最高平均奖励来评估。有关 Atari 的更多详细信息, 请参阅 Atari Env Tutorial .

关于Rainbow算法的实验技巧

我们在LunarLander环境上进行了实验, 把 rainbow (dqn) 策略与 n-step, dueling, priority, and priority_IS 等基准比较. 实验的代码链接在这里 here. 请注意,配置文件默认设置为 dqn ,如果我们想采用 rainbow 需要将策略类型更改如下:

lunarlander_dqn_create_config = dict(
 env=dict(
     type='lunarlander',
     import_names=['dizoo.box2d.lunarlander.envs.lunarlander_env'],
 ),
 env_manager=dict(type='subprocess'),
 policy=dict(type='rainbow'),
)

以下是关于实验设置的详细说明:

Experiments setting

Remark

base

one step DQN (n-step=1, dueling=False, priority=False, priority_IS=False)

n-step

n step DQN (n-step=3, dueling=False, priority=False, priority_IS=False)

dueling

use dueling head trick (n-step=3, dueling=True, priority=False, priority_IS=False)

priority

use priority experience replay buffer (n-step=3, dueling=False, priority=True, priority_IS=False)

priority_IS

use importance sampling tricks (n-step=3, dueling=False, priority=True, priority_IS=True)

  1. reward_mean 相对于 training iteration 被作为评估指标。

  2. 每个实验设置将使用随机种子0、1和2进行三次运行,并对结果进行平均,以确保结果的随机性。

if __name__ == "__main__":
   serial_pipeline([main_config, create_config], seed=0)
  1. By setting the exp_name in config file, the experiment results can be saved in specified path. Otherwise, it will be saved in ‘./default_experiment’ directory.

from easydict import EasyDict
from ding.entry import serial_pipeline

nstep = 1
lunarlander_dqn_default_config = dict(
 exp_name='lunarlander_exp/base-one-step2',
 env=dict(
    ......

结果如下图所示。可以看到,通过使用技巧,收敛速度大大加快。在这个实验设置中, Dueling trick 对性能的贡献最大。

../_images/rainbow_exp.png

参考文献

(DQN) Mnih, Volodymyr, et al. “Human-level control through deep reinforcement learning.” 2015; [https://deepmind-data.storage.googleapis.com/assets/papers/DeepMindNature14236Paper.pdf]

(Rainbow) Matteo Hessel, Joseph Modayil, Hado van Hasselt, Tom Schaul, Georg Ostrovski, Will Dabney, Dan Horgan, Bilal Piot, Mohammad Azar, David Silver: “Rainbow: Combining Improvements in Deep Reinforcement Learning”, 2017; [http://arxiv.org/abs/1710.02298 arXiv:1710.02298].

(Double DQN) Van Hasselt, Hado, Arthur Guez, and David Silver: “Deep reinforcement learning with double q-learning.”, 2016; [https://arxiv.org/abs/1509.06461 arXiv:1509.06461]

(PER) Schaul, Tom, et al.: “Prioritized Experience Replay.”, 2016; [https://arxiv.org/abs/1511.05952 arXiv:1511.05952]

William Fedus, Prajit Ramachandran, Rishabh Agarwal, Yoshua Bengio, Hugo Larochelle, Mark Rowland, Will Dabney: “Revisiting Fundamentals of Experience Replay”, 2020; [http://arxiv.org/abs/2007.06700 arXiv:2007.06700].

(Dueling network) Wang, Z., Schaul, T., Hessel, M., Hasselt, H., Lanctot, M., & Freitas: “Dueling network architectures for deep reinforcement learning”, 2016; [https://arxiv.org/abs/1511.06581 arXiv:1511.06581]

(Multi-step) Sutton, R. S., and Barto, A. G.: “Reinforcement Learning: An Introduction”. The MIT press, Cambridge MA. 1998;

(Distibutional RL) Bellemare, Marc G., Will Dabney, and Rémi Munos.: “A distributional perspective on reinforcement learning.”, 2017; [https://arxiv.org/abs/1707.06887 arXiv:1707.06887]

(Noisy net) Fortunato, Meire, et al.: “Noisy networks for exploration.”, 2017; [https://arxiv.org/abs/1706.10295 arXiv:1706.10295]

其他开源实现