Unity 用ml-agents机器学习造个游戏AI吧(2)(入门DEMO)

浪尽此生 提交于 2020-04-28 11:59:29

[toc]

前言:上一篇博文已经介绍了Unity ml-agents的环境配置(https://www.cnblogs.com/KillerAery/p/10629963.html)了。

个人建议先敲demo再摸清概念比较容易上手,因此本文先提供一个demo示例简单阐述下。

由于过了差不多2年,Unity ml-agents项目API已经更新了很多,以前的demo教程已经不适合了,因此决定翻新Unity ml-agents机器学习系列博客。

本次示例:训练一个追踪红球的白球AI


1. 新建Unity项目,导入package


进入Unity项目,在上方 Window => Package Manager,,然后安装Barracuda这个package(如果没看见,一般就是没有显示All packages或没显示preview package):

<img src="https://img2020.cnblogs.com/blog/1409576/202003/1409576-20200309202859875-769795640.png" width="70%" height="70%">

并将之前下载的ml-agents项目com.unity.ml-agents目录下Editor、Plugin、Runtime复制进新建Unity项目里(建议放在Assets文件夹内)

旧版本ml-agents项目UnitySDK文件夹已被分割为com.unity.ml-agents文件夹(Unity ml-agents包)和Project文件夹(示例项目,含若干个机器学习示例demo)。

2. 编写Agent脚本


RollerAgent 是将用于智能体对象的组件脚本:

//RollerAgent.cs

using UnityEngine;
using MLAgents;
using MLAgents.Sensors;
public class RollerAgent : Agent
{
    public Transform Target;
    public float speed = 10;
    private Rigidbody rBody;

    void Start()
    {
        rBody = GetComponent<Rigidbody>();
    }

    //收集观察结果
    public override void CollectObservations(VectorSensor sensor)
    {
        //观察目标球和智能体的位置
        sensor.AddObservation(Target.position);
        sensor.AddObservation(this.transform.position);
        //观察智能体的速度
        sensor.AddObservation(rBody.velocity.x);
        sensor.AddObservation(rBody.velocity.z);
        //在这里因为目标球是不会动的,智能体也不会在y轴上又运动,所以没有必要观察这些值的变化。
        //sensor.AddObservation(rBody.velocity.y);
    }

    //处理动作,并根据当前动作评估奖励值    
    public override void AgentAction(float[] vectorAction)
    {
        //------ 动作处理
        // 接受两个动作数值
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        rBody.AddForce(controlSignal * speed);

        //------ 奖励信号
        float distanceToTarget = Vector3.Distance(this.transform.position, Target.position);
        // 到达目标球
        if (distanceToTarget < 1.42f)
        {
            //奖励值+1.0f
            SetReward(1.0f);
            Done();
        }

        // 掉落场景外
        if (this.transform.position.y < 0)
        {
            Done();
        }
    }

    //启发函数,玩家可手动操控智能体,用于手动调试智能体或启发模仿学习。
    public override float[] Heuristic()
    {
        var action = new float[2];
        action[0] = -Input.GetAxis("Horizontal");
        action[1] = Input.GetAxis("Vertical");
        return action;
    }

    //Reset时调用
    public override void AgentReset()
    {
        if (this.transform.position.y < 0)
        {
            //如果智能体掉下去,则重置位置+重置速度
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            this.transform.position = new Vector3(0, 0.5f, 0);
        }
        //将目标球重生至一个新的随机位置
        Target.position = new Vector3(UnityEngine.Random.value * 8 - 4, 0.5f, UnityEngine.Random.value * 8 - 4);
    }
}

Agent,即智能体,含有感知和行为——它通过观察环境然后做出相应的行为。在最常使用的强化学习里,智能体的训练模型类似一个黑盒。 每一次模拟步长中,智能体的感知会作为黑盒的输入,然后黑盒会输出行为选择,然后根据行为选择来让智能体做出行为。

当我们需要创建一个智能体类型时,让其继承Agent类,以用于重写智能体CollectObservations,AgentAction,AgentReset等方法。

CollectObservations()

  • 每一个模拟步长都会被调用。
  • 负责收集智能体的对环境的观察信息。

这部分类似于黑箱子的输入。值得注意的是,所需观察的信息越少越好。因此,我们需要尽可能减少不必要的观察信息,这会让训练变得更加快速、准确。

AgentAction()

  • 每一个模拟步长都会被调用。
  • 负责接受决策的行为选择从而让智能体做出行为。示例里,通过行为选择的2个float输入值来驱使球体移动,一旦掉出场景外,便调用Done()。
  • 负责评估此步长的reward(奖励值)。示例里,只要触碰到目标球即可获得一定的reward。

如何根据实际问题设计reward往往是一个难点,设计的不好(例如部分奖励值过大)容易造成网络不收敛。

Heuristic()

  • 通过玩家亲自操控智能体来输出行为选择。

亲自操控智能体可用于模仿学习或调试智能体的行为。

AgentReset()

  • Done()被调用时,它才被调用。
  • 负责重新设置场景,来准备下一次session。

当Done()被调用时,这意味着一次session的结束。然后深度强化学习模型评估整个session的reward并且重新设置场景,以准备下一次session。在示例里,为了让训练更加有效更加广泛化,因此给目标球设置的是随机位置(实际上智能体球也应该设置随机位置)。

3. 搭建好游戏场景


创建一个地板:

创建一个小球:

创建一个智能体(RollerAgent):

先创建一个带刚体的球体对象,然后我们需要给它挂载RollerAgent脚本(挂载后自动额外挂载BehaviorParameters脚本用于配置)和DecisionRequester脚本。

4. 调整脚本参数


Behavior Parameters

每个Agent还必须得附带一个行为参数脚本,行为参数脚本用于定义智能体如何做出决策。

Vector Observation Space Size:观察信息的大小。在本示例中应调整为8,因为示例智能体脚本总共需要观察的特征元素为2个3D位置+2个1D速度,因此总共需要空间为8个float大小。

Vector Action Space Size:动作矢量的大小。在本示例中应调整为2,因为智能体脚本里接受2个浮点型动作输入。动作矢量的元素可以选择两种类型:一种是离散型的整型数值,适用于离散动作,例如下棋的位置选择;另一种则是连续性的浮点数值,适用于连续动作,例如3个float值可以代表一个施加到智能体刚体的力或力矩。

Inference Device:调整为GPU,从而使用GPU来训练。

Behavior Type:行为类型,主要有Default、Heuristic、Inference三种模式。

  1. Default:默认训练模式,用于一般的强化学习。
  2. Heuristic Only:启发模式,玩家亲自操控智能体,可用于模仿学习或调试游戏场景。
  3. Inference Only:推理模式,运行训练好的模型。

Roller Agent

Max Step:决定智能体最多可以有多少步决策,超过限制后则强制Done。特殊地,设置为0意思是不限制步数。在本示例中应调整为0。

Decision Requester

Decision Period:决策间隔。在本示例中应调整为10。


目前场景预览:

在这里,最好先Behavior Type切换成Heuristic Only模式用于调试游戏场景,运行Unity场景后可尝试自己用WASD键盘操控小球,测试游戏场景是否OK。然后确认无问题后再切换回Default

5. 开始训练


然后现在可以打开开始菜单,直接使用cmd命令窗口, cd到之前下载ml-agents项目的目录里

cd C:\Downloads\ml-agents

再输入激活ml-agents环境:

activate ml-agents

开启训练:

mlagents-learn config/config.yaml --run-id=RollerBall-1 --train
  • config/config.yaml是训练配置文件,RollerBall-1是你给训练出来的模型取的名字
  • 此外注意config/config.yaml是不存在的,可以自己仿照官方的示例yaml文件修改配置而新建的。

下面是config.yaml示例:

default:
    trainer: ppo
    batch_size: 10
    beta: 5.0e-3
    buffer_size: 100
    epsilon: 0.2
    gamma: 0.99
    hidden_units: 128
    lambd: 0.95
    learning_rate: 3.0e-4
    max_steps: 3.0e5
    memory_size: 256
    normalize: false
    num_epoch: 3
    num_layers: 2
    time_horizon: 64
    sequence_length: 64
    summary_freq: 1000
    use_recurrent: false
    use_curiosity: false
    curiosity_strength: 0.01
    curiosity_enc_size: 128
    reward_signals:
        extrinsic:
            strength: 1.0
            gamma: 0.99

有关config参数具体配置将放在文末附录。

当出现如下画面:

返还到Unity,点下运行键,那么你就会看到Unity执行训练。

你的命令窗口也会时刻告诉你训练阶段的信息:

  • Step:模拟的步长次数
  • Time Elapsed:所用时间
  • Mean Reward:奖励平均值
  • Std of Reward:奖励标准方差值

一般来说,随着训练的进行,奖励平均值越来越高,奖励标准方差值越来越低。这意味着智能体的行为越来越稳定趋向于获奖收益最高的行为。

现在可以去挂机等待结果了,亦或者在某个时间停止Unity场景运行。那么ml-agents会将目前为止训练出来的数据模型(.nn文件)保存到ml-agents\models目录下。

6. 将训练过的模型整合到Unity中


将训练出来的nn文件导入到Unity项目文件夹中,并在智能体Behavior Parameters脚本上的Model选择刚刚导入的nn文件;然后将Behavior Type调整为Inference Only。

运行Unity场景,看看你跑出来的模型的蠢样了(笑)。

附录

config文件配置

参数配置(翻修中):

参数名 描述 适用算法
trainer The type of training to perform: "ppo", "sac", "offline_bc" or "online_bc". PPO, SAC
batch_size The number of experiences in each iteration of gradient descent. PPO, SAC
batches_per_epoch In imitation learning, the number of batches of training examples to collect before training the model.
beta The strength of entropy regularization. PPO
buffer_size The number of experiences to collect before updating the policy model. In SAC, the max size of the experience buffer. PPO, SAC
buffer_init_steps The number of experiences to collect into the buffer before updating the policy model. SAC
epsilon Influences how rapidly the policy can evolve during training. PPO
hidden_units The number of units in the hidden layers of the neural network. PPO, SAC
init_entcoef How much the agent should explore in the beginning of training. SAC
lambd The regularization parameter. PPO
learning_rate The initial learning rate for gradient descent. PPO, SAC
learning_rate_schedule Determines how learning rate changes over time. PPO, SAC
max_steps The maximum number of simulation steps to run during a training session. PPO, SAC
memory_size The size of the memory an agent must keep. Used for training with a recurrent neural network. See Using Recurrent Neural Networks. PPO, SAC
normalize Whether to automatically normalize observations. PPO, SAC
num_epoch The number of passes to make through the experience buffer when performing gradient descent optimization. PPO
num_layers The number of hidden layers in the neural network. PPO, SAC
behavioral_cloning Use demonstrations to bootstrap the policy neural network. See Pretraining Using Demonstrations. PPO, SAC
reward_signals The reward signals used to train the policy. Enable Curiosity and GAIL here. See Reward Signals for configuration options. PPO, SAC
save_replay_buffer Saves the replay buffer when exiting training, and loads it on resume. SAC
sequence_length Defines how long the sequences of experiences must be while training. Only used for training with a recurrent neural network. See Using Recurrent Neural Networks. PPO, SAC
summary_freq How often, in steps, to save training statistics. This determines the number of data points shown by TensorBoard. PPO, SAC
tau How aggressively to update the target network used for bootstrapping value estimation in SAC. SAC
time_horizon How many steps of experience to collect per-agent before adding it to the experience buffer. PPO, SAC
train_interval How often to update the agent. SAC
num_update Number of mini-batches to update the agent with during each update. SAC
use_recurrent Train using a recurrent neural network. See Using Recurrent Neural Networks. PPO, SAC
  • PPO = Proximal Policy Optimization
  • SAC = Soft Actor-Critic
  • BC = Behavioral Cloning (Imitation)
  • GAIL = Generative Adversarial Imitaiton Learning

参考


另外一提,最新的介绍文档资料示例等都在Unity官方机器学习的github项目,感兴趣可以持续保持关注它的更新:

[1] Unity官方机器学习的github项目 https://github.com/Unity-Technologies/ml-agents

[2] Unity官方博客机器学习概念详解(1) https://blogs.unity3d.com/2017/12/11/using-machine-learning-agents-in-a-real-game-a-beginners-guide/

[3] Unity官方博客机器学习概念详解(2) https://blogs.unity3d.com/2017/06/26/unity-ai-themed-blog-entries/

[4] Unity ml-agents概念详解国内翻译博客 https://blog.csdn.net/u010019717/article/details/80382933

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!