# ML-Agents(三)3DBall例子

前一周忙着公司的考试,都没有怎么学新的,今天补上~

之后的记录,我准备先只研究官方的示例,主要是把研究过程中的疑惑和想法记下来。首先我先补充一下如何利用GPU进行训练,结合(一)中的安装方法,需要CUDA v10.0,cuDNN v7.6.5 for CUDA v10.0,对应Tensorflow的版本是2.0.1。

一、利用GPU进行训练

前置工作在文章(一)中都有,原先的环境可以保留。现在可以拉一个新的ml-agents源码,然后修改ml-agents文件下的setup.py中如下图:

原来是"tensorflow>=1.7,<2.1",现在修改为"tensorflow-gpu>=1.7,<2.1",然后再在Anaconda中新建一个环境,如下:

建好后在命令行中重新安装环境(别忘记cd到新的ml-agents源码),分别输入:

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,然后按以前的方法开始训练,就可以了。

二、3DBall介绍

官方示例中,3Dball是一个比较简单的例子,主要运用了reinforcement learning(强化学习)。就是小球在平台上,萌版平台要控制自己绕x、z轴旋转,从而保持小球在自己头上不掉下来。

现根据官方文档翻译一下:

  • 设置:一个平衡球任务,agent需要保持小球在其脑袋上的平衡

  • 目标:Agent必须尽可能长时间地保持球在头顶的平衡

  • Agent设置:环境中包含12个想同类型的agent,全部使用同样的行为参数

  • Agent奖励设置:

    • 小球每一步保持在方块头顶上就奖励+0.1

    • 如果小球掉落,惩罚-0.1

  • 行为参数

    • 矢量观察空间:8个变量,包括agent方块的旋转角度(两个值,x、z轴方向),球和方块之间的相对位置关系(Vector3),球上刚体的速度(Vector3)
    • 矢量动作空间:类型为ContinuousSize为2,分别控制绕x轴旋转、绕z轴旋转
  • Float属性:三个

    • scale(比例):小球的比例,默认为1,推荐最小值为0.2,最大值为5
    • gravity(重力):重力加速度,默认为9.81,推荐最小值4,最大值为105
    • mass(质量):小球的质量,默认为1,推荐最小值为0.1,最大值为20
  • 基准平均奖励:100

OK,上面是借鉴官方文档,随意翻译了一下,大概可以了解3DBall主要用途和一些主要参数,里面的Float属性我这里不是很明白,在代码中是用在Agent.InitializeAgent()中的SetResetParameters(),这个方法顾名思义应该是对Agent进行初始化的操作。也许在这里,我们可以任意修改小球的比例、质量、重力加速度来改变小球在不同的情况下,训练的效果如何吧。

三、3DBall代码分析

看到目前为止,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的核心实现,观测值通过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()

Agent复位

复位就比较简单了,来看代码:

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重置时,同时重置参数,[Obsolete]这里是指小球的质量和比例,其实我觉得这里没必要,估计之后别的项目有用
//[new]这里重新设置泛化参数,具体见本博“ML-Agents(四)3DBall补充の引入泛化”
SetResetParameters();
}

这里的代码比较简单,注释能看明白即可。

Agent手动设置

这里主要是当训练模式为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.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

