RollerBall项目实战

1.设置 Unity 项目

要完成的第一项任务是创建一个新的 Unity 项目并将 ML-Agents Assets导入其中:

启动 Unity Editor 并创建一个名为“RollerBall”的新项目。

在你的文件系统中,找到包含您所克隆的 ML-Agents 代码仓库的文件夹。

将 ML-Agents 文件夹从 unity-environments/Assets 拖到 Unity Editor Project 窗口中(将ML-Agents-Master文件夹中的Asserts和ProjectSettings拷贝到项目文件夹中,选择覆盖。)。

您的 Unity Project 窗口应包含以下Assets:

2.创建环境:

接下来,我们将创建一个非常简单的场景来充当我们的 ML-Agents 环境。该环境的“physical”组件包括一个 Plane(充当 agent 移动的基础地板)、一个 Cube(充当 agent 寻找的目标)以及一个 Sphere(表示 agent 本身)。

创建地板平板:

在 Hierarchy 窗口中右键单击,选择 3D Object > Plane。
将游戏对象命名为“Floor”。
选择 Plane 以便在 Inspector 窗口中查看其属性。
将 Transform 设置为 Position = (0,0,0)、Rotation = (0,0,0)、Scale = (1,1,1)。
在 Plane 的 Mesh Renderer 上,展开 Materials 属性并将默认材质更改为 floor。(可自行选择与功能实现无关)
(要设置新材质,请单击当前材质名称旁边的小圆圈图标。此时将打开 Object Picker 对话框,然后便可从项目中当前所有材质的列表中选择不同的材质。)

添加目标立方体

在 Hierarchy 窗口中右键单击,选择 3D Object > Cube。
将游戏对象命名为“Target”
选择 Target 以便在 Inspector 窗口中查看其属性。
将 Transform 设置为 Position = (3,0.5,3)、Rotation = (0,0,0)、Scale = (1,1,1)。
在 Cube 的 Mesh Renderer 上,展开 Materials 属性并将默认材质更改为 block。(可自行选择)

添加 Agent 球体

在 Hierarchy 窗口中右键单击,选择 3D Object > Sphere。
将游戏对象命名为“RollerAgent”
选择 Target 以便在 Inspector 窗口中查看其属性。
将 Transform 设置为 Position = (0,0.5,0)、Rotation = (0,0,0)、Scale = (1,1,1)。
在 Sphere 的 Mesh Renderer 上,展开 Materials 属性并将默认材质更改为 checker 1。(可自行选择)
单击 Add Component。
向 Sphere 添加 Physics/Rigidbody 组件。(添加 Rigidbody)
在Assert搜索Behavior,并将BehaviorParamemeters脚本添加至Component。

添加空游戏对象来容纳 Academy 和 Brain

在 Hierarchy 窗口中右键单击,选择 Create Empty。
将游戏对象命名为“Academy”

您可以调整摄像机角度以便在运行时更好地查看场景。接下来的步骤是创建并添加 ML-Agent 组件。

实现 Academy

Academy 对象可在场景中协调 ML-Agents 并驱动模拟中的决策部分。每个 ML-Agent 场景需要一个 Academy 实例。由于 Academy 基类是抽象的,即使不需要对特定环境使用任何方法,您也必须创建自己的子类。

首先,将一个 New Script 组件添加到先前创建的 Academy 游戏对象:

选择 Academy 游戏对象以便在 Inspector 窗口中查看该对象。
单击 Add Component。
在组件列表中单击 New Script(位于底部)。
将该脚本命名为“RollerAcademy”。
单击 Create and Add。
接下来,编辑新的 RollerAcademy 脚本:

在 Unity Project 窗口中,双击 RollerAcademy 脚本,在代码编辑器中将其打开。(默认情况下,新脚本直接放置于 Assets 文件夹中。)
在编辑器中,将基类从 MonoBehaviour 更改为 Academy。
删除默认添加的 Start() 和 Update() 方法。
在这样的基本场景中,我们不需要 Academy 初始化、重置或以其他方式控制环境中的任何对象,因此我们采用最简单的 Academy 实现:

public class RollerAcademy : Academy
{public void AcademyReset(){}public void AcademyStep(){}
}

实现 Agent

要创建 Agent:

选择 RollerAgent 游戏对象以便在 Inspector 窗口中查看该对象。
单击 Add Component。
在组件列表中单击 New Script(位于底部)。
将该脚本命名为“RollerAgent”。
单击 Create and Add。
然后,编辑新的 RollerAgent 脚本:

在 Unity Project 窗口中,双击 RollerAgent 脚本,在代码编辑器中将其打开。
在编辑器中,将基类从 MonoBehaviour 更改为 Agent。
删除 Update() 方法。我们将使用 Start() 函数,所以暂时将其保留。
到目前为止介绍的这些,都是为了将 ML-Agents 添加到任何 Unity 项目而需要执行的基本步骤。接下来,我们将添加逻辑,让我们的 agent 能够使用 reinforcement learning(强化学习)技术学习滚动到立方体。

在这种简单的情况下,我们不使用 Academy 对象来控制环境。以前,如果我们想要改变环境,例如在模拟之前或模拟过程中更改地板的大小,或者添加或删除 agent以及其他物体,我们可以在 Academy 中实现相应的方法。但现在,我们会让 Agent 在成功或失败时完成对自己和目标进行重置的所有工作。

初始化和重置 Agent

agent 到达目标时会将自己标记为完成状态,而 agent 重置函数会将目标移动到随机位置。另外,如果 agent 从平台上滚下,重置函数会将其放回到地板上。

为了移动目标游戏对象,我们需要它的 Transform 对象的引用(这个对象中存储了游戏对象在 3D 世界中的位置、方向和比例)。要取得此引用,请将一个类型为 Transform 的公共字段添加到 RollerAgent 类中。Unity 中的组件的公共字段会显示在 Inspector 窗口中,允许您选择在 Unity Editor 中将哪个游戏对象用作目标。要重置 agent 的速度(并在稍后用力移动 agent),我们需要引用 Rigidbody 组件。Rigidbody 是 Unity 用于物理模拟的主要元素。(请参阅物理以查看 Unity 物理的完整文档。)由于 Rigidbody 组件与我们的 Agent 脚本位于同一个游戏对象上,因此取得此引用的最佳方式是使用 GameObject.GetComponent(),我们可以在脚本的 Start() 方法中调用它。

到目前为止,我们的 RollerAgent 脚本如下所示:

