人工智能学习

初识 Neuroevolution --- 训练 flappy bird

本文主要是介绍初识 Neuroevolution --- 训练 flappy bird,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文/泽白

本文基于 FlappyLearning 仓库,对 神经网络进化(Neuroevolution) 进行了初步了解,以便后续深入。选择这个仓库的原因是因为该仓库代码体积小(只有 game.js 和 Neuroevolution.js 两个脚本),没有外部依赖。并且作为一个游戏切入,会更有趣味性。

首先可以尝试下 FlappyLearning Demo,对整体结果有一个认识,然后可以了解下 神经网络进化(Neuroevolution) 的 wiki 概念,对该项目用到的神经网络模型有一个初步了解,对后续文章中提到的代码实现部分的理解,也会比较有帮助。

游戏实现

仓库整体实现可以用下方这个图(下文称为 图一)概括,通过 game.js 和 Neuroevolution.js 两个脚本实现。其中 game.js 负责游戏逻辑的实现,Neuroevolution.js 负责进化神经网络模型和遗传算法的实现。

神经网络进化1.jpg
game 脚本用来承载游戏逻辑代码,主要看图中左侧部分。其中划分了游戏场景中常用的 sprites,并且定义了一个 Game 对象作为导演,用来控制游戏的开始,运行以及重新来一局,游戏部分通过 canvas 来实现。

游戏运行的整体逻辑可以看左下角部分,划分为 display 和 update 两个方法。首先,整个游戏过程中的状态存储在当前 Game 实例对象的上下文中,比如每只鸟的坐标,管道的位置等。整体逻辑划分十分清晰,通过将所有状态数据化,通过两个独立方法分别去读写状态。

update 方法主要用来和 Neuroevolution 实例通讯,然后更新当前的游戏状态,如每只鸟的坐标信息、管道的数量及位置等,update 的调用频率通过 setTimeout 来控制,间隔为 1000/FPS,FPS 默认为 60。

display 方法主要是读取当前的游戏状态,然后把当前状态绘制在 canvas 上,调用频率是通过 requestAnimationFrame 来控制。

游戏过程

实例化 Game 对象

首先,实例化 Neuroevolution 对象(图一的右上角 init 部分),其中定义了每代鸟的数量,以及网络模型中每一层的神经元数量。一般神经网络具有分层结构,实例化的 network 分别定义了输入层(input layer)、隐藏层(hidden layer)和输出层(output layer)中的神经元(neurons)数量,神经元也叫感知器,可以看Perceptrons - the most basic form of a neural network这篇文章的详细介绍,了解感知器这一概念。

图一的步骤1中实例化了 Game 对象并调用了 start 方法,此时通过 Neuvol 实例创造了第一代50个 network,每个 network 对应1只鸟,他们的权重值均是随机生成。

神经网络进化2.jpg

update 与 Neuroevolution 通讯

图一的步骤2即 update 方法中的逻辑,首先遍历每一只鸟,计算出当前鸟针对 netowrk 需要的输入(input),即两个参数。第1个参数是鸟的 y 坐标与 canvas 高度的比值,第2个参数是下一个上管道的 height 与 canvas 高度的比值,将两个参数作为入参传给 network compute,即图一的步骤3。

神经网络进化3.jpg

network 通过计算,将输出层(output layer)的结果返回,然后对该结果做简单的判断,得出该鸟是向上飞还是伴随重力自由降落。

神经网络进化4.jpg

network compute 方法中,首先将入参赋值给输入层(input layer),然后再传递给隐藏层(hidden layer),层层传递下去,将最终的结果放入输出层(output layer)并返回。这也是一种比较简单的神经网络拓扑结构:前馈网络,信号仅沿一个方向流动,上一层的 value 作为下一层的输入。

神经网络进化5.jpg

此时,已知了当前鸟下一帧是向上还是向下后,即可判断该鸟是否 dead,如果 dead 则将该鸟当前的 network 状态与当前游戏的 score 绑定,按 score 降序排列作为基因存起来(addGenome 方法),即图一的步骤4。

将当前存活的鸟遍历完毕,若依然有存活的鸟,则重复上述过程,否则重新开始新的一代,即图一的步骤5。

每一只鸟 dead 后都将触发 addGenome 方法,一局结束,则会存储50只鸟的 network,即下图中的右侧部分。

神经网络进化6.jpg

产生新的一代(遗传/进化算法)

开始新的游戏即需要产生新的一代鸟,为了让下一代能够比前一代在游戏中得到更高的分数,这里的进化算法主要分为了三部分。第一部分:精英主义,即直接取前一代分数排名前十的基因,复制出新一代的10只鸟。第二部分:随机行为,取排名前十的基因,加上随机因子,产生新一代的10只鸟。第三部分:繁衍,优先取分数高的两个基因进行组合,加上随机因子作为突变,产生新一代中剩余的鸟。

神经网络进化7.jpg

经过进化算法一代代的迭代,network 的表现也会越来越符合预期,大概在第30代即可在游戏中无敌。issue 列表中也有人讨论如何优化算法,做到通过2代即达到了无敌。

体感

学海无涯,借助这个仓库作为尝试,拓展自己深度学习的道路。

这篇关于初识 Neuroevolution --- 训练 flappy bird的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!