DRQN论文解读

论文题目:Deep Recurrent Q-Learning for Partially Observable MDPs
论文链接:https://arxiv.org/abs/1507.06527



Abstract

深度强化学习可以熟练应对复杂的问题,但内存有限,且在每个决策点需要输入整个游戏界面。
为克服这些缺点,本文在DQN中加入循环网络,将第一个post卷积全连接层替换为循环(recurrent) LSTM,称该方法为Deep Recurrent Q-Network(DRQN)。虽然DRQN在每个timestep只输入一帧画面,但通过时间整合信息,在常规的Atari游戏和闪烁版本的游戏(部分可观察)中,达到了DQN的性能。
此外,用部分可观察的数据进行训练,并用完整的观察数据进行评估,DRQN的性能与观察质量有关。当用完整的观察数据进行训练,用部分可观察的数据进行评估,DRQN的性能下降小于DQN。因此,给定相同长度的历史数据,DRQN是一种可行的替代方案,即在DQN的输入层中加入帧的历史数据。虽然该方法在游戏中没有明显的优势,但当观察质量发生变化时,循环网络在评估时具有更好的适应性。

Introduction

DQN是从有限数量的状态中学习映射关系。在实践中,DQN将最近的四帧画面当作输入进行训练,因此DQN无法记住四帧之前的内容。换言之,任何需要超过四帧记忆的游戏都将表现为非MDP问题,因为游戏未来的状态(和奖励)不仅仅取决于DQN当前的输入。游戏不再是MDP问题,而是部分可观察的MDP(POMDP)。现实世界中,任务往往不具有完整的信息,且有噪声,因此是部分可观察的。
如图1所示,许多Atari2600游戏都是POMDP。例如Pong游戏,当前游戏界面只显示球和球拍的位置,但不知道球的速度。了解球的运动方向,对决定球拍的最佳位置是至关重要的。
在这里插入图片描述
我们观察到,当给定部分可观察的状态时,DQN的性能下降了。我们假设DQN可以通过RNN进行改善,以更好地处理POMDP问题。因此,我们引入了DRQN,将DQN与LSTM结合。我们证明了,DRQN可以处理POMDP问题,并且用完整的观察进行训练,用部分可观察的数据进行评估,DRQN相比DQN能更好地处理信息丢失。因此,当观察质量下降时,DRQN表现更好。

Deep Q-Learning

环境是MDP的形式,用4元组(S, A, P, R)表示。在每个t时刻,agent与MDP的观察进行交互:
在这里插入图片描述
Q-Learning是model-free、off-policy的算法,估计在给定状态state下执行某个行动action的长期回报reward的期望值。这些回报的估值,就是Q-values。Q-value的更新:
在这里插入图片描述
Atari游戏中,有太多独一无二的状态,无法单独估计每种状态下的各种行动的Q值,所以2015年有人提出了DQN。
需要最小化损失函数来训练网络参数:
在这里插入图片描述
用DQN训练的Q-values可能是收敛的,也可能是发散的。
在这里插入图片描述
DQN使用三种技巧来提高训练的稳定性:

  1. 将生成的经验保存在经验池中,然后在训练时每次迭代过程中,从经验池中进行采样;
  2. 有一个独立的目标网络,用于向主网络提供更新的目标。每经过10000次迭代,就用主网络的参数更新目标网络的参数,使得两个网络的参数一致;
  3. 诸如RMSProp (Tieleman and Hinton 2012) 或 ADADELTA (Zeiler 2012) 这样的自适应learning rate方法,每个参数对应一个learning rate,根据梯度的历史更新参数。此步骤是为了弥补缺少固定的训练集,不断变化的经验池可能要求某些参数在达到固定的点之后再开始更新;

网络的损失定义如下:
在这里插入图片描述

Partial Observability

