Unity ML-Agents とは、Unityで強化学習をできるようにするUnityのプラグインです。強化学習の「環境」をUnityで動かし、「エージェント」はPython側で動かし、両者を通信させながらエージェントを学習させることができます。

ML-Agents のExample を見ると、ヒューマノイドの歩行、2対2のサッカー、共同作業の箱押しなど、かなりレベルの高いタスクの学習が可能であることがわかります。PPOやSACと呼ばれる強化学習アルゴリズムもすぐに使えるようになっています。

ブログの最後にまとめましたが、ML-Agents の使い方を説明している書籍やYoutubeもあり大変勉強になります。しかし、mML-Agents はアップデートが速く、今現在(2022/3/6)、Release 19が最新ということで、使い方が古いバージョンから若干異なっているところもあります。

そこで、基本的なところはYoutubeや書籍を見ていただくとして、ここでは、Release 19を使う場合のポイントを中心にさっとまとめました。

PC環境
+ windows 10
+ Python環境のminiconda (またはanaconda)がinstallしてある。DLはこちらから
+ Unity Hubがinstallしてある。DLはこちらから

目的
+ ML-agent release 19 が動く環境構築
+ BallRollerの環境を自作してPPOを使って学習させる

以下、基本的にはrelease 19 の公式ドキュメントが情報源となりますが、参考資料も参考にしました。

ml-agents のインストール

公式githubの「main」のプルダウンから、Tags>release_19を選択。

「Code」のプルダウンから、Download Zipを選択しダウンロード、任意のフォルダーで展開(ml-agents-release_19というフォルダが作成される)。

Python環境の準備

[code]
conda create -n mlagents python=3.7.11
conda activate mlagents
[/code]
release_19の公式ドキュメントではpython3.6か3.7をリコメンドしているので、アナコンダパワーシェルプロンプト(以下コンソール)から、python3.7 の仮想環境を作成。ここでは、”mlagents” という仮想環境名にする。

[code]
pip install torch~=1.7.1 -f https://download.pytorch.org/whl/torch_stable.html
[/code]
PyTorch 1.7.1 のinstall。

[code]
pip install -e ./ml-agents-envs
pip install -e ./ml-agents
[/code]
コンソールから、ダウンロードして展開したml-agents-release_19フォルダに移動し、ml-agents-envs, ml-agentをinstall。

Unity準備

新規プロジェクトの作成

公式では、Unity.2020.3 以上が必要とのこと。Unity Hub の「インストール」を押し、「Uniy2020.3.30f1(LTS)」を選択してインストール(結構時間かかる)。

Unity Hubのプロジェクト画面から「新規作成」のプルダウンで、2020.3.30f1を選択。

テンプレート: 3D
プロジェクト名: BallRoller
保存先: C:/myworks/Unity/BallRoller(適宜決める)

>作成

Unityの開発画面が立ち上がる。

ml-agents パッケージのインストール

Window>Package Manager>+ボタン>Add package from disk…

ダウンロードして展開したml-agents-release_19の中の、
com.unity.ml-agentsの中の、package.jsonを選択

[code]
C:\[展開先]\ml-agents-release_19\com.unity.ml-agents\package.json
[/code]

少し時間がかかる。
これで、ML-Agentsのパッケージが入った。

Unity 必要なオブジェクトを作成

ここは、最後に参照しているyoutube動画や本を参考にしてください。ここはメモのみです。

色のマテリアルを3つ作成

Assetsフォルダで右クリック>Create>Material
名前をBlue, Gray, Red としてその色のMaterialを作成

Planeを作成

Hierarchy で右クリック> 3D object > Plane
名前: floor
Position: X:0, Y:0, Z:0
色: AssetsのGrayをplaneオブジェクトにドラッグして色をGrayにする。

Targetを作成

Hierarchy で右クリック> 3D object > Cube
名前: Target
Position: X:2, Y:0.5, Z:0
色: Redにする

Agentを作成

Hierarchy で右クリック> 3D object > Sphere
名前: Agent
Position: X:0, Y:0.5, Z:0
色: Blueにする

Agent にRigidbody を足す

Add Component > Rigidbody

Agent にBehavior Parametersを足す

Add Component > Behavior Parameters
Behavior Name: BallRoller
Space Size: 8
Continuous Action: 2
Discrete Branch: 0

Agent に”RollerAgent”という名前でScriptを足す

Add Component > New Script > 「RollerAgent」> Create and add

RollerAgent.cs

using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;  // release_19 のtutorialではこれが抜けている
 
 
public class RollerAgent : Agent
{
    public Transform target;
    Rigidbody rBody;
 
    public override void Initialize()
    {
        this.rBody = GetComponent();
    }
 
    public override void OnEpisodeBegin()
    {
        if (this.transform.localPosition.y < 0)
        {
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            this.transform.localPosition = new Vector3(0.0f, 0.0f, 0.0f);
        }
        target.localPosition = new Vector3(
            Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
    }
 
    public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(target.localPosition);
        sensor.AddObservation(this.transform.localPosition);
        sensor.AddObservation(rBody.velocity.x);
        sensor.AddObservation(rBody.velocity.z);
    }
 
    public override void OnActionReceived(ActionBuffers actionBuffers)  // Release 3と異なる
    {
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = actionBuffers.ContinuousActions[0];  // Release 3と異なる
        controlSignal.z = actionBuffers.ContinuousActions[1];  // Release 3と異なる
        rBody.AddForce(controlSignal * 10);
 
        float distanceToTarget = Vector3.Distance(
            this.transform.localPosition, target.localPosition);
        if (distanceToTarget < 1.42f)
        {
            AddReward(1.0f);
            EndEpisode();
        }
        if (this.transform.localPosition.y < 0)
        {
            EndEpisode();
        }
    }
 
