
マイケル
みなさんこんにちは!
マイケルです!
マイケルです!

エレキベア
こんにちクマ〜〜〜

マイケル
今回は、最近行っているオセロAI開発の準備として、
ML-Agentsを使った強化学習について触っていこうと思います!
ML-Agentsを使った強化学習について触っていこうと思います!

エレキベア
ML-Agentsクマか〜〜
確かに一回触ってみたかったクマ
確かに一回触ってみたかったクマ

マイケル
オセロAIの学習にはセルフプレイという学習方法を使う予定のため、その使い方まで見ていこうと思っています。
しかし全部まとめると長くなってしまったので、2記事に分けることにしました・・・。
しかし全部まとめると長くなってしまったので、2記事に分けることにしました・・・。

マイケル
というわけで今回は「ML-Agentsを導入し、簡単な強化学習サンプルを作成する」
ところまで実施していきます!
ところまで実施していきます!
今回の目標
- ML-Agentsを導入して簡単なサンプルを作成する
- 使い方や機械学習の流れについて理解する

エレキベア
楽しみクマ〜〜〜
参考資料・書籍

マイケル
今回ML-Agentsのサンプルを作成するにあたり、
基本的に下記の公式ドキュメントを参考に進めました!
基本的に下記の公式ドキュメントを参考に進めました!
GitHub – Unity-Technologies/ml-agents

マイケル
また、それに加えて下記書籍も併用して概要について調べています。
こちらは日本語ですごく分かりやすいですが、一部古くなっている情報もあるためその点には注意しましょう!
こちらは日本語ですごく分かりやすいですが、一部古くなっている情報もあるためその点には注意しましょう!
Unity ML-Agents 実践ゲームプログラミング v1.1対応版

エレキベア
アップデートが頻繁に起こっているのクマね
ML-Agentsとは

マイケル
まずML-Agentsとは何ぞやという話ですが、
ざっくりと下記のようなものになります!
ざっくりと下記のようなものになります!
ML-Agentsとは
- Unityで「強化学習」を行うためのプラグイン
- 学習にはpython環境も用いる

エレキベア
Pythonを用いて学習を行うわけクマね

マイケル
そうだね、とはいえただ使うだけならPythonの知識も
そこまで必要ないため、使ったことない人もご安心ください!
そこまで必要ないため、使ったことない人もご安心ください!
強化学習

マイケル
強化学習がどのような学習法なのかというと、
行動の主体となる「エージェント」が現在の環境を観察し、より多くの報酬を得られるよう学習していく手法
になります。
行動の主体となる「エージェント」が現在の環境を観察し、より多くの報酬を得られるよう学習していく手法
になります。

エレキベア
分かるような分からないようなクマ・・・

マイケル
分かりやすい例でいうと、Youtuberのこーじさんが上げている人工知能系の動画がまさにこれにあたります!
ML-Agentsを使った学習の動画をいくつか上げているのでイメージが分からない人はこちらをご覧ください!
ML-Agentsを使った学習の動画をいくつか上げているのでイメージが分からない人はこちらをご覧ください!
↑こーじさんの動画(いつも見させていただいてます)

エレキベア
強化学習の面白さが滲み出ていて面白いクマね
用語と学習サイクル

マイケル
ML-Agentsを使うにあたりよく出てくる用語は下記の通りです!
用語 | 説明 |
エージェント | 行動する主体 |
環境 | エージェントがいる世界 |
ポリシー | ある状態である行動を行う確率 |
状態 | エージェントの行動によって変化する環境の要素 |
行動 | エージェントが環境に行う働きかけ |
報酬 | 行動の良さを示す指標 |

マイケル
学習のサイクルは下記のようになっていて、
1. 環境を観察して状態を取得する
2. 状態に応じて行動を決定する
3. 行動の結果に応じて報酬を受け取る
4. 1〜3までの経験からポリシーを更新する
といった流れで学習を行います。
1. 環境を観察して状態を取得する
2. 状態に応じて行動を決定する
3. 行動の結果に応じて報酬を受け取る
4. 1〜3までの経験からポリシーを更新する
といった流れで学習を行います。

