前一周忙着公司的考试,都没有怎么学新的,今天补上~
以后的记录,我准备先只研究官方的示例,主要是把研究过程当中的疑惑和想法记下来。首先我先补充一下如何利用GPU进行训练,结合(一)中的安装方法,须要CUDA v10.0,cuDNN v7.6.5 for CUDA v10.0,对应Tensorflow的版本是2.0.1。c#
前置工做在文章(一)中都有,原先的环境能够保留。如今能够拉一个新的ml-agents源码,而后修改ml-agents
文件下的setup.py
中以下图:数组
原来是"tensorflow>=1.7,<2.1"
,如今修改成"tensorflow-gpu>=1.7,<2.1"
,而后再在Anaconda中新建一个环境,以下:dom
建好后在命令行中从新安装环境(别忘记cd到新的ml-agents源码),分别输入:ide
pip install -e ml-agents-envs -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
学习
pip install -e ml-agents -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
命令行
就是分别安装两个环境,能够发现他会自动下载tensorflow_gpu-2.0.1
,以下图:翻译
配置好后,在Unity对应的Agent脚本上,也须要将Inference Device
勾选为GPU
,而后按之前的方法开始训练,就能够了。3d
官方示例中,3Dball是一个比较简单的例子,主要运用了reinforcement learning(强化学习)。就是小球在平台上,萌版平台要控制本身绕x、z轴旋转,从而保持小球在本身头上不掉下来。code
现根据官方文档翻译一下:orm
设置:一个平衡球任务,agent须要保持小球在其脑壳上的平衡
目标:Agent必须尽量长时间地保持球在头顶的平衡
Agent设置:环境中包含12个想同类型的agent,所有使用一样的行为参数
Agent奖励设置:
小球每一步保持在方块头顶上就奖励+0.1
若是小球掉落,惩罚-0.1
行为参数
Continuous
,Size
为2,分别控制绕x轴旋转、绕z轴旋转Float属性:三个
基准平均奖励:100
OK,上面是借鉴官方文档,随意翻译了一下,大概能够了解3DBall主要用途和一些主要参数,里面的Float属性我这里不是很明白,在代码中是用在Agent.InitializeAgent()
中的SetResetParameters()
,这个方法顾名思义应该是对Agent进行初始化的操做。也许在这里,咱们能够任意修改小球的比例、质量、重力加速度来改变小球在不一样的状况下,训练的效果如何吧。
看到目前为止,ml-agents其中的精华就在agent的脚本如何设置了,咱们下面来分析一下Ball3DAgent
代码。
public class Ball3DAgent : Agent { [Header("Specific to Ball3D")] public GameObject ball; Rigidbody m_BallRb; IFloatProperties m_ResetParams; public override void InitializeAgent() { m_BallRb = ball.GetComponent<Rigidbody>(); m_ResetParams = Academy.Instance.FloatProperties; SetResetParameters(); } public void SetBall() { //从Academy中获取小球的属性(质量、比例) m_BallRb.mass = m_ResetParams.GetPropertyWithDefault("mass", 1.0f); var scale = m_ResetParams.GetPropertyWithDefault("scale", 1.0f); ball.transform.localScale = new Vector3(scale, scale, scale); } public void SetResetParameters() { SetBall(); } }
这里初始化应用了InitializeAgent()
方法,这里获取了小球的刚体,而且利用SetBall()
来设置了小球的质量和比例,这里的的m_ResetParams变量是Academy的FloatProperties变量,这里的变量好像是会做为环境参数传递给Python,具体的用途我也还没研究清楚,姑且先看作是初始化小球的属性。
直接上源码。
public override void CollectObservations(VectorSensor sensor) { //平台绕Z轴旋转值 sensor.AddObservation(gameObject.transform.rotation.z); //平台绕X轴旋转值 sensor.AddObservation(gameObject.transform.rotation.x); //小球与平台的相对位置 sensor.AddObservation(ball.transform.position -gameObject.transform.position); //小球刚体的速度 sensor.AddObservation(m_BallRb.velocity); }
以上一共运用了8个观察值,注意Vector3类型的变量算是3个观察值(x,y,z)。
在Ball3DHardAgent项目里,与Ball3DAgent的区别就在于这里少了小球刚体速度的收集,从而致使前者在其余设置都相同的状况下,训练效果不佳,以下图。
能够看到平台的抖动很大,就是由于没有考虑到小球的速度影响而致使训练结果天差地别,所以在用ML-Agents的时候,须要严谨的考虑环境的观测项,可能因为一个观测项的增长或删除,就致使最终学习结果的好坏,这里我也是慢慢才学习,这就是我为何要先研究官方的示例,到时候最坏也能够照猫画虎。
这里是Agent的核心实现,观测值经过Agent收集到Brain处,Brain再经过外部Python训练环境反馈动做,再沿相同的路线返回到Agent的AgentAction(float[] vectorAction)
上(这里不知道个人想法对不对),具体的代码以下。
public override void AgentAction(float[] vectorAction) { //控制平台绕Z轴、X轴旋转的值 //用Mathf.Clamp()将响应的动做值限制到-2到2 var actionZ = 2f * Mathf.Clamp(vectorAction[0], -1f, 1f); var actionX = 2f * Mathf.Clamp(vectorAction[1], -1f, 1f); //平台绕Z轴旋转响应 if ((gameObject.transform.rotation.z < 0.25f && actionZ > 0f) || (gameObject.transform.rotation.z > -0.25f && actionZ < 0f)) { gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ); } //平台绕X轴旋转响应 if ((gameObject.transform.rotation.x < 0.25f && actionX > 0f) || (gameObject.transform.rotation.x > -0.25f && actionX < 0f)) { gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX); } //gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ); //gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX); //当小球在平台上,掉落或飞出平台,分别进行奖励或惩罚 if ((ball.transform.position.y - gameObject.transform.position.y) < -2f || Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f || Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f) { SetReward(-1f);//惩罚1 Done();//这次训练结束并从新开始,会调用AgentReset() } else { SetReward(0.1f);//在平台上的时候,每次动做都奖励0.1 } }
首先是平台对于旋转的响应,我又将两个if的条件去掉训练了一下,发现平台训练过程当中比较不稳,抖动较大,由于只要一来值就让平台旋转,可能这里会形成平台一直在调整姿态的过程当中,而源代码中,以绕Z轴为例,只有在平台Z轴旋转值<0.25f且actionZ>0、或平台Z轴旋转值>0.25f且actionZ<0时才对平台的姿态进行动做,这样就至关于设置了一个缓冲区间,不会让平台不停调整姿态,而是根据小球状况来适当调整姿态。
这里附上两次训练的tensorboard。
红色的是不加if条件的,蓝色的是官方加if的。其实从数据来看,大的趋势都差很少,不过我从训练现象来看,确实官方加if以后训练过程比较稳定。
后面的奖励代码中,有三个条件判断小球应该受到惩罚。
(ball.transform.position.y - gameObject.transform.position.y) < -2f
小球与平台y方向上的差值小于2,以下图:
这里能够看出是小球掉落到平台下边,其实大多数状况是其余两种状况。
Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f
和Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f
这两种放一块儿将,先来看看小球的位置:
此时小球的x,z值都是3,能够看出小球恰好在x轴方向或者z方向滚出了平台边缘。
因此,上面三种状况只要发生一种就对小球Agent作出-1惩罚,同时调用Done()
。
复位就比较简单了,来看代码:
public override void AgentReset() { //复位平台旋转角度 gameObject.transform.rotation = new Quaternion(0f, 0f, 0f, 0f); //令平台随机绕x轴旋转-10~10度 gameObject.transform.Rotate(new Vector3(1, 0, 0), Random.Range(-10f, 10f)); //令平台随机绕z轴旋转-10~10度 gameObject.transform.Rotate(new Vector3(0, 0, 1), Random.Range(-10f, 10f)); //小球刚体速度变为0 m_BallRb.velocity = new Vector3(0f, 0f, 0f); //小球在y(相对平台高度)为4的地方,同时随机x、z值出现 ball.transform.position = new Vector3(Random.Range(-1.5f, 1.5f), 4f, Random.Range(-1.5f, 1.5f)) + gameObject.transform.position; //Agent重置时,同时重置参数,这里是指小球的质量和比例,其实我以为这里不必,估计以后别的项目有用 SetResetParameters(); }
这里的代码比较简单,注释能看明白便可。
这里主要是当训练模式为Heuristic Only
时调用,具体设置以下:
代码以下:
public override float[] Heuristic() { var action = new float[2]; action[0] = -Input.GetAxis("Horizontal"); action[1] = Input.GetAxis("Vertical"); return action; }
这里的代码至关于咱们输入来控制动做向量空间的值,其实就是action[]数组,咱们令action[0]控制平台绕x轴的旋转,action[1]控制平台绕z轴的旋转。
能够试一下,其实要保持小球在平台上还有点难度。
至此第一个例子就研究到这,有什么问题欢迎你们一块儿探讨。
写文不易~所以作如下申明:
1.博客中标注原创的文章,版权归原做者 煦阳(本博博主) 全部;
2.未经原做者容许不得转载本文内容,不然将视为侵权;
3.转载或者引用本文内容请注明来源及原做者;
4.对于不遵照此声明或者其余违法使用本文内容者,本人依法保留追究权等。