46
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ApplibotAdvent Calendar 2021

Day 21

Unity でサクッと機械学習を体験してみよう【ML-Agents】

Last updated at Posted at 2021-12-20

Applibot Advent Calendar 2021」 21日目の記事になります。
前日は @yucchiy_ さんの Unityでアプリ内にアセットを組み込む3つの方法 という記事でした。

はじめに

様々な場面で AI が活用されるようになってきた昨今、機械学習やら**深層学習(DeepLearning)**などの単語を目にする機会も増えました。興味はあるのだけれど、なんとなく難しそう、大変そう… と手が出せていない方、居るのではないでしょうか?(私です)

えいやと試してみたところ、機械学習も Unity も素人の私(サーバサイドエンジニア)ですが、想像以上に簡単に、学習したモデルを動かすまでを体験することが出来ました。

備忘録代わりに手順をまとめたので、ぜひ機械学習に触れたことの無い方も手元で試してみてください。
機械学習ってこんな感じなんだ〜、というふわっとした理解が出来るかと思います。

この記事の内容

Unity で ML-Agents を使った強化学習を行うチュートリアルといった感じです。
Unity も機械学習も知識がなくとも雰囲気がわかるように書いています。

ML-Agents とは

Unity Machine Learning Agents(ML-Agents) の事で、Unity を使って機械学習を行うことのできるフレームワークです。これにより、深い専門知識なしでも、視覚的にわかりやすく機械学習を体験することができます。

この記事では機械学習の一種である強化学習を ML-Agents を使った一連の流れで体験してみます。

1. 環境構築

※ ML-Agents は更新が活発で、リリースサイクルもかなり早いです。使うツールのバージョンに差異があると詰まる可能性が高いのでご注意下さい。記事では、執筆時点で最新の Release 18 に対応した内容となっています。

1-1. Unity のインストール

ML-Agents のリリースに適したバージョンの Unity を使うため UnityHub 経由でインストールを行います。

Unity 公式サイトから UnityHub をダウンロードし、インストールを行った後

こちらから 2019.4.25 をのバージョンの Unity をインストールします。
Release 18 のサンプルがこのバージョンを使っているため)

1-2. Python のインストール

バージョンは 3.63.7 が推奨されているので、今回は 3.7 の最新である 3.7.12 を使います。

バージョンを簡単に切り替えられるよう、pyenv を使ってインストールすることを推奨します。
(導入方法は他の記事に譲ります…)

pyenv install 3.7.12
pyenv global 3.7.12

1-3. mlagents-learn のインストール

学習のためのユーティリティである mlagents-learn を pip 経由でインストールします。
Release 18 では 0.27.0 を使っているので、以下のようにインストールします。

python -m pip install mlagents==0.27.0

以下のコマンドで使い方が表示されるようになれば OK です。

mlagents-learn --help

1-4. ml-agents の Git リポジトリの Clone

ml-agents リポジトリをクローンし release_18 のタグをチェックアウトします。

git clone git@github.com:Unity-Technologies/ml-agents.git
cd ml-agents
git checkout release_18

以降、コマンドを実行する際はこのリポジトリ直下で行うものとします。

これで一通りの準備は完了です。

2. サンプルを動かしてみる

2-1. プロジェクトを開く

Unity Hub を起動してプロジェクト画面の「リストに追加」からクローンしたリポジトリの Project ディレクトリを選択します。

スクリーンショット 2021-12-21 3.03.14.png

スクリーンショット 2021-12-21 3.04.52.png

リストに追加されるので、これを起動します。

2-2. Unity パッケージの追加

サンプルでは以下の Unity パッケージが必要なので、パッケージマネージャでインストールします。

  • com.unity.ml-agents
  • com.unity.ml-agents.extensions

Window > PackageManager > Add package from disk の順に選択。

※ 既にパッケージマネージャに表示されている場合、この手順は不要になります

スクリーンショット 2021-12-21 3.10.57.png

クローンしたリポジトリ内の

  • com.unity.ml-agents/package.json
  • com.unity.ml-agents.extensions/package.json

をそれぞれ選択すれば OK です。

2-3. サンプルを眺める

Assets/ML-Agents/Examples の下に色々なサンプルがあります。

スクリーンショット 2021-12-21 3.15.32.png

試しに Assets/ML-Agents/Examples/3DBall/Scenes/3DBall を開いてみましょう。

スクリーンショット 2021-12-21 3.17.53.png

