見出し画像

Unity ML-Agents Release 18 のチュートリアル

「Unity ML-Agents Release 18」で、強化学習の学習環境を作成する手順をまとめました。

・Unity 2019.4以降
・Unity ML-Agents Release 18
・Python 3.7

前回

1. 学習環境の概要

ボール(RollerAgent)が立方体(Target)に向かって転がるように訓練する学習環境になります。

画像1

今回の学習環境の要素は次のとおりです。

・観察
 ・Vector Observation (サイズ8)
  0 : TargetのX座標
  1 : TargetのY座標
  2 : TargetのZ座標
  : RollerAgentのX座標
  : RollerAgentのY座標
  5 : RollerAgentのZ座標
  6 : RollerAgentのX速度
  7 : RollerAgentのZ速度
・行動
 ・Continuous (サイズ2)
  0 : RollerAgentのX方向に加える力
  1 : RollerAgentのZ方向に加える力
・報酬 :
 ・RollerAgentがTargetに到着 : +1.0 (エピソード完了)
 ・RollerAgentが落下 : +0.0 (エピソード完了)

2. 開発環境のインストール

「Unity ML-Agents」に必要な開発ツールは次のとおりです。

2-1. Unity

以下のサイトから「Unity Hub」をインストールし、「Unity Hub」で「Unity 2019.4」をインストールします。

2-2. Unity ML-Agents

以下のサイトのRelease 18」の「download」から、ZIPファイルをダウンロードして解凍し、フォルダ名を「ml-agents」に変更します。

画像2

フォルダ構成は、次のとおりです。

・com.unity.ml-agents : Unityプラグイン
・ml-agents : 強化学習を行うPythonパッケージ
・ml-agents-envs : Unity-Python間インタフェースのPythonパッケージ
・config : 学習設定ファイル

2-3. Pythonの開発環境

「Python 3.7」の開発環境をインストールします。

WindowsでのPythonの開発環境の準備
MacでのPythonの開発環境の準備

2-4. ML-AgentsのPythonパッケージ

Pythonの仮想環境で、ml-agentsフォルダに移動し、以下のコマンドを実行します。

$ pip install --upgrade pip
$ pip install -e ./ml-agents-envs
$ pip install -e ./ml-agents

3. Unity ML-Agentsのプロジェクトの準備

「Unity ML-Agents」のプロジェクトの準備の手順は、次のとおりです。

(1) Unityを起動し、Unityのプロジェクトを「3D」で新規作成。
(2) メニュー「Window → Package Manager」を開き、「+ → Add package from disk」を選択し、「ml-agents/com.unity.ml-agents/package.json」を選択。

画像3

4. 学習環境の作成

◎ カメラの位置と向きの調整
(1) Hierarchyウィンドウで「Main Camera」を選択。
(2) Inspectorウィンドウで以下を設定。

Position = (0, 4, -10)
Rotation = (20, 0, 0)
Scale = (1, 1, 1)

◎ マテリアルの作成
(1) Projectウィンドウで「Create → Material」で「Material」を作成し、名前に「Gray」を指定。
(2) 「Gray」を選択し、Inspectorウィンドウの「Main Maps → Albedo」(テクスチャ色)で灰色(168,168,168)を指定。
(3) 同様に茶色(212,154,33)のマテリアル「Brown」と、青色(0,35,255)のマテリアル「Blue」を作成。

◎ Floorの追加
(1) Hierarchyウィンドウの「Create → 3D Object → Plane」で「Plane」を追加し、名前に「Floor」を指定。
(2) 「Floor」を選択し、Inspectorウィンドウで以下を設定。

Position = (0, 0, 0)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

(3) 「Floor」の「Mesh Renderer」の「Materials → Element 0」に灰色のマテリアル「Gray」を指定。

◎ Targetの追加
(1) Hierarchyウィンドウの「Create → 3D Object → Cube」で「Cube」を追加し、名前に「Target」を指定。
(2) 「Target」を選択し、Inspectorウィンドウで以下を設定。

Position = (3, 0.5, 3)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

(3) 「Target」の「Mesh Renderer」の「Materials → Element 0」に茶色のマテリアル「Brown」を指定。

◎ RollerAgentの追加
(1) Hierarchyウィンドウの「Create → 3D Object → Sphere」で「Sphere」を追加し、名前に「RollerAgent」を指定。
(2) 「RollerAgent」を選択し、Inspectorウィンドウで以下を設定。

Position = (0, 0.5, 0)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

(3) 「Mesh Renderer」の「Materials → Element 0」に青のマテリアル「Blue」を指定。
(4) 「Add Component」で「Rigidbody」を追加。

5. Unity ML-Agentsのコンポーネントの追加

学習環境に「観察」「行動」「報酬」を設定するため、「ML-Agentsのコンポーネント」を追加します。

