Unity机器学习3 ML-Agents模仿学习(Imitation Learning)

Unity机器学习 ML-Agents第一个例子 上一节我们安装了机器学习mlagents的开发环境,本节我们创建第一个例子,了解什么是机器学习。我们的例子很简单,就是让机器人自主移动到目标位置,不能移动到地板范围外。首先我们来简单的了解以下机器学习的过程。机器学习的过程MLAgents机器强化学习的过程(reinforcement learning)observation - 监视,观察decision - 决策action - 行动reward - 奖罚。 阅读详情

Unity机器学习3 ML-Agents模仿学习(Imitation Learning)

上一章的例子中,机器通过自主学习不断强化训练来学习(Reinforcement Learning),随机移动来到目标球位置,相对来说比较简单,只是通过随机数来学习。如果是复杂一点的环境,可能耗费几百万Step也可能无法学习到。

本章将介绍让机器人通过模仿进行(Imitation Learning)学习,达到并超越。

这里我举例说明什么是模仿学习。
假如你家的小狗狗喜欢撕咬沙发,那么你告诉它不要咬他是听不懂的。你可以找一只仿真小狗玩具或者布偶,让布偶去撕咬沙发,然后你再用你沙包大的拳头揍布偶小狗,看看你家狗狗的反应,如果他明白了撕咬沙发会挨揍,那么他就达到了学习目的。

强化学习和模仿学习(Reinforcement Learning Vs Imitation Learning)

区别就好比上面的例子,强化学习就是让狗自己学会不咬沙发,听起来挺难的,不是吗?模仿学习就是用上面的布偶的办法或者其他一些有效的方法。

或者我们换一个例子:
让一个从来没玩过电子游戏的人玩游戏,他根本不知道手柄的按钮都是干什么的,按了遥感就移动了,按了旁边的按钮A就发射子弹了,这个就属于强化学习。而模仿学习就是有一个游戏高手在旁边指导,你觉得哪一个学习更加有效呢?

机器模仿学习就是要达到这样效率的学习方式。下面我们还是通过一个Demo来了解。

Demo编写

本章的例子我们编写一个喂食器,方块(agent)需要走到按钮处,踩下按钮,这样就会触发掉出一块糖,然后再去吃糖获得奖励。

我们先把场景梳理一遍。
在这里插入图片描述

和上一章场景类似
wall,四个面,BoxCollider我们不勾选IsTrigger,阻止agent掉落。
在这里插入图片描述

plane是地板。
在这里插入图片描述

foodSpawn是出现food的衍生器。
在这里插入图片描述
foodSpawn上需要挂一个脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//UTF8 说明
public class FoodSpawn : MonoBehaviour
{
    public GameObject prefab;

    public bool hasFood;
    GameObject food;

  

    public Vector3 GetFoodAt()
    {
        if (food == null)
            return Vector3.zero;
        return food.transform.localPosition;
    }
    //投食
    public void PutInFood()
    {
        hasFood = true;
        food = GameObject.Instantiate(prefab);
        food.name = "food";
        food.SetActive(true);
        food.transform.parent = transform.parent;
        food.transform.localPosition = transform.localPosition;
    }

    //获取食物(被吃掉)
    public void GetFood()
    {
        hasFood = false;
        if (food != null)
            GameObject.Destroy(food);
        food = null;
    }
}



food(灰色)是foodSpawn创建食物时候的prefab。
在这里插入图片描述

swith是方形的按钮。
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//UTF8 说明
public class FoodSwitch : MonoBehaviour
{
    public FoodSpawn foodSpawn; //触发的食物衍生
    public Renderer renderSwitch;   //改变按钮颜色

    public Material onMat;  //按下的材质
    public Material offMat; //关闭的材质

    public bool isOn;   //按钮是否打开

    public void Clear()
    {
        isOn = false;
        renderSwitch.material = offMat;
        //让按钮还原高度
        renderSwitch.transform.localPosition = new Vector3(0f, -0.5f, 0f);
        //获得食物,并吃掉
        foodSpawn.GetFood();
    }
    public void Switch(bool on)
    {
        if (!isOn && on)
        {
            isOn = true;
            renderSwitch.material = onMat;
         
            //让按钮按下去
            renderSwitch.transform.localPosition = new Vector3(0f, -0.65f, 0f);
            //投食
            foodSpawn.PutInFood();
        }
        else if (isOn && !on)
        {
            isOn = false;
            renderSwitch.material = offMat;
            //让按钮还原高度
            renderSwitch.transform.localPosition = new Vector3(0f, -0.5f, 0f);
            //获得食物,并吃掉
            foodSpawn.GetFood();
        }
    }
}


