深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird

          深度强化学习(DQN-Deep Q Network)之应用-Flappy Bird

                         本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10811587.html

目录

1. 存在问题

2. 解决方案

3. 神经网络结构

4. 实现代码分析

5. 运行结果

6. 参考文献

 


 

1. 存在问题

游戏场景:障碍物以一定速度往左前行,小鸟拍打翅膀向上或向下飞翔来避开障碍物,如果碰到障碍物,游戏就GAME OVER!

规则:

图片大小:80 * 80

4 帧作为一组

小鸟行为:向上跳跃或没有任何动作

目标:小鸟如何实现自动躲避障碍物 ?

 

小鸟飞翔的难点是如何准确判断下一步的动作( up or do nothing),而这正是强化学习想要解决的问题。

因为上一节案例网格的所有状态(state)数目只有 16 种,是一种有限的集合,所以可以先求状态最大价值表 V-Table,后求最优策略表 Q-Table。

但是本节的应用场景有所不同,如果以图片中的像素作为状态,那么状态的种类数:

       

注:每个像素值范围是 0-255,有 256 种可能,图片大小是 80 * 80,4 帧作为一组。

那么这个状态的总量是非常庞大的,几乎可以认为是一种无限的集合,对于这种情况,该如何处理呢 ?

 

2. 解决方案

解决这个问题的方案有如下几点:

1> 确定状态:以连续的 4 帧作为一个状态;

2> 采用卷积神经网络来预测状态的每个行为的价值;

3> 神经网络的目标值是通过贝尔曼最优化方程计算状态的最大价值;

第 2>,3> 结合起来就是深度强化学习 DQN(Deep Q Network),也就是强化学习中引入深度学习。

 

3. 神经网络结构

神经网络结构是由 3 个卷积层 + 3 个池化层 + 2 个全连接层组成,这里要注意两点:

1> 特征图输出尺寸和深度的变化

特征图输出尺寸根据如下公式计算:

   

特征图输出深度是由卷积核的深度决定的。

2> 神经网络的输出含义

1 * 2 表示当前状态每个行为产生的价值

 

4. 代码实现分析

4.1 图片处理

 

 在进入神经网络运算之前,需要对图片进行处理,上面的代码功能是对图片 resize 到 80 * 80 大小,灰度化,二值化,拉平处理,目的有两个:

1> 减少神经网络中的浮点运算(二值化后背景噪声的像素值都为 0, 0 * 任何数 = 0),提升运算效率;

2> 有用信息与背景噪声色差明显(二值化后有用信息像素值都为 255,背景噪声为 0),神经网络在训练时能更快收敛,找出内在规律。

4.2 创建卷积神经网络

 神经网络结构是由 3 个卷积层 + 1 个池化层 + 2 个全连接层组成,跟之前介绍的神经网络结构稍微不一样,之前是 3 个卷积层 + 3 个池化层 + 2 个全连接层组成,

这不影响结果,只要输出都是 1 * 2 就可以了。

注意点:每层运算后输出特征图大小的变化,注意参数大小的设定(卷积核参数,全连接参数);

神经网络的输出是 readout ( 1 * 2),readout_action 是 readout 进行了一个矩阵内积运算,得到结果还是 1* 2 矩阵,然后求和降维,变成 1 * 1,便于后面用 MSE

计算 cost。

4.3 核心方法

 在训练之前,先观察一段时间,采集数据,作为训练时的样本数据。

queue 是保存观察结果的队列,超出设定的最大长度会将最早存入数据丢弃(一段进,另一端出)。

readout.eval 是神经网络运算过程,输入参数是状态(连续 4 帧),输出是状态每个行为对应的回报,

通过 get_next_action 方法获取当前状态下一步最佳行为以及对应索引,当然,在这过程中随机的加入一些探索,

防止训练时陷入局部收敛。

取得最佳行为后,与环境进行交互(game_state.frame_step),获取下一帧图片,即时奖励,是否碰到障碍物这些信息。

然后对下一帧图片进行处理(image_process),缩放尺寸到 80 * 80,灰度化,二值化,拉平处理。

更新图片,组装 4 张图片作为下一个状态s_t1(np.append(x_t1, s_t[:, :, :3]), axis = 2),具体过程如下图:

 

 

 注意:第一个状态的 4 帧图片是将第一张图片复制 3 次,组合 4 张图片。

 用 s_t1 更新当前状态 s_t,然后继续循环,当观察的次数超过设定的阈值(self.OBSERVE),就进入训练阶段。

self.obtain_batch_sample 在保存数据队列 queue 中随机提取 batch = 32 批量的数据信息。

s_j_batch: 当前状态的批量数据

a_batch: 行为批量数据

r_batch: 行为对应即时奖励的批量数据

s_j1_batch: 下一状态批量数据

 

readout.eval: 神经网络的运算过程,这里注意输入是下一状态的数据,那么对应输出是下一状态各个行为的回报。

for 循环内代码目的是求神经网络目标值,通过贝尔曼最优化方程计算状态的最大价值,然后保存在 y_batch 中。

 

注意,y_batch 也需要满足 batch = 32 的批量数据结果。

将 y_batch, a_batch, s_j_batch 送入到神经网络中,进行训练(train_grad.run),每 50000 次迭代,保存一次模型。

说明:tensorflow saver.save 方法只保存最近 5 次生成的模型

训练好模型之后,就进入到预测阶段:

readout.eval 获取当前状态每个行为对应的价值

np.argmax 获取状态最大价值对应的行为索引

根据行为索引,确定最佳行动方向,与环境进行交互(frame_step),小鸟就能做出一个动作,并获取下一帧相关信息,

对下一帧进行图片处理(image_process),更新图片,组装成 4 帧图片作为下一状态,并更新当前状态。

每一次循环,就会产生一个最佳行为,然后与环境交互,小鸟就做出一个最佳的动作,将这些动作串联起来,小鸟就能自动躲避障碍物。

 

5.运行结果

因为不能上传视频,所以只能截取几张典型图片了。我训练了5650000 次生成的模型,以这个模型预测,小鸟能够自动识别障碍物,不会发生碰撞。

完整样例代码放在百度网盘 : 

链接:https://pan.baidu.com/s/1Q68Ono4sSSFpihwcEOr4aw
提取码:p5qz

 

每个方法都做了比较详细的注释,操作步骤见 .md 文档,感兴趣的话可以下载下来亲自体验一下。

小鸟运行结果图片

     

 

在观察,训练时运行代码相关参数打印:

 

 7. 参考文献

[1] https://zhuanlan.zhihu.com/p/35134789

[2] https://github.com/yenchenlin/DeepLearningFlappyBird

[3] https://leovan.me/cn/2020/05/introduction-of-reinforcement-learning/

[4] https://www.leiphone.com/category/academic/y5nyxtWsNUrm37a9.html

[5] https://zhuanlan.zhihu.com/p/25498081

 

 

 

不要让懒惰占据你的大脑,不要让妥协拖垮了你的人生。青春就是一张票,能不能赶上时代的快车,你的步伐就掌握在你的脚下。

posted @ 2019-05-06 21:17  w_x_w1985  阅读(11912)  评论(1编辑  收藏  举报