クイックノート

ちょっとした発見・アイデアから知識の発掘を

ML-Agentsを使ってみる

Unityでは強化学習をサポートしてくれる
ML-Agentsというツールが用意されています。

これで、誰でも簡単に強化学習ができる・・・
のですが、動かすまでが結構大変だったりします。

使い方を解説しているサイトも沢山あったのですが、
どれも若干情報が古いらしく、
そんな設定見当たらないというところが多くありました。

最新の情報は公式のドキュメントを当たるのがベストですが、
少々分かりづらかったので、
自分なりにチュートリアルを実行する手順をまとめ直してみました。

インストール

準備が必要なのは以下の三つです。

  • ML-Agentsのダウンロード
  • mlagentsのインストール
  • Barracudaのインストール

順に見ていきましょう。

ML-Agentsのダウンロード

githubからファイルをダウンロードします。

pythonライブラリのインストール

pythonで必要なライブラリをインストールしておきます。

pip3 install mlagents

を実行します。

Unityパッケージのインストール

Unity上で「Window」→「Package Manager」をクリックし、

f:id:u874072e:20200115155937p:plain:w300
package manager

「Advanced」→「show preview packages」をクリックします。

f:id:u874072e:20200115160130p:plain
show preview packagesにチェック

検索ボックスを活用して「Barracuda」パッケージをインストールします。

f:id:u874072e:20200115160304p:plain
Barracudaをインストール

プロジェクトの作成

チュートリアルに沿って、
新しく学習する環境を作って、
エージェントに行動を学習させてみます。

Player Settings

「Edit」→「Project Settings」->「Player」から、
「Display Resolution Dialog」を「Disabled」に設定しておきます。

f:id:u874072e:20200116133327p:plain:w300
Display Resolution DialogをDisabledに設定

アセットの読み込み

ダウンロードしたフォルダから、
ml-agents-master/UnitySDK/Assets/ML-Agentsを、
プロジェクトのアセットフォルダにドラッグアンドドロップします。

f:id:u874072e:20200115160757p:plain
アセットフォルダにドラッグ&ドロップ

オブジェクトを配置

ML-Agentsのチュートリアルにしたがって、
Plane,Cube,Sphereを配置します。

f:id:u874072e:20200115163142p:plain
オブジェクトを配置

Agentコンポーネントの追加

SphereにRigidbodyを追加して、
学習用のスクリプトを新しく追加します。
ここでは、「testAgent」という名前にしました。

f:id:u874072e:20200115163939p:plain:h300
学習用のエージェントスクリプトを新規作成

スクリプトの記述

学習エージェントの詳細な挙動を「testAgent」に記述します。

Agentクラスの継承

基本となるスクリプトの形を下に示します。

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

public class testAgent : Agent
{
    Rigidbody rb;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
}

MLAgentsを読み込み、
Agentクラスを継承します。

Update()メソッドは削除して、
Start()メソッドのみを残します。
最低限の挙動としてRigidbodyだけ取得して変数に代入しています。

エージェントの動きは、この後実装するメソッドの中で記述していきます。

AgentReset

学習のために環境を反復する必要があります。
環境のリセットをAgentReset()の中で記述していきます。

    public Transform Target;
    public override void AgentReset()
    {
        if (this.transform.position.y < 0)
        {
            // If the Agent fell, zero its momentum
            this.rb.angularVelocity = Vector3.zero;
            this.rb.velocity = Vector3.zero;
            this.transform.position = new Vector3(0, 0.5f, 0);
        }

        // Move the target to a new spot
        Target.position = new Vector3(Random.value * 8 - 4,
                                      0.5f,
                                      Random.value * 8 - 4);
    }

Targetは後でUnity上で設定するターゲットオブジェクトです。

この場合は、エージェントが落下した場合や、
ターゲットに到達した場合に、
エージェントやターゲットの位置を配置し直しています。

CollectObservation

エージェントは、現状を入力として、
行動を選択します。

現状を把握するために用いる情報を、
CollectObservation()で定義します。

    public override void CollectObservations()
    {
        // Target and Agent positions
        AddVectorObs(Target.position);
        AddVectorObs(this.transform.position);

        // Agent velocity
        AddVectorObs(rb.velocity.x);
        AddVectorObs(rb.velocity.z);
    }

AddVectorObs()を使って取得する情報を加えていきます。
上の場合、ターゲットとエージェントの座標、
エージェントの速度の情報を使って行動を決定することになります。

AgentAction

