更多腾讯海量技术文章,请关注云加社区:https://cloud.tencent.com/developer/column
作者:Shawn_Kid
摘要:我尝试使用之前写的的遗传算法来训练一个简单的循环神经网络来玩史莱姆排球,最兴奋有趣的部分是创建AI模块替代玩家控制,看看AI能不能熟练的玩游戏。最后,我使用基本的CNE方法作为初始测试,训练标准的循环神经网络,同时利用convnet.js库训练。
http://otoro.net/slimevolley/
利用递归神经网络玩的"史莱姆排球"游戏。你能打败AI吗?
记得Java小程序很流行的时候,我喜欢玩一个叫“ 史莱姆排球” 的java游戏。虽然游戏的物理引擎让人忍俊不禁,但是我就是被这样简单的游戏迷住了,曾经在晚上躲在宿舍玩了几个小时,工作什么的都忘得一干二净。
由于除了过时的JAVA程序版本之外,在网上实在找不到任何新的版本。所以我开始创建我自己的基于js + html5的游戏版本(完成了神奇的街机风格的“物理引擎”)。我尝试使用之前写的的遗传算法来训练一个简单的循环神经网络来玩史莱姆排球。实际上,我想知道在使用NEAT之类的更先进的算法之前,如果仅仅是一个简单的传统的神经进化技术,是否可以训练一个神经网络使之成为这个游戏的专家呢?
第一步是写一个简单的物理引擎,完成球与地面的反弹效果,球与围栏、玩家的碰撞效果。 这是使用JavaScript中的设计器p5.js库和一些简单的物理数学方程来完成的。为了使球弹跳功能正常工作,我刷完了矢量数学。完成以上功能后,下一步就是添加键盘/触摸板的操作,使玩家无论在手机上还是电脑上都可以移动、跳跃。
最兴奋有趣的部分是创建AI模块替代玩家控制,看看AI能不能熟练的玩游戏。最后,我使用基本的CNE方法作为初始测试,训练标准的循环神经网络,同时利用convnet.js库训练。下图是我们利用循环(神经)网络训练后的图表,当当当当!:
神经网络将代理动作和速度的输入,球的位置和速度,当然还有对手的一切动作。输出将三个信号控件激活,分别是“前进”、“后退”和“跳跃”。另外有4个隐藏的神经元将作为隐藏状态并反馈给输入,这种方式实质上是一个无限深层的前馈神经网络,它能自动记住以前发生的事件和状态,能够制定更复杂的游戏策略。有一点要注意,只有在信号高于某个阈值(0.75)时才会触发这一功能。
我将两边的AI代理一分为二,设置成独立而又相同两部分,无论AI代理是在围栏的左边或是右边玩,它们的位置都是相对于围栏的,而球的位置是根据他们是哪一方。这样一来,被训练过的的AI代理就可以在围栏的任何一边进行游戏并且使用相同的神经网络。
我没有使用sigmoid函数,而是使用支持convnet.js的双曲正切(tanh)函数来控制。
tanh函数定义如下:
tanh函数对于神经网络来说可能是一个更好用的激活函数,因为当输入被引导时,函数值趋向于+1或-1。x轴是游戏的输入部分,例如球与对手的位置和速度(全部在+/-1.0间震荡或给出另一个1.0)同时也输出隐藏神经网络的状态(定义在+/- 1.0以内)。
由于速度和球位置可能是正的或负的,这可能比sigmoid函数更有效率,也更自然。正如前面所解释的那样,我同时将输入也缩小到+/-1.0的范围,类似于隐藏的神经元的输出状态,这样网络上的所有输入的大小的平均数就会大致相同。
训练这样一个递归的神经网络涉及到我之前做的遗传算法训练器,因为实际上没有适合的方法可以返回一个分数,因为任何一方都会有输赢。我最终做的是写一个类似比赛的功能,让训练人群中的每个AI都能与其他AI竞争。如果某AI获胜,它的分数就+1,如果输了就-1。如果游戏时间超过拟定的20秒,不得分也不扣分。每个AI将在训练循环中对抗其他的10个随机AI。最多只保留20%的AI,其余的丢弃掉。然后再次交叉训练产生下一代更强的AI。这种被称为“淘汰竞赛”的方法可以训练出足够聪明的AI去玩一对一的游戏。
通过使用这种方法,我们不需要帮助AI手工编写任何触发代码和游戏规则,而只是简单地探索游戏并找出如何取胜的方法。最后的结果表明,经过几百代的进化,它们的游戏技术非常高超!
下一步可以采用更先进的方法,如NEAT、ESP,但对于一个简单的小游戏来说,这可能太过了。由于游戏策略非常简单,同时,它也是应用在卷积神经网络Deep Q-Learner上的的候选。我想,到目前为止,我已经创造了一个相当强大的史莱姆排球AI,几乎不可能被人类玩家连续击败。
尝试自己去玩游戏,看看你是否能够一直打败它。它可以在PC(键盘控制)或手机/平板上通过触摸控制。PC版本的操作更加容易一点。你可以随意使用Github上的源代码,但是如果它不是最简洁的结构化代码,那么真的对不住了,因为它更像是一个草图,而不是一个的成熟程序。
领取专属 10元无门槛券
私享最新 技术干货