たくさんの AgentCube 君(顔のついた箱みたいなやつ)が出迎えてくれます!

早速再生ボタンを押して実行しましょう。

a.gif

ボールを落とさないようバランスを取る AgentCube 君を眺めることが出来ます。かわいいですね。

これは既に学習済のモデルを動かしている状態となっています。

b.gif

他にもサッカーゲームをする AgentCube 君や

c.gif

3マッチパズルと化した AgentCube 君など、豊富なサンプルを見ることが出来ます。

2-4. サンプルを自分で学習させてみる

学習はどのように行われるのか、3DBall の例で実際に試してみましょう。

mlagents-learn コマンドを使用して学習を行います。以下のコマンドを実行して下さい。

mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun

3DBall.yaml は学習のための構成ファイルで、最適化に大切なハイパーパラメータと呼ばれるものもここに含まれています。ml-agents リポジトリにはサンプル用の構成ファイルも含まれているので、これをそのまま指定している形です。

スクリーンショット 2021-12-21 3.45.13.png

このように表示されたら Unity 上で 3DBall のシーンを実行します。

d.gif

高速で AgentCube 君が動き出しました!
強化学習では Agent のある行動に対して報酬を与えることで、報酬を最大化するように学習し最適化することができます。この光景は、それを視覚的に見ている状況という訳です。

スクリーンショット 2021-12-21 4.07.13.png

コンソールには学習の進捗状況が表示されており、ステップ数や得られた報酬の平均値などを知ることが出来ます。
(ステップが増える毎に、報酬の平均値も増えていくのがわかるかと思います。)

適当なタイミングでシーンの再生を停止し、学習を止めて見て下さい。
スクリーンショット 2021-12-21 4.08.33.png

コンソールに表示されている通り results/first3DBallRun/3DBall.onnx に学習したモデルが生成されています。

cp results/first3DBallRun/3DBall.onnx Project/Assets/ML-Agents/Examples/3DBall/TFModels/My3DBall.onnx

などとコマンドを実行し、アセット内に作ったモデルをコピーします。

スクリーンショット 2021-12-21 3.54.11.png

Hierarchy ウィンドウで 3DBall > Agent のオブジェクトを選択し、
Inspector ウィンドウの Behavior Parameters > Model を見て下さい。

スクリーンショット 2021-12-21 3.57.24.png

3DBall(NNModel) とありますね。これが今適用されている学習済モデルです。

これを、先程作成したモデルにドラッグ & ドロップで置き換えます。

スクリーンショット 2021-12-21 4.01.05.png

これで学習したモデルに差し替える事が出来ました。シーンを再生してみて下さい!

e.gif

差し替えたモデルの出来栄えはいかがでしょうか?
今回はすぐに学習を止めてしまったので、他の学習済のモデルと比べると安定感が無いのがわかるかと思います。
(2行目2列目の AgentCube 君のみ差し替えたモデルを使っています。)

これは学習時間を長くすることで徐々に改善されていくので、自分でもぜひ試してみて下さい。

3. 一から学習環境を作る

最後に、いよいよ自分で1から学習環境を作って強化学習を実行してみましょう。

内容は ML-Agents の公式チュートリアルと同じものになります。

3-1. シーンの作成

Assets フォルダ直下に学習用のシーンを作成します。(右クリックのコンテキストメニューなどから作成出来ます。)
シーンの名前は何でも良いですが、ここでは RollerAgent としました。

スクリーンショット 2021-12-21 4.21.47.png

シーンを開き、Hierarchy ウィンドウから GameObjects を作成します。(右クリックのコンテキストメニューなどから作成出来ます。)

スクリーンショット 2021-12-21 4.27.32.png

以下の3つの GameObjects を作ります。

    • Plane を作成し Floor という名前にする
    • Position を (0, 0, 0), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
    1. ターゲット
    • Cube を作成し Target という名前にする
    • Position を (3, 0.5, 3), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
    1. エージェント
    • Sphere を作成し RollerAgent という名前にする
    • Position を (0, 0.5, 0), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
    • RigidBody コンポーネントを追加する(下図の矢印の辺りから追加出来ます)

全てを良い感じに設定すると、こんな感じになります。

スクリーンショット 2021-12-21 4.44.17.png

3-2. スクリプトの作成

RollerAgent にさらに Script コンポーネントを追加します。

Add Component から New Script を選択し、名前は RollerAgent としておきます。

