zoukankan      html  css  js  c++  java
  • 增强学习训练AI玩游戏

    1.游戏简介

    符号A为 AI Agent。

    符号@为金币,AI Agent需要尽可能的接取。

    符号* 为炸弹,AI Agent需要尽可能的躲避。

    游戏下方一组数字含义如下:

    Bomb hit: 代表目前AI Agent所接取的炸弹数。

    Coin hit:   代表目前AI Agent所接取的金币数。

    Iteration:代表游戏已经进行的帧数,案例正常游玩视频,250ms一帧。高速状态下帧频未知。

    Game Play:每帧会随机产生一个炸弹和一个金币,或者只产生一个炸弹或金币。每帧AI agent可以行动一次, 以及所有的炸弹和金币下降一格。

    当金币和炸弹到最后一格时会自动消失,此时不在参与AI Agent碰撞。

    2.游戏展示

                                     左为AI高速学习视频,右为AI正常游玩视频

    3.实现原理

    学习种类: 增强学习又称强化学习

    学习细节:Q算法 +  值函数线性(参数)逼近,如果您还不知啥么是q算法,啥么是值函数,啥么又是线性参数逼近。那么我推荐您先看看一下资源。

      A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)

    Q-learning toturial

    然后,我来给你讲讲什么是线性参数逼近。我们由浅入深,先探讨一下向量。在2维空间中,我们可以用两个正交的二维基向量i,j来任意二维向量v。写作v = x*i+y*j; 我们只需调整x,y,也就是调整基向量的权重参数,就可以表示不同的向量。同理,N维空间,我们也可以用N个正交的N维基向量表示任意N维向量。那么需要调整的权重也会相应的增加到N个。 回到函数的问题,我们是否可以用类似的方式,用N个基函数的和来表示一个复合函数,并且通过修改每个函数的权重参数来表示不同的复合函数。很明显,答案是可以的。 那么现在的问题是如何调整这些权重,使它表达的复合函数更接近我的目标函数?

    进一步对于强化学习来说,我们不知道目标函数的具体样子。我们通过不断的实验得知函数的输入输出模式为 in:a0 out:b0; in:a1 out:b1.......

    所以我们要建立一个函数f,使其的输入输出与我们的目标函数的输入输出匹配即可。完美的匹配所有输入输出怕是找不到,退而求其次,我们去寻找平均情况下最好的匹配,即允许构造函数f与目标函数t某些输入与输出存在差异,但总体上差距最小。在这里我们使用随机梯度下降

    Q(s, a) φ(s, a)Tθ (θ是有多个权重构成的向量,我们要不断调整θ, φ(s, a)T则为基函数,返回值为向量

    C = 1/2(Q+(s, a) - Q(s, a))2 =1/2 (Q+(s, a) - φ(s, a)Tθ)2
    ∂C/∂θ = -φ(s, a)(Q+(s, a) - φ(s, a)Tθ).

    θ θ + β φ(s, a)(Q+(s, a) - Q(s, a))  β为调整步长。

    4.游戏内状态编码

    Game State:

    本文 AI Agent 采取对其上方4*3区域进行二进制编码。0代表空位置,1代表空间被bomb或coin占据。那么4*3区域需要24bit的数据来表示coin 和 bomb,以本文为例,前12位代表bomb后12位代码coin。相同位置的bomb和coin可以同时为0,代表既没有bomb也么有coin,但不能同时为1,即二者不可重叠。

    对其进行二进制编码的好处为可以把state抽象成为一个int数值,大大了减少了描述state所需的空间。当然监测区域越大状态空间就越大,那么Agent就越智能。

    Game Action:

    左移,右移,不动。

    Feature base φ(s, a):

    用于描述当前状态特征的基函数,在程序中它不返回一个12维向量,而是增加参数i,代表获取第几个特征,函数输入为状态s和指令a,特征函数φ(s, a,i)的返回值取值范围为 -1,0,1。

    φ(s, a)的计算需要使用当前的状态s 和 当下要执行的action。

    Feature base  Weight θ

    θ也是12维向量,用以表示feature base中不同元素的权重。

    Q value:

       Q(s, a) = φ(s, a)Tθ, 这里是向量的点积,乘积的和。

    5.具体实现方法

    本游戏采用值函数线性参数化逼近,对动作状态值函数Q(s, a)进行线性参数话逼近。值函数近似多用于求解连续状态集或大规模状态集。因为state或action太多无法全部保存,所以需要抽象出一个函数,函数的参数为state和 action ,返回值为其分数。

    最后我们的Q值函数可表示为:Q(s, a) = φ(s, a)Tθ,更新权重法则为:θ θ + β φ(s, a)(Q+(s, a) - Q(s, a)),

    对于本文给出的小游戏,简单的使用随机梯度下降法可以对动作状态值函数进行线性近似。并可以取得较好的效果。

    6.代码分享

      相关代码,已上传

      https://github.com/RonTang/QLearningForAiPlayGame/

      需要的同学请自行获取。

    7.未来展望&心语

    研究机器学习只是笔者的业余爱好,故本文使用的最基本的强化学习算法,如有错误请耐心指正。如果读者想要进一步深入学习,不妨了解一下Google DeepMind的各种DQN,OpenAL刚刚出新的强化学习算法PPO。这些新的强化学习算法从效率和效果都有很大提高。当然,具体研究起来肯定是很复杂的,有兴趣的读者自己去研究吧。

    作为一个游戏开发者,在适当的地方使用机器学习是很好的选择。谨记,我们做游戏是为了让玩家开心,不是为了让AI吊打玩家。至于人工智能学者总爱拿游戏做例子,一是为了方便向民间传播研究进度,刷存在感,拉投资。二是某些游戏的状态空间确实比较复杂。比如搞搞围棋,搞搞Dota2,搞搞星际2。

  • 相关阅读:
    Spark Streaming 的容错
    Master 接受其它组件的注册
    Spark Context 概述
    Python 使用random模块生成随机数
    Python 中print 和return 的区别
    Python 访问字典(dictionary)中元素
    PIL:处理图像的好模块
    2.线性回归
    3.梯度下降法
    4.pca与梯度上升法
  • 原文地址:https://www.cnblogs.com/tangzhenqiang/p/9466391.html
Copyright © 2011-2022 走看看