这篇博客是跟着Create your own A.I. in Unity | ML-Agents Tutorial 2020这个视频(油管视频),一步一步使用ML-Agents在Unity中创建自己的强化学习环境。
项目地址
效果:
小球避开左右墙,从斜坡上跳到目标位置。
那我们就开始吧~
配置环境
系统:win10
Unity Version:2019.3.12
ML-Agents Version:Release 4 ,July 15, 2020
tensorflow:1.7.1
python:3.6
环境配置可以参考我的上一个博客~
创建训练环境
新建项目
打开Unity Hub,创建一个3D新项目,命名为BallJump,点击创建。
得到这样的界面
下载packages
新建的项目先下载需要的package,ML-Agent(1.0.0)和ProBuilder(4.2.3)
首先,打开Package Manager
让它显示之前的版本
搜索ML Agents
(注意:当我使用Unity 2018.3.14版本时,我在Package Manager中找不到ML Agents项目,不确定是否和版本有关,因此我下了和视频中一样的Unity版本 2019.3.12,解决了这一问题)
点击ML左边的小箭头,找到之前的1.0.0版本,点击install安装
同样的,安装ProBuilder(4.2.3)
创建场景
创建文件夹
首先在Asserts目录下创建4个新的文件夹,并重命名为Brains(存放训练好的网络),Materials(存放材质),Prefabs(存放整体外观),Scripts(存放代码)
共有五个文件夹
进入Scenes,将场景重命名为BallJumpScene
点击reload,得到目前没有添加物体的空的场景。
加入object
加入一个plane,作为小球滚动的平面
修改名称为Floor
scale的X改为2
得到效果如下
加入两个cube作为左右挡着的墙,两个墙的数据如下
得到
再加入一个sphere作为训练行为的小球
以及再加入一个cube作为小球的目标位置,它的位置之后会随着程序而改变的。
最后要加入一个斜坡,我们自定义斜坡的形状,进入
点击new shape右边的加号,设定prism的形状,点击build创建。
设定位置
设置Material
进入之前创建的Materials目录,新建一个Material
命名为Black,设置颜色为黑色
再新建一个蓝绿色的Material,命名为cyan
创建好两个材料后,拖动到物体上应用,让左右墙和斜坡应用黑色的材质
小球应用蓝绿色的材质,最后结果
设定小球的性质
小球作为训练的目标需要进行设置,首先设定小球为刚体,在BallAgent下点击add component
找到rigidbody,成功设定为刚体
接着编程控制小球的行为,在scripts文件夹下新建一个C#文件,命名为BallAgentLogic
使用VS打开该文件
是这样的
把代码换成如下:
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
public class BallAgentLogic : Agent
{
Rigidbody rBody;
// Start is called before the first frame update
void Start()
{
rBody = GetComponent<Rigidbody>();
}
public Transform target;
public override void OnEpisodeBegin()
{
// Reset agent
this.rBody.angularVelocity = Vector3.zero;
this.rBody.velocity = Vector3.zero;
this.transform.localPosition = new Vector3(-9, 0.5f, 0);
// Move target to a new spot
target.localPosition = new Vector3(12 + Random.value * 8, Random.value * 3, Random.value * 10 - 5);
}
public override void CollectObservations(VectorSensor sensor)
{
// Target and Agent positions & Agent velocity
sensor.AddObservation(target.localPosition);
sensor.AddObservation(this.transform.localPosition);
sensor.AddObservation(rBody.velocity);
}
public float speed = 20;
public override void OnActionReceived(float[] vectorAction)
{
Vector3 controlSignal = Vector3.zero;
controlSignal.x = vectorAction[0];
if (vectorAction[1] == 2)
{
controlSignal.z = 1;
}
else
{
controlSignal.z = -vectorAction[1];
}
// Prevent adding forces after jumping
if (this.transform.localPosition.x < 8.5)
{
rBody.AddForce(controlSignal * speed);
}
float distanceToTarget = Vector3.Distance(this.transform.localPosition, target.localPosition);
// Reached target
if (distanceToTarget < 1.42f)
{
SetReward(1.0f);
EndEpisode();
}
// Fell of platform
if (this.transform.localPosition.y < 0)
{
EndEpisode();
}
}
public override void Heuristic(float[] actionsOut)
{
actionsOut[0] = Input.GetAxis("Vertical");
actionsOut[1] = Input.GetAxis("Horizontal");
}
}
把代码保存后,拖动到BallAgent里
把Target object拖动到BallAgent的Target里
设置Behavior Parameter
加入Decision Requester
设置为5,每五次做一次决定
设置相机位置,在Main camera中设置位置和角度
此时点击play。就可以用这个视角,按键盘上的上下左右键控制小球动啦
如果想让视角一直跟随小球的话,我们再新建一个C#文件,命名为BallAgentFollow
代码为:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallAgentFollow : MonoBehaviour
{
public Transform BallAgentTransform;
private Vector3 _cameraOffset;
// Start is called before the first frame update
void Start()
{
_cameraOffset = transform.position - BallAgentTransform.position;
}
void LateUpdate()
{
transform.position = BallAgentTransform.position + _cameraOffset;
}
}
保存后,拖动到Main camera里
再把小球拖过去
此时再点击play运行,视角跟随小球
训练并查看效果
训练前
为了加快训练的速度,我们把整个场景多复制几遍,让它们同时训练。
创建一个empty,命名为TrainingArea,设置位置000
把这6项都拖到TrainingArea里
把TrainingArea拖到Prefabs里,之后更改Prefab,就可以同步更改Scene,修改很方便。
接下来复制粘贴很多份TrainingArea,摆放的时候沿着箭头移动位置。
接下来在ml-agents-release_4\config\ppo文件目录下创建一个trainer_config.yaml文件,文件内容为
behaviors:
BallAgent:
trainer_type: ppo
hyperparameters:
batch_size: 128
buffer_size: 5000
learning_rate: 3.0e-4
beta: 1.0e-3
epsilon: 0.15
lambd: 0.92
num_epoch: 3
learning_rate_schedule: linear
network_settings:
normalize: true
hidden_units: 128
num_layers: 3
vis_encode_type: simple
memory: null
reward_signals:
extrinsic:
gamma: 0.99
strength: 1.0
keep_checkpoints: 5
max_steps: 9.00e6
time_horizon: 128
summary_freq: 10000
threaded: true
开始训练
训练过程可以参考上一篇博客
打开命令行窗口,激活环境
activate ml-agents2
进入ml-agents文件夹
G:
cd G:\ghy\program\RL\ml-agents-release_4
训练
mlagents-learn config/ppo/trainer_config.yaml --run-id=balljump --train
点击unity中的play开始训练
训练到六十多万次的时候,成功率就已经稳定在了百分之九十
训练一百万次已经有了相当好的结果
按Ctrl+C停止训练
查看训练效果
ml-agents-release_4\results\balljump下的.nn文件拖到Brains文件夹下
这个.nn文件再拖到BallAgent里
这时候在点击Play可以看到训练后的效果(比我玩的好太多了)。