    public override void Heuristic(in ActionBuffers actionsOut)  // Release 3と異なる
    {
        var continuousActionsOut = actionsOut.ContinuousActions;  // Release 3と異なる
        continuousActionsOut[0] = Input.GetAxis("Horizontal");  // Release 3と異なる
        continuousActionsOut[1] = Input.GetAxis("Vertical");    // Release 3と異なる
    }
}

※上のプログラム中のlocalPosition の箇所は、公式では、position。
しかし、環境を複数同時に拡張することを考えるとlocalPosition にしておくべき。

TargetをRollerAgent.csに関連付ける

HierarchyのAgnet をクリック、RollerAgent.csのコンポーネントで、TargetのNone(Transform)のところに、HierarchyのTargetをドラッグ&ドロップ

Decision Requesterを加える

Add Component > Decision Requester
Decision Period: 10

ここまでで、再生ボタンを押して、カーソルキーで青いボールコントロールできれば成功。

Python側のAgentを動かす

学習を開始する

プロジェクトのあるフォルダーのAssert/ML-Agentsにconfigというフォルダーを作って、
config.yaml という名前の以下の内容のファイルを作成。

C:\myWorks\d06_Unity\BallRoller\BallRoller\Assets\ML-Agents\config

2行目のBallRollerは、Add Component > Behavior Parametersでの、
Behavior Name: BallRollerに一致させること。

behaviors:
  BallRoller:
    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
      beta_schedule: constant
      epsilon_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

ML-Agents プラグインを起動する

[code]
mlagents-learn .\config\config.yaml --run-id=first
[/code]
Pythonの仮想環境から、ML-Agentsフォルダに移動してコマンド実行。

※id=first は、学習シミュレーションのid。
学習を実行するたびに異なるidを適当につけると、
その結果は、この名前のフォルダの中に保存される。

上書きしたいときには、[code]--force[/code]オプションをつければよい。

[code]
mlagents-learn --help
[/code]

この状態で、Unity側のPlayボタンを押すと高速でボールが動き出す。学習が開始。

[code]
(mlagents) ...\Assets\ML-Agents> tensorboard --logdir results --port 6006
[/code]
もう一つコンソールを立ち上げて仮想環境をmlagentsに入り、ML-Agents のフォルダに移動し、上のコマンドでグラフ表示用のtensorboardを起動。

ブラウザで、
http://localhost:6006/
を開くとグラフがみれる(ただ、今回試した時には1つの点しかプロットされなかった。リロードしてもだめ。原因調査中。いったん止めてもう一度実行すると見えたりする)。

以下学習の進行にともなって、コンソールに表示されていく。

[code]
behavioral_cloning: None
[INFO] BallRoller. Step: 10000. Time Elapsed: 244.489 s. Mean Reward: 0.554. Std of Reward: 0.497. Training.
[INFO] BallRoller. Step: 20000. Time Elapsed: 507.244 s. Mean Reward: 0.780. Std of Reward: 0.414. Training.
[INFO] BallRoller. Step: 30000. Time Elapsed: 733.210 s. Mean Reward: 0.918. Std of Reward: 0.274. Training.
[INFO] BallRoller. Step: 40000. Time Elapsed: 955.749 s. Mean Reward: 0.964. Std of Reward: 0.185. Training.
[INFO] BallRoller. Step: 50000. Time Elapsed: 1181.433 s. Mean Reward: 0.958. Std of Reward: 0.200. Training.
[INFO] BallRoller. Step: 60000. Time Elapsed: 1423.411 s. Mean Reward: 0.985. Std of Reward: 0.121. Training.
[/code]

Mean Rewardが0.985なので(最大1)、学習が大体学習できていることが分かる。
ここでctrl+Cで止める。

学習したネットワークのファイルは、
first/BallRoller.onnx

初めのディレクトリ名は、--run-id で指定した名前。

これを、Behavior ParametersのModelに指定してUnityを再生し、ボールがターゲットに向かって動き出せば成功。

複数の環境で学習

Unityの、Hierarchy で右クリックし、[Create Enpty]で、GameObjectを作成、Envと命名。

そこに、floorとTarget、Agent をドラッグして、Envの下の階層に入れる。

EnvをAssetsにドラッグすると、EnvのPrefabが作られる。これを、Hierarchyにドラッグして、Envを複製する。もとのEnvとぴったり重なっているので、軸をドラッグして適当にずらす。

この要領で好きなだけEnvを増やすことができる。

この状態で、上記の要領で学習させると、この複数のEnvで同時の学習が実行される。

参考資料

  1. 公式github
    1. Unity-Technologies/ml-agents
    2. 2022/3/6現在で、最新リリースがRelease 19。Python Packageのバージョンが0.28.0, Unity Package 2.21となっている。
    3. Release 19 のDocumation これがメインの参考元です。ただ、これだけだとUnityに慣れていない人は苦労すると思います。

  2. youtube: Junichiro Horikawaチャンネル
    1. [Unity Tutorial] ML-Agents for Unity 入門編
    2. Release 13 を導入して、サンプルを試した後、自作環境での学習までを解説した動画です、とても分かりやすかったです。特にマルチ環境での方法、参考になりました。

  3. 書籍:Unity ML-Agents 実践ゲームプログラミング
    1. v1.1対応版
    2. Release 3 による解説。ML-Agentsを使ったソフト開発の方法が分かりやすく書かれています。