agent就是我们的ai,我们依旧编写一个FoodAgent,继承于FoodAgent,会自动添加BehaviorParameters脚本。我们还要添加一个DecisionRequester脚本。上一章我们都介绍过。
在这里插入图片描述
因为更新了MLAgent版本,Actions的Continuous和Discrete可以混用了。可以看到和上一章有所不同,本章我们用离散的方法来进行。
我们先贴上完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;

public class FoodAgent : Agent
{
    [SerializeField] FoodSwitch foodSwitch;
    [SerializeField] FoodSpawn foodSpawn;
    [SerializeField] Renderer plane;
    float moveSpd = 3f;

    Rigidbody rig;

    private void Awake()
    {
        rig = GetComponent<Rigidbody>();
    }

    //当一段经历开始
    public override void OnEpisodeBegin()
    {

        transform.localPosition = new Vector3(Random.Range(-9f, 0f), 0f, Random.Range(-4f, 4f));
        foodSwitch.transform.localPosition = new Vector3(Random.Range(3f, 9f), 0f, Random.Range(-4f, 4f));

        foodSpawn.transform.localPosition = new Vector3(Random.Range(-9f, 0f), 5f, Random.Range(-4f, 4f));

        foodSwitch.Clear();
        Debug.Log("经历开始");
    }

    //通过传感器把坐标传入监视
    public override void CollectObservations(VectorSensor sensor)
    {
        
        sensor.AddObservation(foodSwitch.isOn ? 1 : 0);
        Vector3 dir = (foodSwitch.transform.localPosition - transform.localPosition).normalized;
        sensor.AddObservation(dir.x);
        sensor.AddObservation(dir.z);

        sensor.AddObservation(foodSpawn.hasFood ? 1 : 0);

        if (foodSpawn.hasFood)
        {
            Vector3 dirfood = (foodSpawn.GetFoodAt() - transform.localPosition).normalized;
            sensor.AddObservation(dirfood.x);
            sensor.AddObservation(dirfood.z);
        }
        else
        {
            sensor.AddObservation(0f);
            sensor.AddObservation(0f);
        }

        //Debug.Log("Observations : " );
    }

    //行动接收
    public override void OnActionReceived(ActionBuffers actions)
    {
        float moveX = actions.DiscreteActions[0];
        float moveZ = actions.DiscreteActions[1];
        bool switchon = actions.DiscreteActions[2] == 1;
        //Debug.Log("OnAction : " + moveX+","+ moveZ + ","+ switchon);
        Vector3 addforce = Vector3.zero;
        switch (moveX)
        {
            case 0:
                addforce.x = 0f; break;
            case 1:
                addforce.x = -1f; break;
            case 2:
                addforce.x = 1f; break;
        }
        switch (moveZ)
        {
            case 0:
                addforce.z = 0f; break;
            case 1:
                addforce.z = -1f; break;
            case 2:
                addforce.z = 1f; break;
        }

        rig.velocity = addforce * moveSpd + new Vector3(0f, rig.velocity.y, 0f);
        //transform.localPosition += new Vector3(moveX, 0f, moveZ) * Time.deltaTime * moveSpd;
        //Debug.Log(rig.velocity+","+ addforce);
        if (switchon)
        {
            Collider[] colls = Physics.OverlapBox(transform.position, Vector3.one * 0.5f);
            for (int i = 0; i < colls.Length; i++)
            {
                if (colls[i].name.Equals("switch"))
                {
                    if (!foodSwitch.isOn)
                    {
                        foodSwitch.Switch(true);
                        AddReward(1f);

                        Debug.Log("AddReward - switch");
                    }
                }
                
            }
        }
        AddReward(-1f / MaxStep);
    }

    

    //启发
    public override void Heuristic(in ActionBuffers actionsOut)
    {
        ActionSegment<int> actions = actionsOut.DiscreteActions;
        switch (Mathf.RoundToInt(Input.GetAxisRaw("Horizontal")))
        {
            case -1:
                actions[0] = 1; break;
            case 0:
                actions[0] = 0; break;
            case 1:
                actions[0] = 2; break;
        }
        switch (Mathf.RoundToInt(Input.GetAxisRaw("Vertical")))
        {
            case -1:
                actions[1] = 1; break;
            case 0:
                actions[1] = 0; break;
            case 1:
                actions[1] = 2; break;
        }
        actions[2] = Input.GetKey(KeyCode.E) ? 1 : 0;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.name.Equals("food"))
        {
            AddReward(1f);
            Debug.Log("AddReward - food");
            Destroy(collision.collider.gameObject);

            foodSwitch.Switch(false);


            EndEpisode();

        }
    }


}


回合开始 - OnEpisodeBegin

在每次回合开始,我们把agent,switch,foodspawn都随机一个位置。

收集观察信息 - CollectObservations

我们需要传入6个数据,如下图,对应BehaviorParameters里的SpaceSize(6),这6个数据依次为:
开关的开关(开or关);
开关的位置(x , z);
食物是否投放;
食物衍生点(x , z) - 没有食物,x、z传入0f。