在现实世界中很少有完整的状态,即马尔可夫性在现实世界中很少成立。POMDP承认输入的是部分可观察的数据,所以能更好地捕捉现实世界的动态过程。形式上, POMDP可以表示为6元组,输入agent的是部分可观察的数据,观察质量根据概率分布由系统产生的。
在这里插入图片描述
普通的DQN没有明确的机制来解释POMDP潜在的状态(只有部分状态被观察到,还有部分状态没被观察到),只有当观察的结果反映了潜在的状态时才有效。一般来说,DQN根据观察来评估Q-value,效果可能好,也可能不好,因为:
在这里插入图片描述
DRQN可以让Q网络更好地评估系统的潜在状态,缩小上述等式左右两边的差异。换言之,DRQN可以根据观察内容更好地估计实际的Q-value,在部分可观察的环境中生成更好的策略。

DRQN Architecture

为了减少循环recurrency的影响,我们对DQN进行了较小的修改,仅将第一个全连接层替换为相同大小的循环的LSTM层。
如图2所示,DRQN的结构中,输入一张84*84预处理后的图像。该图像用三个卷积层处理后,再输入全连接的LSTM层。最后,线性层为每个action输出一个Q-value。在训练过程中,网络的卷积部分和循环部分(LSTM)的参数是从头开始共同学习的。我们对几种不同的结构进行了实验,最终采用了现在这种结构,详情见附录A
在这里插入图片描述

Stable Recurrent Updates

更新一个循环卷积网络,需要向后传递许多包含游戏界面和target value的timestep。LSTM的初始隐藏状态可以设为零,或者从先前的值接着计算。我们考虑两种更新方式:

  1. 引导顺序更新Bootstrapped Sequential Updates:从经验回放池中随机选择episode,然后从episode的开始位置进行更新,直到episode结束。在每个timestep中,目标是由target Q 网络生成的。RNN的隐藏状态是在整个episode上进行的;
  2. 引导随机更新Bootstrapped Random Updates:从经验回放池中随机选择episode,从episode随机一个位置开始更新,只进行unroll 迭代的timestep(例如一次向后调用)。在每个timestep中,目标是由target Q网络生成的。在开始更新前,RNN的初始状态设为零。

顺序更新的优点是将LSTM的隐藏状态从episode一开始就向前推进。然而,对一个完整episode的经验进行顺序采样,违反了DQN的随机采样策略。随机更新更好地遵循随机采样策略。但LSTM的隐藏状态在每次更新开始时必须为零。将隐藏状态设为零,会使LSTM更难学习函数(相比后向传播到达的时间,函数跨越的时间长度更长)。
实验表明,两种更新方式都是可行的,在一组游戏中产生的收敛策略性能接近。因此,为了降低复杂性,本文中均采用随机更新策略。我们希望所有的结果都能推广到顺序更新方式。

Atari Games: MDP or POMDP?

对于Atari 2600游戏,人类和agent只能观察到游戏界面,但单个游戏界面不足以确定游戏的完整状态。DQN用最后四帧的游戏界面,来代替游戏的完整状态。许多游戏本来是POMDP,现在变成了MDP。所研究的游戏中,当输入4帧数据时是完全可观察的,我们需要在不减少DQN输入帧数的情况下引入部分可观察的方法。

Flickering Atari Games

我们引入了Flickering Pong(闪烁版本的Pong游戏)——经典Pong的一种修改版本,在每个timestep,游戏界面要么完全显示,要么是模糊的,概率为0.5,模糊的游戏界面使游戏变成了POMDP。为了在Flickering Pong游戏中胜利,需要整合各帧的信息来估计相关变量,例如球的位置和速度、球拍的位置。由于一半的帧是模糊的,必须对几个可能相邻的模糊的输入具有鲁棒性。对游戏界面的时间序列来说,最重要的是检测物体的速度。图3将游戏界面可视化,最大化不同卷积过滤器(filter)的激活,并证实了10帧的DQN过滤器可以检测物体的速度,尽管可能不如原版本的Pong游戏。
在这里插入图片描述
样本卷积的过滤器从DQN 10帧数据中进行学习。每行的图片是输入帧,最大化指定层中特定卷积过滤器的激活。红色边框是输入中导致最大化激活的图像。第一个卷积层的过滤器仅检测球拍。第二个卷积层的过滤器检测球在特定方向上的移动,有些是同时跟踪球和球拍。第三个卷积层的过滤器,几乎全部都跟踪球和球拍的相互作用,包括偏转、球的速度和飞行方向。尽管一次只能看到一帧画面,单个LSTM单元也能检测到高级别的事件:agent错过了球,球在球拍上的反射,球在墙壁上的反射。如果agent看到的是最后10帧重叠形成的图像,最近的帧会有更高的亮度。

