本文首发于“洪流学堂”微信公众号。
洪流学堂,让你快人几步!

跳一跳介绍

最近微信上非常火的一个小游戏,相信大家都已经玩过了。

玩法

  • 小人跳跃的距离和你按压屏幕的时长有关,按屏幕时间越长,跳的越远
  • 跳到盒子上可以加分,没跳到盒子上游戏结束
  • 连续跳到盒子中心可以成倍加分

开发历程

阅读此文章需要有一定的Unity3d基础和unity-ml-agents基础。
文中有任何纰漏欢迎指正。

用Unity开发跳一跳

先参照微信原版用Unity3d开发了简版的跳一跳。

视频教程 https://edu.csdn.net/course/detail/6975
源码工程 https://github.com/zhenghongzhi/Unity-JumpJump

PPO中一些名词解释

Experience

每一次states,action及输出称为一次experience

episode_length

指的是每一次游戏一个agent直到done所用的步数

batch size

进行gradient descent的一个batch

buffer size

先收集buffer size个数据,然后再计算进行gradient descent

Number of Epochs

会对buffer size的数据处理几遍,比如为2,就会把这些数据处理2遍

Time Horizon

被加入experience的条件是agent done或者收集到time horizon个的数据量才加入,为了搜集到更全的可能性,避免过拟合

模型迭代

迭代1

一开始模型建立很困惑,官方的demo里并没有这种给一个输入以后,需要一段时间等结果才出来进行下一步的例子。

如果使用2个按键分别表示按下和抬起的事件,并且训练出按键之间的联系,训练起来会很慢而且有可能无法拟合。

一开始尝试用Player类型的brain,结果发现无法实现,只能用两个键的方式。然后使用Heuristic来直接模拟按键的时长,即action只有一个值,一个连续型的float,代表按空格的时长。
这样的话只能去掉小人的缩放和台子的缩放效果。(后注:现在想来其实是有一个对应关系的,可以直接通过参数设置出来,但是没有过渡的动画。)

这个模型用5个值作为state,分别是小人位置坐标的x,小人位置坐标的z,下一个盒子位置的x,下一个盒子位置的z,下一个盒子的localScale的x(x和z相同)

在最开始的时候一直在考虑如果小人在空中的时候,action还一直输入,可能会在神经网络中建立出来奇怪的联系。所以本次迭代在小人在空中的时候如果给了大于0的action的时候给一个惩罚,reward -= 1**(这种想法其实是错误的)**

开始训练…

迭代1-1

经过2个小时的训练发现效果很不好
禁止输入应该是一个规则,而不应该惩罚玩家,即使玩家输入游戏也不应该有反馈,所以去掉了小人在空中时候的惩罚。

另外用Academy中的Frame to Skip参数,设为30,来减少无用的输入。

开始训练…

迭代1-2

游戏出现了卡死的情况,游戏中的判定有BUG,导致可以一直接收action并且没有获得reward。
修复BUG…开始训练…

迭代1-3

训练效果一直不好,又重新将unity-ml-agents里面的文档都看了一遍,特别参照best practice将参数重新调整了一遍开始训练。
训练了一个晚上,大概8个小时,效果依然不好…

迭代2

本来想着这么简单的模型,训练出来一定的成果再用curriculum的方式重新训练对比以下,看来只能直接上Curriculum看看效果了…
定义了如下的Curriculum文件

{"measure" : "reward","thresholds" : [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10],"min_lesson_length" : 2,"signal_smoothing" : true, "parameters" : {"max_distance" : [1.1,1.1,1.1,1.1,1.5,1.5,1.5,1.5,2,2,2,2,3,3,3,3],"min_scale" :    [1,1,0.5,0.5,1,1,0.5,0.5,1,1,0.5,0.5,1,1,0.5,0.5],"random_direction":[0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]}
}

这里需要注意的是,thresholds的值要比下面parameters里面的值少一个,因为最后一个lesson是会一直训练下去的,没有threshold

迭代2-1

忽然游戏崩了,发现log是场景里collider太多了
这次训练的效果还不错,但是游戏里还是有bug,导致box生成太多了
将box的生成方式改为对象池的方式,性能能优化不少,也应该不会有刚才的bug了