↑学習のサイクル

エレキベア
学習を進めることでポリシーを更新していくクマね

マイケル
また、この学習環境の1フレームを「1ステップ」、
訓練一回分を「1エピソード」という単位で表現しています。
こちらは実際に使用しながら見ていきましょう!
訓練一回分を「1エピソード」という単位で表現しています。
こちらは実際に使用しながら見ていきましょう!
ML-Agentsの環境構築

マイケル
それでは早速環境を構築していきます!
今回はOSはMacで、下記のバージョンで構築しました。
今回はOSはMacで、下記のバージョンで構築しました。
バージョン | |
Unity | 2021.3.1f1 |
ML-Agents | Release19 |
Python | 3.7.10 |
↑今回使用したバージョン

マイケル
自分が行った環境構築手順について記載していきますがあくまで参考程度にし、
基本的に環境構築は公式の手順を参照した方がよいです。
Gitリポジトリ内にインストール手順が記載されているため、そちらを参照しましょう!
基本的に環境構築は公式の手順を参照した方がよいです。
Gitリポジトリ内にインストール手順が記載されているため、そちらを参照しましょう!
Unity-Technologies/ml-agents – Reference (Release19)
– Installation

エレキベア
分かりやすくまとめられているクマね

マイケル
こちらを参考に、
・Python環境の構築
・ML-Agentsリポジトリのクローン
・ML-Agentsのunity packageをインストール
といった手順で進めていきます。
・Python環境の構築
・ML-Agentsリポジトリのクローン
・ML-Agentsのunity packageをインストール
といった手順で進めていきます。
Python環境の構築

マイケル
まずはpython環境を構築します。
ドキュメントには「Python3.6または3.7のインストールをおすすめします」と記述されているため、今回は現時点の3.7の最新である3.7.10をインストールしました。
ドキュメントには「Python3.6または3.7のインストールをおすすめします」と記述されているため、今回は現時点の3.7の最新である3.7.10をインストールしました。

マイケル
またpython環境を初めて構築する場合、複数バージョン管理できる
pyenvやanyenvを使用してインストールすることをおすすめします。
下記にpyenvを使用したインストール方法の記事のリンクを貼っておくので参考にインストールしましょう!
pyenvやanyenvを使用してインストールすることをおすすめします。
下記にpyenvを使用したインストール方法の記事のリンクを貼っておくので参考にインストールしましょう!
MacにpyenvをインストールしてPython環境を構築する

エレキベア
anyenvはマジで便利クマね

マイケル
ちなみに自分は必要なものだけ入れたい派なので、基本的にanacondaは入れません!
Python環境を構築したら、下記コマンドでmlagentsをインストールしましょう。
Python環境を構築したら、下記コマンドでmlagentsをインストールしましょう。
python -m pip install mlagents==0.28.0

マイケル
必要な依存パッケージも一緒にインストールされるようなのでこれだけで問題ないはず!
気になる方は pip list コマンドでインストールした内容を確認しましょう。
気になる方は pip list コマンドでインストールした内容を確認しましょう。

エレキベア
これだけでPython環境構築は完了クマね
ML-Agentsリポジトリのクローン

マイケル
次に学習やサンプル確認で使用する、ML-Agentsのリポジトリをクローンします。
インストールしたいブランチを指定して落としましょう。
インストールしたいブランチを指定して落としましょう。
git clone --branch release_19 https://github.com/Unity-Technologies/ml-agents.git

エレキベア
訓練用パラメータのサンプル等も用意されているのクマね
ML-Agentsのunity packageをインストール

マイケル
そして次はUnity環境へのインストールです。
PackageManagerから直接インストールすることもできますが、使用するリポジトリのバージョンと合わせるため、package.jsonを指定したインストールにしておいた方がよいです。
PackageManagerから直接インストールすることもできますが、使用するリポジトリのバージョンと合わせるため、package.jsonを指定したインストールにしておいた方がよいです。

マイケル
「Add package from disk」から、「ml-agents/com.unity.ml-agents/package.json」を指定してインストールしましょう。


エレキベア
これでUnity側の環境構築も完了クマね
サンプルプロジェクトを動かす

