Notifications
Article
Unity机器学习代理ML-Agents强化学习示例解析
Published 8 months ago
457
0
Unity机器学习代理ML-Agents作为连结Unity和机器学习的桥梁,为无数开发者提供了各种可能性。4月,我们进行了第一期Unity ML-Agents 强化学习直播,向广大开发者介绍了如何使用ML-Agents创建一个强化学习项目,以及如何去训练它。今天将由Unity技术经理鲍健运带领大家重温本次直播的内容。
ML-Agents目前是v0.4版本,加入了好奇心驱动的探索(Curiosity-Driven Exploration)算法,还实现了编辑器内训练(In Editor Training)模式,丰富了机器学习的功能。在整理原有Platform2D-ML项目时,我将该项目迁移到ML-Agents v0.4版本,有意将v0.4一部分新功能加入其中。因此,本文中的项目设置与代码与4月25日直播的时候会稍有不同。
这是直播课程内容。

项目介绍

该机器学习示例项目基于Unity官方发布在Asset Store上的2D游戏开发套件 —2D Game Kit,展示的是通过机器学习的强化学习训练主角Ellen,进行简单的横版过关的游戏操作。
机器学习展示用的关卡是Main场景,是基于2D Game Kit的example第一关修改而来的。大家可以发现后面延绵起伏的平台,这些正是用于验证我们机器学习训练结果的。
机器学习训练用的关卡是TrainingScene。它是一个比较封闭,限制比较多的场景。为什么需要做这样的设计呢?
因为现实中的游戏关卡有非常多的状态与参数,其中有一部分是机器学习需要参考和影响的,而另外有一些则是无关甚至是敢干扰的因素。所以需要设计个场景去除尽可能多的不必要因素,帮助机器学习训练的结果趋向于理想的表现。
在这个示例项目中,我们只希望角色Ellen只关注与不同层高平台间的跳跃,进而制作这样简单的场景。

原理分析

根据机器学习强化学习的方法,进行如下需求分析:
  • 目标:让Ellen在平台上运动,到达终点。
  • 观察值:角色脚下是否接触地面,角色前方是不是遇到台阶。
  • 动作:默认角色横向向右移动,仅有操作是向上跳跃。
  • 奖励:保持在地面奔跑(+0.001);如果前方有台阶而跳跃(+0.1);如果前方没有台阶但跳跃(-0.5)。
理想训练结果:Ellen在Platform上奔跑,遇到Front进行跳跃,如此行进直到终点。

工程搭建

因为本项目需要使用2D Game Kit套件、ML-Agents工具和TensorFlowSharp插件,关联的资源都比较大。所以,我们只提供和示例项目相关的部分资源,其他的内容请各位移步下文所提及的相关链接进行下载。
1. Unity 版本选用
本项目所使用的ML-Agents版本为v0.4,所以需要安装Unity 2017.2及以上版本来进行开发。
2.搭建ML-Agents v0.4环境
在此前的微信技术文章中,我们发布过搭建ML-Agents的具体方法。现在版本升级到v0.4,大多数步骤还是与原来相近的,只不过TensorFlow的版本要求从原来的1.4.0改为1.7.1。
Windows 10 搭建:
  • 从www.anaconda.com/download/#windows 下载安装 Anaconda Python 3.6 version
  • 管理员权限运行Anaconda Prompt
  • 输入“conda create -n ml-agents python=3.6”创建ML-Agents机器学习环境
  • 输入“activate ml-agents”激活环境
  • 输入“pip install tensorflow==1.7.1”通过pip安装TensorFlow 1.7.1版本
  • 从Github下载完ML-Agents之后,输入“cd /d *dir*”(*dir*代表ML-Agents下python目录)
  • 输入“pip install .”通过requirement.txt安装ML-Agents相关机器学习工具库(记住install后面的是空格加英文句号)
  • 等待环境安装完成
MacOS 搭建:
  • 从www.python.org/downloads/mac-osx/ 下载安装Python 3 for Mac
  • 输入“pip install tensorflow==1.7.1”通过pip安装TensorFlow 1.7.1版本
  • 从Github下载完ML-Agents之后,输入“cd *dir*”(*dir*代表ML-Agents下python目录)
  • 输入“pip install .”通过requirement.txt安装ML-Agents相关机器学习工具库(记住install后面的是空格加英文句号)
  • 等待环境安装完成
