imuncle / imuncle.github.io

大叔的个人小站
https://imuncle.github.io/
78 stars 17 forks source link

NeuroEvolution(神经进化)初体验 #56

Open imuncle opened 5 years ago

imuncle commented 5 years ago

在GitHub上找到一个有趣的项目FlappyLearning,在线demo地址在这里

前段时间正好我看了一些机器学习方面的教程,顿时起了兴趣,下载下来读了源码。

首先说,JavaScript语言是不适合搞机器学习和神经网络的,因为它对矩阵运算支持非常差,基本就靠for循环运算矩阵了。换言之,用js写出来的小程序肯定复杂不到哪去,正适合我这种初学者入门。

昨天我把这个项目的游戏部分剥离了出来,可以点这里试玩,使用鼠标或手指点击控制小鸟煽动翅膀。

今天则研究了一下它的神经网络部分。

首先还是简单介绍一下什么是神经网络。

神经元

神经网络是模仿人脑的神经系统设计出来的,神经网络由很多神经元组成。典型的神经元的样子如下:

image

上面的神经元有三个输入(input)和一个输出(output),每一个输入有一个权重(weight),三者关系如下:

output = input1 * weight1 + input2 * weight2 + input3 * weight3

神经网络

神经网络就是由数个神经元组合起来的一个大整体:

Q21B}N~5T~O35$@_UXZ9A04

其中,最左侧一列的神经元是输入层,最右侧一列是输出层,剩下中间的是隐藏层。可以看出,隐藏层越多,每一层神经元数目越多,整个系统就更复杂,就能实现更加复杂的功能。

项目详解

在这个小项目中,神经网络较为简单,结构如下:

image

上图中的红线代表数据输入(输出),蓝线代表中间运算传递的数据(相对于用户不可见),每一条蓝线都有一个权重,所以上面的神经网络有6个权重。

游戏刚开始的时候会生成50只小鸟,每一只小鸟都有自己的神经网络,各自的权重都是随机生成的(每只小鸟有一个数组存储各个权重),所以面对前方的管道有不同的反应。

每只小鸟的情况都不一样,那么肯定有的小鸟飞的远,得分高,有的就得分低。这时候程序保留下得分最高的小鸟的权重数组。当然每一代的权重不能保持完全一致,新一代的小鸟全都继承自上一代的优秀小鸟,并且在此基础上随机更改部分权重,又进行新一轮的筛选。

神经网络的输入参数有两个,一个是小鸟的高度,另一个是通道的高度,神经网络通过比较这两个通道的数据对是否煽动翅膀这件事进行判断,如果output大于0则煽动,小于0则不煽动。

其实可以很容易和自然界生物进行类比,每只小鸟的权重数组就像是它的基因一样,每一轮筛选后保留最好的基因,然后遗传给下一代,遗传的时候会发生一些基因突变,这些突变有好的有坏的,最后的进化结果交给环境和时间。

但也由于基因变异的时候是随机的,不可控的,所以会出现下一代不如上一代的情况,运气好的话只需要几代就能超神一直飞下去,运气不好的话就是训练六七十代都飞不过去。

物竞天择,适者生存

这是最好的体现了。

项目修改

这个神经网络的输入只有两个,我觉得还差一个小鸟和通道的水平距离这一个关键信息,所以我对神经网络做了点修改:

NU_%$5JQ6I1RHZ9KAS$3NIW

我的神经网络隐藏层增加到了2层,输入参数增加到3个,需要给模型训练的参数增加到21个,所以需要更多的训练次数。我训练了1041代后,终于超神了:

image

改进

这个小游戏每次刷新之后都要从头训练,但在训练之后其实可以把最后的最好的数据(权重数组)保存下来,下次运行直接超神。

别说,无聊的时候看着这只小鸟不断往前飞还挺有意思的。

imuncle commented 5 years ago

mind