Unity ML-Agents 之 平衡球案例的实现整理(内含实现步骤)

tech2022-09-10  85

 

 

Unity ML-Agents 之 平衡球案例的实现整理(内含实现步骤)

 

目录

Unity ML-Agents 之 平衡球案例的实现整理(内含实现步骤)

一、简单介绍

二、原理实现

三、原理拆解

四、注意事项

五、效果预览

六、实现步骤

七、训练过程数据的可视化查看(tensorboard.exe 查看可视化数据)

八、关键脚本

九、训练后记


 

一、简单介绍

Unity 中使用人工智能 ML-Agents 的功能,包括环境搭建,ML-Agents 集成到Unity,使用 mlagents 训练,训练结果在 Unity 中使用等。

本节介绍,在 Unity 使用 ML-Agents,编写重写 平衡球案例,然后训练,得到训练模型的方法 Demo。关键是学会,判断设置重写重置的条件,怎么设置奖励(惩罚),怎么模拟操作,观察的变量、控制的变量等,关键是学会每个案例奥妙,便会后期更复杂的铺垫。

 

这里不在讲解环境搭建,相关的环境搭建,可参见

Unity ML-Agents 之 环境配置(Anaconda 下载安装等),简单的搭建场景实现简单训练的Demo(内含详细步骤)

 

二、原理实现

1、继承 Agent ,重写五个函数,Initialize()、OnEpisodeBegin()、 CollectObservations()、 OnActionReceived()、 Heuristic()

1)Initialize ()函数相当于 Start()函数,获取小球的刚体

2)OnEpisodeBegin()新一段开始函数,可以重置小球坠落出界后的重新开始的位置,以及 Cube 重新开始的一定范围的随机旋转

3)CollectObservations()观察变量,包括球相对于Cube 的相对位置、球的速度、Cube X Z 的旋转

4)OnActionReceived ()改变 Cube XZ的两个变量,球出界的判断,以及设置奖励

5)Heuristic ()在 HeuristicOnly 模式操作小球的输入,这里是水平竖直Axis 操纵

2、编写好脚本训练模型

 

三、原理拆解

1、观察的变量

 

2、球的坠落出界判断

 

3、坠落出界之后,重置初始化位置

1)球在Cube 上方的一定区域

2)Cube X Z 上的适当任意旋转

 

四、注意事项

1、其实要真正模拟一个平衡球的案例,考虑的东西挺多的,必要的我们需要抽象出来。这个案例没有添加球的太多物理属性,例如球的摩擦、弹力、角速度等,需要的话大家可以自行添加,进行训练

2、训练的时候,可以拷贝多个模型一起训练,可以加快训练速度(但是要考虑自己CPU的性能,过多不一定好)

3、训练的时候,程序中的不必要代码打印最好关闭,不然,可能会影响训练速度

 

五、效果预览

训练后的效果

 

开始训练的效果

 

六、实现步骤

1、打开 Unity,新建工程

 

2、在菜单 Window - Package Manager ,打开包管理

 

3、搜索 Barracuda ,下载安装该 Package (不然导入 ML-Agents 包会报错)

 

4、把 ml-agents-master 中的 com.unity.ml.agents 文件夹中的 Editor 、Plugins、Runtime 导入 Unity

 

5、搭建一个场景,Cube(+Sphere)、Sphere ,对应取名,配色即可

 

6、在工程中添加脚本 AIAgent_Balance ,继承 Agent,重写五个函数

1)Initialize ()函数相当于 Start()函数,获取小球的刚体

2)OnEpisodeBegin()新一段开始函数,可以重置小球坠落出界后的重新开始的位置,以及 Cube 重新开始的一定范围的随机旋转

3)CollectObservations()观察变量,包括球相对于Cube 的相对位置、球的速度、Cube X Z 的旋转

4)OnActionReceived ()改变 Cube XZ的两个变量,球出界的判断,以及设置奖励

5)Heuristic ()在 HeuristicOnly 模式操作小球的输入,这里是水平竖直Axis 操纵

 

7、把脚本挂载到 AIAgent_Balance_Cube 上,并把 Balanced_Sphere 球体对应赋值

 

8、设置 BehaviorParameters 脚本中的 VectorObservation 的 Space Size 为 8 (观察变量),VectorAction 动作变量为 2 (操作的就是 Cube 的 X Z上的旋转值), BehaviorType 设置为 HeuristicOnly ,先自己操作玩一下

 

9、自己操作,还是挺麻烦的,接下来,训练模型

 

10、添加一个 Train 文件夹,添加一个训练配置文件,注意Behavior 名称,会用到

 

11、BehaviorParameters 脚本中的 BehaviorName 为配置文件中的名称 BalanceBall, BehaviorType 设置为 Default ,并根据电脑CPU的性能适当拷贝多的训练模型,加快训练效果

 

12、打开命令行

 

13、激活已经配置好 ml-agents 环境,切换到平衡球工程训练文件夹,使用 mlagents-learn BalanceBall.yaml,开始训练

 

14、出现 Play button,回到 Unity ,Play 运行场景

 

15、这里训练过程中的效果(从老掉到逐渐稳定)

 

16、训练结束(训练结果还是很不不错的,到252000 次后,基本没有球掉落的情况),会自动保存一个 训练 xxx.nn 文件

 

17、把训练好的 xxx.nn 赋值到 BehaviorParameters 脚本中的 Model

 

18、运行场景,训练效果还是很不错的

 

七、训练过程数据的可视化查看(tensorboard.exe 查看可视化数据)

1、打开 Anacoda 构建的训练环境下的 Scripts(tensorboard.exe 能找到)

 

