目录

AI玩Flappy-Bird-基于Q-Learning和DQN的机器学习

AI玩Flappy Bird || 基于Q-Learning和DQN的机器学习

https://i-blog.csdnimg.cn/direct/dabb494b5afe4f6caa30c7b09850749c.png

Flappy Bird 游戏需要玩家控制一只小鸟越过管道障碍物。玩家只可以进行“跳跃”或者“不操作”两种操作,即点或不点。点则让小鸟上升一段距离,不点小鸟继续下降。若小鸟碰到障碍物或地面,则游戏失败。

本项目目的是开发一个深层神经网络模型,具体地,利用图像中的不同对象 训练卷积神经网络 ,进行基于游戏画面场景状态分析进行 图像识别分类 。从原始像素中学习游戏的特性,并决定采取相应行动,本质上是一个对游戏场景中特定状态的 模式识别 过程,在此设计了一个强化学习系统,通过自主学习来玩这款游戏。

当通过很少预定的行为进行编程不能充分解决问题时,可采用 强化学习 方式,这是一种通过进行 场景训练 ,使算法在输入未知和多维数据(如彩色图片)时做出正确的决策方式。通过这种方式,算法可以学会自动对图像进行 特征提取 ,对于训练中未出现的场景和状态也同样可以进行 分类和预测

(1)去除背景颜色——背景使用黑色

为了节省内存将其缩小为84x84大小的图像,每帧图像色阶都是0-255。 此外,为了提高卷积神经网络的精度,在这一步去除背景层并用纯黑色背景代替,以去除噪声。

https://i-blog.csdnimg.cn/direct/b5578ed0536e496f9f031f43bdee2944.png

(2) 对图像进行处理——灰度处理

依次对所得游戏图像进行缩放、灰度化以及调整亮度处理。在当前帧进入一个状态之前,处理几帧图像叠加组合的多维图像数据(如在模型构建部分提到的),当前帧与先前帧重叠时,灰度稍有降低,当我们远离最新帧时强度降低。因此,这样输入的图像将提供关于小鸟当前所在轨迹的良好信息,其处理过程如图2所示。

https://i-blog.csdnimg.cn/direct/0306de0e86da495b9a56325ee260d578.png

代码:

https://i-blog.csdnimg.cn/direct/f33cc90ee8184756ad976312f0cb0ec5.png

(1)贝尔曼方程

强化学习的目标是使总回报(奖励)最大化。在Q-Learning中,它是非策略的,迭代更新使用的是贝尔曼方程,获得Q值的目标值,

https://i-blog.csdnimg.cn/direct/ea2d7f1322c047c0a52be3a1b02f68fb.png

其中s′和a′ 分别是下一帧的状态和动作(1或0),r是奖励(-1,0.1,1),γ是折扣因子。Qi(s,a)是为( s , a )矩阵在第i次迭代的Q值。这种更新迭代将收敛得到一个最佳的Q函数。为了防止学习僵化,这个动作值函数可以用一个函数(这里为深度学习网络)近似,以便能更好概括不可预见的状态。

https://i-blog.csdnimg.cn/direct/56694787d9bf4b498cb106f5af655339.png

具体应用:

在训练的每个迭代中,通过以上代码应用贝尔曼方程来计算目标 Q 值(记为y_batch); 在这里,对于每个批次中的样本,目标 Q 值通过应用贝尔曼方程计算得到,考虑了当前奖励以及下一个状态的最大预测Q值。

(2) 各个重要值的具体设定:

学习率 (lr): 1e-6

折扣因子 (gamma): 0.99

初始探索率 (initial_epsilon): 0.1

最终探索率 (final_epsilon): 1e-4

每批图像数量 (batch_size): 32

重放记忆池大小 (replay_memory_size): 3000

图像预处理尺寸 (image_size): 84

最大迭代次数 (num_iters): 200000

https://i-blog.csdnimg.cn/direct/57f207effb0d4c8199264b75488a7589.png

然后通过当前模型的预测值和动作来计算当前状态的 Q 值(记为q_value):

https://i-blog.csdnimg.cn/direct/60126f78f27640ba8ab1af507897ddc6.png

这里,将当前模型的预测结果与动作进行乘积,然后对结果进行求和,从而得到当前状态的Q值。 在损失计算部分,使用均方误差损失函数(MSELoss)来衡量模型的训练效果:

https://i-blog.csdnimg.cn/direct/629a9e01df6b4ae68c3ac8d9fbd1fe51.png

https://i-blog.csdnimg.cn/direct/476a2f8f6cd0457ba4784f763638bd4a.png

这里将当前状态的 Q 值(q_value)和目标 Q 值(y_batch)之间的均方误差作为损失值,然后通过反向传播和优化器更新模型参数。

均方误差(mean square error, MSE),是反应估计量与被估计量之间差异程度的一种度量,设t是根据子样确定的总体参数Ɵ的一个估计量,(Ɵ-t) ^2 的数学期望,称为估计量t 的均方误差。(n为样本个数)

在当前模型结构中,首先有三个卷积层,然后是两个完全连接层,最终完全连接层的输出是两个动作的得分,结果由损失函数得出。损失函数自动进行Q学习参数设置。遵循空间批量规范,在每个卷积层后都添加ReLu。输入图像的大小84×84,每个时刻有两种可能的输出操作,每次动作将会获得一个得分值,以此决定最佳动作。

