Unity3D ML-Agent-0.8.1 学习二(单代理学习)

写的目的

前面一篇已经介绍了ML-Agent怎么装环境,怎么训练,这篇来做个简单的例子,以便于上手,基于官方的案例
本篇主要讲述一个简单的例子,单个代理的训练,涉及到一点点代码,我尽可能的多讲点原理,少些点代码,也不讲公式,否则看到公式一般兴趣没了,先理解为主。
在这里插入图片描述

滚动的小球项目-单代理

先看我们的项目要做什么吧,我们要训练一个小球,让他在一个平台上去找方块,就那么简单,如果用代码写,那估计直接就移动到方块点就行了,为什么还要用AI训练呢,因为我们从简单入门,一些简单的例子里有着深刻的思想和原理。
不需要下载任何资源,用的都是内置资源,那我们开始吧。
在这里插入图片描述

创建目录

我们可以按照他的例子,创建相应的目录RollerBall
在这里插入图片描述

Brain 大脑,可以存放训练后的神经网络,即TFModels下的东西
Prefabs 预制,存放要多个代理训练的训练预制
Scenes 场景
Scripts 代码
TFModels 训练后的神经网络文件,提供给大脑用
创建场景

我们创建了一个叫SingleRollerBall的场景,里面需要创建一个平台(Floor),一个代理小球(RollerAgent),一个方块目标(Target),至于要设置什么材料贴图你喜欢就行,然后还要提供训练的环境(Academy)。把小球和方块的y设置成0.5,即都拉到平台上,不要陷进去。

同时需要给RollerAgent添加Rigidbody组件,因为需要设置速度,再添加2个脚本,RollerAcademy继承Academy,RollerAgent继承Agent,分别添加给相应的物体。然后创建一个大脑:
在这里插入图片描述
可以命名为SingleRollerBallLearningBrain,然后设置相应参数:
在这里插入图片描述
RollerAcademy还需要设置要训练的大脑,即刚才创建的SingleRollerBallLearningBrain,Control是用来训练的,打勾即为训练模式,不打勾即测试模式。在这里插入图片描述

写代码逻辑

写代码之前,先介绍一些简单的深度强化学习的概念,主要是一种通过奖励,试错学习的方式,设定目标奖励,向着奖励进化,根据环境选择动作,影响环境,获得奖励的不断循环,最终学习出获得奖励的方法,底层当然是神经网络参数的训练啦,环境可以看成是特征向量,输入到神经网络,得到预测奖励,然后预测奖励和目标奖励生成差距,通过反向传播,梯度下降法,类似一种求参数对结果的影响大小来调节参数的方法,优化神经网络参数来降低差距,最终使得预测和目标无限接近,即得最好的模型。
RollerAcademy.cs的代码基本不用写,只要继承Academy即可

using MLAgents;
using UnityEngine;

public class RollerAgent : Agent
{
    /// <summary>
    /// 目标
    /// </summary>
    public Transform Target;
    /// <summary>
    /// 代理的刚体组件
    /// </summary>
    Rigidbody rBody;
    /// <summary>
    /// 移动的速度,也可以看成给物体施加的力大小
    /// </summary>
    public float speed = 10;
    void Start()
    {
        rBody = GetComponent<Rigidbody>();
    }

    /// <summary>
    /// 完成一次任务后重新设置相应属性,调用done后会调用
    /// </summary>
    public override void AgentReset()
    {
        //判断是否掉下平台,是就要重新初始化属性,角速度,速度,本地坐标等
        if (transform.localPosition.y < 0)
        {
            rBody.angularVelocity = Vector3.zero;
            rBody.velocity = Vector3.zero;
            transform.localPosition = new Vector3(0, 0.5f, 0);
        }

        /*重新设置时目标位置也要重新设置,因为平台大小是5x5的,平台中心在(0,0),
         *目标的宽度是1,所以设置成左右4.5的距离刚好,y轴方向0.5,
         *使得刚好在平台上,不然可能陷下去或者飘起来了
         */
        Target.localPosition = new Vector3(Random.Range(-4.5f,4.5f),
                                      0.5f,
                                      Random.Range(-4.5f, 4.5f));
    }