迭代2-2

嗯,这么训练确实不错,tensorboard里的cumulative_reward一直在增长,但是训练了一段时间以后想到一个可能存在的问题,由于第一个max_distance是1.1,和最小distance是一样的,也就是说下一个盒子总是距离现在的盒子1.1米,可能会有过拟合的问题,而且threshold貌似有点太大了,一直没有切换到下一个lesson

于是赶紧停掉训练,将第一个max_distance改成了1.2重新训练

迭代2-3

发现了不会切换lesson的问题,赶紧去查,在issues里面发现了答案,只有global_done为true时才会切换,需要将academy设为done或者设置一个max steps
这次将每次game over的时候academy设置为done
后来发现这样其实是有点问题的,write_summary之后cumulative_reward会清空,如果刚好这之后的cumulative_reward波动出来大的值,那么就会跳过lesson,这样随机性很大。怪不得官方的demo用的是max step 50000

迭代2-4

经过30小时的训练,第一版终于训练出来了,但是结果很不理想

如图:
1. 第一个过程就是开始设置max_distance是1.1的时候,增长的很快
2. 修改为1.2之后,又训练了一段时间,发现不会切换lesson,然后改了bug
3. 后面lesson切换的很快
4. 最后训练了很久,但是cumulative_reward也没到1

于是开始反思模型上的问题,要简化模型,优化Curriculum。

迭代3

将state重新定义为2个,一个是小人与下一个盒子之间的距离,一个是下一个盒子的size
Curriculum也重新定义为:

{"measure" : "reward","thresholds" : [5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],"min_lesson_length" : 2,"signal_smoothing" : true, "parameters" : {"max_distance" : [1.2,1.2,1.2,1.2,1.5,1.5,1.5,1.5,2,2,2,2,3,3,3,3],"min_scale" :    [1,0.9,0.7,0.5,1,0.9,0.7,0.5,1,0.9,0.7,0.5,1,0.9,0.7,0.5],"random_direction":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}
}

由于现在state中是小人与下一个盒子之间的距离,而生成与跳跃方向又是游戏系统定的,所以random direction就没有什么用了。
而且问了能加快训练速度,重构了游戏和场景,使得可以有很多游戏instance可以一起训练,去掉random direction可以避免游戏之间发生冲突

迭代3-1

出现了两次Info/cumulative_reward突然剧烈下降并且再也回不去的情况,虽然这两次发生的时候都进行了别的工程webgl的编译,但是应该还是参数的问题
1. 怀疑是layer为1的锅,虽然模型很简单,因为并不是线性关系那么简单,所以把layer加为2重新训练
1. 看来不是layer为1的锅。怀疑原地跳的话-0.1的惩罚有点太大了,改为-0.01重新训练试一下
1. 再次训练还是出现了剧烈下降,这次直接删掉原地跳的惩罚,再试验看看是什么问题
1. 还是会出现剧烈下降,试着寻找问题的原因
1. 修改了以下内容:
- 去掉normalization,改为手动normalization
- academy max steps改为1000

还是不行!!!!!!!!!!!!!!!

开始怀疑是多个instance同时运行出现的问题,但是没找到多个instance同时运行的逻辑问题

经过反复思考,得到是游戏机制问题。小人跳跃时不应该接收输入,否则的话前一个step的输入得到的reward值会是0,无法对应起来。之前设置的skipfram30确实有问题,无法将states,action和reward对应起来

2018年1月27日23点19分
但是经过debug发现,有超过200帧还无法接收下次输入的情况,高达5000帧,这样就没法用skip frame这个值了,训练速度会太慢太慢,怀疑程序有bug,调试中。。。

发现高达5000帧时,有player掉到地面以下的情况,可能是物理穿透,,加上一个y位置的判断,如果y的值小于1,那么表示小人穿透了地面gameover,并且将ground的box厚度改大

而且发现frame skip 有bug,还是我没理解对,竟然每帧都会执行step
Edit:
I find in Academy.cs line:345 that following code is not surrounded by if (skippingFrames == false).
Am I misunderstanding something?

AcademyStep();foreach (Brain brain in brains)
{brain.Step();
}

