[Unity3D]ml-agent入门案例

ml-agent是unity中用于将机器学习算法嵌入到gameobject的一个插件。在我的游戏项目中,我想尝试将机器学习和深度学习算法带入到游戏中,让游戏角色能够利用我们给出的数据自动通关,因此想到尝试使用这个插件。写下这个帖子供也用到mlagent的入门同学进行学习参考。ml-agent的详细内容可以参照官方文档,里面也有详细的英文介绍和入门教程(中文版的维护的并不太好,所以学习主要以英文为主)。

环境搭建

环境搭建主要是安装配置unity以及anaconda,这些教程网络很多,这里不赘述。

ml-agent包下载

下载ml-agents插件和安装所需要的包
可以通过git下载,也可以通过直接去ml-agents插件地址下载

git clone https://github.com/Unity-Technologies/ml-agents.git

下载完成后开始安装所需要的包。

pip install mlagents 

训练最简单的例子3DBall

打开uinty,插件的项目在Project里,在场景中找到3DBall就可以进入到该场景中。

之后在命令行把目录切换到根目录下,切记,否则可能出现找不到文件,因为他会去config下找trainer_config.yaml文件,如果在其他目录下会找不到。然后在命令行输入

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

如果没有报错,那么命令行会提醒你在unity中点击开始按钮就会开始训练了。

训练

这个是训练前的情况,可以看到小球很容易就掉到盒子下方了。(中间的卡顿是训练周期结束重置造成的)。

这个经历了20000次左右训练之后的,盒子基本可以控制住小球不掉落,越多的训练小球能够保持得更稳。

代码分析

游戏中的机器学习主要分为几个步骤:接口抽离、算法选取、设计环境、参数调整。环境已经又unity调整好了,所以这里不多说,参数调整也不是这里的重点,主要聊聊接口抽离和算法的选取。

接口抽离

  1. Initialize ()函数相当于 Start()函数,获取小球的刚体。
    public override void Initialize()
        {
            m_BallRb = ball.GetComponent<Rigidbody>();
            m_ResetParams = Academy.Instance.EnvironmentParameters;
            SetResetParameters();
        }
  2. OnEpisodeBegin()新一段开始函数,可以重置小球坠落出界后的重新开始的位置,以及 Cube 重新开始的一定范围的随机旋转。
    public override void OnEpisodeBegin()
        {
            gameObject.transform.rotation = new Quaternion(0f, 0f, 0f, 0f);
            gameObject.transform.Rotate(new Vector3(1, 0, 0), Random.Range(-10f, 10f));
            gameObject.transform.Rotate(new Vector3(0, 0, 1), Random.Range(-10f, 10f));
            m_BallRb.velocity = new Vector3(0f, 0f, 0f);
            ball.transform.position = new Vector3(Random.Range(-1.5f, 1.5f), 4f, Random.Range(-1.5f, 1.5f))
                + gameObject.transform.position;
            //Reset the parameters when the Agent is reset.
            SetResetParameters();
        }
  3. CollectObservations()观察变量,包括球相对于Cube 的相对位置、球的速度、Cube X Z 的旋转。
    public override void CollectObservations(VectorSensor sensor)
        {
            if (useVecObs)
            {
                sensor.AddObservation(gameObject.transform.rotation.z);
                sensor.AddObservation(gameObject.transform.rotation.x);
                sensor.AddObservation(ball.transform.position - gameObject.transform.position);
                sensor.AddObservation(m_BallRb.velocity);
            }
        }
  4. OnActionReceived ()改变 Cube XZ的两个变量,球出界的判断,以及设置奖励。
     public override void OnActionReceived(ActionBuffers actionBuffers)
        {
            var actionZ = 2f * Mathf.Clamp(actionBuffers.ContinuousActions[0], -1f, 1f);
            var actionX = 2f * Mathf.Clamp(actionBuffers.ContinuousActions[1], -1f, 1f);
    
            if ((gameObject.transform.rotation.z < 0.25f && actionZ > 0f) ||
                (gameObject.transform.rotation.z > -0.25f && actionZ < 0f))
            {
                gameObject.transform.Rotate(new Vector3(0, 0, 1), actionZ);
            }
    
            if ((gameObject.transform.rotation.x < 0.25f && actionX > 0f) ||
                (gameObject.transform.rotation.x > -0.25f && actionX < 0f))
            {
                gameObject.transform.Rotate(new Vector3(1, 0, 0), actionX);
            }
            if ((ball.transform.position.y - gameObject.transform.position.y) < -2f ||
                Mathf.Abs(ball.transform.position.x - gameObject.transform.position.x) > 3f ||
                Mathf.Abs(ball.transform.position.z - gameObject.transform.position.z) > 3f)
            {
                SetReward(-1f);
                EndEpisode();
            }
            else
            {
                SetReward(0.1f);
            }
        }
  5. Heuristic ()在 HeuristicOnly 模式操作小球的输入,这里是水平竖直Axis 操纵。
    public override void Heuristic(in ActionBuffers actionsOut)
        {
            var continuousActionsOut = actionsOut.ContinuousActions;
            continuousActionsOut[0] = -Input.GetAxis("Horizontal");
            continuousActionsOut[1] = Input.GetAxis("Vertical");
        }

算法选取

这里使用的是PPO(Proximal Policy Optimization)算法,是一种新型的Policy Gradient算法。Policy Gradient不通过误差反向传播,它通过观测信息选出一个行为直接进行反向传播,当然出人意料的是他并没有误差,而是利用reward奖励直接对选择行为的可能性进行增强和减弱,好的行为会被增加下一次被选中的概率,不好的行为会被减弱下次被选中的概率。

Policy Gradient算法对步长十分敏感,但是又难以选择合适的步长,在训练过程中新旧策略的的变化差异如果过大则不利于学习。PPO提出了新的目标函数可以再多个训练步骤实现小批量的更新,解决了Policy Gradient算法中步长难以确定的问题。

拓展

通过这个入门案例可以将思路拓展到更多的游戏。这种强化学习的思想是让计算机在不断尝试中,以获得最优学习结果的前提下,找到每个状态下的最优行为,也称作马尔可夫学习过程。ml-agent官方也提供了很多应用场景,可以在包中自行尝试。

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值