    /// <summary>
    /// 收集环境信息,即需要传给tensorflow训练的特征向量,
    /// 可以理解为我把环境重要的信息告诉你,你帮我看看我下一步要怎么做。
    /// 这个个数会定义在Brain的参数里
    /// </summary>
    public override void CollectObservations()
    {
        // 我们需要目标和代理的位置,x,y,z 两个即6个值,位置代表我还有里多少距离就要到目标了,以便调节速度
        AddVectorObs(Target.localPosition);
        AddVectorObs(transform.localPosition);

        // 代理的速度,根据距离可以来调节速度,速度也会影响去目标的快慢程度
        AddVectorObs(rBody.velocity.z);
        AddVectorObs(rBody.velocity.x);
        
    }

    /// <summary>
    /// 代理得到决策后采取的动作,会定义在Brain的参数里,即可看做Brain给的决策动作,需要x,z的方向
    /// </summary>
    /// <param name="vectorAction"></param>
    /// <param name="textAction"></param>
    public override void AgentAction(float[] vectorAction, string textAction)
    {
        
        // 获得决策的动作数组
        Vector3 controlSignal = Vector3.zero;
        
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        //给代理施加的方向*力,即向量
        rBody.AddForce(controlSignal * speed);

        // 给予相应的奖励
        float distanceToTarget = Vector3.Distance(transform.localPosition,
                                                  Target.localPosition);

        // 达到目标则给予奖励,并且重新开始下一次迭代
        if (distanceToTarget < 1.42f)
        {
            SetReward(1.0f);
            Done();
        }

        // 如果滚下平台也重新下一次迭代
        if (transform.localPosition.y < 0)
        {
            Done();
        }
    }
}

代码基本都注释了,需要注意的是,要定义输入特征,有连续和离散之分,因为我们的是移动向量和位置,所以是连续的,然后需要在大脑里定义,space size:8代表我们有8个数值的空间,底层应该会转化为特征向量给tensorflow,至于action:2表示需要有个输出,即告诉我x,z该怎么走,即x,z的方向,得到后乘以力大小,就可以了,这个训练只需要进行x,z控制即可完成。
还有为什么都用localPosition,是因为后面方便多个代理一起训练,不然都跑世界坐标去了。
在这里插入图片描述
在训练前,还可以通过创建一个Player Brain来进行手动控制,试试有没什么问题,具体看图:
在这里插入图片描述
上面的设置和训练的一样,只是下面的输入时键盘按键,因为x,z方向,键盘只有4个,key就表示键盘按键,index表示对应的动作索引,因为动作只需要2个,从0开始索引,然后value就对应的值,表示方向了。

开始训练

训练之前要进行Control的勾选:
在这里插入图片描述
还有个可选的,就是是否要配置训练信息,如果不配置即执行默认配置,但是不一定适合这个训练的情况,因为参数不同会影响不同的训练时间和效果,具体以后会说明,这个调参应该属于比较麻烦的事了,需要有机器学习的基础了。我这里在config/trainer_config.yaml中加了要训练大脑的参数,是根据官方给的参数,名字和大脑名字一样即可,训练时会自动匹配:
在这里插入图片描述
然后打开命令行,到项目根目录下,输入训练命令,可参考我的:

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

在这里插入图片描述
根据提示点击unity编辑器的play按钮,即可开始训练,记得要快点哦,不然时间一久就断开通信了。
可以看到我训练了10000次,就到达最高奖励了。
在这里插入图片描述
之后就将输出的SingleRollerBallLearningBrain.nn放入TFModels下,然后拖入大脑属性面板里,即
在这里插入图片描述
去掉Control的够,play即可看到效果,如果训练的好,你会看到小球每次都会去找到目标,而且不会掉下去。

训练分析

有个很重要的分析工具,可以可视化,叫tensorboard,你可以在summaries文件夹下看到你刚才训练后的数据文件,用命令行打开:

tensorboard --logdir=summaries --host=localhost

在这里插入图片描述
在浏览器里输入他说的地址即可看到:
在这里插入图片描述
挑几个解释下:

Environment/Cumulative Reward 表示奖励的走势图,可见是向1靠近的
Environment/Episode Length 每一轮训练的时长,即1000步的时间,会发现时间越来越短,说明代理不走弯路了
Losses/Value Loss 即实际的平均奖励和理论的奖励1越来越接近了,损失变小了

总结

通过把这个基本的流程跑下来,可以理解这个训练的基本知识了,其他的可以慢慢再研究,比如多个代理训练,我在想是不是要用GPU会更快,并行处理嘛,下次试试。还有一些配置参数,分析参数以后会慢慢说明的,至于整个运行的原理和架构,还有模仿学习和视觉学习,后面有时间也会研究下,会给分享出来,希望更多的人能够收益。

补充附上项目主要文件unity3D-ml-agent-0.8.1

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵,部分图片来自网络,侵删。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值