0. 资料来源

官方Github文档: https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Learning-Environment-Create-New.md

请添加图片描述

1. 基础准备

完成 Unity (2023.2.13f1) 版本的安装 与 ML Agents 和 ML Agents Extensions 包的安装,Ubuntu系统的可参考我之前发表的博客:
https://blog.csdn.net/CDSN985144132/article/details/145768687?sharetype=blogdetail&sharerId=145768687&sharerefer=PC&sharesource=CDSN985144132&spm=1011.2480.3001.8118

① 但是如果需要自己写脚本,Ubuntu 需要自行解决 VSCode 安装 C# 语言的问题,WIndows 安装 Unity 时可以选装 Visual Studio插件。

② 目前 MAC 和 Linux 的 Unity Editor 仍然不支持UI字体变大。。。

※ 因为以上两个原因,我目前弃坑 Ubuntu 的 Unity,回到 Windows 设备上,大家慎重考虑。

以下是客服的回答:
请添加图片描述

2. 创建Unity项目并进行图像界面的操作

2.1 新建项目 并 确认包(坑超多!注意Unity版本,项目创建位置)

2.1.1 在Unity Hub(2023.2.13f1) 中的 官方Examples所在位置 创建新3D项目,命名为RollerBall。

① 必须是 Unity Hub(2023.2.13f1) 版本,因为官方的Examples是在此版本中建立,别的版本不一定能打开。我没找到(2023.2.13f1),所以装了(2023.2.13f1c1),igrone版本区别也可运行,目前没报错。
官方的各种版本安装链接如下:
https://unity.com/releases/editor/archive
尽量使用 Unity Hub 安装,如果提示无法安装,可退出 Hub ,以管理员运行,重复操作可成功。我将Windows相关的插件、Visual Studio都装上了。

② 位置为 (你的ml-agents文件夹克隆位置)\ml-agents\Project\Assets\ML-Agents\Examples,点Create projects。
※ 不在官方的Examples位置创建,会导致一堆报错,已踩坑。

请添加图片描述

2.1.2 在Packages窗口中确保有 ML Agents 和 ML Agents Extensions 包,如无则点“+”从本地安装,具体可看以下链接的第6点:

https://blog.csdn.net/CDSN985144132/article/details/145768687?sharetype=blogdetail&sharerId=145768687&sharerefer=PC&sharesource=CDSN985144132&spm=1011.2480.3001.8118

请添加图片描述

2.1.3 在左下角的 Project 中确认有 ML Agents 和 ML Agents Extensions

请添加图片描述

2.1.4 放大Unity UI界面字体(仅支持 windows )(非官方步骤,不需要可跳过)

※ 仅支持 windows ,Ubuntu 无UI Scaling功能(官方确认),可统一更改应用显示百分比,但切换其他应用会很难受
① 上方菜单栏 → Edit → Preferences → UI Scaling 箭头,去掉方框中的勾选,改百分比,如下图:

请添加图片描述

2.2 创建基础环境

2.2.1 添加地板(Floor)

① 右键Hierarchy(层次结构)窗口 → 3D Object → Plane,重命名为Floor。
② 设置位置为(0, 0, 0),缩放为(1, 1, 1)。

在这里插入图片描述

2.2.2 添加目标立方体(Target)

① 右键Hierarchy窗口 → 3D Object → Cube,重命名为Target。
② 设置位置为(3, 0.5, 3),缩放为(1, 1, 1)。

请添加图片描述

2.2.3 添加Agent小球(RollerAgent)

① 右键Hierarchy窗口 → 3D Object → Sphere
② 重命名为RollerAgent。
③ 设置位置为(0, 0.5, 0),缩放为(1, 1, 1)。
④ 单击“Add Component”。
⑤ 搜索添加 Rigidbody 组件(用于物理模拟)。

请添加图片描述

2.2.4 集合进入训练区

① 右键Hierarchy窗口 → Create Empty
② 重命名为TrainingArea。
③ 右边Inspector窗口→Transform框右上角三点→Reset
④ 确保 Position:(0,0,0)Rotation:(0,0,0)Scale:(1,1,1)
⑤ 将Floor、Target、RollerAgent拖入TrainingArea下。

