Unity MLトレーニング学習環境構築(初級編)part2

0.はじめに

本記事では、「ml-agents-release_3(2020年6月10日発売)」のリリースを使って、Unityで "ボール(Agent)" が "ボックス(Target)" を追いかけるトレーニング環境を、全3回に渡って構築していきます。
第2回は、シーンの構築です。

1.フィールド(plane)の作成

(1)ヒエラルキーウィンドウの「+マーク」より「3D Object → Plane」を選択する。

画像1

(2)インスペクタ―ウィンドウ内の設定
①名前を『Floor』に変更する。
②「Position」と「Rotation」を『0, 0, 0』、「Scale」を『1, 1, 1』に設定(確認)。

画像2

2.エージェントの作成

(1)ヒエラルキーウィンドウの「+マーク」より「3D Object → Sphere」を選択する。
(2)インスペクタ―ウィンドウ内の設定
①名前を『RollerAgent』に変更する。
②「Position」を『0, 0.5, 0』、「Rotation」を『0, 0, 0』、「Scale」を『1, 1, 1』に設定する。
③「Add Component → Physics」から『Rigdbody』を選択

画像3


3.ターゲットの作成

(1)ヒエラルキーウィンドウの「+マーク」より「3D Object → Cube」を選択する。
(2)インスペクタ―ウィンドウ内の設定
①名前を『Target』に変更する。
②「Position」を『3, 0.5, 3』、「Rotation」を『0, 0, 0』、「Scale」を『1, 1, 1』に設定する。

画像4


4.グループ化

(1)ヒエラルキーウィンドウの「+マーク」より「Create Empty」を選択する。
(2)インスペクタ―ウィンドウ内の設定
①名前を『TrainingArea』に変更する。
「Position」と「Rotation」を『0, 0, 0』、「Scale」を『1, 1, 1』に設定(確認)。
(3)
ヒエラルキーウィンドウより、『Floor』、『Target』、『RollerAgent』を「TrainingArea」にドラッグしてまとめる。

画像5


5.カメラ位置の設定

(1)"Main Camera"のインスペクタウィンドウを開き、「Position」を『0, 4, -10』、「Rotation」を『10, 0, 0』、「Scale」を『1, 1, 1』に設定する。
※これは、奥も見えるように設定しただけです。「Position」「Rotation」は、好みの位置に調整してください。

画像8


6.プログラムの作成

(1)プロジェクトウィンドウの「+マーク」より「C# Script」を選択し、『RollerAgent』と名前をつけて作成する。
(2)『RollerAgent.cs』を「Visual Studio 2017」で開く。
(3)次のコードを入力します(コピー可)。開いたプログラムを全部選択し、上書きすることでスムーズに進みます。

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