行动 - OnActionReceived

在这里插入图片描述
我们再来巩固下上一章的内容,这里也比较容易和SpaceSize混淆。
注意我们在BehaviorParameters里因为配置了3个离散数据(Discrete Branches)。
分支0代表了moveX,可能出现三种情况(0,1,2),所以是3;
分支1代表了moveZ,同上;
分支2代表了是否按下了按钮。

代码中获得了上面的数据后,把moveX,moveZ传给了刚体进行物理移动。
swithon获得到按下按钮后,判断agent附近是否有按钮,如果有就按下按钮,这时候会有一个食物创建出来,并进行奖励。

函数最后有一个AddReward(-1f / MaxStep); 这个是为了让机器用最少的步数来学习。

吃掉食物 - OnCollisionEnter

这里检测到如果agent碰到了food就给予奖励,并删除food对象,并自动跳起食物开关。

启发 - Heuristic

这样所有的逻辑就通了,我们再来编写一个启发,来验证我们脚本是否正常执行。
首先通过判断左右是否按下传入第一个参数。
然后通过判断上下是否按下传入第二个参数。
最后通过判断是否按下了E传入第三个参数。
这样就模拟了机器的3个行动指令。

测试运行

到这里所有代码准备完毕了,我们来测试是否通畅。我们把BehaviorType调整到Heuristic Only,点击运行。
请添加图片描述
运行良好。

机器自主学习

首先我们也单独配置一个yaml。我们可以把上一节的movetarget.yaml复制一份,改为food.yaml

behaviors:
  FoodAgent:
    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

注意,这里要修改behaviors的名字为FoodAgent,要和BehaviorParameters里的名字对应,也就是yaml文件的第二行。
然后我们开始mlagent的运行环境

进入项目目录输入

venv\scripts\activate

mlagents-learn config/food.yaml --run-id=foodtest1

在这里插入图片描述
我们把Unity的Behavior Type改回Default进入学习模式。
点击开始运行。
请添加图片描述
我们从GIF中可以看到,还算运气好,agent机器人按照随机的这种运行模式,进入了开关范围并按下了开关,黄色的Food也掉落了下来,但是agent并没有跑向food,因为所有的机器逻辑都是随机的,如果场景再更加复杂,只靠随机数来让机器学习,那么可能等到下班或者退休了。

所以这才开始进入本章的主题-模仿学习(Imitation Learning)

模仿学习(Imitation Learning)的学习录制

我会点击agent对象,添加新的脚本Demonstration Recorder(示范录制)
在这里插入图片描述
我们勾选Record复选框。
这里的名字随意,我这里还命名成FoodAgent,目录是Recorders。
我们把BehaviorType改为Heuristic Only。 这样我们再次运行起来后会把我们的Heuristic保存起来,作为训练人工智能的学习“影片”。我们点击运行后,进行几次操作后关闭游戏,就会生成一个demo文件。后面机器模仿学习会使用到。
在这里插入图片描述
我们把这个文件放入assets里看看
在这里插入图片描述
它会告诉您您玩了多少集以及您积累了多少奖励。
因为我们有两次奖励,所以MeanReward大概在1.9以上是比较高的奖励了。

录制使用和yaml配置

为了让机器学习使用这个FoodAgent.demo,我们需要修改yaml配置文件。
如下:

behaviors:
  FoodAgent:
    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
      gail:
        strength: 0.1
        demo_path: Recorders/FoodAgent.demo
    behavioral_cloning:
      strength: 0.1
      demo_path: Recorders/FoodAgent.demo   
    max_steps: 500000
    time_horizon: 64
    summary_freq: 10000

在reward_signals里添加gail。

Gail - 模仿

GAIL (Generative Adversarial Imitation Learning) 代表模仿,是一种模仿学习算法,它使用对抗模仿学习,类似于 GAN(Generative Adversarial Networks)。

我们需要配置几个主要的gail参数:

strength

如果你想他做出和你的模仿相同的举动,可以设置strength为1.0,但是我们可以希望agent变得比你的操作做的更好、更加聪明,所以推荐strength占比不要太高。

demo_path

就是我们的模仿文件,这里填写路径和文件名Recorders/FoodAgent.demo

behavioral_cloning (BC) - 行为克隆

行为克隆behavioral_cloning (BC) 训练代理的神经网络以精确模仿一组演示中显示的动作。它基本上是一种完全复制所展示的任何内容的代理。这仅对最基本的 AI 代理有用。我们显然不会使用 BC,因为我们的代理和方块在随机位置生成。这使得代理无法正确执行任务,因为每个场景都是新的。

如果您想使用预先录制的演示帮助您的代理学习(尤其是在奖励稀少的环境中),除了获得外在奖励外,您通常可以同时启用低强度的 GAIL 和BC。因此,我们将使用 代表“生成对抗模仿学习”的GAIL。使用这种方法,有效地使用了两个神经网络。