・Behaviour Parameters : 「観察」や「行動」のデータ型を指定。
・ Agentクラスを継承したスクリプト : 「人工知能への観察の提供」「人工知能が決定した行動の実行」「行動結果に応じた報酬」を指定。
・Decision Requester : 何フレーム毎に行動を決定(変更)するかを指定。

5-1. Behavior Parametersの追加

「観察」や「行動」のデータ型を指定するコンポーネントです。

(1) 「RollerAgent」に「Add Component」で「Behavior Parameters」を追加。
(2) 「RollerAgent」を選択し、Inspectorウィンドウで以下を設定。

画像5
Behavior Name = RollerBall
Vector Observation → Space Size = 6
Vector Observation → Stacked Vectors = 1
Actions → Continuous Actions = 2
Actions → Discrete Branches = 0

5-2. Agentクラスを継承したスクリプトの追加

「人工知能への観察の提供」「人工知能が決定した行動の実行」「行動結果に応じた報酬」を指定するスクリプトです。

(1) コンポーネント「RollerAgent」を選択して、「Add Component」で新規スクリプト「RollerAgent」を追加。

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

// RollerAgent
public class RollerAgent : Agent
{
    public Transform target;
    Rigidbody rBody;

    // 初期化時に呼ばれる
    public override void Initialize()
    {
        this.rBody = GetComponent<Rigidbody>();
    } 

    // エピソード開始時に呼ばれる
    public override void OnEpisodeBegin()
    {
        // RollerAgentが床から落下している時
        if (this.transform.localPosition.y < 0)
        {
            // RollerAgentの位置と速度をリセット
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            this.transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f);
        }

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

    // 観察取得時に呼ばれる
    public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(target.localPosition); //TargetのXYZ座標
        sensor.AddObservation(this.transform.localPosition); //RollerAgentのXYZ座標
        sensor.AddObservation(rBody.velocity.x); // RollerAgentのX速度
        sensor.AddObservation(rBody.velocity.z); // RollerAgentのZ速度
    }

    // 行動実行時に呼ばれる
    public override void OnActionReceived(ActionBuffers actionBuffers)
    {
        // RollerAgentに力を加える
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = actionBuffers.ContinuousActions[0];
        controlSignal.z = actionBuffers.ContinuousActions[1];
        rBody.AddForce(controlSignal * 10);

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

        // RollerAgentが床から落下した時
        if (this.transform.localPosition.y < 0)
        {
            EndEpisode();
        }
    } 

    // ヒューリスティックモードの行動決定時に呼ばれる
    public override void Heuristic(in ActionBuffers actionsOut)
    {
        var continuousActionsOut = actionsOut.ContinuousActions;
        continuousActionsOut[0] = Input.GetAxis("Horizontal");
        continuousActionsOut[1] = Input.GetAxis("Vertical");
    }
}

Agentクラスのオーバーライドメソッドは、次のとおりです。

・Initialize() : インスタンス生成時の初期化。
・OnEpisodeBegin() : エピソード開始時の初期化。
・CollectObservations(VectorSensor sensor) : 人工知能への状態の提供。
・OnActionReceived(ActionBuffers actionBuffers) : 人工知能が決定した行動を受け取り実行し、行動結果に応じて報酬を提供。
・Heuristic(in ActionBuffers actionsOut) : 人間による行動の決定。

(2) Hierarchyウィンドウで「RollerAgent」を選択し、Inspectorウィンドウで以下を設定。
Targetには、HierarchyウィンドウのTargetを「RollerAgent」のTargetにドラッグ&ドロップします。

画像5
Max Step = 1000
Target = Target

5-3. Decision Requesterの追加

何フレーム毎に行動を決定(変更)するかを指定するコンポーネントです。

(1) 「RollerAgent」に「Add Component」で「Decision Requester」を追加。
(2) 「RollerAgent」を選択し、Inspectorウィンドウで以下を設定。

画像6
Decision Period = 10

6. 学習環境の動作確認

UnityエディタのPlayボタンで実行すると、学習前に学習環境の動作確認ができます。方向キーでボールを動かし、立方体に衝突すると立方体が移動し、ボールが落下すると床の上に戻ります。

画像7

UnityエディタをPlayボタンで実行した時に、適用されるモードは、次のとおりです。

(1) 学習を行うPythonスクリプトが実行中 → 学習
(2) (1)以外で、Behavior ParametersのModelが存在 → 推論
(3) (1)(2)以外で、Heuristic()を定義 → ヒューリスティック (今回はこれ)

7. Pythonスクリプトによる学習

Pythonスクリプトによる学習を行い、「推論モデル」を生成します。

(1) 「ml-agents/config」に「RollerBall.yaml」を作成し、以下のように編集。
学習時に必要なハイパーパラメータを設定します。

