「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.6
か 3.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
ディレクトリを選択します。
リストに追加されるので、これを起動します。
2-2. Unity パッケージの追加
サンプルでは以下の Unity パッケージが必要なので、パッケージマネージャでインストールします。
com.unity.ml-agents
com.unity.ml-agents.extensions
Window > PackageManager > Add package from disk
の順に選択。
※ 既にパッケージマネージャに表示されている場合、この手順は不要になります
クローンしたリポジトリ内の
com.unity.ml-agents/package.json
com.unity.ml-agents.extensions/package.json
をそれぞれ選択すれば OK です。
2-3. サンプルを眺める
Assets/ML-Agents/Examples
の下に色々なサンプルがあります。
試しに Assets/ML-Agents/Examples/3DBall/Scenes/3DBall
を開いてみましょう。
たくさんの AgentCube 君(顔のついた箱みたいなやつ)が出迎えてくれます!
早速再生ボタンを押して実行しましょう。
ボールを落とさないようバランスを取る AgentCube 君を眺めることが出来ます。かわいいですね。
これは既に学習済のモデルを動かしている状態となっています。
他にもサッカーゲームをする AgentCube 君や
3マッチパズルと化した AgentCube 君など、豊富なサンプルを見ることが出来ます。
2-4. サンプルを自分で学習させてみる
学習はどのように行われるのか、3DBall の例で実際に試してみましょう。
mlagents-learn
コマンドを使用して学習を行います。以下のコマンドを実行して下さい。
mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun
3DBall.yaml
は学習のための構成ファイルで、最適化に大切なハイパーパラメータと呼ばれるものもここに含まれています。ml-agents リポジトリにはサンプル用の構成ファイルも含まれているので、これをそのまま指定している形です。
このように表示されたら Unity 上で 3DBall のシーンを実行します。
高速で AgentCube 君が動き出しました!
強化学習では Agent のある行動に対して報酬を与えることで、報酬を最大化するように学習し最適化することができます。この光景は、それを視覚的に見ている状況という訳です。
コンソールには学習の進捗状況が表示されており、ステップ数や得られた報酬の平均値などを知ることが出来ます。
(ステップが増える毎に、報酬の平均値も増えていくのがわかるかと思います。)
適当なタイミングでシーンの再生を停止し、学習を止めて見て下さい。
コンソールに表示されている通り results/first3DBallRun/3DBall.onnx
に学習したモデルが生成されています。
cp results/first3DBallRun/3DBall.onnx Project/Assets/ML-Agents/Examples/3DBall/TFModels/My3DBall.onnx
などとコマンドを実行し、アセット内に作ったモデルをコピーします。
Hierarchy ウィンドウで 3DBall > Agent
のオブジェクトを選択し、
Inspector ウィンドウの Behavior Parameters > Model
を見て下さい。
3DBall(NNModel)
とありますね。これが今適用されている学習済モデルです。
これを、先程作成したモデルにドラッグ & ドロップで置き換えます。
これで学習したモデルに差し替える事が出来ました。シーンを再生してみて下さい!
差し替えたモデルの出来栄えはいかがでしょうか?
今回はすぐに学習を止めてしまったので、他の学習済のモデルと比べると安定感が無いのがわかるかと思います。
(2行目2列目の AgentCube 君のみ差し替えたモデルを使っています。)
これは学習時間を長くすることで徐々に改善されていくので、自分でもぜひ試してみて下さい。
3. 一から学習環境を作る
最後に、いよいよ自分で1から学習環境を作って強化学習を実行してみましょう。
内容は ML-Agents の公式チュートリアルと同じものになります。
3-1. シーンの作成
Assets フォルダ直下に学習用のシーンを作成します。(右クリックのコンテキストメニューなどから作成出来ます。)
シーンの名前は何でも良いですが、ここでは RollerAgent
としました。
シーンを開き、Hierarchy ウィンドウから GameObjects を作成します。(右クリックのコンテキストメニューなどから作成出来ます。)
以下の3つの GameObjects を作ります。
-
- 床
-
Plane
を作成しFloor
という名前にする - Position を (0, 0, 0), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
-
- ターゲット
-
Cube
を作成しTarget
という名前にする - Position を (3, 0.5, 3), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
-
- エージェント
-
Sphere
を作成しRollerAgent
という名前にする - Position を (0, 0.5, 0), Rotation を (0, 0, 0), Scale を (1, 1, 1) にする
- RigidBody コンポーネントを追加する(下図の矢印の辺りから追加出来ます)
全てを良い感じに設定すると、こんな感じになります。
3-2. スクリプトの作成
RollerAgent にさらに Script コンポーネントを追加します。
Add Component
から New Script
を選択し、名前は RollerAgent
としておきます。
コンポーネントも追加され、Assets 直下にスクリプト用のファイルも生成されました。これを開きます。
そして、ここにコードを書いていく訳なのですが…
この記事では体験することが目的なので、完成形のコード全体を貼ってしまいます。
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 をドラッグ & ドロップで設定します。
また、さらに RollerAgent に コンポーネントの追加
から以下コンポーネントを追加します。
- Decision Requester
-
Decision Period
を 10 に設定
-
- Behavior Parameters
-
Behavior Name
をRollerBall
に設定 -
Vector Observation > Space Size
を 8 に設定 -
Actions > Continuous Actions
を 2 に設定
-
これで設定は全て完了です。
3-4. 手動での動作テスト
Behavior Parameters
の Behavior Type
を Heuristic Only
にすることでキーボードの入力で Agent を操作する事が出来ます。試しに変更してからシーンを再生してみましょう。キーボードで操作してみて、ターゲットに触れたら再設置されることや、画面外に落ちたらリスポーンする事などを確認しましょう。
確認が出来たら Behavior Parameters
の Behavior Type
は Default
に戻しておきます。
3-5. 学習させてみる
では、サンプルで行ったのと同様 mlagents-learn
コマンドを使用して学習を行います。その際の構成ファイルはチュートリアル通りに次のものを使ってみます。
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 でシーンを再生して下さい。高速で学習が進んでいく様子が見られます。のんびり待ちましょう。
適当な時間が経過したら、良き所で停止してモデルを生成します。
サンプル同様に以下のようなコマンドで Asset 直下にコピーし
cp results/RollerBall/RollerBall.onnx Project/Assets/RollerBall.onnx
RollerAgent の Behavior Parameters > Model
にドラッグ & ドロップしモデルを設定し、シーンを実行すれば…
自分で学習させたモデルを実行する事が出来ました!
おわりに
今回の記事では、一通りの ML-Agents を使った機械学習の流れを説明しました。
だいぶ駆け足の説明でしたが、雰囲気は何となく感じられたでしょうか?
思ったよりも簡単に機械学習を体験出来るということが伝わったら幸いです。
みなさまも、年末年始の休暇などで是非試してみてはいかがでしょうか。
参考文献
公式 Documents(Release18
版)