behavioral_cloning:
  strength: 0.1
  demo_path:Recorders/FoodAgent.demo  

这个行为克隆。他获得了和你一样的行为,然后和gail结合产生了和你相似的行为。

这里注意,最好格式全部使用空格,如果有tab,会提示报错,用过python的语法的朋友应该都了解。

    self.get_mark())
yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token
  in "config/food.yaml", line 24, column 7

或者有其他错误提示。直到正常启动看到Unity的文字logo。

具体的配置可以参考这里。
关于BC(behavioral_cloning)和Gail可以看这里。

机器模仿学习

我们可以复制多个ground组,让很多agent一起学习。如图:
在这里插入图片描述

我们关闭DemonstrationRecorder的Record的勾。
我们再次调整HavroralType为default。
运行机器学习环境
mlagents-learn config/food.yaml --run-id=foodtest9
请添加图片描述
这样就开始群体训练了。

这里我发现有时很卡,看了下参数,可以把下面两个批次处理数量改大一些。
hyperparameters:
batch_size: 1024
buffer_size: 8192

训练了一下午,发现机器会越来越笨。再次阅读文档,调整了参数。

behaviors:
  FoodAgent:
    trainer_type: ppo
    hyperparameters:
      batch_size: 1024
      buffer_size: 8192
      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
    behavioral_cloning:
        demo_path: Recorders/FoodAgent.demo
        strength: 0.5
        steps: 150000
    reward_signals:
        extrinsic:
            strength: 1.0
            gamma: 0.99
        curiosity:
            strength: 0.02
            gamma: 0.99
            encoding_size: 256
        gail:
            strength: 0.01
            gamma: 0.99
            encoding_size: 128
            demo_path: Recorders/FoodAgent.demo
    max_steps: 5000000
    time_horizon: 64
    summary_freq: 10000
  
yaml重要参数说明

文档里说到最好gail的strength小于0.1,看到官方的例子,都是0.01,我也改小了。
“gamma”决定了agent是应该寻求即时奖励还是追求从长远来看将获得更多奖励的策略。较低的值会导致前者,而较高的值(如 0.99)将寻找可以长期获得回报的东西。
“batch_size”和“buffer_size”确定代理在更新策略并继续梯度下降之前应该使用多少经验,以减少梯度下降期间的体验,但在更新策略时提供更多体验。这些 必须是彼此的倍数,否则数学不成立。
“beta”值。这会影响代理将采取的随机操作的数量。较高的值使其更随机。让我们将其设置为 0.003,因为如果代理找到了最大化奖励的路径,则任务不一定需要很大的偏差。
“max_steps”值从 500,000 增加到 5,000,000,以便为我们提供更多空间让代理训练。
该配置文件包含所谓的“超参数(hyperparameters)”,它们是一组特殊的参数,可以在最细粒度的级别上影响神经网络。
hidden_units-值是神经网络中将使用的神经元数量。
num_layers-是我们要使用的神经元层数。显然,这两个值越大,训练时间就越长,但如果你正在训练一个复杂的代理,你可能需要额外的神经元,以提高精度。

增加成功绿色提示

我给界面上显示了两个时间,左边的是当前时间,右边的是最短吃到食物的时间,如果在一个合理范围内(允许比最短时间大greenrange(5秒)时长)plane就是绿色的,如果超出了最大时间一段范围就变成灰色。

最后的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;

public class FoodAgent : Agent
{
    [SerializeField] FoodSwitch foodSwitch;
    [SerializeField] FoodSpawn foodSpawn;
    [SerializeField] Renderer plane;
    [SerializeField] TextMesh text;
    float moveSpd = 3f;

    Rigidbody rig;

    float btime;
    float greentime = 1000f;   //当前最快结束的
    float usetime;//本次用时
    const float greenrange = 5f;    //比最快值长,也是绿色

    private void Awake()
    {
        rig = GetComponent<Rigidbody>();
    }

    //当一段经历开始
    public override void OnEpisodeBegin()
    {
        btime = Time.time;
        transform.localPosition = new Vector3(Random.Range(-9f, 0f), 0f, Random.Range(-4f, 4f));
        foodSwitch.transform.localPosition = new Vector3(Random.Range(3f, 9f), 0f, Random.Range(-4f, 4f));

        foodSpawn.transform.localPosition = new Vector3(Random.Range(-9f, 0f), 5f, Random.Range(-4f, 4f));

        foodSwitch.Clear();
        Debug.Log("经历开始");
    }