behaviors:
  RollerBall:
    # トレーナー種別
    trainer_type: ppo
   
    # 基本設定
    max_steps: 500000
    time_horizon: 1000
    summary_freq: 12000
    keep_checkpoints: 5    
   
    # 学習アルゴリズムの設定
    hyperparameters:
      batch_size: 64
      buffer_size: 12000
      learning_rate: 0.0003
      beta: 0.001
      epsilon: 0.2
      lambd: 0.99
      num_epoch: 3
      learning_rate_schedule: linear
   
    # ニューラルネットワークの設定
    network_settings:
      normalize: true
      hidden_units: 128
      num_layers: 2
      vis_encode_type: simple
     
    # 報酬の設定
    reward_signals:
      extrinsic:
        gamma: 0.99
        strength: 1.0

各パラメータについては、以下を参照。

(2) Pythonの仮想環境で、ml-agentsフォルダに移動し、以下のコマンドを実行。
「--run-id」は学習IDで学習結果の出力先フォルダ名にもなります。学習毎に変更してください。

$ mlagents-learn ./config/RollerBall.yaml --run-id=RollerBall-ppo-1
                         ▄▄▄▓▓▓▓
                   ╓▓▓▓▓▓▓█▓▓▓▓▓
              ,▄▄▄m▀▀▀'  ,▓▓▓▀▓▓▄                           ▓▓▓  ▓▓▌
            ▄▓▓▓▀'      ▄▓▓▀  ▓▓▓      ▄▄     ▄▄ ,▄▄ ▄▄▄▄   ,▄▄ ▄▓▓▌▄ ▄▄▄    ,▄▄
          ▄▓▓▓▀        ▄▓▓▀   ▐▓▓▌     ▓▓▌   ▐▓▓ ▐▓▓▓▀▀▀▓▓▌ ▓▓▓ ▀▓▓▌▀ ^▓▓▌  ╒▓▓▌
        ▄▓▓▓▓▓▄▄▄▄▄▄▄▄▓▓▓      ▓▀      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌   ▐▓▓▄ ▓▓▌
        ▀▓▓▓▓▀▀▀▀▀▀▀▀▀▀▓▓▄     ▓▓      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌    ▐▓▓▐▓▓
          ^█▓▓▓        ▀▓▓▄   ▐▓▓▌     ▓▓▓▓▄▓▓▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▓▄    ▓▓▓▓`
            '▀▓▓▓▄      ^▓▓▓  ▓▓▓       └▀▀▀▀ ▀▀ ^▀▀    `▀▀ `▀▀   '▀▀    ▐▓▓▌
               ▀▀▀▀▓▄▄▄   ▓▓▓▓▓▓,                                      ▓▓▓▓▀
                   `▀█▓▓▓▓▓▓▓▓▓▌
                        ¬`▀▀▀█▓

       
Version information:
  ml-agents: 0.25.0,
  ml-agents-envs: 0.25.0,
  Communicator API: 1.5.0,
  PyTorch: 1.8.0
[learn.py:245] run_seed set to 8994
[torch.py:58] default Torch device: cpu
[environment.py:211] Listening on port 5004. Start training by pressing the Play button in the Unity Editor.

mlagents-learnの引数については、以下を参照。

(3) Unity EditorのPlayボタンを押して学習開始。
20,000ステップほどで学習できます。

RollerBall. Step: 1000. Time Elapsed: 16.079 s. Mean Reward: 0.233. Std of Reward: 0.423. Training.
RollerBall. Step: 2000. Time Elapsed: 25.849 s. Mean Reward: 0.279. Std of Reward: 0.449. Training.
RollerBall. Step: 3000. Time Elapsed: 35.810 s. Mean Reward: 0.450. Std of Reward: 0.497. Training.
    :
RollerBall. Step: 17000. Time Elapsed: 176.080 s. Mean Reward: 1.000. Std of Reward: 0.000. Training.
RollerBall. Step: 18000. Time Elapsed: 186.137 s. Mean Reward: 1.000. Std of Reward: 0.000. Training.
RollerBall. Step: 19000. Time Elapsed: 196.108 s. Mean Reward: 1.000. Std of Reward: 0.000. Training.
画像8

macOSではセキュリティのため、以下のようなエラーが表示されます。キャンセルして、「設定→セキュリティとプライバシー」の「ダウンロードしたプリケーションの実行許可」で「このまま許可」を押してから、再実行してください。

(4) Ctrl-Cで学習完了すると、「results/RollerBall-ppo-1/RollerBall.onnx」に推論モデルが生成されています。

【おまけ】 TensorBaord

以下のコマンド実行後、「http://localhost:6006/」をブラウザで開くことで、学習状況をグラフで確認できます。

$ tensorboard --logdir=results
画像9

次回



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