请添加图片描述

3. 新建代理脚本 并 连接 Visual Studio

3.1 创建代理脚本

① 选择 RollerAgent 游戏对象以在 Inspector 窗口中查看它。
② 单击“Add Component”→滑到底部“New Script”,重命名为"RollerAgent"→点击“Create and Add”。

请添加图片描述

③ 添加完成后如图,会出现在“Projects”的“Assets”中,双击即可编辑:

请添加图片描述

3.2 unity 连接 Visual Studio 进行 C#脚本编写:(非官方步骤,但建议操作,在 VS 中有代码提示)

参考以下 CSDN 链接:

https://blog.csdn.net/xks18232047575/article/details/134545094

① 完成连链接后,双击对应脚本,即可进入 Visio Studio 界面。
② 上方“工具”→“选项”→“常规”→“颜色主题”→“深色” (个人编码习惯深色界面)

请添加图片描述

4. 编辑脚本

4.1 完整的 RollerAgent.cs脚本,可直接取用,复制代码,保存即可

先上完整代码+超详细注释(可直接阅读,带一些C#知识点,已加入步骤6的键盘测试代码),具体的分段解释可自行查看官方解释:
https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Learning-Environment-Create-New.md

// 引入必要的程序包(类似工具箱)
using System.Collections;        // 基础系统工具(虽然本例未直接使用,但保留无害)
using System.Collections.Generic; // 列表等数据结构工具(本例未直接使用)
using UnityEngine;               // Unity引擎核心功能
using Unity.MLAgents;           // ML-Agents机器学习框架核心
using Unity.MLAgents.Sensors;   // 用于Agent的观察功能
using Unity.MLAgents.Actuators; // 新增的命名空间

// 定义RollerAgent类,继承自Agent基类(冒号表示继承)
public class RollerAgent : Agent // 类名必须与文件名一致
{
    // 【字段声明】
    // Rigidbody类型变量:用于物理模拟的刚体组件
    // private表示仅本类可以访问(未写修饰符时默认为private)
    Rigidbody rBody;

    // public表示可以在Unity编辑器中设置,Transform类型存储物体的位置/旋转/缩放信息
    public Transform Target;     // 目标物体的位置信息

    // float表示浮点数(带小数),public变量会显示在Unity Inspector面板
    public float forceMultiplier = 10; // 控制移动力度的放大系数

    // Start方法:Unity的初始化函数,在对象创建后第一帧更新前调用
    void Start()
    {
        // GetComponent<类型>() 获取当前物体上的指定类型组件
        // 这里获取Rigidbody组件并赋值给rBody变量
        rBody = GetComponent<Rigidbody>();
    }

    // OnEpisodeBegin方法:ML-Agents的重写方法,每个训练回合开始时调用
    public override void OnEpisodeBegin()
    {
        // 判断代理的Y轴位置是否小于0(掉下平台)
        // transform是当前物体的Transform组件,localPosition是局部坐标位置
        if (this.transform.localPosition.y < 0) // this可省略,表示当前实例
        {
            // 重置物理状态
            rBody.angularVelocity = Vector3.zero; // 角速度归零
            rBody.velocity = Vector3.zero;        // 线性速度归零
            // 重置位置到平台中心(0,0.5,0),Y=0.5因为球体半径是0.5
            this.transform.localPosition = new Vector3(0, 0.5f, 0);
        }

        // 设置目标物体的新位置:
        // Random.value返回0-1的随机数,8-4的操作使范围变为-4到+4
        // 保持Y轴0.5(立方体高度为1,放在平台表面)
        Target.localPosition = new Vector3(
            Random.value * 8 - 4, // X轴:-4到4
            0.5f,                 // Y轴固定
            Random.value * 8 - 4  // Z轴:-4到4
        );
    }

    // CollectObservations方法:收集环境观察数据供AI学习
    public override void CollectObservations(VectorSensor sensor)
    {
        // 添加目标位置观察(3个浮点数:x,y,z)
        sensor.AddObservation(Target.localPosition); // 加入观察列表

        // 添加代理自身位置观察(3个浮点数)
        sensor.AddObservation(this.transform.localPosition);

        // 添加速度观察(只需要x和z轴,y轴速度不影响平面移动)
        sensor.AddObservation(rBody.velocity.x); // X轴速度
        sensor.AddObservation(rBody.velocity.z); // Z轴速度
        // 总观察值数量 = 3 + 3 + 2 = 8
    }

    // OnActionReceived方法:处理AI决策的动作输入
    public override void OnActionReceived(ActionBuffers actionBuffers)
    {
        // 从动作缓冲区获取连续动作(AI的输出)
        // ActionBuffers包含离散和连续动作,这里用连续动作[0]和[1]
        Vector3 controlSignal = Vector3.zero; // 初始化三维向量(0,0,0)
        controlSignal.x = actionBuffers.ContinuousActions[0]; // 第一个动作控制X轴
        controlSignal.z = actionBuffers.ContinuousActions[1]; // 第二个动作控制Z轴

        // 应用力到刚体(ForceMode默认为Force,持续施加力)
        rBody.AddForce(controlSignal * forceMultiplier);

        // 计算与目标的距离(使用三维空间距离公式)
        float distanceToTarget = Vector3.Distance(
            this.transform.localPosition,
            Target.localPosition
        );

        // 判断是否到达目标(1.42是经验值,因为立方体对角线≈1.414)
        if (distanceToTarget < 1.42f)
        {
            SetReward(1.0f);  // 给予1分奖励
            EndEpisode();     // 结束当前回合
        }
        // 如果掉下平台(Y坐标小于0)
        else if (this.transform.localPosition.y < 0)
        {
            EndEpisode(); // 结束回合(不给奖励)
        }
    }
    
    // 在训练期间或调试时,通过键盘输入手动控制代理的行为
    public override void Heuristic(in ActionBuffers actionsOut)
    {
        var continuousActionsOut = actionsOut.ContinuousActions;
        continuousActionsOut[0] = Input.GetAxis("Horizontal");
        continuousActionsOut[1] = Input.GetAxis("Vertical");
    }
}

5. Unity Editor 中最后的 Agent 设置

5.1 将 Target 拖动到 Roller Agent (Script)的 Target 栏目中

① 先点击 Hierarchy 的 RollerAgent,如图左红框。看右边的 Inspector 窗口,如右图红框。
② 往下拉 看到 Roller Agent (Script)栏目中的Target,可以直接点击右边的选项选择 Target。
③ 但我们按官网的文字来操作:拖动 左边蓝色椭圆框的 Target 到 Roller Agent (Script)中的Target,完成关联。
※ 这一步的目的就是建立具体对象对代码中的的 Target 的关联

请添加图片描述

5.2 添加 Decision Requester ,设置 Decision Period

① Decision Requester 使用 Add Component 按钮添加,在 Ml-Agent 选项中。
② 添加后,将 Decision Period 设置为10。

请添加图片描述

5.3 添加 Behavior Parameters 并设置参数

① 官方说需要手动添加,但我是直接有这个 Component 的。
② 如果没有,则使用 Add Component 按钮添加 Behavior Parameters ,在 Ml-Agent 选项中。
③ 添加后,如红框中的设置如图。

请添加图片描述

6. 添加测试代码,已添加在步骤 4 中的完整代码末尾

6.1 使用方向键控制小球运动,确保其他设置正常

① 需要扩展类 Heuristic() 中的方法RollerAgent。
② 代码如下,放在步骤 4 中的完整代码末尾:

public override void Heuristic(in ActionBuffers actionsOut)
{
    var continuousActionsOut = actionsOut.ContinuousActions;
    continuousActionsOut[0] = Input.GetAxis("Horizontal");
    continuousActionsOut[1] = Input.GetAxis("Vertical");
}

6.2 进行测试

① 将 Behavior Type 设置为 Heuristic Only,即刚刚新写的 Heuristic()类。
② 点击上方的 播放 按钮。

请添加图片描述

③ 使用 键盘方向键 控制小球运动,按上方暂停键可结束测试。

请添加图片描述

7. 设置训练超参数

① 在 ml-agents 文件夹下找到 config 文件夹,用 windows 系统自带的 记事本 新建 rollerball_config.yaml 文件,将 txt 扩展名改为 yaml 即可。
② 文件内容如下,可以先不改动完成教程,后续根据自己的需求改动:

behaviors:
  RollerBall:
    trainer_type: ppo
    hyperparameters:
      batch_size: 10
      buffer_size: 100
      learning_rate: 3.0e-4
      beta: 5.0e-4
      epsilon: 0.2
      lambd: 0.99
      num_epoch: 3
      learning_rate_schedule: linear
      beta_schedule: constant
      epsilon_schedule: linear
    network_settings:
      normalize: false
      hidden_units: 128
      num_layers: 2
    reward_signals:
      extrinsic:
        gamma: 0.99
        strength: 1.0
    max_steps: 500000
    time_horizon: 64
    summary_freq: 10000

③ 超参数设置来源于官网教程:
https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Learning-Environment-Create-New.md
④ 超参数详解文档官网链接:
https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Training-Configuration-File.md

8. 在终端中运行训练命令:

※ 官网没说,但有大坑,据我测试,需要对步骤6.2中的 Behavior Type 作如下修改:

① 将 Inference Device 从 Default 改为 Computer Shader (有的版本可能显示 CPU),即用 CPU 进行训练的意思。对照官方教程图(白色底色为官方教程图)可发现。

② 将Behavior Type 改为 Default,这个相对好理解,因为刚刚的测试选用了键盘控制 “Heuristic Only”。

在这里插入图片描述
请添加图片描述

③ 在终端打开 mlagents 所在的环境,打开 ml-agents 的文件夹,运行以下训练代码:

mlagents-learn config/rollerball_config.yaml --run-id=RollerBall

④ 正常情况会显示如下:

请添加图片描述

⑤ 点击 Unity Editor 中的 “play” 按钮,即可看到小球开始自动运行。
※ 大家可能留意到,我的代码末尾多了 “ --force”,这是由于每一次训练都需要对应一个新的id号,我前面操作失败了,id被占用了,所以加 “ --force”时强制覆盖的意思。

请添加图片描述

⑥ 看到小球自动运行基本就正式进入训练了,过一会就可以看到 Info 如下:
关注 Step 步数到达步骤7中设置的max_steps: 500000,
关注 Mean Reward 平均奖励接近 1 则成功,也可以手动 “Ctrl + C” 结束训练。

请添加图片描述

9. 打开 TensorBoard 实时查看训练数据:

TensorBoard 使用教程及参数讲解官方链接:
https://github.com/Unity-Technologies/ml-agents/blob/develop/docs/Using-Tensorboard.md

① 打开新的 cmd终端窗口,打开所在虚拟环境,打开到 ml-agents 的文件夹。
② 运行以下命令:

tensorboard --logdir results

③看到以下输出:

请添加图片描述

④ 打开浏览器,输入:localhost:6006,即可打开 TensorBoard 界面,点击上方蓝框中的 SCALARS 和 下方蓝框中的 Policy,即可动态监控训练过程的参数,右上角的刷新号即可刷新:

请添加图片描述

⑤ 关注第一个图,Agent 可以获得的最大奖励是 1.0,因此当 Agent 成功解决问题时,Cumulative Reward 会接近该值。

10. 更换训练好的模型:

① 到达 Max Step 后会结束训练,显示如下结果:

请添加图片描述

② 用资源管理器打开 ml-agents\ results\RollerBall\RollerBall,看到 .onnx文件 即为你训练并保存的模型,一般有两个。一个应该是最高分的,一个应该是最后的。
③ 将这两个 .onnx文件 拖入Unity Editor 中的 Assets 。
④ 将训练好的模型拖动到 RollerAgents 的 Behavior Parameters 的 Model 中。
⑤ 设置 Inference Device 为Default 或 Burst (有的版本显示CPU)。
⑥ Behavior Type 改为 Inference Only。
⑦ 点击上方的 Play,就可以看到小球自动在找方块。

请添加图片描述

本教程终于完成了,希望可以帮大家避开一些坑,欢迎大家一同钻研探讨!!! ~~

Logo

更多推荐