using System.Collections.Generic;
using UnityEngine;public class RollerAgent : Agent
{Rigidbody rBody;void Start () {rBody = GetComponent<Rigidbody>();}public Transform Target;public override void AgentReset(){if (this.transform.position.y < -1.0){// agent 掉落this.transform.position = Vector3.zero;this.rBody.angularVelocity = Vector3.zero;this.rBody.velocity = Vector3.zero;}else{// 将目标移动到新的位置Target.position = new Vector3(Random.value * 8 - 4,0.5f,Random.value * 8 - 4);}}
}

接下来,让我们实现 Agent.CollectObservations() 函数。

观测环境

Agent 将我们收集的信息发送给 Brain,由 Brain 使用这些信息来做决策。当您训练 agent(或使用经过训练的模型)时,数据将作为特征向量输入到神经网络中。为了让 agent 成功学习某个任务,我们需要提供正确的信息。为了决定要收集哪些信息,一个好的经验法则是考虑您在计算问题的分析解决方案时需要用到什么。

在我们的示例中,我们的 agent 收集的信息包括:

  • 目标的位置。一般来说,为了进行更一般化的训练,较好的做法是使用其他对象的相对位置而不是绝对位置。请注意,agent 仅收集 x 和 z 坐标,因为地板与 x-z 平面平行,并且目标位置的 y 分量不会改变。
// 计算相对位置
Vector3 relativePosition = Target.position - this.transform.position;// 相对位置
AddVectorObs(relativePosition.x / 5);
AddVectorObs(relativePosition.z / 5);
  • agent 本身在地板范围内的位置。收集此数据时收集的是 agent 与地板每个边的距离。
// 与平台边缘的距离
AddVectorObs((this.transform.position.x + 5) / 5);
AddVectorObs((this.transform.position.x - 5) / 5);
AddVectorObs((this.transform.position.z + 5) / 5);
AddVectorObs((this.transform.position.z - 5) / 5);
  • agent 的速度。这有助于 agent 学习去控制自己的速度,使其不会越过目标和从平台上滚下。
// Agent 速度
AddVectorObs(rBody.velocity.x / 5);
AddVectorObs(rBody.velocity.z / 5);

所有值都除以 5 可将神经网络的输入归一化到范围 [-1,1]。(因为平台的跨度为 10 个单位,所以使用数字 5。)

总的来说,状态观测结果包含 8 个值,当我们开始设置 Brain 属性时,我们需要使用连续状态空间:

List<float> observation = new List<float>();
public override void CollectObservations()
{// 计算相对位置Vector3 relativePosition = Target.position - this.transform.position;// 相对位置AddVectorObs(relativePosition.x/5);AddVectorObs(relativePosition.z/5);// 与平台边缘的距离AddVectorObs((this.transform.position.x + 5)/5);AddVectorObs((this.transform.position.x - 5)/5);AddVectorObs((this.transform.position.z + 5)/5);AddVectorObs((this.transform.position.z - 5)/5);// Agent 速度AddVectorObs(rBody.velocity.x/5);AddVectorObs(rBody.velocity.z/5);
}

Agent 代码的最后一部分是 Agent.AgentAction() 函数,此函数接收 Brain 的决策。

动作

Brain 的决策以动作数组的形式传递给 AgentAction() 函数。此数组中的元素数量由 agent 的 Brain 的 Vector Action Space Type 和 Vector Action Space Size 设置确定。RollerAgent 使用连续向量运动空间,并需要 Brain 提供的两个连续控制信号。因此,我们要将 Brain Vector Action Size 设置为 2。第一个元素 action[0] 确定沿 x 轴施加的力;action[1] 确定沿 z 轴施加的力。(如果我们允许 agent 以三维方式移动,那么我们需要将 Vector Action Size 设置为 3。)注意,Brain 并不知道动作数组中的值是什么意思。训练过程只是根据观测输入来调整动作值,然后看看会得到什么样的奖励。

RollerAgent 使用 Rigidbody.AddForce 函数将 action[] 数组中的值应用到其 Rigidbody 组件 rBody:

Vector3 controlSignal = Vector3.zero;
controlSignal.x = Mathf.Clamp(action[0], -1, 1);
controlSignal.z = Mathf.Clamp(action[1], -1, 1);
rBody.AddForce(controlSignal * speed);

agent 将动作值限制在 [-1,1] 范围内,原因有两个。首先,学习算法对于尝试非常大的值的动机较小(因为不会对 agent 行为产生任何影响),这样可以避免神经网络计算中出现数值不稳定的问题。其次,我们没有在别的地方采取措施阻止神经网络返回过大的值,所以我们希望在任何情况下都将它们限制在合理的范围内。

奖励

Reinforcement learning(强化学习)需要奖励。应在 AgentAction() 函数中分配奖励。学习算法使用在模拟和学习过程的每个步骤中分配给 agent 的奖励来确定是否为 agent 提供了最佳动作。您会希望 agent 完成分配的任务(在此情况下是指到达目标立方体)时奖励 agent,而在 agent 彻底失败(掉下平台)时惩罚 agent。有时,您可以通过一些子奖励来鼓励帮助 agent 完成任务的行为,从而加快训练速度。例如,如果 agent 在某个步骤中靠近目标,则 RollerAgent 奖励系统会提供小奖励,并会在每个步骤提供很小的负奖励来促使 agent 快速完成其任务。

RollerAgent 会计算到达目标所需的距离。当到达目标时,代码将 Agent.reward 变量增加 1.0,并通过将 agent 设置为 done 来将 agent 标记为完成。

float distanceToTarget = Vector3.Distance(this.transform.position,Target.position);
// 已到达目标
if (distanceToTarget < 1.42f)
{Done();AddReward(1.0f);
}

**注意:**当您将 agent 标记为完成状态时,它将停止活动,直到重置为止。您可以通过设置 Inspector 中的 Agent.ResetOnDone 属性, 以便当它被标记为完成状态时,立即重置 agent。你也可以等待 Academy 自己重置环境。本教程中的 RollerBall 环境的重置依赖于 ResetOnDone 机制,并且我们目前没有为 Academy 设置 Max Steps 限制,在这样的条件下 Academy 绝不会自己重置环境。

为了鼓励 agent 继续往前,我们还要在它进一步接近目标时提供奖励(保存先前的步距测量值):

// 进一步接近
if (distanceToTarget < previousDistance)
{AddReward(0.1f);
}

此外还可以为了鼓励 agent 更快完成任务而在每个步骤中分配负奖励:

// 时间惩罚
AddReward(-0.05f);

最后,为了惩罚 agent 掉下平台,会为它分配一个大的负奖励,不仅如此,当它掉下平台后,我们还要将 agent 设置为完成状态,以便它在下一步重置自己:

// 掉下平台
if (this.transform.position.y < -1.0)
{Done();AddReward(-1.0f);
}
AgentAction()

利用上面列出的动作和奖励逻辑,AgentAction() 函数的最终版本如下所示:

public float speed = 10;
private float previousDistance = float.MaxValue;public override void AgentAction(float[] vectorAction, string textAction)
{// 奖励float distanceToTarget = Vector3.Distance(this.transform.position,Target.position);// 已到达目标if (distanceToTarget < 1.42f){Done();AddReward(1.0f);}// 进一步接近if (distanceToTarget < previousDistance){AddReward(0.1f);}// 时间惩罚AddReward(-0.05f);// 掉下平台if (this.transform.position.y < -1.0){Done();AddReward(-1.0f);}previousDistance = distanceToTarget;// 动作,大小 = 2Vector3 controlSignal = Vector3.zero;controlSignal.x = Mathf.Clamp(vectorAction[0], -1, 1);controlSignal.z = Mathf.Clamp(vectorAction[1], -1, 1);rBody.AddForce(controlSignal * speed);}

请注意函数之前定义的 speed 和 previousDistance 类变量。由于 speed 是公共变量,您可以从 Inspector 窗口中设置该值。

最终 Editor 设置

现在,所有游戏对象和 ML-Agent 组件都已准备就绪,因此可以在 Unity Editor 中将一切串起来了。这包括将 Behavior 对象分配给 Agent,并设置 Behavior 属性,使这些属性与我们的 agent 代码兼容。

将 Target 游戏对象从 Hierarchy 窗口拖到 RollerAgent 的 Target 字段。

最后,选择 Agent 游戏对象以便能够在 Inspector 窗口中查看该对象的属性。点开Behavior下拉菜单设置以下属性:

Vector Observation Space Size = 8
Vector Action Space Type = Continuous
Vector Action Space Size = 2

至此训练之前的准备工作已经完成。接下去开始训练

开始训练

注意*:一定要把UseHeuristic选项的钩给去了在训练
打开控制台
进入ml-agent-master文件夹(使用cd进入,cd …退出);
运行以下命令:

mlagents-learn config/trainer_config.yaml --run-id=RollerBall --train

执行完以上命令,出现 INFO:mlagents.envs:Start training by pressing the Play button in the Unity Editor. 即可回到

Unity 中,点击 Play 运行场景

训练完毕后会在当前目录下生成一个二进制文件。将其拖入工程项目的Assert文件夹,同步更新项目,将这个文件放入BehaviorParameters的Model上,点击运行即可看到训练好的小球AI。

ML-Agents学习之RollerBall项目相关推荐

  1. 机器学习框架ML.NET学习笔记【1】基本概念与系列文章目录

    一.序言 微软的机器学习框架于2018年5月出了0.1版本,2019年5月发布1.0版本.期间各版本之间差异(包括命名空间.方法等)还是比较大的,随着1.0版发布,应该是趋于稳定了.之前在园子里也看到 ...

  2. 《ML Papers Explained》开源项目!

    Datawhale干货 方向:机器学习,编辑:AI科技评论 机器学习领域的研究进展迅速,研究者既要及时跟进最新研究,也要不时地回顾经典.寒假开始,各位机器学习er在度假之余,想必也不会忘了自己卷王的身 ...

  3. 如何用 Python 进行基于深度学习的计算机视觉项目开发?

    令人惊喜的"智能"年代 深度学习有着广阔的前景 我们正处在一个"智能"的年代,比如智能手机中的语音助手.机器翻译和人脸识别:战胜过日本将棋冠军.国际象棋冠军, ...

  4. No module named MNIST_写给小白的用fashion-mnist入门机器学习和深度学习的简单项目(非常全面!!!)...

    这是一个入门机器学习和深度学习的小项目,以fashion-mnist数据为基础.分别利用机器学习(随机森林)和深度学习(多层感知机/卷积神经网络)方法进行训练.完整的包含数据读取,数据处理,训练, 验 ...

  5. 【AI初识境】给深度学习新手开始项目时的10条建议

    这是专栏<AI初识境>的第12篇文章.所谓初识,就是对相关技术有基本了解,掌握了基本的使用方法. 在成为合格的深度学习算法工程师,尤其是工业界能够实战的调参选手之前,总会踏足很多的坑. 今 ...

  6. 学习机器学习的项目_辅助项目在机器学习中的重要性

    学习机器学习的项目 提示与建议 (Tips and Advice) There are a few questions that are asked frequently by machine lea ...

  7. springcloud gateway ribbon使用_Github点赞接近 70k 的Spring Cloud学习教程+实战项目推荐!牛批!...

    这篇文章继续来推荐 Spring Cloud 的教程和实战项目了!想必不用不多说,大家都知道 Spring Cloud 的重要程度.几乎稍微有点规模的公司,一般都离不开要和微服务打交道.同时,Spri ...

  8. 学习Coding-iOS开源项目日志(二)

    继续前篇:<学习Coding-iOS开源项目日志(一)>,接着本第二篇<学习Coding-iOS开源项目日志(二)>讲解Coding-iOS开源项目. 前言:作为初级程序员,想 ...

  9. 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)

    一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...

最新文章

  1. Matlab与线性代数 -- 矩阵的右除
  2. java上机练习01
  3. netcat nc端口监听 反向连接中断问题
  4. Linux网络编程 之 无连接和有连接通信(二)
  5. task.run 强制结束线程_图文介绍进程和线程的区别
  6. 转:ReLU激活函数:简单之美
  7. 时间日期、查找、压缩类
  8. 【Django 2021年最新版教程17】数据库操作 models 存在更新 不存在新建update_or_create
  9. 查看Linux root disk,linux查看硬盘4K对齐方法
  10. 【0基础运筹学】【超详细】列生成(Column Generation)
  11. 关于 FAT12 文件系统
  12. word使用过程中遇到的问题记录(二):如何画柱状图和折线图的组合图?
  13. 视频流调试过程(海康威视+Kurento)
  14. Juniper JNCIS-ER jn0-350 148Q
  15. 量子力学之电子自旋与四个量子数
  16. 何为 Token?什么是基于 token 的认证?
  17. 解决 输入kubectl get pods -o wide后没有显示ip
  18. unity3d 人物对话_unity3d实现插件快速开发对话系统
  19. 隐私保护计算技术指南-1
  20. AI Studio vLoong能源AI挑战赛——异常检测赛A榜第三名方案

热门文章

  1. 手机计算机怎么玩24点游戏,计算器游戏怎么玩_计算器游戏新手玩法介绍_快吧手游...
  2. 前非著名程序员,现不知名产品人
  3. 向上沟通2-冰山理论
  4. Lambda表达式到底是什么?——简单了解Lambda表达式
  5. 【Javaweb】TCP原理(三次握手四次挥手)
  6. Women in Tech | 关于职业与成长,她们给人奋进的启发和动力
  7. h5跳转微信小程序,短信外链外部跳转微信打开任意第三方网址url,抖音跳转微信添加好友直接方法?
  8. 【27】grad-cam的简单逻辑实现以及效果展示
  9. 处理机和CPU的区别
  10. Documentation/timers/hpet.txt