エージェントの動作はAgentAction()で記述します。
ここでは、行動と終了判定及びその結果の報酬を定義します。

    public float speed = 10;
    public override void AgentAction(float[] vectorAction)
    {
        // Actions, size = 2
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        rb.AddForce(controlSignal * speed);

        // Rewards
        float distanceToTarget = Vector3.Distance(this.transform.position,
                                                  Target.position);

        // Reached target
        if (distanceToTarget < 1.42f)
        {
            SetReward(1.0f);
            Done();
        }

        // Fell off platform
        if (this.transform.position.y < 0)
        {
            Done();
        }

    }

把握した現状から導かれた選択がvectorActionに渡されます。
このvectorActionを使ってUnity上のオブジェクトを動かします。
上のスクリプトではvectorActionを動力に設定しています。

また、1サイクルの終了条件として、

  • ターゲットに到達した場合
  • エージェントが落ちた場合

を設定しています。
終了条件に合致した場合はDone()を呼び出してサイクルを終了しています。

ターゲットに到達した場合は報酬をsetRewardで報酬を与えています。

Targetの設定

再びUnity上での操作に戻ります。
testAgentのターゲットとして、
Cubeを選択します。

f:id:u874072e:20200116140248p:plain
ターゲットの設定

Behavior Parameterの追加

エージェントの設定を行うために、
Behavior Parametersコンポーネントを追加します。

f:id:u874072e:20200116133710p:plain:h300
Behavior Parameterの追加

エージェントの入力と出力に合うように設定します。

f:id:u874072e:20200116154052p:plain:w300
Behavior Parameterの設定

  • Vector ObservationのSpace Size : 観測する情報の数(今の場合、ターゲットの座標(3)+エージェントの座標(3)+x,z軸のエージェントの速度(2)で8個)
  • Vector ActionのSpace Type: 行動の変数型(今回の場合、動力を表すので連続値(Continuous)
  • Vector ActionのSpace Size: 行動の変数の数(今回の場合、x,z軸の動力なので2個)

学習の実行

環境の準備とエージェントの定義が終わったら、
いよいよ学習を実行します。

学習の実行には、まずターミナル上で、
学習のプロセスを走らせて、
その後、Unityの再生ボタンを押すことで開始します。

mlagents-learnプロセスの実行

学習を行うには、一旦Unityから離れて、
ターミナル上でmlagents-learnを起動する必要があります。

起動コマンドは下の通りです。

mlagents-learn  config/trainer_config.yaml  --run-id=test-1 --train

config/trainer_config.yamlは学習の設定ファイルです。
ダウンロードしたml-agents-masterの中にある
デフォルトの設定ファイルconfig/trainer_config.yamlを指定しています。

--run-idには学習結果を区別するための名前を指定します。

Unityで再生ボタンをクリックする

コマンドを実行すると、
下のような画面が表示され、
「Start trainning by pressing the Play button」のメッセージが現れます。

f:id:u874072e:20200116155731p:plain
プロセスの起動画面

このメッセージを確認した後に、
Unity上の再生ボタンをクリックします。

正しく実行できていれば、
自動的にボールが転がり始めます。

最初のうちは全然ターゲットに向かいませんが、
しばらくすると、ターゲットに向かって動くようになり、
学習が進んでいる様子がわかります。

おまけ:学習状況をtensorboardで確認する

ターミナル上にも学習ログが表示されますが、
tensorboardを使うとグラフィカルに学習状況が確認できます。

tensorboardを使うには、
ターミナル上で次のコマンドを実行します。

tensorboard --logdir summaries

summariesは学習結果が保存されているフォルダです。

コマンドを実行後、ブラウザから
http://localhost:6006/ にアクセスすると、
下のような画面が表示され、
学習状況の確認ができます。

f:id:u874072e:20200116161340p:plain
TensorBoardの画面

学習結果の活用

強化学習によって、
現状の入力と行動への出力の対応関係が学習されます。
この学習の結果をエージェントに設定すれば、
エージェントが自分で行動を選択することができます。

学習結果はmodelsフォルダに保存されています。
models/test-1の中のMy Behavior.nnファイルを
Unityのアセットフォルダに移しておきましょう。
※ファイルの名前は、Behavior Parameterで設定したBehavior Nameで決まります。

このファイルをエージェントのBehavior ParameterのModelに設定します。

f:id:u874072e:20200116162001p:plain:w300
学習済みモデルの設定

これで実行してみると下の動画のように、
上手に追いかけてくれました。


箱を追いかけるボール

まとめ

ML-Agentsを使って強化学習を行う流れを、
チュートリアルに従って実行してみました。

準備がかなり多めなので、
初見の敷居が高そうですが、
エージェントの記述はかなりシンプルなので使いやすそうです。

もう少し手順が簡略化されて、
スクリプトやオブジェクトの配置に集中できるようになるとさらに便利ですね。

プライバシーポリシー