ホーム
ゲーム開発
Unity
UnrealEngine
C++
ゲーム数学
ゲームAI
サウンド
アニメーション
GBDK
制作日記
3DCG
Houdini
Blender
USD
グラフィックス
テクノロジ
生成AI関連
動画制作
ツール開発
フロントエンド関連
サーバサイド関連
ソフトウェア設計
ハードウェア関連
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
その他
ブログについて
都会のエレキベア
ラーメン日記
四コマ漫画
おすすめアイテム
おもしろコラム
お問い合わせ
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • ゲーム数学
    • ゲームAI
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • 3DCG
    • Houdini
    • Blender
    • USD
    • グラフィックス
  • テクノロジ
    • 生成AI関連
    • 動画制作
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • ソフトウェア設計
    • ハードウェア関連
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • その他
JP|EN
  1. ホーム
  2. 20220710_01

【Unity】ML-Agentsで簡単な強化学習を試してみる【RollerBall】

UnityゲームAIML-Agents機械学習
2022-07-11

マイケル
マイケル
みなさんこんにちは!
マイケルです!
エレキベア
エレキベア
こんにちクマ〜〜〜
マイケル
マイケル
今回は、最近行っているオセロAI開発の準備として、
ML-Agentsを使った強化学習について触っていこうと思います!
エレキベア
エレキベア
ML-Agentsクマか〜〜
確かに一回触ってみたかったクマ
マイケル
マイケル
オセロAIの学習にはセルフプレイという学習方法を使う予定のため、その使い方まで見ていこうと思っています。
しかし全部まとめると長くなってしまったので、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を使うにあたりよく出てくる用語は下記の通りです!
用語 説明
エージェント 行動する主体
環境 エージェントがいる世界
ポリシー ある状態である行動を行う確率
状態 エージェントの行動によって変化する環境の要素
行動 エージェントが環境に行う働きかけ
報酬 行動の良さを示す指標
マイケル
マイケル
学習のサイクルは下記のようになっていて、
1. 環境を観察して状態を取得する
2. 状態に応じて行動を決定する
3. 行動の結果に応じて報酬を受け取る
4. 1〜3までの経験からポリシーを更新する
といった流れで学習を行います。

↑学習のサイクル
エレキベア
エレキベア
学習を進めることでポリシーを更新していくクマね
マイケル
マイケル
また、この学習環境の1フレームを「1ステップ」、
訓練一回分を「1エピソード」という単位で表現しています。
こちらは実際に使用しながら見ていきましょう!

ML-Agentsの環境構築

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

↑今回使用したバージョン

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

Unity-Technologies/ml-agents – Reference (Release19)
– Installation

エレキベア
エレキベア
分かりやすくまとめられているクマね
マイケル
マイケル
こちらを参考に、
・Python環境の構築
・ML-Agentsリポジトリのクローン
・ML-Agentsのunity packageをインストール
といった手順で進めていきます。

Python環境の構築

マイケル
マイケル
まずはpython環境を構築します。
ドキュメントには「Python3.6または3.7のインストールをおすすめします」と記述されているため、今回は現時点の3.7の最新である3.7.10をインストールしました。
マイケル
マイケル
またpython環境を初めて構築する場合、複数バージョン管理できる
pyenvやanyenvを使用してインストールすることをおすすめします。
下記にpyenvを使用したインストール方法の記事のリンクを貼っておくので参考にインストールしましょう!

MacにpyenvをインストールしてPython環境を構築する

エレキベア
エレキベア
anyenvはマジで便利クマね
マイケル
マイケル
ちなみに自分は必要なものだけ入れたい派なので、基本的にanacondaは入れません!
Python環境を構築したら、下記コマンドでmlagentsをインストールしましょう。
python -m pip install mlagents==0.28.0
マイケル
マイケル
必要な依存パッケージも一緒にインストールされるようなのでこれだけで問題ないはず!
気になる方は 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を指定したインストールにしておいた方がよいです。
マイケル
マイケル
「Add package from disk」から、「ml-agents/com.unity.ml-agents/package.json」を指定してインストールしましょう。
↑インストール後の状態
エレキベア
エレキベア
これで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
を開いて実行すると下記のように動作しました。
↑3DBallサンプルを動かした例
エレキベア
エレキベア
学習済の状態で動かせるクマね
マイケル
マイケル
以上で環境構築は完了です!

RollerBallのサンプルを作る

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

Unity-Technologies/ml-agents (Release19) Learning-Environment-Create-New.md

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

プロジェクト構成