    //通过传感器把坐标传入监视
    public override void CollectObservations(VectorSensor sensor)
    {
        
        sensor.AddObservation(foodSwitch.isOn ? 1 : 0);
        Vector3 dir = (foodSwitch.transform.localPosition - transform.localPosition).normalized;
        sensor.AddObservation(dir.x);
        sensor.AddObservation(dir.z);

        sensor.AddObservation(foodSpawn.hasFood ? 1 : 0);

        if (foodSpawn.hasFood)
        {
            Vector3 dirfood = (foodSpawn.GetFoodAt() - transform.localPosition).normalized;
            sensor.AddObservation(dirfood.x);
            sensor.AddObservation(dirfood.z);
        }
        else
        {
            sensor.AddObservation(0f);
            sensor.AddObservation(0f);
        }

        //Debug.Log("Observations : " );
    }

    //行动接收
    public override void OnActionReceived(ActionBuffers actions)
    {
        float moveX = actions.DiscreteActions[0];
        float moveZ = actions.DiscreteActions[1];
        bool switchon = actions.DiscreteActions[2] == 1;
        //Debug.Log("OnAction : " + moveX+","+ moveZ + ","+ switchon);
        Vector3 addforce = Vector3.zero;
        switch (moveX)
        {
            case 0:
                addforce.x = 0f; break;
            case 1:
                addforce.x = -1f; break;
            case 2:
                addforce.x = 1f; break;
        }
        switch (moveZ)
        {
            case 0:
                addforce.z = 0f; break;
            case 1:
                addforce.z = -1f; break;
            case 2:
                addforce.z = 1f; break;
        }

        rig.velocity = addforce * moveSpd + new Vector3(0f, rig.velocity.y, 0f);
        //transform.localPosition += new Vector3(moveX, 0f, moveZ) * Time.deltaTime * moveSpd;
        //Debug.Log(rig.velocity+","+ addforce);
        if (switchon)
        {
            Collider[] colls = Physics.OverlapBox(transform.position, Vector3.one * 0.5f);
            for (int i = 0; i < colls.Length; i++)
            {
                if (colls[i].name.Equals("switch"))
                {
                    if (!foodSwitch.isOn)
                    {
                        foodSwitch.Switch(true);
                        AddReward(1f);

                        Debug.Log("AddReward - switch");
                    }
                }
                
            }
        }
        AddReward(-1f / MaxStep);
    }

    

    //启发
    public override void Heuristic(in ActionBuffers actionsOut)
    {
        ActionSegment<int> actions = actionsOut.DiscreteActions;
        switch (Mathf.RoundToInt(Input.GetAxisRaw("Horizontal")))
        {
            case -1:
                actions[0] = 1; break;
            case 0:
                actions[0] = 0; break;
            case 1:
                actions[0] = 2; break;
        }
        switch (Mathf.RoundToInt(Input.GetAxisRaw("Vertical")))
        {
            case -1:
                actions[1] = 1; break;
            case 0:
                actions[1] = 0; break;
            case 1:
                actions[1] = 2; break;
        }
        actions[2] = Input.GetKey(KeyCode.E) ? 1 : 0;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.collider.name.Equals("food"))
        {
            AddReward(1f);
            Debug.Log("AddReward - food");
            Destroy(collision.collider.gameObject);

            foodSwitch.Switch(false);

            //计算用时
            float nowtime = Time.time;
            usetime = nowtime - btime;
            if (usetime < greentime)
            {
                greentime = usetime;
                
            }
            if (usetime - greenrange < greentime)
            {
                isgreen = true;
                //如果比最短时间大一定数值还是允许是绿色的。
                plane.material.color = Color.green;
            }

            EndEpisode();

        }
    }

    bool isgreen;
    private void Update()
    {
        usetime = Time.time - btime;
        text.text = ((int)usetime).ToString()+"/" +((int)greentime).ToString(); 
        if (isgreen)
        {
            //如果是绿色的,检测超时就改为灰色
            
            if (usetime - greenrange > greentime)
            {
                //如果比最短时间大一定数值还是允许是绿色的。
                plane.material.color = Color.gray;
                isgreen = false;
            }
        }
    }


}

请添加图片描述
上面的GIF是最终效果,开始很长一段时间agent都吃不到食物,甚至开关都找不到,一旦成功了,后面会越来越聪明了。调整yaml参数会让你的agent学习事半功倍。我们看到右边的数字基本都在3-5秒左右。

我们成功获得了AI文件后。
在这里插入图片描述
复制FoodAgent.onnx到项目里,并且挂到Model里,并设置InerenceOnly,我们看看训练的成果吧。

请添加图片描述

好了,本章的模仿学习就到这里了。
下一章我们可能会做一个更加复杂的机器学习的例子。

本章源码demo2

引用:
MLAgent

CodeMonkey

GameDev Academy