2、按住 Shift + 鼠标右键,点击在此处打开 Powershell 窗口

注意:按住 Shift + 鼠标右键时千万别选中任何项目文件,不然右键打不开如图菜单

 

3、打开 输入 如图命令,即可绑定一个网址,查看可视化数据图

( .\tensorboard.exe --logdir 训练的工程路径文件夹位置绝对路径 --host=127.0.0.1)

 

4、在网页输入回车,即可看到训练数据过程可视化图: http://127.0.0.1:6006/

 

八、关键脚本

1、AIAgent_Balance.cs

using System.Collections; using System.Collections.Generic; using Unity.MLAgents; using Unity.MLAgents.Sensors; using UnityEngine; namespace XANStudy_MLAgents { /// <summary> /// 平衡球,平衡 AI 代理 /// </summary> [RequireComponent(typeof(DecisionRequester))] public class AIAgent_Balance : Agent { // 平衡球 public GameObject Balanced_Sphere; // 平衡球的刚体 private Rigidbody rgbodyBalanced_Sphere; /// <summary> /// 初始化函数 /// </summary> public override void Initialize() { rgbodyBalanced_Sphere = Balanced_Sphere.GetComponent<Rigidbody>(); } /// <summary> /// 新阶段开始 /// </summary> public override void OnEpisodeBegin() { // 平衡板每次新阶段开始的初始化随机旋转 AIAgentBalanceCubeInitRandomRotation(); // 小球速度归零 小球位置随机生成在Cube 上头(注意位置) BalancedSphereInitRandomPosition(); } /// <summary> /// 收集观察变量 /// </summary> /// <param name="sensor"></param> public override void CollectObservations(VectorSensor sensor) { // 观察总共 3+3+1+1 个值 { // 球相对Cube 的位置 3 sensor.AddObservation(Balanced_Sphere.transform.position - this.transform.position); // 球的速度 3 sensor.AddObservation(rgbodyBalanced_Sphere.velocity); // Cube 旋转 x z 1+1 sensor.AddObservation(this.transform.eulerAngles.x); sensor.AddObservation(this.transform.eulerAngles.z); } } /// <summary> /// 接收动作变量 /// </summary> /// <param name="vectorAction"></param> public override void OnActionReceived(float[] vectorAction) { //Debug.Log("vectorAction[0] : " + vectorAction[0]); //Debug.Log("vectorAction[1] : " + vectorAction[1]); // 操作 Cube ,避免小球出界坠落 float x = 2 * Mathf.Clamp(vectorAction[0], -1, 1); float z = 2 * Mathf.Clamp(vectorAction[1], -1, 1); // 绕 X 前后旋转 this.transform.Rotate(Vector3.right, z); // 绕 Z 左右旋转 this.transform.Rotate(Vector3.forward, -x); // 判断小球是否出界坠落 if (JudgeBallIsDropOut()==true) { // 设置负值的奖励(惩罚) SetReward(-1.0f); // 重新开始 EndEpisode(); } else{ // 设置的奖励 (这个会差不多美帧调用,太多可能不好,关键是与 上面的 负值惩罚有一定比例) SetReward(0.1f); } } /// <summary> /// 手动输入操作变量 /// </summary> /// <param name="actionsOut"></param> public override void Heuristic(float[] actionsOut) { // 水平垂直操作物体的数据 actionsOut[0] = Input.GetAxis("Horizontal"); actionsOut[1] = Input.GetAxis("Vertical"); } /// <summary> /// 平衡板每次新阶段开始的初始化随机旋转 /// </summary> private void AIAgentBalanceCubeInitRandomRotation() { this.transform.rotation = Quaternion.identity; // 平衡Cube 开始在X和Z上有随机 -10,10 的旋转 this.transform.Rotate(Vector3.right,Random.Range(-10.0f,10.0f)); this.transform.Rotate(Vector3.forward,Random.Range(-10.0f,10.0f)); } /// <summary> /// 小球速度归零 /// 小球位置随机生成在Cube 上头(注意位置) /// </summary> private void BalancedSphereInitRandomPosition() { this.rgbodyBalanced_Sphere.velocity = Vector3.zero; this.Balanced_Sphere.transform.position = new Vector3(Random.Range(-2f,2f),5, Random.Range(-2f, 2f)) + this.transform.position; } /// <summary> /// 判断球是否出界或坠落 /// </summary> /// <returns></returns> private bool JudgeBallIsDropOut() { // 后面的值是保险值(前面的值其实可以判定出界,后面保证正真出界而已) return ((Balanced_Sphere.transform.position.y - this.transform.position.y) < (0 +(-1.0f)) // 球出 Cube 距离 || Mathf.Abs(Balanced_Sphere.transform.position.x - this.transform.position.x) > (2.5f+0.5f) || Mathf.Abs(Balanced_Sphere.transform.position.z - this.transform.position.z) > (2.5f + 0.5f) ); } } }

 

2、BalanceBall.yaml

behaviors: BalanceBall: trainer_type: ppo hyperparameters: batch_size: 64 buffer_size: 12000 learning_rate: 0.0003 beta: 0.001 epsilon: 0.2 lambd: 0.99 num_epoch: 3 learning_rate_schedule: linear network_settings: normalize: true hidden_units: 128 num_layers: 2 vis_encode_type: simple reward_signals: extrinsic: gamma: 0.99 strength: 1.0 keep_checkpoints: 5 max_steps: 500000 time_horizon: 1000 summary_freq: 12000 threaded: true

 

九、训练后记

1、可以给球体添加物理材质,和修改 角速度,更真实的模拟,看看训练结果会怎么样

 

2、BalanceBall.physicMaterial 属性如图

 

 

最新回复(0)