3.Unity打开ML-Agents项目
使用Unity打开ML-Agents的unity-environment目录,打开项目工程。从https://s3.amazonaws.com/unity-ml-agents/0.4/TFSharpPlugin.unitypackage 下载针对ML-Agents v0.4的TensorFlowSharp插件(python → C# API插件),将unitypackage导入工程。
4.导入2D Game Kit开发者套件
从Asset Store资源商店下载(https://assetstore.unity.com/packages/essentials/tutorial-projects/2d-game-kit-107098),导入2D Game Kit套件到现在的项目工程中。
5.导入 Platform2D-ML包到工程
除去ML-Agents与2D Game Kit使用到的部分,原有Platform2D-ML项目包体其实很小,大约超过2MB。大家可以到这个地址去下载:https://oc.unity3d.com/index.php/s/yEtIIKyT4ELfq7Y 。将这个Unity包导入该项目
6.调整项目工程设置参数
因为默认Unity的脚本Runtime是基于.Net 3.x的,但是TensorFlowSharp是需要.Net 4.x,所以需要在Unity → Project Settings → Player Settings → Other Settings → Configuration中做些调整。
需要将Scripting Runtime Version设置为.Net 4.6(Unity 2017.x)或4.x(Unity 2018.x),API就会自动切换到4.6或4.x。并且在代码中能够让TensorFlow功能生效,需要打开宏定义,在Scripting Define Symbols添加ENABLE_TENSORFLOW。
现在基础搭建的部分就完成了。

训练解析

下图所展示的就是Platform2D-ML项目的结构。我们双击打开TrainingScene训练场景。
1.代码部分
  • 脚本CheckpointChecker.cs
void OnTriggerEnter2D(Collider2D collider) { if (collider.gameObject.tag == "Player") { enteredCheckpoint = true; } } void OnTriggerExit2D(Collider2D collider) { if (collider.gameObject.tag == "Player") { enteredCheckpoint = false; } }
这个脚本的主要功能就是在于判定角色Ellen是否进入或离开了检测点,便于处理Agent重置。
  • 脚本PlatformerAcademy.cs 与 PlatformerDecision.cs
ML-Agents v0.4与v0.3在代码撰写方面的比较大的区别是,将功能统一迁移到了MLAgents的命名空间下。PlatformerAcademy只是单纯继承自MLAgents的Academy基础类,override二个基本方法,PlatformerDecision情况相近,二个类的实现目的主要是为了留出可以进行扩展的空间。
  • 脚本PlatformerAgent.cs
这个类是进行强化学习训练主要的功能区域。
开始部分创建了4个参数,分别是:
  1. m_Agent:ML-Agents的训练代理对象,也是场景中的角色Ellen。
  2. m_Goal:目标终点,其实就是场景的Checkpoint。
  3. playerCharacter:角色Ellen,Gamekit2D的角色控制器对象。
  4. initalPosition:角色的其实位。
帮助判定的检测方法:
1、HasPlatformInFront:用于检测角色前面是否有台阶(Front)
public bool HasPlatformInFront(Vector2 position, int layer) { Vector2 positionCentered = new Vector2(position.x, position.y + .5f); Vector2 direction = Vector2.right; LayerMask layerMask = 1 << layer; RaycastHit2D hitFront = Physics2D.Raycast(positionCentered, direction, 1f, layerMask); if (hitFront && playerCharacter.CheckForGrounded()) return true; return false; }
2、IsGrounded:用于检测角色是否踏在地面上
public bool IsGrounded(Vector2 position) { Vector2 adjustedPosition = new Vector2(position.x, position.y + .5f); Vector2 direction = -Vector2.up; LayerMask layerMask = 1 << 31; RaycastHit2D grounded = Physics2D.Raycast(adjustedPosition, direction, 1f, layerMask); return grounded; }
Override机器学习代理Agent的方法:
1、 InitializeAgent:初始化Agent的状态
public override void InitializeAgent() { // 获取角色Ellen上的Gamekit2D → PlayerCharacter对象 playerCharacter = m_Agent.GetComponent<PlayerCharacter>(); // 将原有角色的初始位置保存下来 initialPosition = m_Agent.transform.position; }
2、 CollectObservations:收集观察值
public override void CollectObservations() { // 收集角色是否接触地面 AddVectorObs(IsGrounded(m_Agent.transform.position) ? 1f : 0f); // 收集角色前面是否有台阶 AddVectorObs(HasPlatformInFront(m_Agent.transform.position, 31) ? 1f : 0f); }
3、AgentAction:代理操作功能相关处理
public override void AgentAction(float[] vectorAction, string textAction) { // 在地面即驱动角色向前移动 if (IsGrounded(m_Agent.transform.position)) { playerCharacter.SetHorizontalMovement(5f); } // 获取输入操作值 int action = Mathf.FloorToInt(vectorAction[0]); // 在不操作的情况下,判断是否在地面 if (action == 0f && IsGrounded(m_Agent.transform.position)) { // 符合情况,添加0.001的奖励 AddReward(0.001f); } // 在按space跳跃的情况下,判断是否在地面 else if (action == 1f && IsGrounded(m_Agent.transform.position)) { // 给予角色向前20f,向上15f的移动 → 斜前方跳跃 playerCharacter.SetMoveVector(new Vector2(20f, 15f)); // 如果前面有台阶 if (HasPlatformInFront(m_Agent.transform.position, 31)) { // 获得0.1的奖励 AddReward(0.1f); } // 如果前面没有台阶 else { // 扣除0.5的奖励 AddReward(-0.5f); } } // 是否碰到监测点 if (m_Goal.GetComponent<CheckpointChecker>().enteredCheckpoint) { // 碰到即完成一个强化学习周期 Done(); } }
4、 AgentReset:强化学习周期完成后的代理重设
public override void AgentReset() { // 将角色重置回初始位置 m_Agent.transform.position = initialPosition; }
2.训练部分
1、将TrainingScene场景中的PlatformerBrain的Brain Type修改为External模式
2、 打开相关命令行工具(Windows 10电脑启动Anaconda Prompt;macOS电脑 启动Terminal)
3、通过“cd”命令进入项目“python”目录
4、输入“python learn.py --train”,进行强化学习训练
(在Mac环境下,Unity的Logo+文字的显示很漂亮,但是由于编码显示的问题,Windows环境下显示效果就一言难尽了……)
ML-Agents v0.4版本开始支持编辑器内训练的方法,命令行末出现了“unityagents: Start training by pressing the Play button in the Unity Editor.”即点击Unity编辑器上的运行按钮就可以在直接进行强化学习训练,原有之前的版本在发布应用来训练方式其实也保留了下来,但是直接通过编辑器环境训练能获得更好的体验。
完成50000次训练之后,在python/model/ppo目录下会生成机器学习相关的文件。
在Unity ML-Agents中需要使用的是生成的.bytes文件,这里是editor_PlatformerAcademy_ppo.bytes。
5、将训练生成的.bytes文件放到Unity工程中
6、修改PlatformerBrain的Brain Type为Internal模式,并制定Graph Model为editor_PlatformerAcademy_ppo.bytes
点击运行按钮查看训练效果:
角色Ellen能够正常在平台上跑动,可以跳跃过台阶。大家如果仔细观察,会发现她在台阶前会有比较长的跑动等待。
在Python目录下有个Brain参数配置的文件,叫做trainer_config.yaml,其中有许多XXXBrain形式的参数表。这些XXXBrain其实是从Default扩展而来的。由于这个项目没有为PlatformerBrain进行过特定的设置,因此强化学习的训练是直接参照default的。原有单纯的PPO算法训练方式让Agent的探索可能比较保守,如果使用稍微积极一些的方式,可能效果会更好。
ML-Agents v0.4版本加入了一个新的算法:好奇心驱动的探索 (Curiosity-Driven Exploration)。
ML-Agents工程中也提供了相关的使用项目:金字塔探索者(Pyramids)。
在trainer_config.yaml中设置Curiosity相关的参数,可能会得到更好的效果。我们可以在该文件文末,仿照PyramidBrain添加如下参数表:
PlatformerBrain:
use_curiosity: true
curiosity_strength: 0.01
curiosity_enc_size: 256
batch_size: 128
buffer_size: 2048
hidden_units: 512
num_layers: 2
beta: 1.0e-2
max_steps: 1.0e5
num_epoch: 3
保存后,从1步开始重新训练。
在观察训练过程时,可以发现角色的操作似乎已经很理想了。当然,我们完全可以在命令行中直接按键Ctrl+C或者点击Unity的运行按钮中断训练,保存训练数据.bytes二进制文件。
将训练完的文件重新放回Unity中,并Internal模式下进行演示,观察训练结果。
现在Ellen可以在一遇到台阶就能完成跳跃,虽然还有些瑕疵,但是比原有的训练结果改善不少。
7、打开Main场景,找到Academy → Brain,设置Brain Type为Internal,指定Graph Model为新的.bytes文件,观察强化学习在实际游戏场景中的效果。
这里我稍微调整了TimeScale,让播放稍快些。使用Unity ML-Agents进行强化学习示例解析暂告一段落。

小结

下次还会发布进行模仿学习示例解析,敬请广大开发者期待。更多Unity官方技术直播课程尽在Unity Connect平台,更多Unity技术内容尽在Unity官方技术论坛(Unitychina.cn) !

Unity China
492
Comments