マイケル
最後に正常にインストールできたかを確認するため、サンプルプロジェクトを開いて動かしてみます。
ml-agents/Project/Assets/ML-Agents配下にサンプルが格納されているため、そのままフォルダごとUnityプロジェクトにインポートします。
ml-agents/Project/Assets/ML-Agents配下にサンプルが格納されているため、そのままフォルダごとUnityプロジェクトにインポートします。

エレキベア
サンプルプロジェクトもいろいろ用意されているクマね

マイケル
しかし、自分の環境だと下記のようにいくつかエラーが出る状態になりました。
それぞれ対処してもいいですが、今回は面倒くさいのでエラーになっているフォルダは削除して確認します。
それぞれ対処してもいいですが、今回は面倒くさいのでエラーになっているフォルダは削除して確認します。
Assets/ML-Agents/Examples/PushBlockWithInput/Scripts/PushBlockActions.cs(15,19): error CS0234: The type or namespace name 'InputSystem' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)
↑このようなエラーが出た今回はエラーとなっている
Assets/ML-Agents/Examples/PushBlockWithInput
Assets/ML-Agents/Editor/Tests/SampleExporter.cs
を丸々削除して解消。

マイケル
エラーが解消したら試しに一つサンプルを動かしてみます。
Assets/ML-Agents/Examples/3DBall/Scenes/3DBall.unity
を開いて実行すると下記のように動作しました。
Assets/ML-Agents/Examples/3DBall/Scenes/3DBall.unity
を開いて実行すると下記のように動作しました。


エレキベア
学習済の状態で動かせるクマね

マイケル
以上で環境構築は完了です!
RollerBallのサンプルを作る

マイケル
環境構築が出来たところで、簡単な強化学習のサンプルを作っていきます。
こちらも公式チュートリアルに手順が記載されているので、詳細はそちらをご覧ください!
こちらも公式チュートリアルに手順が記載されているので、詳細はそちらをご覧ください!
Unity-Technologies/ml-agents (Release19) Learning-Environment-Create-New.md

エレキベア
球オブジェクトがターゲットに向かって転がっていく動きを学習させるサンプルなのクマね
プロジェクト構成

マイケル
オブジェクトとしてCube(Target)、Plane(Floor)、Sphere(RollerAgent)を作成し、下記のように配置します。
また、RollerAgentにはRigidbodyもアタッチしておきます。
また、RollerAgentにはRigidbodyもアタッチしておきます。


エレキベア
オブジェクトもこれだけでかなりシンプルクマね
Agentのスクリプト作成