值得注意的是,DRQN在这项任务中表现很好,即使在每个timestep中仅输入一帧。在一帧的情况下,DRQN的卷积层不可能检测到任何类型的速度。所以,高级别(higher-level)的循环层需要同时补偿闪烁版本中游戏界面和卷积速度检测的不足。
图3(d)中证实,LSTM层中的单个单元能够通过时间整合有噪声的单帧信息,以检测高级别的Pong游戏的事件:玩家错过球、球在球拍上反射、球在墙壁上反射。
DRQN使用后向传播最后10个timestep进行训练。因此,非循环的10帧DQN和循环的1帧DRQN,都可以获取相同游戏界面的历史数据(2015年有人提出,LSTM可以在训练时通过有限的一组timestep学习函数,然后在测试时将他们推广到更长的序列中)。因此,在处理部分可观测性时,可以选择使用具有长期历史观测数据的非循环深度网络,或使用在每个timestep中由单个观测值训练的循环网络。本节的结果表明,循环网络可以通过时间整合信息,并在卷积网络的输入层中保存帧的数据,这种方案是可行的。

Evaluation on Standard Atari Games

我们选择了以下九种Atari游戏进行评估:

  • Asteroids and Double Dunk:包含不断闪烁的画面,有利于循环学习;
  • Beam Rider, Centipede, and Chopper Command:射击游戏;
  • Frostbite:与Frogger类似的游戏;
  • Ice Hockey and Double Dunk:运动类游戏,需要定位球员、传球、踢球,球员需要进攻和防守;
  • Bowling:在特定时间执行行动来引导保龄球;
  • Ms Pacman:特点是闪烁的幽灵和药丸;

给定最后四帧作为输入,所有的这些游戏都是MDP,而不是POMDP。表1中的结果表明,DRQN和DQN的表现差不多。
在这里插入图片描述
在这里插入图片描述

MDP to POMDP Generalization

循环网络能在标准的MDP上训练,然后在评估时推广到POMDP吗?为了解决这个问题,我们评估了DRQN和DQN在所有9个游戏的flickering版本中得分最高的策略,见表1.
图5显示,当这两种算法由于信息丢失而导致性能的显著下降,当观察质量下降时,DRQN比DQN更能维持性能。
在这里插入图片描述
我们得出结论,循环网络对信息丢失具有一定的鲁棒性,即使是用完整的状态信息进行训练。

Related Work

当使用策略梯度(policy gradient)时,LSTM网络已经被证明可以用来解决POMDP问题。与策略梯度不同,我们使用时间差分(temporal-difference)更新来引导动作值函数(action-value function)。此外,通过一起训练卷积层和LSTM层,我们能够直接从像素中学习,不需要手工设计的特征。
用LSTM作为advantage-function的逼近器,来解决部分可观察的corridor和cartpole游戏,结果证明比非LSTM的RNN效果更好。虽然原理上类似,corridor和cartpole游戏的特征是只有一些特征的较小的状态空间。
2015年,有人将LSTM与深度强化学习结合,以证明循环有助于玩基于文本的游戏。方法是类似的:虽然生成的文本比较复杂,但MDP具有相对低维度的状态空间。两种游戏中比较复杂的只有56个基本状态。相比之下,Atari游戏的状态空间更大,典型的游戏中有数百万个不同的状态。然而,文本游戏的行动空间更大,一个分支可以达到222,而Atari只有18.

Discussion and Conclusion

