やみとものプログラミング日記 やみとものプログラミング日記
TOP 【ML-Agents】Unityで強化学習始めてみた
【ML-Agents】Unityで強化学習始めてみた

【ML-Agents】Unityで強化学習始めてみた

機械学習 強化学習 Unity
作成日時: 2020年11月8日
更新日時: 2020年11月10日
こんにちは、やみともです。
これからしばらく毎週土曜日に強化学習に関する記事をアップしていこうと思います。
初回のこの記事は、UnityでML-Agentsを使って強化学習始めてみた、という記事です。

最終的に下の動画のようにエージェント(球)がターゲット(立方体)に向かって移動するように学習します。



まずはML-Agentsのインストールから始めます。
記事執筆時点でのML-Agentsの最新安定バージョンはRelease 9なので、Release 9の公式インストール手順を参考にインストールを行っていきます。

Unityのインストール

まずはUnityのインストールです。
Unity 2018.4以降が必要で、Unity Hubからのインストールが推奨されています。
インストール方法についてはこの記事を参考にしてください。

今回、私はUnity 2019.4.12f1をインストールしました。
Unity 2020を試してみましたがML-Agents Unityパッケージがインストール出来なかったためUnity 2019にしました。

Pythonのインストール

Python 3.6.1以降が必要です。
個人的にAnacondaを使用することをおすすめします。
Anacondaのインストール方法はこの記事を参考にしてください。

Anacondaをインストールし、condaコマンドが使えるようになったらコマンドプロンプトで次のコマンドを実行してください。
conda create -n python39 python=3.9
conda activate python39
この記事ではPython 3.9.0を使用します。

ML-Agentsリポジトリのクローン

gitがインストールされていることを仮定します。gitがインストールされていない場合はこの記事などを参考にgitをインストールしてください。

以下のコマンドを実行してML-Agentsリポジトリをクローンしてください。
git clone --branch release_9 https://github.com/Unity-Technologies/ml-agents.git

ml-agents-envs、ml-agentsのインストール

まず、先ほどクローンしたリポジトリのフォルダに入ります。
cd ml-agents
ml-agents-envsとml-agentsを順番にインストールします。
condaの仮想環境がpython39になっていることを確認してください。
pip3 install -e ./ml-agents-envs
pip3 install -e ./ml-agents

Unityプロジェクトの作成とML-Agents Unityパッケージの追加

Unity Hubを起動して、プロジェクトから「新規作成」の右の▼をクリックして、2019・・・(細かいバージョンは場合により異なるかもしれない)を選択します。



テンプレートは「3D」を選択し、プロジェクト名に「RollerBall」、保存先を設定し作成をクリックします。



次にML-Agents Unityパッケージをインストールします。
UnityのメニューからWindow -> Package Managerをクリックします。



出てきたウィンドウの左上の+▼のところをクリックし、Add package from disk...をクリックします。



クローンしたML-Agentsリポジトリの中のcom.unity.ml-agentsフォルダの中のpackage.jsonを選択し、開くをクリックします。
インポートが始まるのでしばらく待ちます。

学習環境の作成

ではエージェントが学習する環境を作っていきます。
まず、床を作ります。Hierarchyウィンドウを右クリックし、3D Object -> Planeを選択します。



Sceneビューに平面が表示されたと思います。次にもう一度Hierarchyウィンドウで先ほど作ったPlaneを選択します。
すると右側のInspectorウィンドウにPlaneのプロパティが表示されるので、下の画像のようにプロパティを変更します。(元から正しい値が設定されていれば変更は不要です)

(1. オブジェクト名をPlaneからFloorに変更。 2. TransformのPosition、Rotation、Scaleを設定。)



次にエージェントが追いかける目標となる立方体を配置します。
Hierarchyウィンドウを右クリックし、3D Object -> Cubeを選択します。



床と同様に、オブジェクト名をTarget、TransformのPositionを(3, 0.5, 3)、Rotationを(0, 0, 0)、Scaleを(1, 1, 1)に設定します。



エージェントとなる球を配置します。
Hierarchyウィンドウを右クリックし、3D Object -> Sphereを選択します。
これまでと同様に、オブジェクト名をRollerAgentに変更し、TransformのPositionを(0, 0.5, 0)、Rotationwo(0, 0, 0),Scaleを(1, 1, 1)に変更します。

RollerAgentをHierarchyウィンドウで選択した状態でInspectorウィンドウの一番下にあるAdd Componentをクリックし、Physics -> Rigidbodyを追加します。



今後のため環境を構成するオブジェクトをグループ化します。
Hierarchyウィンドウを右クリックし、Create Emptyを選択します。
空のオブジェクトが作成されるので、オブジェクト名をTrainingAreaとし、Transformをリセット(下の画像参照)します。



HierarchyウィンドウでFloor、Target、RollerAgentをそれぞれTrainingAreaにドラッグしてグループ化します。
表示が下の画像のようになればOKです。



エージェントの実装

HierarchyウィンドウでRollerAgentを選択し、Inspectorウィンドウの一番下のAdd Componentをクリックし、表示された一覧の一番下のNew scriptを選択して、スクリプトファイル名にRollerAgentと指定してスクリプトを作成します。



ProjectウィンドウのRollerAgentスクリプトをダブルクリックし、エディタを開いて編集します。



RollerAgentスクリプトがエディタで開かれますが、既存のコードを全て削除して下のコードを貼り付けます。



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 forceMultiplier = 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 * forceMultiplier);

        // 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();
        }
    }
}

最後のエディタ設定

エディタで行う最後の設定を行っていきます。

HierarchyウィンドウでRollerAgentを選択し、その状態で同じくHierarchyウィンドウのTargetをInspectorウィンドウのRoller AgentスクリプトのTargetの右のNone(Transform)と表示されているところにドラッグします。



次にHierarcyウィンドウでRollerAgentが選択されている状態で、Inspectorウィンドウの一番下のAdd Componentをクリックし、ML-Agents -> Decision Requesterを選択します。



追加されたDecision RequesterコンポーネントのDecision Periodを10に変更します。



同様に、HierarchyウィンドウでRollerAgentを選択し、Inspectorウィンドウの一番下のAdd ComponentからML-Agents -> Behavior Parametersを追加します。

そして追加されたBehavior ParametersコンポーネントのBehavior NameをRollerBallに、Vector ObservationのSpace Sizeを8に、Vector ActionのSpace TypeをContinuousに、Space Sizeを2に変更します。



訓練設定ファイルの作成

クローンしたML-Agentsリポジトリの中の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
これらはハイパーパラメータというもので、エージェントを訓練(学習)する際に、自分で調整する必要のあるパラメータです。

訓練の実行

いよいよ訓練開始です!
コマンドプロンプトを開いてクローンしたML-Agentsリポジトリのフォルダに入り以下のコマンドを実行します。

mlagents-learn config/rollerball_config.yaml --run-id=RollerBall

コマンドプロンプトにUnityのロゴが表示され、Listening on port 5004. Start training by pressing the Play button in the Unity Editor.と表示されたらUnityの上部にある再生ボタン(▶)をクリックします。

これで学習が開始されます。最初のうちはステージの外にエージェントが落ちたりすることが多いですが、しばらくするとTargetに向かって移動するようになります。

次回は学習の高速化などについて記事にしたいと思います。
また、この記事に関して不備などがあれば私のTwitterにリプライなどで教えていただけると幸いです。

最後まで読んで頂きありがとうございました。