在github上发了个issuse,寻求建议
重新调试测试,用代码的方式检测skipframe的最佳值,设为了200
是否跳到盒子上端的检测方式改为法线检测
并且将上述的代码加到了if判断里面

迭代3-2

2018年1月28日
今天早上起来发现模型还是不行,而且游戏里还有bug
14点29分
在github上发了个issuse,作者给了个建议,可以使用unsubscribe和resubscribe的方式来让小人在空中的时候不接受action
但是测试后发现不行,因为动态unsubscribe和resubscribe的话,agents数量是动态变化的,python端上次输入和这次输出的信息,可能长度不相等
输入的时候可能有10个小人的信息,但是输出的时候只有8个或20个

修复了游戏里的bug:跳到了下一个盒子侧面,又和当前的盒子发生了碰撞,会造成逻辑问题

最终解决方案还是得用frame skip,这次游戏运行稳定了,通过统计找到一个最佳值是137,而且小人每一步都不会超过137帧。将场景中game instance的数量设置为100个,layer 1,hidden units 32
开始训练

发现一个报错,game instance数量太多,导致socket buffer超出的问题,复现了几次,出现问题时收到的buffer长度都是1460或者1460的倍数。然后意识到这是由于socket的包分包所致

路由器有一个MTU( 最大传输单元),一般是1500字节,除去IP头部20字节,留给TCP的就只有MTU-20字节。所以一般TCP的MSS为MTU-20=1460字节。

还是会出现剧烈下降的问题,应该是learning rate的问题,learning rate太大了,降低learning rate到1e-4
终于训练成功了,但是跳到中心的几率不高,感觉需要修改reward,给跳到中心加分多一些 试试中心+1,台子上+0.1试试

迭代3-3

2018年1月29日13点21分
终于训练出比较成功的模型了,当前设置了小人最多跳100步,所以cumulative_reward最好也就是100

Step: 349000. Mean Reward: 88.70098911968347. Std of Reward: 10.67634076995865.
Saved Model
Step: 350000. Mean Reward: 89.22838773491591. Std of Reward: 9.210647049058082.
Saved Model
Step: 351000. Mean Reward: 89.44072978303747. Std of Reward: 12.138629221972357.
Saved Model

其实所有东西都搞对以后训练的速度还是挺快的,大概到200K步的时候Mean Reward就能到70了

后记

搞完以后尝试修复socket分包的问题,修复完创建PR的时候发现:

development-0.3的分支中已经修复这个问题

哈哈,白费功夫了~不过对python的socket通信以及粘包有了更深的了解

总结

这个游戏也算是开创了一个mg-agents的游戏类型:需要等待一些时间才能得到reward的情况。
虽然最终是用skip frame解决的,但是中间做了很多的探索,也发现了ml-agents的一些局限。
贡献:在GitHub上提了一个pull request(解决了env含有子目录时export_graph的bug)和2个issue(一个是寻求这种类型游戏的建议——作者回复会跟进这种类型游戏的支持;一个是unity端解析socket buffer的json失败的问题,自己修复了这个问题,不过development-0.3的分支中已经修复这个问题)。
自己在Unity3d的一些细节开发,增强学习、ml-agents的使用和理解上也有不小的进步。
共同交流,共勉~



交流群:492325637
关注“洪流学堂”微信公众号,让你快人几步