现实世界中,任务的状态信息往往是不完整且有噪声的,所以是部分可观察的。我们对DQN进行了改进,将LSTM与DQN结合来处理POMDP问题,即DRQN。尽管在每一步中只输入一帧数据,DRQN仍然能够跨越多个帧整合信息,以检测相关信息,例如屏幕上物体的速度。此外,在闪烁版本的Pong游戏中,对于处理这种部分可观察问题,DRQN比常规的DQN表现得更好。
当训练部分是部分可观察的,DRQN可以将策略推广到完全可观察的情形。在Pong游戏中,算法的性能与观察质量有关,当每个游戏界面都能观察到时,性能达到最佳水平。结果表明,循环网络学习的策略具有鲁棒性,能处理丢失的游戏界面,并随着观察质量的提高,性能也随之提高。当用常规的Atari游戏进行训练,用闪烁版本的游戏进行评估时,对不同质量的观察信息,DRQN比DQN的表现更好。
实验中,Pong游戏代表了一类游戏。在一组闪烁版本的10帧MDP数据中,使用循环网络在性能上没有明显的提升。在常规的Atari游戏中,DRQN和DQN的表现也没有显著差异。
我们得出结论,虽然DRQN在处理状态观察问题时是一种可行的方法,与在卷积网络的输入层中保存观察信息相比,性能上没有表现得更好。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用TensorFlow实现DRQN(Deep Recurrent Q-Network)的示例代码: ```python import tensorflow as tf import numpy as np class DRQN: def __init__(self, state_dim, action_dim, hidden_dim, batch_size, learning_rate, memory_size, max_steps): self.state_dim = state_dim self.action_dim = action_dim self.hidden_dim = hidden_dim self.batch_size = batch_size self.learning_rate = learning_rate self.memory_size = memory_size self.max_steps = max_steps self.replay_memory = [] self.build_model() self.sess = tf.Session() self.sess.run(tf.global_variables_initializer()) def build_model(self): self.state_input = tf.placeholder(tf.float32, [None, self.max_steps, self.state_dim]) self.action_input = tf.placeholder(tf.int32, [None]) self.q_target = tf.placeholder(tf.float32, [None]) cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=self.hidden_dim) outputs, states = tf.nn.dynamic_rnn(cell, self.state_input, dtype=tf.float32) output = outputs[:, -1, :] w1 = tf.Variable(tf.random_normal([self.hidden_dim, self.action_dim])) b1 = tf.Variable(tf.zeros([self.action_dim])) self.q_value = tf.matmul(output, w1) + b1 self.predict_action = tf.argmax(self.q_value, axis=1) action_one_hot = tf.one_hot(self.action_input, self.action_dim) q_value_action = tf.reduce_sum(tf.multiply(self.q_value, action_one_hot), axis=1) self.loss = tf.reduce_mean(tf.square(self.q_target - q_value_action)) self.optimizer = tf.train.AdamOptimizer(self.learning_rate).minimize(self.loss) def store_experience(self, state, action, reward, next_state, done): self.replay_memory.append((state, action, reward, next_state, done)) if len(self.replay_memory) > self.memory_size: self.replay_memory.pop(0) def choose_action(self, state): if np.random.uniform() < 0.1: return np.random.choice(self.action_dim) else: return self.sess.run(self.predict_action, feed_dict={self.state_input: [state]})[0] def learn(self): if len(self.replay_memory) < self.batch_size: return samples = np.random.choice(len(self.replay_memory), self.batch_size, replace=False) states = np.zeros([self.batch_size, self.max_steps, self.state_dim]) actions = np.zeros([self.batch_size]) rewards = np.zeros([self.batch_size]) next_states = np.zeros([self.batch_size, self.max_steps, self.state_dim]) dones = np.zeros([self.batch_size]) for i, sample in enumerate(samples): state, action, reward, next_state, done = self.replay_memory[sample] states[i] = state actions[i] = action rewards[i] = reward next_states[i] = next_state dones[i] = done q_values_next = self.sess.run(self.q_value, feed_dict={self.state_input: next_states}) max_q_values_next = np.max(q_values_next, axis=1) q_targets = rewards + (1 - dones) * 0.99 * max_q_values_next self.sess.run(self.optimizer, feed_dict={self.state_input: states, self.action_input: actions, self.q_target: q_targets}) ``` 这是一个简单的DRQN实现,它使用LSTM作为循环层,并且处理具有可变长度的序列输入。该模型使用经验回放进行训练,并且在每个时间步上选择动作时使用epsilon-greedy策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值