Unity ML-Agents安装配置与强化学习环境搭建全指南 深度强化学习作为机器学习的重要分支,通过智能体与环境的交互试错来学习最优策略,其核心原理基于奖励机制与价值函数迭代。这一技术为复杂决策问题提供了数据驱动的解决方案,在游戏AI、机器人控制、自动驾驶仿真等领域展现出巨大价值。Unity ML-Agents作为官方开源工具包,实现了游戏引擎与PyTorch等机器学习框架的无缝对接,为开发者提供了强大的3D仿真训练平台。本文聚焦于ML-Agents环境配置的完整流程,涵盖Unity编辑器与Python训练端的版本匹配、Conda虚拟环境管理、gRPC通信配置等关键 阅读详情

相关推荐

AI技术选型实战地图:符号AI、连接主义与混合智能落地指南

人工智能不是单一技术,而是涵盖符号推理、统计学习、行为交互等多范式的工程体系。理解符号AI的可解释性优势、连接主义对非结构化数据的强拟合能力,以及混合智能在可信性与泛化性之间的平衡,是企业技术落地的前提。这些范式决定了模型是否可审计、部署是否依赖GPU、响应能否满足毫秒级要求,并直接影响金融风控的合规性、工业质检的稳定性及边缘设备的功耗表现。本文基于23个已交付项目实测数据,系统梳理七类主流AI技术在数据需求、硬件门槛、可解释性与典型延迟上的真实差异,为业务需求匹配最适配、最低风险、最高ROI的技术路径。

weixin_33743248的博客 504

Unity3D ML-Agent-0.8.1 学习四(模仿学习)

Unity3D Ml-Agent-0.8.1 学习四(模仿学习)写的目的场景设置修改配置并训练总结 写的目的 本篇介绍模仿学习,即玩家边玩,代理边学习,主要分为在线学习和离线学习,在线就是跟着师傅一起学,离线就是看是师傅录制的资料学习,我们主要讲在线学习,就是玩家边玩,AI边学习,可以实时观察学习的效果,离线学习只是记录玩家信息,产生生成一个文件,命令行学习文件即可,不多做介绍。 场景设置 可以...

王伟王胖胖的博客 1793

SIMA 2:无需人类数据的通用游戏AI如何革新NPC与游戏测试

通用人工智能(AGI)旨在让机器具备类似人类的广泛认知与学习能力,其核心挑战之一是跨环境的知识迁移与基于语言的交互。强化学习作为实现这一目标的关键技术,通过智能体与环境的持续交互来学习最优策略,其价值在于能够处理复杂、动态的决策问题。在游戏开发与自动化测试领域,这项技术正展现出巨大潜力。具体而言,像SIMA这样的智能体,通过结合多模态理解和基于内在动机的课程学习,能够仅凭像素输入和自然语言指令,在多样化的3D虚拟环境中执行任务。这为创造能动态理解玩家意图、行为更自主的NPC,以及实现高效、自动化的游戏内容测

weixin_30888413的博客 372

模仿学习与强化学习的结合(原理讲解与ML-Agents实现)

模仿学习与强化学习结合能产生超级强悍的训练效果,是训练困难任务的必备框架

小星AI 1万+

AI Agent闭环系统架构设计与工程实践

AI Agent系统通过感知-决策-执行-反馈的闭环架构实现智能行为。感知模块采用多模态融合技术处理视觉、语音等输入,决策层运用强化学习与经典规划算法生成最优策略。工程实践中,执行监控和容错机制保障系统可靠性,而反馈学习则持续优化模型性能。这种架构在智能客服、工业自动化等场景展现价值,其中多模态感知和强化学习是提升Agent适应性的关键技术。系统设计需平衡算法复杂度与工程可行性,通过分布式架构和量化加速解决性能瓶颈。

weixin_33721427的博客 382

使用ML-Agent进行演示录制和模仿学习 Unity3D

观察空间是代理可以观察到的环境信息,而动作空间是代理可以采取的行动。例如,如果您正在创建一个模仿走路的代理,观察空间可以包括代理当前的位置、速度和角度等信息。例如,如果您正在创建一个模仿走路的代理,观察空间可以包括代理当前的位置、速度和角度等信息。一旦您的代理配置为模仿学习模式,您可以使用ML-Agent的训练功能来训练代理使用ML-Agent进行演示录制和模仿学习 Unity3D。在ML-Agent中,我们可以使用。一旦您的代理配置为模仿学习模式,您可以使用ML-Agent的训练功能来训练代理。

JfiqMaster的博客 542

强化学习+Unity仿真(三):C#脚本编写(一)

创建C#脚本,包括如何手动控制智能体,智能体的观测空间、动作空间,强化学习的奖励函数等。注:本文所有代码均来自于,仅作学习使用。

pingping_TEL的博客 806

人工智能-强化学习:Imitation Learning(模仿学习)= Learning by Demonstration(示范学习)【每一步action都没有reward】

