本案例源自ML-Agents官方的示例,Github地址:https://github.com/Unity-Technologies/ml-agents,本文是详细的配套讲解。

本文基于我前面发的两篇文章,需要对ML-Agents有一定的了解,详情请见:Unity强化学习之ML-Agents的使用、ML-Agents命令及配置大全。

我前面的相关文章有:

ML-Agents案例之Crawler

ML-Agents案例之推箱子游戏

ML-Agents案例之跳墙游戏

ML-Agents案例之食物收集者

ML-Agents案例之双人足球

Unity人工智能之不断自我进化的五人足球赛

ML-Agents案例之地牢逃脱

环境说明

本案例的环境要比以往大了很多倍,智能体要在这个相当大的环境中去寻找一个绿色的方块,而方块位于一个金字塔的顶端,想要触碰这个方块必须要推倒金字塔,而金字塔和方块不是一开始就有的,必须要触碰按钮才会出现在随机地点,按钮会刷新在随机的位置。因此智能体想要完成任务,必须要经过寻找按钮–>触碰按钮–>寻找金字塔–>推倒金字塔–>触碰绿色方块,这几个步骤,步骤的复杂和环境的庞大对训练是一个相当大的挑战。

由于奖励太过稀疏,这次的任务如果使用以往的寻常方法是几乎不可能得到一个好的结果的,因此这里我们需要应用到一个好奇心机制,(Curiosity),使得智能体在探索未知事物中得到奖励,才能有效推动训练的进展。

状态输入:

可以看到,智能体采用了射线传感器Ray Perception Sensor 3D,并且使用了三个,以获得上中下的立体视角,上中下三层的每一层都有七条射线,总共有21条射线,每一条射线检测的标签有墙壁、目标金字塔的石头、普通金字塔的石头、目标方块、闭合的开关、断开的开关。参数见下图。关于该传感器的详细说明见ML-Agents案例之推箱子游戏。三个传感器在参数上只有细微差别。

除了射线传感器的输入之外,代码中海油四个输入维度,分别是智能体的速度(三维,Local Space),开关是否闭合。

动作输出:

输出只有一个离散的动作,包含五个值,分别是什么都不做,向前走,向后走,左转,右转。较少的输出会大大降低神经网络复杂度,减少训练时间。缺点是同一时间只能执行一个动作,降低智能体的灵活性,例如不能同时前进和旋转。

代码讲解

智能体代码PyramidAgent.cs:

初始化方法Initialize():

public override void Initialize()
{// 获取刚体m_AgentRb = GetComponent<Rigidbody>();// 获取控制整个环境的脚本m_MyArea = area.GetComponent<PyramidArea>();// 获取开关的脚本m_SwitchLogic = areaSwitch.GetComponent<PyramidSwitch>();
}

状态输入方法CollectObservations:

public override void CollectObservations(VectorSensor sensor)
{if (useVectorObs){// 输入开关的状态sensor.AddObservation(m_SwitchLogic.GetState());// 输入智能体的速度向量sensor.AddObservation(transform.InverseTransformDirection(m_AgentRb.velocity));}
}

动作输出方法OnActionReceived:

public override void OnActionReceived(ActionBuffers actionBuffers)
{// 给予时间惩罚,鼓励快速结束游戏AddReward(-1f / MaxStep);MoveAgent(actionBuffers.DiscreteActions);
}
public void MoveAgent(ActionSegment<int> act)
{var dirToGo = Vector3.zero;var rotateDir = Vector3.zero;// 接收神经网络的输出var action = act[0];// 输出处理switch (action){case 1:dirToGo = transform.forward * 1f;break;case 2:dirToGo = transform.forward * -1f;break;case 3:rotateDir = transform.up * 1f;break;case 4:rotateDir = transform.up * -1f;break;}// 执行输出transform.Rotate(rotateDir, Time.deltaTime * 200f);m_AgentRb.AddForce(dirToGo * 2f, ForceMode.VelocityChange);
}

在一个episode开始时执行方法OnEpisodeBegin():

// 相比以前需要加上这句
using System.Linq;
public override void OnEpisodeBegin()
{// 取0-9并打乱顺序var enumerable = Enumerable.Range(0, 9).OrderBy(x => Guid.NewGuid()).Take(9);var items = enumerable.ToArray();// 清理区域,销毁场景中所有金字塔(包括真*金字塔)m_MyArea.CleanPyramidArea();// 智能体速度归零m_AgentRb.velocity = Vector3.zero;// 把自己的位置放到items[0]的区域m_MyArea.PlaceObject(gameObject, items[0]);// 随机自己的旋转rotationtransform.rotation = Quaternion.Euler(new Vector3(0f, Random.Range(0, 360)));// 重置按钮(回到未触发状态,位置随机)m_SwitchLogic.ResetSwitch(items[1], items[2]);// 生成六个石头金字塔m_MyArea.CreateStonePyramid(1, items[3]);m_MyArea.CreateStonePyramid(1, items[4]);m_MyArea.CreateStonePyramid(1, items[5]);m_MyArea.CreateStonePyramid(1, items[6]);m_MyArea.CreateStonePyramid(1, items[7]);m_MyArea.CreateStonePyramid(1, items[8]);
}

碰撞检测OnCollisionEnter方法:

void OnCollisionEnter(Collision collision)
{// 如果碰到目标方块,那么游戏结束,加2分if (collision.gameObject.CompareTag("goal")){SetReward(2f);EndEpisode();}
}

挂在开关下的脚本PyramidSwitch.cs:

// 初始化,获取父物体中的脚本
void Start()
{m_Area = gameObject.transform.parent.gameObject;m_AreaComponent = m_Area.GetComponent<PyramidArea>();
}

重置开关方法:

public void ResetSwitch(int spawnAreaIndex, int pyramidSpawnIndex)
{// 把开关放置到指定位置m_AreaComponent.PlaceObject(gameObject, spawnAreaIndex);// 设定开关状态为断开m_State = false;m_PyramidIndex = pyramidSpawnIndex;tag = "switchOff";// 旋转归零transform.rotation = Quaternion.Euler(0f, 0f, 0f);// 材质变成未触发的状态myButton.GetComponent<Renderer>().material = offMaterial;
}

碰撞检测:

void OnCollisionEnter(Collision other)
{// 当碰到未打开的开关,开关变为打开状态,并创造一个金字塔if (other.gameObject.CompareTag("agent") && m_State == false){myButton.GetComponent<Renderer>().material = onMaterial;m_State = true;// 生成真*金字塔m_AreaComponent.CreatePyramid(1, m_PyramidIndex);tag = "switchOn";}
}

整个环境的控制脚本PyramidArea.cs:

参数设置(可以在Unity编辑器中自由更改):

public GameObject pyramid;
public GameObject stonePyramid;
// 生成区域数组
public GameObject[] spawnAreas;
public int numPyra;
public float range;

生成两种金字塔的方法:

public void CreatePyramid(int numObjects, int spawnAreaIndex)
{CreateObject(numObjects, pyramid, spawnAreaIndex);
}public void CreateStonePyramid(int numObjects, int spawnAreaIndex)
{CreateObject(numObjects, stonePyramid, spawnAreaIndex);
}void CreateObject(int numObjects, GameObject desiredObject, int spawnAreaIndex)
{for (var i = 0; i < numObjects; i++){// 生成金字塔,并且作为本物体的子物体var newObject = Instantiate(desiredObject, Vector3.zero,Quaternion.Euler(0f, 0f, 0f), transform);// 移动金字塔到指定位置PlaceObject(newObject, spawnAreaIndex);}
}

移动金字塔:

public void PlaceObject(GameObject objectToPlace, int spawnAreaIndex)
{// 生成区域的位置var spawnTransform = spawnAreas[spawnAreaIndex].transform;var xRange = spawnTransform.localScale.x / 2.1f;var zRange = spawnTransform.localScale.z / 2.1f;// 位置在范围内做一定的随机objectToPlace.transform.position = new Vector3(Random.Range(-xRange, xRange), 2f, Random.Range(-zRange, zRange))+ spawnTransform.position;
}

销毁所有的金字塔:

public void CleanPyramidArea()
{foreach (Transform child in transform)if (child.CompareTag("pyramid")){Destroy(child.gameObject);}
}

配置文件

配置1:

behaviors:Pyramids:trainer_type: ppohyperparameters:batch_size: 128buffer_size: 2048learning_rate: 0.0003beta: 0.01epsilon: 0.2lambd: 0.95num_epoch: 3learning_rate_schedule: linearnetwork_settings:normalize: falsehidden_units: 512num_layers: 2vis_encode_type: simplereward_signals:extrinsic:gamma: 0.99strength: 1.0curiosity:gamma: 0.99strength: 0.02network_settings:hidden_units: 256learning_rate: 0.0003keep_checkpoints: 5max_steps: 10000000time_horizon: 128summary_freq: 30000

相比于以往的设置,不同的地方在于奖励信号的设置多了一项Curiosity,也就是好奇心奖励信号,这个奖励信号在本项目中是必须的,通过给予奖励鼓励智能体在环境中探索新事物,这样才能使智能体在稀疏奖励的环境下顺利训练,其参数如下:

      curiosity:gamma: 0.99strength: 0.02network_settings:hidden_units: 256learning_rate: 0.0003

gamma:折扣因子,决定了未来奖励对于现在的状态及动作价值的影响程度。推荐:0.8-0.995。

strength:好奇心模块产生的奖励大小,应该设得足够大使其不被环境的奖励淹没,但也不能设得过大反过来淹没环境的奖励。推荐:0.001-0.1。默认为1。

hidden_units:好奇心网络的隐藏层节点个数。

learning_rate:学习率,用于更新好奇心模块,如果训练不稳定,应当减小。推荐:1e-5 - 1e-3。

对于Curiosity的具体讲解请查看:

李宏毅强化学习课程

强化学习——Intrinsic Curiosity Module

配置2:

behaviors:Pyramids:trainer_type: ppohyperparameters:batch_size: 128buffer_size: 2048learning_rate: 0.0003beta: 0.01epsilon: 0.2lambd: 0.95num_epoch: 3learning_rate_schedule: linearnetwork_settings:normalize: falsehidden_units: 512num_layers: 2vis_encode_type: simplereward_signals:extrinsic:gamma: 0.99strength: 1.0rnd:gamma: 0.99strength: 0.01network_settings:hidden_units: 64num_layers: 3learning_rate: 0.0001keep_checkpoints: 5max_steps: 3000000time_horizon: 128summary_freq: 30000

可以看到,第二种配置不同的地方在于没有使用Curiosity奖励机制,使用了另外一种奖励机制,它叫做Random Network Distillation,中文为随机网络蒸馏,简称RND。

      rnd:gamma: 0.99strength: 0.01network_settings:hidden_units: 64num_layers: 3learning_rate: 0.0001

其中参数的配置和Curiosity一致,多出一个可以调节的网络层数num_layers。

它和Curiosity一样,属于智能体自身的内部奖励,鼓励智能体积极探索。

运行效果:在100万个step过后智能体能够达到平均1.5以上的奖励。比Curiosity的训练速度要快很多。

详细信息请查看:

强化学习中的好奇心驱动学习算法:随机网络精馏探索技术

exploration by random network distillation

效果演示

后记

本文探究了在稀疏奖励的环境下,我们怎么让智能体更加有效地学习策略,这里我们采用了鼓励探索的方法,主要增加了基于好奇心(Curiosity)的奖励机制,以及基于随机网络蒸馏(Random Network Distillation)的奖励机制。ML-Agents提供了便利的参数设置,使得我们不用去实现那些复杂的网络结构,仅仅靠几行设置就能完美使用这个功能。我认为这种好奇心奖励机制的发展将是未来通用人工智能实现的重要一步。

ML-Agents案例之金字塔相关推荐

  1. Python技术栈与Spark交叉数据分析双向整合技术实战--大数据ML样本集案例实战

    版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客.QQ邮箱地址:1120746 ...

  2. ML-Agents案例之蠕虫

    本案例源自ML-Agents官方的示例,Github地址:https://github.com/Unity-Technologies/ml-agents,本文是详细的配套讲解. 本文基于我前面发的两篇 ...

  3. 热门 | Google Brain前员工深度盘点2017人工智能和深度学习各大动态

    翻译 | AI科技大本营 参与 | shawn 编辑 | Donna 2017年是人工智能井喷的一年.Google Brain团队前成员Denny Britz在自己的博客WILDML上对过去一年人工智 ...

  4. 人工智能/数据科学比赛汇总 2019.6

    内容来自 DataSciComp,人工智能/数据科学比赛整理平台. Github:iphysresearch/DataSciComp 本项目由 ApacheCN 强力支持. 微博 | 知乎 | CSD ...

  5. Unity红球吃绿球强化学习小任务——Ubuntu20.04系统于2022年2月26日实现

    Unity红球吃绿球强化学习小任务--Ubuntu20.04系统于2022年2月26日实现 Unity红球吃绿球强化学习小任务 一.主机环境参数说明 二.具体教程以之前提供的视频介绍为主,需要修改的章 ...

  6. Unity人工智能机器学习(环境安装篇)

    Unity人工智能学习,需要搭建一个机器学习的环境(Python环境和tensorboard) 使用Anaconda便可快速搭建 以下是汽车自动驾驶绕开障碍物的机器学习演示: 机器学习前: 机器学习训 ...

  7. 一文了解 2018年最火爆的30个机器学习项目

    机器学习是当前最为火爆的话题之一,机器学习的开源项目也层出不穷,让人目不暇接.本文从受欢迎程度方面,对比以及挑选出了去年发布的30个最火的机器学习项目. 下面,让我们一起来看看,2018年究竟有哪些机 ...

  8. 10个必备的机器学习开源工具

    机器学习十大开源工具 机器学习是未来.但机器会灭绝人类吗? 这应该是一个牵强附会的想法. 作为机器学习开发人员,您一定希望成功实现目标.这就是用于机器学习的开源工具的用武之地. 机器学习开源社区是活跃 ...

  9. 干货丨2017年AI与深度学习要点大全

    2017已经正式离我们远去~ ~ ~ 博客WILDML的作者.曾在Google Brain做了一年Resident的Denny Britz,就把他眼中的2017年AI和深度学习的大事,进行了一番梳理汇 ...

  10. 新年快乐!这是份值得收藏的2017年AI与深度学习要点大全

    若朴 夏乙 编译自 WILDML 量子位 出品 | 公众号 QbitAI 2017已经正式离我们远去. 过去的一年里,有很多值得梳理记录的内容.博客WILDML的作者.曾在Google Brain做了 ...

最新文章

  1. Selenium 爬虫时遇到的问题 Selenium message:session not created
  2. OpenCV的滤波与卷积
  3. 自己搭建mysql服务要知道的二三事
  4. 蓝桥杯 单点最短路径问题
  5. jquery环形3D立体旋转特效
  6. pads 文本不能修改_修改PDF文件很难?其实很简单,只是你少了一个好用的PDF编辑器...
  7. DB2建立不记录日志的表
  8. atitit 英文与中文与阿拉伯文的简化解决方案.docx
  9. java已知两坐标求直线长度_java计算两点间的距离方法总结
  10. 腾讯云支付系统架构介绍
  11. 华人“芯片女神”苏妈的硅谷传奇之路
  12. [网络安全自学篇] 七十八.XSS跨站脚本攻击案例分享及总结(二)
  13. python爬网站图片教程_Python超简单的爬取网站中图片
  14. 极米H5值得入手吗?极米H5实际体验如何?画面对比实测
  15. 为文字添加下划线和中划线
  16. vim 无法使用backspace 删除键进行删除
  17. 谷歌11亿美元买台企手机团队 对硬件有长远计划
  18. Linux压力测试工具—Siege命令
  19. pytorch——VGG网络搭建
  20. python清空字典保留变量方法,python关于字典的常用方法

热门文章

  1. Google Earth Engine APPS(GEE)—— Landsat 数据的时间序列分析来监测森林转化和退化 (CODED)整体框架(万字长文)
  2. AutoLisp从入门到放弃(十三)
  3. 菜鸟写Python-Pycharm执行Scrapy项目报:Scrapy-no active project 和(或)Unknown command: crawl错误
  4. c语言用后缀字母表示不同数制,C语言基础知识总结
  5. 跨考计算机 专硕还是学硕,考研我该如何抉择!专硕学硕不纠结
  6. nutch 抓取流程解析
  7. 主控芯片成功案例:搭载北京君正X1000芯片,收款计算合二为一
  8. python mkv转mp4,如何将mkv格式转换成mp4视频呢
  9. python求15 17 23 65 97的因数_Python练习题
  10. 使用示波器测量运放带宽和压摆率