マイケル
次に球オブジェクトの学習を行うスクリプトを作成します。
下記のようにAgentクラスを継承して学習用の関数をオーバーライドし、処理を記述します。
下記のようにAgentクラスを継承して学習用の関数をオーバーライドし、処理を記述します。
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using UnityEngine;
namespace RollerBall
{
/// <summary>
/// RollerAgent
/// </summary>
public class RollerAgent : Agent
{
[SerializeField] private Transform target;
private Rigidbody _rBody;
/// <summary>
/// オブジェクト初期化
/// </summary>
public override void Initialize()
{
_rBody = GetComponent<Rigidbody>();
}
/// <summary>
/// エピソード開始
/// </summary>
public override void OnEpisodeBegin()
{
// 床から落下していたら位置をリセットする
if (transform.localPosition.y < 0)
{
_rBody.angularVelocity = Vector3.zero;
_rBody.velocity = Vector3.zero;
transform.localPosition = new Vector3(0.0f, 0.5f, 0.0f);
}
// ターゲットの位置をランダムに変える
target.localPosition = new Vector3(Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
}
/// <summary>
/// 観察値の設定
/// </summary>
/// <param name="sensor"></param>
public override void CollectObservations(VectorSensor sensor)
{
sensor.AddObservation(target.localPosition);
sensor.AddObservation(transform.localPosition);
sensor.AddObservation(_rBody.velocity.x);
sensor.AddObservation(_rBody.velocity.z);
}
/// <summary>
/// ポリシーによって決定された行動に応じて行動を実行する
/// 結果に応じて報酬取得とエピソード完了を行う
/// </summary>
/// <param name="actions"></param>
public override void OnActionReceived(ActionBuffers actions)
{
// Agentに力を加える
// ContinuousActionsを使用した場合(-1.0〜1.0)
var controlSignal = Vector3.zero;
controlSignal.x = actions.ContinuousActions[0];
controlSignal.z = actions.ContinuousActions[1];
_rBody.AddForce(controlSignal * 10);
// ターゲットとの距離に応じて報酬を与える
var distanceToTarget = Vector3.Distance(transform.localPosition, target.localPosition);
if (distanceToTarget < 1.42f)
{
AddReward(1.0f);
EndEpisode();
} else if (transform.localPosition.y < 0)
{
EndEpisode();
}
}
/// <summary>
/// ヒューリスティックモードの設定
/// </summary>
/// <param name="actionsOut"></param>
public override void Heuristic(in ActionBuffers actionsOut)
{
// 方向キーで操作する
var continuousActions = actionsOut.ContinuousActions;
continuousActions[0] = Input.GetAxis("Horizontal");
continuousActions[1] = Input.GetAxis("Vertical");
}
}
}
↑球オブジェクトの学習クラス
エレキベア
この中に学習サイクルの処理が定義されているクマね

マイケル
処理内容については後々順を追って説明していきます!
このスクリプトをRollerAgentオブジェクトにアタッチして下記のように設定します。
このスクリプトをRollerAgentオブジェクトにアタッチして下記のように設定します。


マイケル
MaxStepは1回の学習で行動できるステップ数になります。
ここでは1000に設定しました。
ここでは1000に設定しました。

マイケル
そして
・Behaviour Parameters
・Decision Requester
の2つもアタッチし、下記のように設定します!
・Behaviour Parameters
・Decision Requester
の2つもアタッチし、下記のように設定します!


エレキベア
何の値を設定しているのか分からないクマ

マイケル
気になるかもしれないけど、数値の意味についてもこの後流れに沿って説明していきます!
学習環境の準備としては以上になります!
学習環境の準備としては以上になります!
強化学習の流れ

マイケル
それでは強化学習の流れに沿って、
スクリプトの内容と設定値について見ていきます!
スクリプトの内容と設定値について見ていきます!

↑学習のサイクル

エレキベア
状態取得→行動→報酬取得 のサイクルだったクマね
観察状態の取得

マイケル
まずは状態取得の部分から!
こちらはVector Observationの部分が観察値の設定になっています。
こちらはVector Observationの部分が観察値の設定になっています。


マイケル
浮動小数配列を観察値とするパラメータで、サイズを8に指定しています。
何故かというと、
・Targetの位置(X,Y,Z)
・自分の位置(X,Y,Z)
・自分の移動速度(X,Z)
で8つの値を観察値として設定しているためです。
何故かというと、
・Targetの位置(X,Y,Z)
・自分の位置(X,Y,Z)
・自分の移動速度(X,Z)
で8つの値を観察値として設定しているためです。
/// <summary>
/// 観察値の設定
/// </summary>
/// <param name="sensor"></param>
public override void CollectObservations(VectorSensor sensor)
{
sensor.AddObservation(target.localPosition);
sensor.AddObservation(transform.localPosition);
sensor.AddObservation(_rBody.velocity.x);
sensor.AddObservation(_rBody.velocity.z);
}
↑観察値の設定
エレキベア
なるほどクマ
Vector3は3つ分の値の設定になるクマね
Vector3は3つ分の値の設定になるクマね

マイケル
ちなみにStacked Vectorsは過去の観察値をスタックする数の指定になります。
過去の値も含めて観察対象にしたい場合にはこのパラメータを上げましょう!
過去の値も含めて観察対象にしたい場合にはこのパラメータを上げましょう!
行動

マイケル
そして次は行動について!
行動には
Continuous:連続値(–1.0〜1.0)
Discrete:離散値(0、1、2…)
の2種類がありますが、ここではContinuousを使用して行動しています。
行動には
Continuous:連続値(–1.0〜1.0)
Discrete:離散値(0、1、2…)
の2種類がありますが、ここではContinuousを使用して行動しています。


マイケル
行動として受け取りたいのはエージェントの速度(X,Z)になるため、
2つと設定しています。
こちらはOnActionReceived関数で受け取ることができます。
2つと設定しています。
こちらはOnActionReceived関数で受け取ることができます。
/// <summary>
/// ポリシーによって決定された行動に応じて行動を実行する
/// 結果に応じて報酬取得とエピソード完了を行う
/// </summary>
/// <param name="actions"></param>
public override void OnActionReceived(ActionBuffers actions)
{
// Agentに力を加える
// ContinuousActionsを使用した場合(-1.0〜1.0)
var controlSignal = Vector3.zero;
controlSignal.x = actions.ContinuousActions[0];
controlSignal.z = actions.ContinuousActions[1];
_rBody.AddForce(controlSignal * 10);
・・・略・・・
}
↑ContinuousActionsを受け取って行動する
エレキベア
学習が進むにつれてこの値の精度が上がっていくクマね

マイケル
Discreteを使った場合の学習については後で解説しますので
そちらはお待ちください。。
そちらはお待ちください。。
報酬取得

マイケル
そして最後に行動した結果に応じて報酬を与えます!
AddReward関数に報酬値を設定するのですが、1ステップ内の報酬は-1.0〜1.0の間にするのが望ましいらしいです。
AddReward関数に報酬値を設定するのですが、1ステップ内の報酬は-1.0〜1.0の間にするのが望ましいらしいです。
/// <summary>
/// ポリシーによって決定された行動に応じて行動を実行する
/// 結果に応じて報酬取得とエピソード完了を行う
/// </summary>
/// <param name="actions"></param>
public override void OnActionReceived(ActionBuffers actions)
{
・・・略・・・
// ターゲットとの距離に応じて報酬を与える
var distanceToTarget = Vector3.Distance(transform.localPosition, target.localPosition);
if (distanceToTarget < 1.42f)
{
AddReward(1.0f);
EndEpisode();
} else if (transform.localPosition.y < 0)
{
EndEpisode();
}
}

マイケル
1つの訓練が終わったらEndEpisode関数を呼び出して
エピソードを終了させましょう!
このサイクルを繰り返すことで学習していきます!
エピソードを終了させましょう!
このサイクルを繰り返すことで学習していきます!

エレキベア
ペットをしつけている気分になるクマね
ヒューリスティックモードの設定

マイケル
おまけになりますが、
・学習モデルを設定していない状態
・Behaviour TypeをHeuristic Onlyに指定
のどちらかの状態で再生すると、手動で動かせるモード(ヒューリスティック)として動作させることができます。
・学習モデルを設定していない状態
・Behaviour TypeをHeuristic Onlyに指定
のどちらかの状態で再生すると、手動で動かせるモード(ヒューリスティック)として動作させることができます。


マイケル
下記のようにHeuristic関数をオーバーライドして操作を記述することで、
操作した結果を行動値として渡すことができます。
操作した結果を行動値として渡すことができます。
/// <summary>
/// ヒューリスティックモードの設定
/// </summary>
/// <param name="actionsOut"></param>
public override void Heuristic(in ActionBuffers actionsOut)
{
// 方向キーで操作する
var continuousActions = actionsOut.ContinuousActions;
continuousActions[0] = Input.GetAxis("Horizontal");
continuousActions[1] = Input.GetAxis("Vertical");
}

エレキベア
学習開始する前に操作して確かめることができるクマね
訓練ファイルの作成

マイケル
これで準備は整ったので、学習するための訓練ファイルを作成します。
下記のようなyamlファイルを作成し、ml-agents/config辺りに配置します。
下記のようなyamlファイルを作成し、ml-agents/config辺りに配置します。
\behaviors:
RollerBall:
# トレーナー種別
trainer_type: ppo # ppo(オンポリシー) or sac(オフポリシー)
# ハイパーパラメータ
hyperparameters:
# PPO、SAC共通
batch_size: 10 # 勾配降下(適正な値に近づける)の更新1回に使用される経験の数 (Continuousの場合は大きな数、Discreteの場合は小さな数の方がよい)
buffer_size: 100 # ポリシーの更新を行う前に収集する経験の数(batch_sizeの倍数でなければならない)
learning_rate: 3.0e-4 # 学習率の初期値 (高いほど学習済とみなして結果を信用する)
learning_rate_schedule: linear # 学習率をどのように変化させるか (linearは後半になるほど高くし結果を信用する)
# PPO固有
beta: 5.0e-4 # 行動決定のランダムさ
epsilon: 0.2 # 勾配降下のポリシー更新比率に対する許容限界の指定 (低くすると安定するが時間がかかる)
lambd: 0.99. # GAEを計算するときに使用する正規化パラメータ
num_epoch: 3 # 勾配降下にポリシー更新時に訓練データを学習させる回数 (小さくすると安定するが時間がかかる)
beta_schedule: constant # betaをどのように変化させるか
epsilon_schedule: linear # epsilonをどのように変化させるか
# ニューラルネットワーク
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 # 統計情報の保存頻度となるステップ数

マイケル
学習方法のベースとして大きく
・ppo(オンポリシー)
・sac(オフポリシー)
の指定が出来るのですが、ここではppoを指定しています。
各パラメータはコメントとして書いた内容になりますが、詳細について知りたい方は公式のドキュメントを参照しましょう!
・ppo(オンポリシー)
・sac(オフポリシー)
の指定が出来るのですが、ここではppoを指定しています。
各パラメータはコメントとして書いた内容になりますが、詳細について知りたい方は公式のドキュメントを参照しましょう!
Unity-Technologies/ml-agents(Release19) ml-agents/Training-Configuration-File.md

エレキベア
いろいろあって分からんクマ・・・
こればっかりは触って慣れていくしかないクマね
こればっかりは触って慣れていくしかないクマね
強化学習実行

マイケル
訓練ファイルを配置したら、ml-agentsフォルダ配下で下記コマンドを実行します。
その状態でUnityプロジェクトのPlayボタンを押下すると学習が開始されます。
その状態でUnityプロジェクトのPlayボタンを押下すると学習が開始されます。
# 学習開始
# run-idで指定した名前のフォルダに出力される
mlagents-learn ./config/RollerBall.yaml --run-id=firstRun


エレキベア
何か面白いクマね

マイケル
run-idの名前は自由に指定してよいですが、二回目以降は下記のように上書きor再開を指定する必要があります。
こちらもよく使うと思うので覚えておきましょう!
こちらもよく使うと思うので覚えておきましょう!
# 学習済のフォルダに対して上書きする
mlagents-learn ./config/RollerBall.yaml --run-id=firstRun --force
# 学習途中のフォルダに対して再開する
mlagents-learn ./config/RollerBall.yaml --run-id=firstRun --resume

マイケル
学習経過のログやモデルはresultsフォルダ配下に出力されます。
こちらをtensorboardコマンドとして指定すると学習経過を見ることができます。
こちらをtensorboardコマンドとして指定すると学習経過を見ることができます。
# tensorboardを開く
tensorboard --logdir results/firstRun --port 6006


マイケル
こちらの詳しい見方については下記をご参照ください!
今回はこちらのCumulative Reward(平均累積報酬)が1に収束してきたらCtrl+Cで学習を停止させましょう。
するとresults/[run-id]フォルダ配下に学習したモデルが出力されます。
今回はこちらのCumulative Reward(平均累積報酬)が1に収束してきたらCtrl+Cで学習を停止させましょう。
するとresults/[run-id]フォルダ配下に学習したモデルが出力されます。
Unity-Technologies/ml-agents tensorboard

エレキベア
これは中々奥が深そうクマ〜〜
作成したモデルで推論する

マイケル
学習したモデルで動作を確認(推論)してみましょう!
出力されたモデル(今回はRollerBall.onnx)をUnityにインポートして、Behavior Parametersに指定RollerBall.onnxします。
出力されたモデル(今回はRollerBall.onnx)をUnityにインポートして、Behavior Parametersに指定RollerBall.onnxします。


マイケル
この状態でPlayボタンを押下すると推論モードとして動作し、
下記のように学習した内容に沿って動作するようになっているはずです!
下記のように学習した内容に沿って動作するようになっているはずです!


エレキベア
おお〜〜なんか生きてるみたいクマ

マイケル
以上で学習の一通りの流れは完了です!
これより先はおまけの内容になるため、興味がある方のみご覧ください!
これより先はおまけの内容になるため、興味がある方のみご覧ください!
その他の知識
離散値を使用して学習させるパターン

マイケル
今回はContinuous(連続値)を行動として指定しましたが、
Discrete(離散値)を指定した場合も見てみましょう!
Discrete(離散値)を指定した場合も見てみましょう!

マイケル
Behaviour Parametersの設定は下記のようになります。


マイケル
今回は
0:何もしない、1:上移動、2:下移動、3:左移動、4:右移動
の5つをアクションとして登録しています。
こうした場合、スクリプトも下記のように修正する必要があります。
0:何もしない、1:上移動、2:下移動、3:左移動、4:右移動
の5つをアクションとして登録しています。
こうした場合、スクリプトも下記のように修正する必要があります。
/// <summary>
/// ポリシーによって決定された行動に応じて行動を実行する
/// 結果に応じて報酬取得とエピソード完了を行う
/// </summary>
/// <param name="actions"></param>
public override void OnActionReceived(ActionBuffers actions)
{
// Agentに力を加える
// DiscreteActionsを使用した場合(branches: 1, branch 0 size: 5)
// 0:無し、1:上移動、2:下移動、3:左移動、4:右移動
var controlSignal = Vector3.zero;
var actionType = actions.DiscreteActions[0];
if (actionType == 1) controlSignal.z = 1.0f;
if (actionType == 2) controlSignal.z = -1.0f;
if (actionType == 3) controlSignal.x = -1.0f;
if (actionType == 4) controlSignal.x = 1.0f;
_rBody.AddForce(controlSignal * 10);
// ターゲットとの距離に応じて報酬を与える
var distanceToTarget = Vector3.Distance(transform.localPosition, target.localPosition);
if (distanceToTarget < 1.42f)
{
AddReward(1.0f);
EndEpisode();
} else if (transform.localPosition.y < 0)
{
EndEpisode();
}
}
/// <summary>
/// ヒューリスティックモードの設定
/// </summary>
/// <param name="actionsOut"></param>
public override void Heuristic(in ActionBuffers actionsOut)
{
// 方向キーで操作する
var discreteActions = actionsOut.DiscreteActions;
if (Input.GetKey(KeyCode.UpArrow)) discreteActions[0] = 1;
if (Input.GetKey(KeyCode.DownArrow)) discreteActions[0] = 2;
if (Input.GetKey(KeyCode.LeftArrow)) discreteActions[0] = 3;
if (Input.GetKey(KeyCode.RightArrow)) discreteActions[0] = 4;
}
↑Discreteを使用した場合
エレキベア
こっちを使うメリットとしてはどんなものがあるのクマ??

マイケル
例えばだけど、攻撃アクションが
0:ソード、1:ビーム、2:ハンマー
といった形になっていたとすると、0(ソード)と2(ハンマー)の間は1(ビーム)ではないよね。
そんな感じで連続じゃない値を行動として指定したい場合に使用するといいよ!
0:ソード、1:ビーム、2:ハンマー
といった形になっていたとすると、0(ソード)と2(ハンマー)の間は1(ビーム)ではないよね。
そんな感じで連続じゃない値を行動として指定したい場合に使用するといいよ!

エレキベア
なるほどクマ〜〜〜
それぞれが完全に分かれている場合があるクマね
それぞれが完全に分かれている場合があるクマね
sacを使って訓練するパターン

マイケル
次は訓練ファイルについての補足です!
今回はppoを指定して学習しましたが、sac(オフポリシー)を指定する場合には下記のような設定値になります。
それぞれ固有のパラメータがあるのと、各パラメータも適正値が異なるため注意しましょう!
今回はppoを指定して学習しましたが、sac(オフポリシー)を指定する場合には下記のような設定値になります。
それぞれ固有のパラメータがあるのと、各パラメータも適正値が異なるため注意しましょう!
# 詳細な設定範囲については下記を参照
# https://github.com/Unity-Technologies/ml-agents/blob/release_19_docs/docs/Training-Configuration-File.md
behaviors:
RollerBall:
# トレーナー種別
trainer_type: sac # ppo(オンポリシー) or sac(オフポリシー)
# ハイパーパラメータ
hyperparameters:
# PPO、SAC共通
batch_size: 64
buffer_size: 12000 # SACの場合、batch_sizeの数千倍に指定する必要がある
learning_rate: 3.0e-4
learning_rate_schedule: constant # SACの場合、constantがデフォルト
# SAC固有
buffer_init_steps: 0 # 学習開始前に何ステップ分のランダムな行動を経験バッファに埋めるか
tau: 0.005 # SACモデル更新中のターゲットの更新の大きさ
steps_per_update: 10.0 # ポリシー更新に対するステップの平均的比率
save_replay_buffer: false # 訓練を終了して再開する際、経験リプレイバッファを保存、ロードする (ONにするとかなりのディスク容量を占有する)
init_entcoef: 0.5 # 訓練開始時にエージェントがどの程度探索するか
reward_signal_steps_per_update: 10.0 # ポリシー更新に対する報酬シグナルのステップ平均比率
# ニューラルネットワーク
network_settings:
normalize: false
hidden_units: 128
num_layers: 2
vis_encode_type: simple # これを指定しないと上手く学習できなかった
# 報酬シグナル
reward_signals:
extrinsic:
gamma: 0.99
strength: 1.0
# 基本設定
max_steps: 500000
time_horizon: 64
summary_freq: 10000
threaded: true # ステップ実行中にポリシーを更新することで高速化する (ppoのポリシーに反するためそちらではfalseにする)
↑sacを使用した場合
マイケル
オンポリシーが現在のポリシーで得られた経験のみを利用するのに対して、
オフポリシーは過去の経験も利用して現在のポリシーを予測します。
学習に必要なステップ数が少なくなる代わりに不安定になりやすいので、学習する内容に応じてどちらを使用するかは決めましょう!
オフポリシーは過去の経験も利用して現在のポリシーを予測します。
学習に必要なステップ数が少なくなる代わりに不安定になりやすいので、学習する内容に応じてどちらを使用するかは決めましょう!

エレキベア
中々難しいところクマね
学習を効率化したい場合

マイケル
そして最後は学習効率を上げるための設定について!
こちらはアプリ化する等の対処法があるようですが、一つの環境内に複数のエージェントを用意するのが簡単に設定できて効果が高いようです。
こちらはアプリ化する等の対処法があるようですが、一つの環境内に複数のエージェントを用意するのが簡単に設定できて効果が高いようです。

マイケル
下記のようなイメージになりますね


エレキベア
数回分の訓練を一気に行ってしまおうというわけクマね

マイケル
注意点としては、学習させる座標をローカル座標として指定しないといけない点です。
位置がそれぞれ違うのでそれはそうですよね・・・。
位置がそれぞれ違うのでそれはそうですよね・・・。

エレキベア
しかしこれは簡単に出来るしいいアイデアクマね
おわりに

マイケル
ML-Agentsの環境導入とサンプル作成については以上になります!
どうだったかな??
どうだったかな??

エレキベア
機械学習は難しそうだったクマが、
触ってみるとイメージが掴めてきたクマ
触ってみるとイメージが掴めてきたクマ

マイケル
パラメータの調整が難しそうだけど、
使い方自体はそんなに難しくはなかったね
使い方自体はそんなに難しくはなかったね

マイケル
次の記事ではオセロAI開発に向けて、セルフプレイを駆使した学習について
進めていこうかと思います!
お楽しみに〜〜〜!!
進めていこうかと思います!
お楽しみに〜〜〜!!

エレキベア
クマ〜〜〜〜
【Unity】ML-Agentsで簡単な強化学習を試してみる【RollerBall】〜完〜
※次回の記事はこちら!
コメント