スクリーンショット 2021-12-21 4.49.20.png

コンポーネントも追加され、Assets 直下にスクリプト用のファイルも生成されました。これを開きます。
そして、ここにコードを書いていく訳なのですが…

この記事では体験することが目的なので、完成形のコード全体を貼ってしまいます。

RollerAgent.cs
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Actuators;

public class RollerAgent : Agent
{
    Rigidbody rBody;

    void Start()
    {
        rBody = GetComponent<Rigidbody>();
    }

    public Transform Target;
    public override void OnEpisodeBegin()
    {
        // If the Agent fell, zero its momentum
        if (this.transform.localPosition.y < 0)
        {
            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(ActionBuffers actionBuffers)
    {
        // Actions, size = 2
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = actionBuffers.ContinuousActions[0];
        controlSignal.z = actionBuffers.ContinuousActions[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
        else if (this.transform.localPosition.y < 0)
        {
            EndEpisode();
        }
    }

    public override void Heuristic(in ActionBuffers actionsOut)
    {
        var continuousActionsOut = actionsOut.ContinuousActions;
        continuousActionsOut[0] = Input.GetAxis("Horizontal");
        continuousActionsOut[1] = Input.GetAxis("Vertical");
    }
}

簡単に説明すると Unity.MLAgents.Agent クラスの持つ以下3つのメソッドを拡張しています。

  • OnEpisodeBegin()
    • シーンの初期化を行う(ランダムにターゲットを設置するなど)
  • CollectObservations(VectorSensor sensor)
    • 環境の情報の収集を行う(ターゲットの位置、エージェント自体の位置および速度など)
  • OnActionReceived(ActionBuffers actionBuffers)
    • 行った行動による報酬の決定など(ターゲットに近いほど高得点!)

詳しくは 公式チュートリアルの説明 を見て下さい。

また、この後の手動での動作テストのため Heuristic メソッドも拡張しています。

このコードをそのまま保存します。

3-3. Unity とスクリプトの接続

Hierarchy ウィンドウの RollerAgent を選択し、Script コンポーネントの Target の欄に Target の GameObject をドラッグ & ドロップで設定します。

スクリーンショット 2021-12-21 5.12.41.png

また、さらに RollerAgent に コンポーネントの追加 から以下コンポーネントを追加します。

  • Decision Requester
    • Decision Period を 10 に設定
  • Behavior Parameters
    • Behavior NameRollerBall に設定
    • Vector Observation > Space Size を 8 に設定
    • Actions > Continuous Actions を 2 に設定

スクリーンショット 2021-12-21 5.17.10.png

これで設定は全て完了です。

3-4. 手動での動作テスト

Behavior ParametersBehavior TypeHeuristic Only にすることでキーボードの入力で Agent を操作する事が出来ます。試しに変更してからシーンを再生してみましょう。キーボードで操作してみて、ターゲットに触れたら再設置されることや、画面外に落ちたらリスポーンする事などを確認しましょう。

f.gif

確認が出来たら Behavior ParametersBehavior TypeDefault に戻しておきます。

3-5. 学習させてみる

では、サンプルで行ったのと同様 mlagents-learn コマンドを使用して学習を行います。その際の構成ファイルはチュートリアル通りに次のものを使ってみます。

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

詳細が気になる方は 公式ドキュメント を確認してみて下さい!

config/rollerball_config.yaml にファイルを作成し、以下コマンドを実行して学習を開始します。

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

待機中になったら Unity でシーンを再生して下さい。高速で学習が進んでいく様子が見られます。のんびり待ちましょう。

g.gif

適当な時間が経過したら、良き所で停止してモデルを生成します。

サンプル同様に以下のようなコマンドで Asset 直下にコピーし

cp results/RollerBall/RollerBall.onnx Project/Assets/RollerBall.onnx

RollerAgent の Behavior Parameters > Model にドラッグ & ドロップしモデルを設定し、シーンを実行すれば…

h.gif

自分で学習させたモデルを実行する事が出来ました!

おわりに

今回の記事では、一通りの ML-Agents を使った機械学習の流れを説明しました。
だいぶ駆け足の説明でしたが、雰囲気は何となく感じられたでしょうか?
思ったよりも簡単に機械学習を体験出来るということが伝わったら幸いです。
みなさまも、年末年始の休暇などで是非試してみてはいかがでしょうか。

参考文献

公式 Documents(Release18版)

46
26
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?