はじめに
Windows10でUnityとML-Agentsというパッケージを使用して,強化学習を行うやり方を説明します.
基本的にこちらのドキュメントにそって説明を行いたいと思います.
この記事では次のようにボールにAgentを搭載し,四角いボックスを追いかけさせるプログラムを0から作成していきます.
目次
実行環境
バージョン | |
---|---|
Windows10 | 1909 |
Unity | 2019.4.3f1 |
Python(Anaconda3) | 3.7.6 |
ML-Agents | Release 3 |
ML-Agentsは現在(2020/07/14)で最新であるRelease 3
を使用します.
Release 3
ではUnityに関しては2018.04
以降,Pythonに関しては3.6.1
以上が対応しています.
Pythonの環境にAnacondaを使用する場合は関係ないですが,ML-Agentsのインストールの際にpip3
が必要になります.
環境構築
Unityのインストール
次のサイトにアクセスし,Unity Hubをダウンロートします.
Unity HubはUnityのバージョン管理をしてくれるソフトウェアです.
Unity Hubのインストールが完了したら,次にアカウントの登録を行います.
Unityのサイトでアカウントを作成し,サインインしてください.
次にライセンスの登録を行います.
今回はUnity Personalを使用するので次のように選びます.
続いてUnity本体のインストールを行います.次の画面から適当なバージョンを選択してインストールしてください.もしVisual Studioがない場合,ここで自動的にインストールしてくれます.
インストールに結構時間がかかります.
Python(Anaconda3)のインストール
次のサイトにアクセスし,下の方のPython3.7 64-Bit Graphical Installerをダウンロードします.
https://www.anaconda.com/products/individual#windows
インストーラーがダウンロードできたら,後は流れでインストールしていきます.
途中にAnaconda3のパスを環境変数に登録するかしないかの確認が入りますが,特になにも無ければ環境変数に登録しても大丈夫だと思います(もうすでにPythonの環境を構築していたり複数のバージョンを管理しているなどがなければ...)が推奨されていないみたいです.
ここのチェックを付けない場合,自分で環境変数を通す必要があります(Anaconda Promptを使う場合は必要ないかも).
今回はPowerShellを使って実行していきます.
PowerShellでAnacondaを使用できるようにする
環境変数にパスが通っているとPowerShellでPythonが実行できるようになります.
しかし,Anacondaで仮想環境を作ってそこでいろいろしたいときにconda activate
で仮想環境に入ったりするんですが,デフォルトのPowerShellだと上手く実行できません.
自分はPowerShellが好きなので,なんとしてでもPowerShellで実行したいです.
いろいろ探していたら次の記事でやり方が報告されていたので参考にしました.
PowerShellで次のコマンドを実行します.
conda init powershell
ここでPowerShellを再起動したりするとエラーがでるようになると思います.
次に管理者権限でPowerShellを開き,次のコマンドを実行します.
実行しますか~と聞かれるのでYESを選択.
Set-ExecutionPolicy RemoteSigned
PowerShellを再起動して,次のように(base)
と表示されたら成功です.
Anacondaに強化学習用の仮想環境を作成する
Anacondaが使えるようになったら,強化学習用の仮想環境を作成します.
仮想環境を作成することで,環境の切り替えや,壊れた際に簡単にやり直すことができます.
次のコマンドで仮想環境を作成します.
conda create -n ml-agents python=3.6
仮想環境を切り替える際はconda activate <名前>
を実行します.
conda activate ml-agents
次のように(ml-agents)
を表示されれば成功です.
ML-Agents Release 3 のセットアップ
次のML-AgentsのReleaseのページから,ソースコードをダウンロードします.
下の方に行くとボタンがあるのでSource code(zip)
を選択して,ダウンロードします.
そして,適当なフォルダに解凍してください.
コマンドラインからGitを実行できる人は以下のコマンドでRelease3をダウンロードすることができます.
git clone --branch release_3 https://github.com/Unity-Technologies/ml-agents.git
ここからは先程作成した仮想環境(ml-agents)
に入った状態おこないます.
次のコマンドでPythonのmlagentsパッケージをインストールします.
pip3 install mlagents
次に先程GitHubからダウンロードして解凍したフォルダに移動して,PowerShellを開きます.
そして次のコマンドを実行します.
pip3 install -e ./ml-agents-envs
pip3 install -e ./ml-agents
サンプルプログラムの動作チェック
ここではML-Agentsのサンプルの1つである3DBall
の強化学習を行っていきます.
次のようにボックスが上にボールを乗せている状況を考えます.強化学習を行いボールを落とさないようにボックスにバランスをとらせることが目標です.
それではやっていきましょう.
Unity Hubを開いて,プロジェクト→リストに追加をクリックします.フォルダを開くダイアログがでるので先程ダウンロードしたml-agents-release_3\Projectを指定します.
次にUnityのバージョンを更新します.Unityバージョンの欄をクリックして先程インストールしたバージョンを選択します.
その状態でProjectをクリックするとUnityが開かれるのですが,初回は次のようにプロジェクトをアップグレードしますか?というダイアログがでるので確認をクリックして進みます.
プロジェクトが開かれたら,次のようにProjectビューからML-Agents→Examples→3DBall→Scenesをダブルクリックで開き,3DBallというシーンをダブルクリックしてください.
すると,青いボックスが12個並んだシーンが表示されます.こちらのシーンには最初からトレーニング済みの学習モデルがセットされているため,この状態で上の再生(Play)ボタンを押すと,しっかりとバランスを取る動作を行います.
今回は学習を行うので,トレーニング済みの学習モデルを一度プレハブから取り除きます.
取り除く際は下の手順のようにプレハブを操作することで,シーン全体のボックスの内容を変更することができます.
- ProjectビューからML-Agents→Examples→3DBall→Prefabsをダブルクリックで開く
- 3DBallのプレハブををダブルクリック.するとHierarchyビューに表示されます.
- HierarchyビューからAgentを選択
- InspectorビューからBehabior Parameteresのモデルを選択
- モデルとしてNoneを選択.
これで学習済みモデルを引き剥がすことができました.
この状態で,再生(Play)ボタンを押すと,青いボックスを矢印キーで動かすことができるようになります.
試しにやってみます(すべてのボックスが同期して動くので次のGIFでは左上のボックスに注目しています)が結構難しいです.
それでは学習を行っていきましょう.
PowerShell
でGitHubからダウンロートしてきたml-agents-release_3フォルダを開きます.
そこで次のコマンドを実行します.
run-id
は識別子のようなもので重複は許されません.この名前のフォルダに学習モデルが保存されます.
mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun
実行して次の画面のようにUnityのロゴが出て,Start training by pressing the Play button in the Unity Editor.
という表記がでたら,Unityの画面に戻り,再生(Play)ボタンを押してください.
すると次のように自動で高速にボックスが動き,学習が始まります.
しばし待ちましょう(10分もしないくらい?).
もし,途中で終了する場合はUnity側の再生ボタンを再度クリックすることで終了できます(PowerShell側からやると学習結果が消えます).
正常に終了したら,学習は成功です.
学習結果はml-agents-release_3\results\first3DBallRun\3DBall.nnに保存されます.
その学習結果を次の画面参考に,ProjectビューからML-Agents→Examples→3DBall→TFModelsを開き,そこにドラッグ&ドロップします.
すると次のように3DBall 1という名前で保存されます.
後は先程学習モデルを引き剥がしたときと同様にこの学習モデルを割り当てます.
- ProjectビューからML-Agents→Examples→3DBall→Prefabsをダブルクリックで開く
- 3DBallのプレハブををダブルクリック.するとHierarchyビューに表示されます.
- HierarchyビューからAgentを選択
- InspectorビューからBehabior Parameteresのモデルを選択
- モデルとして3DBall 1を選択.
そうしたら,再生ボタンを押して学習したモデルを確認してみましょう.
下のGIFではわかりにくいですが,最初からついていた事前学習済みモデルより,少し動きが荒い気がしましたが,ちゃんとボールを落とさないように学習しています!
また,訓練の過程をグラフィカルに観察することができます.
学習を開始するとresult
フォルダが作成されるので,それがあるフォルダで以下のコマンドを実行してください.
tensorboard --logdir=results --port=6006
すると以下のパスで学習過程を見ることができます.
以上でサンプルプログラムの動作チェックは終了です.
新しい学習環境の作成と強化学習
ここでは強化学習を行うためにUnityのプロジェクトを作るところから自分でやっていこうと思います.
Unity Hubを開いてプロジェクトから新規作成を選択します.
プロジェクト名をRollerBallにして作成をクリック.
プロジェクトが作成されたら,最初のシーンの名前がSampleSceneになっているので下のようにProjectビューからRollerBallにリネームします.
次にML-AgentsのUnityパッケージをインストールします.
左上のWindowタブからPackage Managerを選択してください.
Package Managerが開いたら左上の+ボタンからAdd package from diskを選択してください.
そうしたらml-agents-release_3\com.unity.ml-agents\package.jsonを開いてください.
インポートに少し時間がかかります.
次にゲームオブジェクトを配置していきます.
Hierarchyビューで右クリックして,まず最初に次のようにPlaneを追加します.
そして名前をFloorにリネームしてください.
同様にCubeを追加します.
そして名前をTargetにし,Positionを(3,0.5,3)に変更します.
この時のInspectorビューは下のようになります.
同様にSphereを追加します.
そして名前をRoolerAgentにして,positionを(0,0.5,0)に変更します.
この時のInspectorビューは下のようになります.
次にRollerAgentのInspectorビューの下にいくと,Add Componentというボタンがあるのでクリックして,下の図のようにRigidbodyを追加してください.
これでゲームオブジェクトの追加は終わりで,最後にHierarchyビューでEmptyなGameObjectを作成し,TrainingAreaとリネームして,そこに先程作成したゲームオブジェクトたちを入れておきます.
このようにすることで,管理が楽になります.
次にスクリプトの追加を行っていきます.
RollerAgentのInspectorビューの下のAdd Componentをクリックし,New Scriptで新しくスクリプトを追加します.
名前を次のようにRollerAgentとしてください.
するとRollerAgentにスクリプトが適用されます.
このスクリプトを編集したいのでProjectビューから,RollerAgentというスクリプトが追加されていると思うので,ダブルクリックして開いてください.デフォルトだとVisual Studioが起動します.
Visual Studioが起動したら,全文を以下のスクリプトに書き換えてください.
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
public class RollerAgent : Agent
{
Rigidbody rBody;
void Start()
{
rBody = GetComponent<Rigidbody>();
}
public Transform Target;
public override void OnEpisodeBegin()
{
if (this.transform.localPosition.y < 0)
{
// If the Agent fell, zero its momentum
this.rBody.angularVelocity = Vector3.zero;
this.rBody.velocity = Vector3.zero;
this.transform.localPosition = new Vector3(0, 0.5f, 0);
}
// Move the target to a new spot
Target.localPosition = new Vector3(Random.value * 8 - 4,
0.5f,
Random.value * 8 - 4);
}
public override void CollectObservations(VectorSensor sensor)
{
// Target and Agent positions
sensor.AddObservation(Target.localPosition);
sensor.AddObservation(this.transform.localPosition);
// Agent velocity
sensor.AddObservation(rBody.velocity.x);
sensor.AddObservation(rBody.velocity.z);
}
public float speed = 10;
public override void OnActionReceived(float[] vectorAction)
{
// Actions, size = 2
Vector3 controlSignal = Vector3.zero;
controlSignal.x = vectorAction[0];
controlSignal.z = vectorAction[1];
rBody.AddForce(controlSignal * speed);
// Rewards
float distanceToTarget = Vector3.Distance(this.transform.localPosition, Target.localPosition);
// Reached target
if (distanceToTarget < 1.42f)
{
SetReward(1.0f);
EndEpisode();
}
// Fell off platform
if (this.transform.localPosition.y < 0)
{
EndEpisode();
}
}
public override void Heuristic(float[] actionsOut)
{
actionsOut[0] = Input.GetAxis("Horizontal");
actionsOut[1] = Input.GetAxis("Vertical");
}
}
最後に少しだけML-Agentsのコンポーネントを追加して終了です.
- RollerAgentコンポーネントのInspectorビューの下からAdd Componentをクリックします.
-
Decision Requester
を検索して追加します. -
Decision Period
を10に変更します. - HierarchyビューからTargetオブジェクトをRollerAgentスクリプトのTargetフィールドにドラッグ&ドロップします.
- RollerAgentコンポーネントのInspectorビューの下からAdd Componentから
Behavior Parameters
を追加します.この時もうすでに追加されている場合があります. -
Behavior Parameters
のパラメータを次のように変更します.-
Behavior Name
to RollerBall -
Vector Observation
>Space Size
= 8 -
Vector Action
>Space Type
= Continuous -
Vector Action
>Space Size
= 2
-
以上の変更をしたあとにRollerAgentのInspectorビューが次のようになっていればOKです.
これでUnity上での作業は終了です.
サンプルプログラム同様に手動でボールを動かすことができます.この状態で再生ボタンを押して矢印キーで動かしてみましょう.結構難しいです.
次に強化学習用のハイパーパラメータ用のConfigファイルを作成します.
UnityのRollerBallプロジェクトのフォルダにconfig
フォルダを作成して,そこに新しくrollerball_config.yaml
を作成してください.内容は以下をコピペしてください.
behaviors:
RollerBall:
trainer_type: ppo
hyperparameters:
batch_size: 10
buffer_size: 100
learning_rate: 3.0e-4
beta: 5.0e-4
epsilon: 0.2
lambd: 0.99
num_epoch: 3
learning_rate_schedule: linear
network_settings:
normalize: false
hidden_units: 128
num_layers: 2
reward_signals:
extrinsic:
gamma: 0.99
strength: 1.0
max_steps: 500000
time_horizon: 64
summary_freq: 10000
各ハイパーパラメータについては検索するといろいろ詳細な情報が得られるので検索してみてください.
準備が完了したので早速学習を行っていきましょう.
サンプルプログラムと同様にまずPowerShellを開き先程作成したAnacondaのml-agens
仮想環境に入ります.
そして,次のコマンドを実行したあと,Unity側で再生ボタンを押して学習を開始します.
mlagents-learn config/rollerball_config.yaml --run-id=RollerBall
試行回数が50万回に設定されていますが,ログを見ていたら10万回くらいには平均報酬が収束していたので,途中で学習をやめ,これを学習済みモデルとしました(学習をやめるときはUnity側で停止するようにしましょう).
下は終了時点での出力です.
resultフォルダに結果が保存されているので,サンプルプログラムを動かしたときと同様にドラッグ&ドロップでProjectビューの適当なところにインポートします.
学習済みモデルがインポートできたら,これをAgentに適用します.
- HierarchyビューからRollerAgentを選択する
- InspectorビューからBehabior Parameter→Modelをクリック
- 先程追加したRollerBallを選択
以上の操作をやって再生ボタンを押してみましょう.
はじめに示したように,ボールがボックスを追いかけるAgentを作成することができたでしょうか?
さいごに
UnityとML-Agentsを使って強化学習を行う環境を構築してきました.
シンプルな問題設定の場合,意外と簡単に実行できることがわかりました.
今後はこれらを使って様々なモデルの強化学習を行っていきたいと思います.