本文介绍unity强化学习ML-Agents插件的应用,训练红球完成游戏任务。
本文所使用的软件:Unity2021LTS; VS2019 profession
由于作者对强化学习及unity均有一定知识背景,其基础内容均不做记录。
1 下载unity官方工具包(上不去就科学上网),下载完成后将文件放置于项目文件夹中
https://gitcode.net/mirrors/unity-technologies/ml-agents?utm_source=csdn_github_accelerator
2 创建python环境,本文使用的解释器为python3.6
2.1 下载mlagents(安装有问题可以更换清华源)
2.1.1分别 依序 定位到ml-agents-envs与ml-agents的目录下,执行以下指令
pip install -e.
2.1.2 安装完成后,cd至原始目录,输入以下指令检查是否安装成功
mlagents-learn --help
部分教程在下载mlagents会把神经网络的包(tenserflow)装好,但是我的没有,并且错误提示我没有pytorch神经网络包(可能是由于插件版本不同吧),所以我还需单独安装pytorch。完成之后重复以上指令直至没有错误,此时python环境便已经完成好了搭建。
AssertionError: A compatible version of PyTorch was not installed. Please visit the PyTorch homepage (https://pytorch.org/get-started/locally/) and follow the instructions to install. Version 1.6.0 and later are supported.
2.2 在unity中安装Barracude(调用CPU跑强化学习的插件)
官方解释:Barracuda is lightweight and cross-platform Neural Net inference library. Barracuda supports inference both on GPU and CPU.
在unity中导入Editor,Plugins,Runtime文件夹,将其复制至Unity本地Assets文件夹下
3 创建unity环境
3.1 创建一个1.5m*1.5m的地板,两个球体(分别命名为Target与AI,材质自创自选),在本文中,红色表示AI,绿色表示Target,为AI添加一个刚体组件。在Assets本地文件夹下,创建名为Scripts的文件夹用来保存脚本程序。
3.2 创建名为RollerAgent的脚本文件,
在脚本文件中,需添加额外引用Unity.MLAgents与Unity.MLAgents.Sensors;将父类继承改为Agent
3.3 读取目标小球位置与刚体组件
//拿到目标小球的坐标
public Transform Target;
//拿到刚体组件(运动所需)
Rigidbody rBody;
rBody = GetComponent<Rigidbody>();//为了控制移动,拿到AI刚体组件
3.4 agent中的四个函数
//进入新一轮调用的函数
public override void OnEpisodeBegin()
{
base.OnEpisodeBegin();
}
//收集观察的结果
public override void CollectObservations(VectorSensor sensor)
{
base.CollectObservations(sensor);
}
//接收动作,是否给予奖励
public override void OnActionReceived(float[] vectorAction)
{
base.OnActionReceived(vectorAction);
}
//手动操作智能体
public override void Heuristic(float[] actionsOut)
{
base.Heuristic(actionsOut);
}
3.4.1 手动操作智能体函数设定
在Heuristic函数中,设计如下指令:
actionsOut[0] = Input.GetAxis("Horizontal"); //获取水平轴的输入值,即A\D键
actionsOut[1] = Input.GetAxis("Vertical"); //获取垂直轴的输入值,即W\S键
在OnActionReceived函数中,将vectorAction输出值控制台观察
Debug.Log(vectorAction[0]);
Debug.Log(vectorAction[1]);
将脚本文件挂至AI物体,观察AI是否显示Benavior Parameters组件,并将AI组件设置如下:
不同版本的ML-Agents插件在此处组件:actions维度设置上如下所示:
Continuous Actions代表连续动作维度;Discrete Branches代表离散动作维度
为AI添加Decision Requester组件
运行调试,操作WASD键观察控制台输出动作。
为智能体添加动作,在OnActionReceived函数中修改如下指令:
public override void OnActionReceived(float[] vectorAction)
{
//Debug.Log("Horizontal:" + vectorAction[0]);
//Debug.Log("Vertical:" + vectorAction[1]);
Vector3 control = Vector3.zero; //定义控制信号
control.x = vectorAction[0];
control.z = vectorAction[1];
rBody.AddForce(control * 10.0f);
}
运行,操作AI运动,观察AI状态
3.4.2 新一轮调用函数
将AI组件中Max Step设置为120,此时游戏会每隔两分钟进行一次刷新,将初始函数代码定义如下,观察运行结果。
public override void OnEpisodeBegin()
{
Debug.Log("ok!");
//重新开始设置小球初始位置
this.transform.position = new Vector3(2.0f, 0.5f, 2.0f); //初始位置
this.rBody.velocity = Vector3.zero; //初始速度
this.rBody.angularVelocity = Vector3.zero;//初始旋转速度
}
3.4.3 接收动作,接收奖励。
将AI物体组件下的目标设置为Target(不设置会提示找不到目标!!)
将OnActionReceived定义如下:
public override void OnActionReceived(float[] vectorAction)
{
//Debug.Log("Horizontal:" + vectorAction[0]);
//Debug.Log("Vertical:" + vectorAction[1]);
Vector3 control = Vector3.zero; //定义控制信号
control.x = vectorAction[0];
control.z = vectorAction[1];
rBody.AddForce(control * 10.0f);// 移动小球
//小球出界
if (this.transform.position.y < 0)
{
EndEpisode();
}
//小球完成任务
float distance = Vector3.Distance(this.transform.position, Target.position);
if (distance < 1.41f)
{
//给定奖励
SetReward(1.0f);
EndEpisode();
}
}
3.4.4 收集观察值(难点部分)及位置重置
在新一轮游戏开始前,随机目标位置
//随机Target位置
Target.position = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
收集观察值,在CollectObservations函数下列写我们需要的观察值;
public override void CollectObservations(VectorSensor sensor)
{
sensor.AddObservation(Target.position);//收集Target坐标
sensor.AddObservation(this.transform.position);//收集AI坐标
sensor.AddObservation(rBody.velocity.x); //两个速度
sensor.AddObservation(rBody.velocity.z);
}
在组件中修改观察值参数
3.5 修正部分参数及模型,将只有小球掉落平台才会重置小球位置。(在此之前,将Max Step设置为0)
if (this.transform.position.y < 0)
{
this.transform.position = new Vector3(2.0f, 0.5f, 2.0f); //初始位置
}
this.rBody.velocity = Vector3.zero; //初始速度
4 模型训练
在Assets文件夹下建立Train文件夹,将config.yaml放于文件夹中,文件中behaviors文件名需与上述提到的命名保持一致。
激活我们创建的python环境,cd至Train文件夹路径下,执行以下命令即可开始训练。
mlagents-learn config.yaml
这条命令的意思是采用的配置文件是config.yaml,以config这个名字来进行训练,训练数据也将保存在官方包下results目录下的同名文件夹,在第二次进行训练时,须在该指令后加入“--force”,此为强制执行训练过程,这会覆盖上一次的数据,如果没有写–force而存在同名文件夹,则训练无法执行。
本文所用的pytorch包的版本如下:
在训练完成后会在Train—results—ppo文件夹下生成一个神经网络,即我们最终要训练的神经网络,将其加入AI组件中的模型中,即完成了unity强化学习的训练过程。
注:本文参考资料如下:
快速入门Unity机器学习 - SiKi学院|SiKi学堂 - unity|u3d|虚幻|ue4/5|java|python|人工智能|视频教程|在线课程
本文所介绍的部分方法多来源于以上内容,但由于软硬件版本的不同,本文所描述的方法与以上内容略有差异,特此记录,方便后续翻看学习,有任何描述错误的地方欢迎指正!