https://i-blog.csdnimg.cn/direct/de7863d16e7747bbbbb8fcf02758a7d2.png

图像resize成84x84大小!

https://i-blog.csdnimg.cn/direct/1250460e89b24969ac842c7980b96d9f.png

https://i-blog.csdnimg.cn/direct/6aba45841dc34bb3b8aeecdfc8d5e8ce.png

可以看到,这里的网络使用了连续三个卷积层+两个全连接层的形式。最后输出为2个值,即动作选择。

(1)增加样本池

在Q-Learning中,以连续方式记录的经验数据是高度相关的。若使用相同的顺序更新DQN参数,训练过程就会受到干扰。与从一个标记的数据集中采样小批量训练分类模型类似,这里同样应该在抽取出的获得更新的DQN经验中引入一定的随机性。为此设置一个 经验回放存储器 ,用来存储每帧游戏画面的经验数据,直到达到其最大存储容量。(DQN的一大特点就是设置了数据库,后续的每次训练从数据库中抽取数据。这样可以使得训练更加有效。)

https://i-blog.csdnimg.cn/direct/4d85de62123c41169bb903f5c4dcc8da.png

程序中,使用了一个队列replay_memory来当作经验池,经验池大小replay_memory_size设置为30000,如果数据库容量达到上限,将会把最先进入的数据抛出,即队列的先入先出。

https://i-blog.csdnimg.cn/direct/50287728f35048a8a6426ed56bc2a8d3.png

过大的经验池会占用更多的内存资源,可能导致计算效率低下或资源不足。

过小的经验池可能导致模型无法充分利用历史经验数据,从而影响模型的训练效果和性能。

经验池大小与批次大小(batch size)密切相关,它们共同决定了模型每次更新时能够处理的经验数据数量。批次大小也是一个需要仔细调整的超参数。

(2) 利用神经网络计算Q值

输入状态值,输出为Q值,根据大量的数据去训练神经网络的参数,最终得到Q-Learning的计算模型。

https://i-blog.csdnimg.cn/direct/90d8a4a5b9664407bb9505da65106b34.png

这里有三个卷积层(conv1、conv2、conv3),它们依次对输入数据进行处理。每个卷积层都会提取输入数据的某些特征,并将结果传递给下一个层。每次卷积操作后,output变量都会更新为新的特征映射。

在将数据传递给全连接层之前,通常需要将卷积层输出的多维张量(通常是一个四维张量:批量大小 x 通道数 x 高度 x 宽度)展平为一个二维张量(批量大小 x 特征数量)。.view()函数就是用来进行这种展平操作的。在这里,output.size(0)保留了批量大小不变,而-1则让PyTorch自动计算第二个维度的大小,以确保数据的总元素数量不变。

经过展平后,数据被传递给两个全连接层(fc1和fc2)。这些层通常用于对提取的特征进行分类或回归。

(1)开启游戏模拟器,会打开一个窗口,实时显示游戏的信息,获取游戏的状态

(2)创建样本池

(3)当训练次数小于设置的迭代次数(300万)时,进入训练 获得的第一个数值, 也就是从神经网络当中的q数值

(4)执行一个随机动作或者神经网络计算的Q(s,a)值选择对应的动作

(5)样本池使用一个大小确定的队列来进行维护,其中存放的是游戏过程中的数据state, action, reward, next_state, terminal

(6)得到下一帧图像进行数据预处理

(7)每执行一次动作,游戏会返回执行该动作之后的一帧图像,把样本池更新,

(1)初始化Q函数Q,目标Q函数Q ̂= Q对于每一个回合

a)对于每一个时间步iter

探索与利用(随着训练的次数越来越多,Q值函数越来越精确,比较能确定较好的动作,把epsilon的值变小,减少探索,即较少随机决定动作)

b)对于给定的状态state ,基于Q (epsilon - 贪心)执行动作action

c)获得反馈reward,并获得新的状态next_state

d)将(state, action , reward , next_state)存储到缓冲区中(更新经验池)

e)从缓冲区中采样(通常以批量形式)( state, action , reward , next_state)

f)目标值是y = reward + 〖max〗_a Q ̂ (state , action)

(2)更新Q的参数使得Q(state , action)尽可能接近于回归

(3)每C步重置Q ̂=Q

使用train.py每隔50000次训练产生保存的模型,产生游戏对应画面的下一个动作,累计计算得分,直到小鸟掉落或撞管道换下一个模型测试,最后根据每个模型的得分,产生得分曲线图。

https://i-blog.csdnimg.cn/direct/fa78a79c42324ae69254830fe453d132.png

通过get_args()函数获取用户输入的参数。循环测试不同迭代次数下的游戏表现。将每次迭代的得分记录下来,并输出到控制台。使用matplotlib绘制图表,展示迭代次数与游戏得分的关系。最后保存图表为图片文件。

200万次

https://i-blog.csdnimg.cn/direct/995f85acac1045848d774d6c816036a2.png

https://i-blog.csdnimg.cn/direct/5c6a2da05c62432689b872e25d456c16.png