Unity3d开发跳一跳AI(ML-agents)全纪录相关推荐

  1. Unity3d开发跳一跳-郑洪智-专题视频课程

    Unity3d开发跳一跳-2883人已学习 课程介绍         使用Unity2017.3开发"跳一跳"小游戏的教程. 课程收益     用Unity3d 2017.3实现微 ...

  2. [视频教程]用Unity3d开发跳一跳小游戏

    本文首发于"洪流学堂"微信公众号. 洪流学堂,让你快人几步成为Unity大牛! 开发成果 包含的知识点 编辑器基本用法及操作 简单的C#编程 刚体Rigidbody组件 动态生成物 ...

  3. 指尖大冒险、跳一跳升级版html5游戏全代码

    指尖大冒险.跳一跳升级版html游戏全代码 博主的话 文件目录 运行图片 指尖大冒险.html style.css 进行下一个游戏的开发! 博主的话 这是最后一个纯原生js代码编出来的游戏了.我连这个 ...

  4. python 实现跳一跳自动化代码_跳一跳AI(wai gua)的实现原理详细介绍

    12月28日,微信发布了V6.6.1新版本,新增了一系列小程序游戏,主推游戏"跳一跳"的每周更新排行榜也激也了一些玩家的刷分热情,现在很多大牛在github上发布了程序代玩的各种语 ...

  5. 微信跳一跳 可以直接更改分数, POST 请求没有校验

    这两天逛 v 站出现了一众微信跳一跳 'AI',已经被刷屏了-- https://www.v2ex.com/t/418833 https://www.v2ex.com/t/418775 https:/ ...

  6. unity之跳一跳(完整版)

    1.场景 (1)creat->3D objict->plane 并重命名为ground,做为地面(如下图) (2)并调整颜色,大小至适合(如下图) 调正颜色:创建material(proj ...

  7. AI 玩微信跳一跳的正确姿势:跳一跳 Auto-Jump 算法详解

    作者丨安捷 & 肖泰洪 学校丨北京大学硕士生 研究方向丨计算机视觉 本文经授权转载自知乎专栏「学术兴趣小组」. 最近,微信小游戏跳一跳可以说是火遍了全国,从小孩子到大孩子仿佛每一个人都在刷跳一 ...

  8. “跳一跳”小游戏这么火爆,它是如何做的设计和开发?

    2018 伊始,最火爆的不是春晚和红包,而是从天而降的"跳一跳".这款来自微信的轻量级小游戏,以 2800 万人 / 小时的惊人 PCU 数据,稳据小游戏排行榜首位.如果你还不了解 ...

  9. Chrome暗藏的恐龙跳一跳,已经被AI轻松掌握了

    夏乙 郭一璞 发自 凹非寺 量子位 出品 | 公众号 QbitAI 什么!未连接到互联网!! 明明是联网状态,为什么我想访问的页面 无!法!打!开! 淡定. 作为一个Google Chrome浏览器的 ...

最新文章

  1. docker image存储路径_使用fluentd作为docker日志驱动收集日志
  2. 【Django】安装及配置
  3. 最好用的硬盘搜索工具--Ava find pro
  4. 2019测试指南-测试测试原理
  5. 重磅:.NET 6 发布首个预览版
  6. php网页布局边框,用CSS来设置网页当中的边框
  7. arm 交叉编译找不到so_嵌入式杂谈之交叉编译
  8. 3000字长文剖析!企业大数据到底是什么,从哪来,怎么用?
  9. 彻底扔掉PostMan了,这套国产替代方案是真的香…
  10. configure 包,出现error: no acceptable C compiler found in $PATH 问题
  11. jsp action java_jsp中Action使用session方法实例分析
  12. SocksProxy代理服务器下载,附IE使用socks代理的方法
  13. 电脑笔记本利用谷歌浏览器进行网页截长图滚动截图
  14. ad19覆铜_AD19如何单独设置单个焊盘与铜皮的连接方式
  15. 谁是鱼谁是饵?红队视角下蜜罐识别方式汇总
  16. 1加3减5加7减9C语言表示,c语言中1+三分之一加五分之二加七分之三
  17. Eclipse插件 JSDT
  18. 我也有拖延症,你呢?
  19. 120M硬盘的jslinux
  20. 【微积分易错点总结】函数、极限和连续

热门文章

  1. 屏幕距离和坐便转换工具_【软件推荐】你和大神的距离,只差这几个效率工具!...
  2. 指定开局五子棋c语言代码,C语言案例:控制台版本的五子棋游戏【代码】
  3. ajax 清洗剂,Choice浴室清洁剂大测评!最好用的只要$3.5!这些产品最好别买...
  4. mysql 脚本命令大全,linux 常用Mysql脚本命令
  5. C++局部重载new delete方法剖析
  6. ++i和i++哪个效率更高
  7. KVM-Arch-Figure
  8. 用QEMU构建嵌入式LINUX系统
  9. 网站主机 技术+类型
  10. PHP导出成PDF【TCPDF插件】