Notifications
Article
【ML-Agent】使用机器学习来做一个 RollBall 吧 !🤪
Published 7 months ago
1.6 K
24
🧐 ml-agent 极简“Hello World”项目,一起来试试有趣的机器学习吧🧠
前置学习: Ml-Agent环境搭建 (必看) 在 Unity 中使用 YAML 文件保存数据 (选看) 前言 + 吐槽: 本文使用的是 0.11.0 版本,使用高版本会出现错误。😣( 初写本文时用的是 0.10.0 刚写完就发现版本更新,本着用新版本的原则我就重写了一次,然后刚刚我发现又更新了!,这谁顶得住,一周刷了俩次版本号🤦‍♂️🤦‍♂️)
这篇文章我们可以学到如何制作一个机器学习版的滚动的小球,我们要训练一个小球让它自己滚到方块的位置,同时还要学会避免从平台上掉下去。

创建一个训练环境

现在我们来搭建一个最简单的训练环境我们需要以下三种脚本:
  1. 至少一个 Agent 脚本
  2. 每个 Agent 一个 Behavior Parameters 脚本
  3. 一个 Academy 脚本
Agent 也就是我们的 “机器人”,它通常放在一个 GameObject 上用来生成这个物体的观测结果、执行动作、分配奖励。
Behavior Parameters 用来设置 Agent 的行为、观测方式、要使用的模型、以及设置推理引擎。
Academy 用来协调 Agent 的观测与决策过程。在 Academy 中可以指定一些环境的参数,比如渲染质量等。 External Communicator 就位于 Academy 中。(External Communicator 是用来将 Unity 环境与 Python 的 API 联系起来)
基础知识就先补充到这里,我们来搭建场景:
Academy:
创建一个空物体,将它命名为 Academy 然后为它创建一个脚本命名为 “Roller Academy” 继承 Academy 类:
using MLAgents; public class RollerAcademy : Academy { }
Agent:
创建一个球体,将它命名为 Agent 然后为它创建一个脚本命名为 “Roller Agent” 并继承 Agent 类:
using MLAgents; public class RollerAgent : Agent { }
然后给 Agent 添加一个组件 “Behavior Parameters” , 顺便你也可以挑选一个喜欢的颜色让他看起来不那么单调,这里我选择了黄色。
最后给 Agent 添加 Rigidbody 组件,因为我们一会要控制它行动:
至此我们的 ML-Agent 基本骨架已经搭建完成,不过如果想让它有目的的动起来我们还缺少一些东西:
Floor :
创建一个平面,将它重命名为 Floor,用来承载我们的小球和目标方块。当然你同样可以选择一个好看的材质赋予它。
Target:
创建一个立方体,命名为 Target ,一会我们就要训练小球来追踪这个小方块。这里我同样选给它换上了一个"红色的衣服",这样更像是官方案例( RollBall )中的小方块。
最后我们把 地板、小球、目标,这三个物体设置为 Academy 的子物体:
这里要注意下它们三者的坐标,需要把 小球 和 目标 的 Y 坐标提高 0.5 它们才能正常的生成在地板的上面。顺便说一句,它们的命名、颜色与功能无关,你可以将它们改成随便你喜欢的名字比如小红、小黄等,不过我建议你最好用英文。

编写 Agent 代码:

先设置我们需要用到的变量:
public class RollerAgent : Agent { public Transform target; // 目标的位置 public float speed; // Agent 的移动速度 private Rigidbody _rigidbodyr; // Agent 的刚体组件 }
初始化 :
private void Start() { _rigidbodyr = GetComponent<Rigidbody>(); }
重写 Agent 的一些函数,这里我先说一下在 Agent 中几个关键函数的用处:
1. AgentReset : 一次训练后如何重置环境。
2. AgentAction : 执行大脑传递回的行为,在这个函数中控制 Agent 的行为以及根据行为给予 Agent奖励。
3. SetReward : 给予 Agent 奖励。
4. CollectObservations : 给大脑传递当前 Agent 的观测的所有数据。AddVectorObs 函数通常写在这个函数中。
5. AddVectorObs : 添加一个要传递给大脑的观测数据。
6. Done : 一次训练结束前调用,比如小球掉下平台。如果要销毁 Agent 必须在销毁前调用次方法。
7. Heuristic : 这个函数允许我们通过键盘来手动控制 Agent ,当我们写好一个 Agent 后可以用这个函数来手动测试行为是否正常。
现在我们来完成 Roller Agent 脚本 :
using MLAgents; using UnityEngine; public class RollerAgent : Agent { public Transform target; public float speed; private Rigidbody _rigidbodyr; private void Start() { _rigidbodyr = GetComponent<Rigidbody>(); } public override void AgentReset() { if (this.transform.localPosition.y < 0) { // 小球掉下去后重置小球 _rigidbodyr.angularVelocity = Vector3.zero; _rigidbodyr.velocity = Vector3.zero; transform.localPosition = new Vector3( 0, 0.5f, 0); } // 让 Target 随机移动到一个点 var rValueX = (Random.value * 8) - 4; var rValueZ = (Random.value * 8) - 4; target.localPosition = new Vector3(rValueX, 0.5f, rValueZ); } public override void CollectObservations() { // Target 和 Agent 的位置 AddVectorObs(target.localPosition); AddVectorObs(transform.localPosition); // Agent 的速度,检测是否掉下去 AddVectorObs(_rigidbodyr.velocity.x); AddVectorObs(_rigidbodyr.velocity.z); } public override void AgentAction(float[] vectorAction, string textAction) { // 接受大脑传递的行为 print(vectorAction[2]); var controlSignal = Vector3.zero; controlSignal.x = vectorAction[0]; controlSignal.z = vectorAction[1]; _rigidbodyr.AddForce(controlSignal * speed); // 算出 Agent 和 Target 的距离 var distanceToTarget = Vector3.Distance(transform.localPosition, target.localPosition); // 根据距离来判断是否碰撞到 Target 然后给出奖励 if (distanceToTarget < 1.5f) { SetReward(1.0f); Done(); } // 掉下去平台 if (transform.localPosition.y < 0) { Done(); } } //手动测试 public override float[] Heuristic() { var action = new float[2]; action[0] = Input.GetAxis("Horizontal"); action[1] = Input.GetAxis("Vertical"); return action; } }
现在我们的所有脚本都已经编写完毕,我在本代码中坐标使用局部坐标,原因是可能未来我们会在一个场景放置多个训练环境为了预防出错,当然这都是后话本文中不会涉及只有一个训练环境的话使用全局坐标也不会出问题。

在 Editor 中完成 Agent 设置

  • - Behavior Name 可以随便起
  • - Behavior Observation / Space Size 设置为 8 ,因为我们刚刚在代码中观测了 8 个数据( targer.position + agent.position + rigidbody.x + rigidbody.z = 3 + 3 + 1 +1 = 8 )
  • - 设置 Vector Action / Space Type 为 Continuous
  • - 设置 Vector Action / Space Size 为 2
  • - Inference Device 设置为 CPU ,如果部观测图片的话设置为 CPU 会更快一些
  • - 如果想要使用 Heuristic 函数进行手动操作必须要勾选这个复选框
  • - 设置 Decision Interval 为 10 ,这个是决策间隔设置越长越慢
  • - 设置 Target
  • - 设置 Agent 速度

开始训练模型

打开 ML-Agent 的安装目录进入 config 文件下 :
创建一个 YAML 格式的文件,我将它命名为 config 你们可以根据自己的用途来命名。( 如果想了解更多关于 YAML 文件的用法可以参考我上一篇文章 )
然后将 trainer_config 文件的 default 复制过来,修改三个参数:
batch_size: 10 buffer_size: 100 # 必须为 batch_size 的整数倍 max_steps : 3.0e4 # 训练步数 30000 步
然后打开 Miniconda 激活环境 切换到安装 ml-agent 的目录输入命令:
mlagents-learn config/config.yaml --run-id=RollerBall-0 --train
  • - config 这个文件按你刚刚命名的方式来
  • - run-id 后面设置这次训练出来的模型的名字可以随意设置
输入命令后等待他运行,直到出现这个画面后在编辑器中点击 Play 按钮 ▶
接下来就是漫长的挂机时间,20000 步的话普通笔记训练差不多要用十分钟左右。等训练完毕后我们可以在 ML-agent 的安装目录下找到 models 文件夹 在文件夹下有你的所有训练文件:
这里我已经训练过很多个版本了,然后继续打开文件夹找到 .nn 文件:
这个文件就是我们最终的训练结果,只要将这个文件放入 Agent 的 Behavior Parameters 组件的 Model 选项中我们的小球就可以正常运行了~
最终成果 :
😋 如果你觉得本文还不错,请点个赞👍让我知道 ~
超级汽水
超级热爱 - Student
14
Comments
黑白灰
5 months ago
非常还的教程👍
0
3万训练完了,报酬 那里一直没啥变化,请问是什么原因造成的 谢谢
0
Unity社区
Staff
6 months ago
Hunter非常好的教程,很细致。非常棒的开发者, 希望多出内容。 加油加油!
@Hunter 感谢支持中文原创,恭喜获得新年开运大礼包,收货地址私信我哦~
1
H
Hunter
6 months ago
非常好的教程,很细致。非常棒的开发者, 希望多出内容。 加油加油!
1
王刚
7 months ago
超级汽水🤣 这个东西其实并不是越多越好,你参数调节小一点多试几次。只要你的奖励机制没问题这种简单的场景效果都很好的
那可以调节哪些参数呢?还有config.yaml文件一些其他参数含义以及应用能讲一下吗
0