Unityで機械学習(その5)

Unity

今回はRaycastという見えない光線を照射することでTargetを見つけるという機械学習を行う。

作成

UnityHumを開き新規3DプロジェクトからRaycastMLという名でプロジェクトを作成する。

packageのインストール

PackageManagerを開き+ボタンからadd package from diskを選択する

GitHubからインストール済みのml-agentsフォルダ->com.unity.ml-agents->package.jsonを選択しインポートする。(ここらへんの手順はここに詳しく記載Mac,Win)

ステージの作成

準備ができたのでさっそくステージを作成していこう。

○Create3Dオブジェクトからplaneを選択

○Create3DオブジェクトからSphereを作成。Targetとリネームする。トランスフォームは以下

○Targetタグを作成して、付与する。

○(任意)マテリアルを付与しよう。ここでは赤くしてみた。

○主人公を作成しよう。まずは原点にCreateEmptyしてAgentとリネーム

○体を作ろう。Agentを右クリックして、新規Cubeを作成してBodyとリネーム。トランスフォームは以下

○頭を作る。Agentを右クリックして、新規Sphereを作成しHeadとリネーム。トランスフォームは以下

○(任意)好きな色をつけよう。

○Agentを選択してRigidbodyを付与。コンストレインツを設定して回転はY軸方向のみができるようにしておく

Agentとしての設定

機械学習できるよう設定をしていく。Agentを選択しAddComponentからBehaviorParametersを付与。以下のように設定する。

(解説) BehaviorParametersは機械学習する際に必須となる。
Behavior Name:設定ファイル(yaml)から参照する際の識別子となる
○Branch 0 Size:5は以下5つの行動の数
0:移動なし
1:前進
2:後退
3:右回転
4:左回転

Ray Sensorの設定

Agentを選択して、AddComponentからRay Perception Sensor 3Dを選択。以下のように設定する。

(解説)
SensorName:センサー名
Detactable Tags:検出タグ
RayPerDirection:中心から左右のレイの数
MaxRayDegrees:最外のレイの正面からの角度
SphereCastRadius:レイとして飛ばす球の半径
RayLength:レイの長さ

スクリプトの作成

○新規C#スクリプトからNekoAgentを作成以下のように記述し、Agentにアタッチする。

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

public class NekoAgent : Agent {
    public Transform target;
    Rigidbody rb;

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

    // エピソード開始時に呼ばれる
    public override void OnEpisodeBegin() {
        // Agentの落下時
        if (transform.localPosition.y < 0) {
            // Agentの位置と速度をリセット
            rb.angularVelocity = Vector3.zero;
            rb.velocity = Vector3.zero;
            transform.localPosition = Vector3.zero;
        }

        // Targetの位置のリセット
        target.localPosition = new Vector3(
            Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
    }

    // 行動実行時に呼ばれる
    public override void OnActionReceived(ActionBuffers actions) {
        Vector3 dirToGo = Vector3.zero;
        Vector3 rotateDir = Vector3.zero;
        int action = actions.DiscreteActions[0];

        if (action == 1) dirToGo = transform.forward;
        if (action == 2) dirToGo = transform.forward * -1.0f;
        if (action == 3) rotateDir = transform.up * -1.0f;
        if (action == 4) rotateDir = transform.up;
        transform.Rotate(rotateDir, Time.deltaTime * 200f);
        rb.AddForce(dirToGo * 0.4f, ForceMode.VelocityChange);

        // RaycastAgentがTargetの位置に到着
        float distanceToTarget = Vector3.Distance(
            transform.localPosition, target.localPosition);
        if (distanceToTarget < 1.42f) {
            AddReward(1.0f);
            EndEpisode();
        }

        // RaycastAgentが落下
        if (this.transform.localPosition.y < -0.1f) {
            EndEpisode();
        }
    }

    // ヒューリスティックモードの行動決定時に呼ばれる
    public override void Heuristic(in ActionBuffers actionsOut) {
        var actions = actionsOut.DiscreteActions;
        actions[0] = 0;
        if (Input.GetKey(KeyCode.UpArrow)) actions[0] = 1;
        if (Input.GetKey(KeyCode.DownArrow)) actions[0] = 2;
        if (Input.GetKey(KeyCode.LeftArrow)) actions[0] = 3;
        if (Input.GetKey(KeyCode.RightArrow)) actions[0] = 4;
    }
}

○インスペクターから以下のように設定する

○Agentを選択し、AddComponentからDecision Requesterを追加。以下のように設定する

Heuristicで試す

Heuristicをオーバーライドしているのでこの段階で試すことができる実行してみよう。
矢印キーでAgentが動くのでTargetまで移動してみよう。

訓練ファイルの作成

bashに移動して、GitHubからクローンしたml-agentsフォルダに移動し、configフォルダ内にneko.yamlを作成する。

内容は以下をコピペする。

behaviors:
  Neko:
    trainer_type: ppo
    hyperparameters:
      batch_size: 128
      buffer_size: 2048
      learning_rate: 0.0003
      beta: 0.005
      epsilon: 0.2
      lambd: 0.95
      learning_rate_schedule: linear
    network_settings:
      normalize: true
      hidden_units: 128
      num_layers: 2
    reward_signals:
      extrinsic:
        gamma: 0.99
        strength: 1.0
    checkpoint_interval: 500000
    max_steps: 500000
    time_horizon: 64
    summary_freq: 10000
    threaded: true

このパラメータの詳細はここにある。

学習開始

では学習を開始しよう。以下のコマンドを入力して、Unityを実行する

$ mlagents-learn ./config/neko.yaml --run-id=neko1

学習できてきたと思ったらUnityの再生を止めよう。学習ファイルはresultsフォルダに入っているのでそれをUnityにドラッグ

Behavior PrametersのModelに登録。再生して学習の成果を見よう。

学習の成果をご覧あれ

終わりに

今回はセンサーを使って状況を判断し、行動をするという学習を行った。フィールドをさまよう敵の行動AIとしても使えそうだ。

考書

以下の書籍を参考にしています。

Unity
スポンサーリンク
シェアする
mjpurinをフォローする

コメント

タイトルとURLをコピーしました