- Imitation Learning(模仿学习)是从给定的展示中进行学习。机器在这个过程中,也和环境进行交互,但是,并没有显示的得到 reward。 - 在某些任务上,也很难定义 reward。如:自动驾驶,撞死一人,reward为多少,撞到一辆车,reward 为多少,撞到小动物,reward 为多少,撞到 X,reward 又是多少,诸如此类。。。 - 另外,某些人类所定义的 reward,可能会造成不可控制的行为,如:我们想让 agent 去考试,目标是让其考 100,那么,这个 agent 则可

u013250861的博客 3123

Unity(ML-agents) for Imitaion Learning.

Behavior Cloning//行为克隆是。

To be a better man 612

深入解析ACS SPiiPlus运动控制器的托管API架构与实战应用

本文深入解析了ACS SPiiPlus运动控制器的托管API架构,详细介绍了其核心模块、设计哲学与实战应用。通过C#/.NET封装的托管接口,开发者能够高效实现多轴协同运动控制、EtherCAT总线集成以及事件驱动的异步编程,显著提升高精度工业自动化设备的开发效率与系统稳定性。

jwt8token的博客 861

PCB压合原理与工艺全流程深度解析

PCB压合是多层印制电路板制造中的核心工序,其本质并非简单物理叠加,而是高分子树脂流动、玻璃布应力释放、铜箔热膨胀及界面能调控的协同过程。理解压合原理,需掌握温度-压力-时间三维曲线动态关系;优化工艺流程,须兼顾叠板精度、热压参数匹配与冷却策略;关键影响因素如半固化片(PP)选型、铜箔表面处理、设备温场均匀性、结构对称性、环境湿度及操作手法,共同决定层间结合力、翘曲度与孔壁质量。本文围绕PCB压合原理、工艺流程、关键影响因素三大维度展开,融合IPC标准、实测数据与产线案例,为工艺工程师、NPI人员及设备维护

weixin_29191081的博客 250

ML-AGENT模仿学习(一)

https://v.qq.com/x/page/i070855nabf.html unity官方老师讲解视频如上。 什么是模拟学习 有很多开发者都咨询过这个问题,甚至还会追问“模仿学习与强化学习的区别是什么?” Alexandre Attia和Sharone Dayan在今年1月发表的《模仿学习全面概述》中,做出了定义:模仿学习是学习者尝试模仿专家行为,从而获取最佳性能的一系列任务。这里的“学习者...

qq_23158477的博客 1122

vrep和matlab,使用Matlab与V-REP联合仿真 - Play V-REP with Matlab

OS: Win10 x64Matlab: R2016bV-REP: V-REP PRO EDU v3.5.0 下载、安装与支持V-REP操作基础V-REP仿真基础Matlab环境准备一个简单的例子对V-REP有一定了解的读者可以直接跳到第三节Matlab环境准备。下载、安装与支持V-REP提供Windows、Linux和MacOS三个平台的应用程序支持,任意平台都提供教育版和专业版两个版本。教育版...

weixin_42660494的博客 3210

ml-agents0.7_ML-Agents工具包v0.6:改进了大脑的可用性和模仿学习

ml-agents0.7We’ve added a two new enhancements in the Unity ML-Agents Toolkit v0.6 based on your feedback! The first enhancement improves the usability of Brains by turning them from MonoBehaviors to ...

culiao6493的博客 316

WINCC8.1工业组态软件安装与授权配置指南

SCADA系统作为工业自动化控制的核心平台,通过实时数据采集与监控实现生产流程可视化。WINCC作为西门子旗舰级组态软件,其8.1版本凭借稳定的运行时环境在汽车制造、流程工业等领域广泛应用。本文从工业控制系统软件安装规范切入,重点解析WINCC8.1与Automation License Manager的协同工作原理,详细说明包括系统环境检查、安装包校验、授权文件配置等关键技术环节。针对工程实施中常见的内存配置不足、授权管理器报错等典型问题,提供经过现场验证的解决方案,特别适用于需要进行产线监控系统升级维护

cqwf95925的博客 1650

芒果YOLO11改进44:主干Backbone篇之MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

包括YOLOv5、YOLOv7、YOLOv8等模型改进 369

Generative Adversarial Imitation Learning(Gail) 论文阅读

原版:对于agent做出的动作a,r(s, a) = − log(1 − D(s, a)) ,被判别器判定越接近专家行为,奖励就越大,这种方式适用于有生存奖励的RL环境,比如说Atari游戏,但对于想尽快结束的环境可能不适合,如果用这种方式也需要结合环境原本奖励并把Gail奖励的系数调低。相较于PPO 其需要一个额外的判别器D,D的作用是用来区分agent做出的动作和expert做出的动作,越接近于expert的动作 D的输出越接近1.Gail是一种使用PPO更新方法的模仿学习,

qq_44152415的博客 857

WiFi偏门协议(四):增强的传输机制802.11aa