public class RollerAgent : Agent
{
   Rigidbody rBody;
   void Start()
   {
       rBody = GetComponent<Rigidbody>();
   }

(4)" }"と同じインデントの位置から、次のプログラムを入力する。

public Transform Target;
public override void OnEpisodeBegin()
{
    if(this.transform.localPosition.y < 0)
    {
        // Agentが落ちたら運動量を0にする
        this.rBody.angularVelocity = Vector3.zero;
        this.rBody.velocity = Vector3.zero;
        this.transform.localPosition = new Vector3(0, 0.5f, 0);
    }
    // Targetを新しい場所に移動させる
    Target.localPosition = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
}

プログラム解説:
・各エピソードの開始時に、"OnEpisodeBegin()"関数が呼び出され、新たしいエピソードの環境がセットアップされる。
・"ボール(Agent)" が "ボックス(Target)"に到達するたびに、そのエピソードを終了し、"OnEpisodeBegin()"関数は "ボックス(Target)"をランダムな場所に移動させる。
・さらに"ボール(Agent)" が "Floor"から落ちが場合、"ボール(Agent)" を"Floor"に戻す。

(5)" }"と同じインデントの位置から、次のプログラムを入力する。

public override void CollectObservations(VectorSensor sensor)
{
    // TargetとAgentの位置
    sensor.AddObservation(Target.localPosition);
    sensor.AddObservation(this.transform.localPosition);

    // Agentの速度
    sensor.AddObservation(rBody.velocity.x);
    sensor.AddObservation(rBody.velocity.z);
}

プログラム解説:
・Agentが意思決定をできるように情報収集をする。
・Agentが収集する情報には、Targetの位置、Agent自体の位置、Agentの速度が含まれる。
・これは、Agentが目標をオーバーシュートして"Floor"から落ちないように速度を制御することを学習するのに役立ちます。

(6)" }"と同じインデントの位置から、次のプログラムを入力する。

public float forceMultiple = 10;
public override void OnActionReceived(float[] vectorAction)
{
    // xとz方向の移動(Action size = 2)
    Vector3 controlSignal = Vector3.zero;
    controlSignal.x = vectorAction[0];
    controlSignal.z = vectorAction[1];
    rBody.AddForce(controlSignal * forceMultiple);

    // 報酬
    float distanceToTarget = Vector3.Distance(this.transform.localPosition, Target.localPosition);

    // 目標達成
    if(distanceToTarget < 1.42f)
    {
        SetReward(1.0f);
        EndEpisode();
    }

    // Floorから落ちたら
    if(this.transform.localPosition.y < 0)
    {
        EndEpisode(); 
    }
}

プログラム解説:
・"OnActionReceived()関数で、行動を受け取り、強化学習に必要な報酬を割り当てる。
・今回は2次元で移動するので、x軸とz軸方向の移動の2つのアクションを用意する。action[]配列の値をそのRigidbodyコンポーネントに適用する。
・AgentがTargetに到達すると1.0の報酬が与えられ、"Episode()"を呼び出して、終了したとマークする。
・AgentがFloorから落ちた場合は、エピソードを終了して、リセットする。

(7)" }"と同じインデントの位置から、次のプログラムを入力する。

  public override void Heuristic(float[] actionsOut)
   {
       actionsOut[0] = Input.GetAxis("Horizontal");
       actionsOut[1] = Input.GetAxis("Vertical");
   }

}  <-これは「public class RollerAgent : Agent { 」の終わり

プログラム解説:
・キーボードを使用してAgentを制御し、動作を確認するテスト用のプログラムである。

(8)上書き保存して、Unityに戻りエラーがないか確認する。


7.Scriptの追加と(テスト)実行

(1)先ほど作成した『RollerAgent.cs』を、「RollerAgent」にドラッグして追加する。この時、自動的に「Behavior Parameters」が追加される。

scriptの追加

(2)"RollerAgent"のインスペクタウィンドウの「Add Component」より検索欄に『Decision Requester』を入力し、追加する。
(3)"RollerAgent"のインスペクタウィンドウ内の設定を、それぞれ次のようにする。
①Behavior Parameters
 ・"Behavior Name"を『RollerAgent』
 ・"Vector Observation"の「Space Size」を8
 ・"Vector Action"の「Space Type」を『Continuous』
 ・"Vector Action"の「Space Size」を2
 ・"Behavior Type"を『heuristic Only』 
②Decision Requester
 ・"Decision Period"を10
③RollerAgent
 ・"Target"に、ヒエラルキーウィンドウの"Target"(ボックス)をドラッグ
 して追加​

画像8

(4)再生ボタンを押して実行し、以下の動作が出来ているか確認する。
 ・矢印キー(またはAWSDキー)で、ボールが動く。
 ・ボックスに当たると消えて、別の場所に移動する。ただしボールは現在位置のまま。
 ・落ちると、ボールは"Floor"の中心に、ボックスはランダムな位置に配置される。

(5)動作を確認出来たら、"RollerAgent"のインスペクタウィンドウ内の
「Behavior Parameters」の"Behavior Type"を『Default』 に戻す
※これをしないと、学習時に自分でボールを操作しないといけなくなる。

8.まとめ

これで、学習するための環境が整いました。次回(最終回)は、トレーニングと推論、Agentのパフォーマンスの統計監視についてです。


この記事が気に入ったらサポートをしてみませんか?