ML-Agents(三)3DBall例子的更多相关文章

  1. css通用小笔记02——浮动、清除(三个例子)

    css中通常会用到浮动与清除,也是一个必须掌握的知识点,概念性的东西不多说,下面举几个例子,来说明它的用法:1.文字环绕效果  2.多个div并排显示 3.清除浮动(默认显示) 一.文字环绕效果: h ...

  2. 统计学习方法笔记--EM算法--三硬币例子补充

    本文,意在说明<统计学习方法>第九章EM算法的三硬币例子,公式(9.5-9.6如何而来) 下面是(公式9.5-9.8)的说明, 本人水平有限,怀着分享学习的态度发表此文,欢迎大家批评,交流 ...

  3. keras神经网络三个例子

    keras构造神经网络,非常之方便!以后就它了.本文给出了三个例子,都是普通的神经网络 例一.离散输出,单标签.多分类 例二.图像识别,单标签.多分类.没有用到卷积神经网络(CNN) 例三.时序预测, ...

  4. golang关键字select的三个例子, time.After模拟socket/心跳超时

    golang关键字select的三个例子, time.After模拟socket/心跳超时   例子1 select会随机选择一个可执行的case   // 这个例子主要说明select是随机选择一个 ...

  5. TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)

    // 9个显示函数 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控 ...

  6. 大叔学ML第三:多项式回归

    目录 基本形式 小试牛刀 再试牛刀 调用类库 基本形式 上文中,大叔说道了线性回归,线性回归是个非常直观又简单的模型,但是很多时候,数据的分布并不是线性的,如: 如果我们想用高次多项式拟合上面的数据应 ...

  7. Flask--第三个例子,写一个接口,该接口返回html前端页面,模板的使用

     将接口数据返回至html前端页面有两种方法 方法一: 1 @app.route('/index',methods=['get']) 2 def open_index(): 3 page=open(' ...

  8. jquery第二期:三个例子带你走进jquery

    jquery是完全支持css的,我们举个例子来看看使用jquery的方便之处,这功劳是属于选择器的: 例1: <!DOCTYPE html PUBLIC "-//W3C//DTD HT ...

  9. 【Python】三个例子教你写代码

    这篇文章包括用Python编写的斐波那契数列,三位数的水仙花数和百钱买百鸡的基础代码: (一)斐波那契数列: ''' def hanshu(n): n_1 = 1 n_2 = 1 m = n sumn ...

随机推荐

  1. 会编程的 AI + 会修 Bug 的 AI,等于什么 ?

    2017-02-25 Python开发者 (点击上方公众号,可快速关注) 关于人工智能未来的畅想,除了家庭服务机器人,快递无人机,医用机器人等等,Lucas Carlson 认为人工智能在另外一个领域 ...

  2. 【RxJava Demo分析】(二)Schedulers线程调度器 · Hans Zone

    用Schedulers(调度器)实现多任务(并发,Concurrency)的例子 废话不多说我们看一下有关于RxJava的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

  3. 安卓权威编程指南-笔记(第21章 XML drawable)

    在Andorid的世界里,凡事要在屏幕上绘制的东西都可以叫drawable,比如抽象图形,Drawable的子类,位图图形等,我们之前用来封装图片的BitmapDrawable就是一种drawable ...

  4. 使用Python生成自己的特色二维码

    二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据 ...

  5. PHP 导出网页表格如何对标签中的内容设置属性

    当在使用php导出excel表格的时候,有时需要将某一列专门设置成文本属性 方法: 在需要设置属性的的<td>标签中 添加  style='vnd.ms-excel.numberforma ...

  6. 怎样解决使用feof()函数时出现的问题?

    feof函数        昨天在做一个课程设计时,一个函数的功能是将文件中的数据一条条的读到链表中去.既然不确定有多少条数据,那只能借助feof()函数了,本来文件部分就没学好,也就知道这一个方法. ...

  7. 浅谈ConcurrentDictionary与Dictionary

    在.NET4.0之前,如果我们需要在多线程环境下使用Dictionary类,除了自己实现线程同步来保证线程安全外,我们没有其他选择.很多开发人员肯定都实现过类似的线程安全方案,可能是通过创建全新的线程 ...

  8. VUE中登录密码显示与隐藏的最简设计——基于iview

    目录 VUE中登录密码显示与隐藏的最简设计--基于iview 1.背景 2.实现最终效果 2.1 隐藏密码 2.2 显示密码 3.实现思路 3.1 v-if判断当前密码显示状态 3.2 密码隐藏状态 ...

  9. Arthas 实战,助你解决同名类依赖冲突问题

    上篇文章中,小黑哥分析 Maven 依赖冲突分为两类: 项目同一依赖应用,存在多版本,每个版本同一个类,可能存在差异. 项目不同依赖应用,存在包名,类名完全一样的类. 第二种情况,往往是这个场景,本地 ...

  10. python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...