区分Unicast和Multicast的优先级,以及设定不同的重传次数,以细化EDCA机制。 SCS(StreamClassification Service) 如上图,在VI,VO内各自又增加了一个queue, 对应不同的MAC header。VI和VO内的两个queue可以分别对应UC和MC。这样就提供了同一个AC内的更细粒度的优先级区分。当然还可以使用Drop Eligibility Indication子域来区分不同的重传次数。 改善Multicast数据传...

reekyli的专栏 1790

ML-Agent的Demo录制和模仿学习

你只需要为自己的Agent加入如下组件,并勾选Record,系统就会自动在你第二次点击play按钮的时候,在路径为"Demonstration Directory"(默认为“Assets/Demonstrations”)的地方,创建一个名为“DemonstrationName”的demo文件 ...

~勿据散客~的博客 543

迟滞比较器原理及计算

为什么要用迟滞比较器 在讲迟滞比较器之前,我们先看一个案例。 在产品设计中常常需要用到电机,而电机在从运转到停止过程中需要泄放能量,这种能量大部分以电压的形式反馈回电源母线(Vbus)导致Vbus母线电压升高,特别是功率大又转速快的电机需要急刹时,产生的反馈电压更高,严重时可能导致母线上其他器件的损坏。 为了防止将电机反馈的能量泄放掉,我们需要设计一个电路来检测母线电压,当母线电压高于某一安全阈值时,打开MOSFET Q1将母线上的能量通过电阻R5以热的形式消耗掉。 假如用一般的比较器,设计如下: Vbu

sinat_15677011的博客 2万+

Aurix TC3xx系列MCU ResourceM模块配置(多核资源分配)

为减轻主核的负载率或者平衡各个核的资源分配,通常需要把一些MCU内部资源分配到从核上,在EB tresos工具中,通过ResourceM模块实现多核资源分配。

m0_38045338的博客 1386

AI Agent训练环境设计:从原理到实战,破解智能体“间歇性天才”难题

在人工智能领域,智能体(Agent)的训练效果不仅取决于模型算法,更关键的是其交互与学习的环境。一个设计良好的训练环境,如同精准的“健身房”和“试炼场”,需要清晰定义观察空间、动作空间和奖励函数,为Agent提供稳定、真实且高效的反馈。其核心原理在于,环境通过强化学习等范式,为Agent的“试错”过程提供“对错”标准,引导其学习有效策略。高质量的环境设计具有极高的技术价值,它能显著提升训练效率、策略的鲁棒性以及从仿真到现实(Sim2Real)的迁移能力。在应用场景上,无论是机器人控制、游戏AI,还是软件自动

weixin_34056162的博客 315

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

MMSkills:为通用视觉智能体赋予多模态技能,跨越感知与行动鸿沟

在人工智能领域,视觉-语言模型(VLM)和大语言模型(LLM)已能出色地完成图像描述、场景理解和复杂问答,这标志着感知智能的成熟。然而,从理解世界到动手改变世界,智能体需要将视觉、语言等多模态信息转化为可执行的具体动作,这涉及到程序性知识的学习与运用。其技术价值在于构建能真正在物理世界中完成任务的通用智能体,是迈向具身智能和实用机器人的关键一步。应用场景广泛覆盖家庭服务、工业自动化及人机交互等领域。本文探讨的MMSkills框架,正是系统性地为智能体构建“多模态技能”库的研究基准,旨在通过模仿学习、强化学习

weixin_30897079的博客 398

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Unity强化学习工具包MLAgents环境搭建

Unity在强化学习中应用

weixw99的博客 2182

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Imitation Learning(模仿学习)

这种方法的核心思想是让机器学习模型从已有的数据中学习,而不是通过试错的方式。然而,它也有局限性,比如可能无法处理未知的、多样化的情境,或者在训练数据中未观察到的情况。总之,Behavior Cloning 是模仿学习的一种实现方式,它们之间存在关联,但 Imitation Learning 更广泛地指代了从专家行为中学习的各种方法。在这些领域中,模仿学习可以帮助机器学习模型更快地学习到有效的策略,从而提高整体的性能。2. 表示学习:从收集到的数据中提取特征,将这些特征表示成机器学习模型可以理解的格式。

3014

ML-Agents Toolkit v0.3 Beta发布:模仿学习,反馈驱动的功能等

ml-agents0.7We are happy to announce that the ML-Agents team is releasing the latest version of our toolkit, v0.3. 我们很高兴地宣布ML-Agents团队将发布我们工具箱的最新版本 v0.3。 This is our biggest release yet, and many of...

culiao6493的博客 504
上一篇: Android学习笔记1 - 第一行代码
下一篇: Unity ECS小知识1 - PhysicsTrigger Event
Thinbug
博客等级 码龄22年 2万+粉丝 187原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinbug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值