Unityでは強化学習をサポートしてくれる
ML-Agentsというツールが用意されています。
これで、誰でも簡単に強化学習ができる・・・
のですが、動かすまでが結構大変だったりします。
使い方を解説しているサイトも沢山あったのですが、
どれも若干情報が古いらしく、
そんな設定見当たらないというところが多くありました。
最新の情報は公式のドキュメントを当たるのがベストですが、
少々分かりづらかったので、
自分なりにチュートリアルを実行する手順をまとめ直してみました。
インストール
準備が必要なのは以下の三つです。
- ML-Agentsのダウンロード
- mlagentsのインストール
- Barracudaのインストール
順に見ていきましょう。
ML-Agentsのダウンロード
githubからファイルをダウンロードします。
pythonライブラリのインストール
pythonで必要なライブラリをインストールしておきます。
pip3 install mlagents
を実行します。
Unityパッケージのインストール
Unity上で「Window」→「Package Manager」をクリックし、
「Advanced」→「show preview packages」をクリックします。
検索ボックスを活用して「Barracuda」パッケージをインストールします。
プロジェクトの作成
チュートリアルに沿って、
新しく学習する環境を作って、
エージェントに行動を学習させてみます。
Player Settings
「Edit」→「Project Settings」->「Player」から、
「Display Resolution Dialog」を「Disabled」に設定しておきます。
アセットの読み込み
ダウンロードしたフォルダから、
ml-agents-master/UnitySDK/Assets/ML-Agents
を、
プロジェクトのアセットフォルダにドラッグアンドドロップします。
オブジェクトを配置
ML-Agentsのチュートリアルにしたがって、
Plane,Cube,Sphereを配置します。
Agentコンポーネントの追加
SphereにRigidbodyを追加して、
学習用のスクリプトを新しく追加します。
ここでは、「testAgent」という名前にしました。
スクリプトの記述
学習エージェントの詳細な挙動を「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を選択します。
Behavior Parameterの追加
エージェントの設定を行うために、
Behavior Parameters
コンポーネントを追加します。
エージェントの入力と出力に合うように設定します。
- 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」のメッセージが現れます。
このメッセージを確認した後に、
Unity上の再生ボタンをクリックします。
正しく実行できていれば、
自動的にボールが転がり始めます。
最初のうちは全然ターゲットに向かいませんが、
しばらくすると、ターゲットに向かって動くようになり、
学習が進んでいる様子がわかります。
おまけ:学習状況をtensorboardで確認する
ターミナル上にも学習ログが表示されますが、
tensorboardを使うとグラフィカルに学習状況が確認できます。
tensorboardを使うには、
ターミナル上で次のコマンドを実行します。
tensorboard --logdir summaries
summaries
は学習結果が保存されているフォルダです。
コマンドを実行後、ブラウザから
http://localhost:6006/ にアクセスすると、
下のような画面が表示され、
学習状況の確認ができます。
学習結果の活用
強化学習によって、
現状の入力と行動への出力の対応関係が学習されます。
この学習の結果をエージェントに設定すれば、
エージェントが自分で行動を選択することができます。
学習結果はmodels
フォルダに保存されています。
models/test-1
の中のMy Behavior.nn
ファイルを
Unityのアセットフォルダに移しておきましょう。
※ファイルの名前は、Behavior Parameter
で設定したBehavior Name
で決まります。
このファイルをエージェントのBehavior Parameter
のModelに設定します。
これで実行してみると下の動画のように、
上手に追いかけてくれました。
まとめ
ML-Agentsを使って強化学習を行う流れを、
チュートリアルに従って実行してみました。
準備がかなり多めなので、
初見の敷居が高そうですが、
エージェントの記述はかなりシンプルなので使いやすそうです。
もう少し手順が簡略化されて、
スクリプトやオブジェクトの配置に集中できるようになるとさらに便利ですね。