マイケル
マイケル
オブジェクトとしてCube(Target)、Plane(Floor)、Sphere(RollerAgent)を作成し、下記のように配置します。
また、RollerAgentにはRigidbodyもアタッチしておきます。
↑オブジェクトの作成と配置
エレキベア
エレキベア
オブジェクトもこれだけでかなりシンプルクマね

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オブジェクトにアタッチして下記のように設定します。
↑スクリプトのアタッチとパラメータ設定
マイケル
マイケル
MaxStepは1回の学習で行動できるステップ数になります。
ここでは1000に設定しました。
マイケル
マイケル
そして
・Behaviour Parameters
・Decision Requester
の2つもアタッチし、下記のように設定します!
↑エージェントの振る舞いを設定する
エレキベア
エレキベア
何の値を設定しているのか分からないクマ
マイケル
マイケル
気になるかもしれないけど、数値の意味についてもこの後流れに沿って説明していきます!
学習環境の準備としては以上になります!

強化学習の流れ

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

↑学習のサイクル
エレキベア
エレキベア
状態取得→行動→報酬取得 のサイクルだったクマね
観察状態の取得
マイケル
マイケル
まずは状態取得の部分から!
こちらはVector Observationの部分が観察値の設定になっています。
↑観察値の設定
マイケル
マイケル
浮動小数配列を観察値とするパラメータで、サイズを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つ分の値の設定になるクマね
マイケル
マイケル
ちなみにStacked Vectorsは過去の観察値をスタックする数の指定になります。
過去の値も含めて観察対象にしたい場合にはこのパラメータを上げましょう!
行動
マイケル
マイケル
そして次は行動について!
行動には
Continuous:連続値(–1.0〜1.0)
Discrete:離散値(0、1、2…)
の2種類がありますが、ここではContinuousを使用して行動しています。
↑行動として受け取るパラメータの設定
マイケル
マイケル
行動として受け取りたいのはエージェントの速度(X,Z)になるため、
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の間にするのが望ましいらしいです。
        /// <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に指定
のどちらかの状態で再生すると、手動で動かせるモード(ヒューリスティック)として動作させることができます。
↑ヒューリスティックモードの設定
マイケル
マイケル
下記のように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辺りに配置します。
\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を指定しています。
各パラメータはコメントとして書いた内容になりますが、詳細について知りたい方は公式のドキュメントを参照しましょう!

Unity-Technologies/ml-agents(Release19) ml-agents/Training-Configuration-File.md

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

強化学習実行

マイケル
マイケル
訓練ファイルを配置したら、ml-agentsフォルダ配下で下記コマンドを実行します。
その状態で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 --logdir results/firstRun --port 6006
↑学習経過を見ることができる
マイケル
マイケル
こちらの詳しい見方については下記をご参照ください!
今回はこちらのCumulative Reward(平均累積報酬)が1に収束してきたらCtrl+Cで学習を停止させましょう。
するとresults/[run-id]フォルダ配下に学習したモデルが出力されます。

Unity-Technologies/ml-agents tensorboard

エレキベア
エレキベア
これは中々奥が深そうクマ〜〜

作成したモデルで推論する

マイケル
マイケル
学習したモデルで動作を確認(推論)してみましょう!
出力されたモデル(今回はRollerBall.onnx)をUnityにインポートして、Behavior Parametersに指定RollerBall.onnxします。
↑学習したモデルを設定
マイケル
マイケル
この状態でPlayボタンを押下すると推論モードとして動作し、
下記のように学習した内容に沿って動作するようになっているはずです!
↑ボールが賢くなりました
エレキベア
エレキベア
おお〜〜なんか生きてるみたいクマ
マイケル
マイケル
以上で学習の一通りの流れは完了です!
これより先はおまけの内容になるため、興味がある方のみご覧ください!

その他の知識

離散値を使用して学習させるパターン

マイケル
マイケル
今回はContinuous(連続値)を行動として指定しましたが、
Discrete(離散値)を指定した場合も見てみましょう!
マイケル
マイケル
Behaviour Parametersの設定は下記のようになります。
↑Discreteを使用する場合の設定値
マイケル
マイケル
今回は
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(ビーム)ではないよね。
そんな感じで連続じゃない値を行動として指定したい場合に使用するといいよ!
エレキベア
エレキベア
なるほどクマ〜〜〜
それぞれが完全に分かれている場合があるクマね

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】〜完〜

※次回の記事はこちら!

UnityゲームAIML-Agents機械学習
2022-07-11
記事をSNSで共有する
X
Facebook
LINE
はてなブックマーク
Pocket
LinkedIn
Reddit

著者の各種アカウント
フォローいただけると大変励みになります!

関連記事
【Unity】Light2DとTimelineを活用した2Dライブシーンの構築
2026-07-20
【Unity】Timeline × Excelでスライドショーを効率よく制作する
2024-10-31
【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
2024-05-28
【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
2024-04-14
【Unity】第二回 Wwiseを使用したサウンド制御 〜インタラクティブミュージック編〜
2024-03-30
【Unity】第一回 Wwiseを使用したサウンド制御 〜基本動作編〜
2024-03-30
【Unity】第二回 CRI ADXを使用したサウンド制御 〜インタラクティブミュージック編〜
2024-03-28
【Unity】第一回 CRI ADXを使用したサウンド制御 〜基本動作、周波数解析編〜
2024-03-28