目录
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、运行场景,训练效果还是很不错的
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
{
///
/// 平衡球,平衡 AI 代理
///
[RequireComponent(typeof(DecisionRequester))]
public class AIAgent_Balance : Agent
{
// 平衡球
public GameObject Balanced_Sphere;
// 平衡球的刚体
private Rigidbody rgbodyBalanced_Sphere;
///
/// 初始化函数
///
public override void Initialize()
{
rgbodyBalanced_Sphere = Balanced_Sphere.GetComponent();
}
///
/// 新阶段开始
///
public override void OnEpisodeBegin()
{
// 平衡板每次新阶段开始的初始化随机旋转
AIAgentBalanceCubeInitRandomRotation();
// 小球速度归零 小球位置随机生成在Cube 上头(注意位置)
BalancedSphereInitRandomPosition();
}
///
/// 收集观察变量
///
///
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);
}
}
///
/// 接收动作变量
///
///
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);
}
}
///
/// 手动输入操作变量
///
///
public override void Heuristic(float[] actionsOut)
{
// 水平垂直操作物体的数据
actionsOut[0] = Input.GetAxis("Horizontal");
actionsOut[1] = Input.GetAxis("Vertical");
}
///
/// 平衡板每次新阶段开始的初始化随机旋转
///
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));
}
///
/// 小球速度归零
/// 小球位置随机生成在Cube 上头(注意位置)
///
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;
}
///
/// 判断球是否出界或坠落
///
///
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 属性如图