見出し画像

Unity ML-Agents Release 3 の新機能

「Unity ML-Agents Release 3」の新機能 をまとめました。

1. Vector Observation の新しい設定方法

「Unity ML-Agents Release 3」は、以下の3つの方法で、「Vector Observation」を設定することができます。

(1) Agent.CollectObservations()をオーバーライドし、提供されたVectorSensorに観察を追加。
(2) 観察として利用するエージェントのフィールドとプロパティに[Observable]属性を追加。
(3) ISensorインターフェイスとSensorComponentでISensorオブジェクトを実装。

(1)は従来の設定方法、(2)が「Release 3」から新規追加された方法、(3)がサンプル(Basic)があったものの、はじめてドキュメントが追加された方法になります。

2. [Observable] によるVector Observationの設定

観察として利用するエージェントのフィールドとプロパティに[Observable]属性を追加することで、観察を設定します。例えば、「3DBall」の例では、エージェントに次のようにプロパティを追加することで剛体速度を観察できます。

using Unity.MLAgents.Sensors.Reflection;

public class Ball3DAgent : Agent {

    [Observable]
    public Vector3 RigidBodyVelocity
    {
        get {return m_BallRb.velocity;}
    }
}

[Observable]は現在、「Vector2」「Vector3」「Vector4」「Quaternion」「列挙型」だけでなく、「float」「int」「bool」などほとんどの基本データ型をサポートしています。

[Observable]の設定は、「Behavior Parameters」の「Observable Attributes」で行います。

画像1

Ignore(デフォルト): すべての[Observable]を無視。
Exclude Inhelited : エージェントクラスのみ[Observable]を検査(継承を除外)。
Examine All : エージェントクラスの継承元も含めて[Observable]を検査。

内部的には、リフレクションを使用して、エージェントのどのメンバーが[Observable]かを調べます。CollectObservations()やISensorよりも遅くなる可能性がありますが、パフォーマンスに著しく影響を与えるほどではありません。

【注意】 [Observable]をエージェントクラスのフィールドとプロパティに追加する時、エージェントの「Behavior Parameters」で「Space Size」を設定する必要はありません。

3. ISensorインターフェイスとSensorComponent によるVector Observationの設定

ISensorインターフェイスとSensorComponentでISensorオブジェクトを実装することで、観察を設定します。一般に上級ユーザーを対象としています。

ISensorオブジェクトはISensorインターフェイスを継承して、SensorComponentを利用して、観察のために必要ないくつかのメソッドを実装します。このオブジェクトは、エージェントとなるゲームオブジェクト、または子ゲームオブジェクトにアタッチする必要があります。

「SensorComponent」は、次の4種類が用意されています。

SensorComponent : Vector Observationを観察として使用。
CameraSensorComponent : カメラのVisual Observationを観察として使用。
RenderTextureSensorComponent : レンダーテクスチャのVisual Observationを観察として使用。
RayPerceptionSensorComponent : Raycast Observationを観察として使用。
【注意】 ISensorインターフェイス、SensorComponentsを使用する場合、エージェントの「Behavior Parameters」で「Space Size」を設定する必要はありません。

5. 訓練設定ファイル - PPO・SAC

「Unity ML-Agents Release 3」では、「訓練設定ファイル」(*.yaml)の仕様が大幅に変更されました。

(1) 「訓練設定ファイル」は、環境ごとに1ファイルになった。(以前は全環境で1ファイル)
(2) 「カリキュラム学習」や「環境パラメータのランダム化」の設定も、「訓練設定ファイル」に含むようになった。
(3) 「default」セクションはな無くなった。
(4) サブセクションの構成が整理された。

PPOの訓練設定ファイルの例は、次のとおりです。

behaviors:
  BehaviorPPO:
    # トレーナー種別
    trainer_type: ppo

    # 基本設定
    max_steps: 5.0e5
    time_horizon: 64
    summary_freq: 10000
    keep_checkpoints: 5
    checkpoint_interval: 50000
    threaded: true
    init_path: null

    # ハイパーパラメータ
    hyperparameters:
      # PPOとSAC共通
      batch_size: 1024
      buffer_size: 10240
      learning_rate: 3.0e-4
      learning_rate_schedule: linear

      # PPO固有
      beta: 5.0e-3
      epsilon: 0.2
      lambd: 0.95
      num_epoch: 3

    # ニューラルネットワーク
    network_settings:
      vis_encoder_type: simple
      normalize: false
      hidden_units: 128
      num_layers: 2

      # LSTM
      memory:
        sequence_length: 64
        memory_size: 256

    # BC
    behavioral_cloning:
      demo_path: Project/Assets/ML-Agents/Examples/Pyramids/Demos/ExpertPyramid.demo
      strength: 0.5
      steps: 150000
      batch_size: 512
      num_epoch: 3
      samples_per_update: 0

    # 報酬シグナル
    reward_signals:
      # Extrisic
      extrinsic:
        strength: 1.0
        gamma: 0.99
 
      # Curiosity
      curiosity:
        strength: 0.02
        gamma: 0.99
        encoding_size: 256
        learning_rate: 3.0e-4

      # GAIL
      gail:
        strength: 0.01
        gamma: 0.99
        encoding_size: 128
        demo_path: Project/Assets/ML-Agents/Examples/Pyramids/Demos/ExpertPyramid.demo
        learning_rate: 3.0e-4
        use_actions: false
        use_vail: false

    # セルフプレイ
    self_play:
      window: 10
      play_against_latest_model_ratio: 0.5
      save_steps: 50000
      swap_steps: 2000
      team_change: 100000

SACの訓練設定ファイルの例は、次のとおりです。その他の機能(メモリ、BC、Curiosity、セルフプレイ)の設定は変更されていないことに注意してください。

behaviors:
  BehaviorSAC:
    # トレーナー種別
    trainer_type: sac

    # 基本設定
      # <PPOと同じ>

    # ハイパーパラメータ
    hyperparameters:
      # PPOとSAC共通
      # <PPOと同じ>
 
      # SAC固有
      buffer_init_steps: 0
      tau: 0.005
      steps_per_update: 10.0
      save_replay_buffer: false
      init_entcoef: 0.5
      reward_signal_steps_per_update: 10.0

    # ニューラルネットワーク
    network_settings:
      # <PPOと同じ>

    # BC
    behavioral_cloning:
      # <PPOと同じ>

    # 報酬シグナル
    reward_signals:
      # Extric
      extrinsic:
        # <PPOと同じ>

      # Curiosity
      curiosity:
        # <PPOと同じ>
 
      # GAIL
      gail:
        # <PPOと同じ>

    # セルフプレイ
    self_play:
        # <PPOと同じ>

訓練設定ファイルの詳細については、「Training Configuration File」を参照。

6. 訓練設定ファイル - カリキュラム学習

カリキュラム学習を有効にするには、サブセクション「curriculum」を訓練設定ファイルに追加します。

カリキュラム学習の訓練設定ファイルの例は、次のとおりです。

behaviors:
  BehaviorY:
    # < 上と同様 >

# カリキュラム学習
curriculum:
  BehaviorY:
    measure: progress
    thresholds: [0.1, 0.3, 0.5]
    min_lesson_length: 100
    signal_smoothing: true
    parameters:
      wall_height: [1.5, 2.0, 2.5, 4.0]

環境内の同じ「Behavior Name」を持つエージェントは、対応するカリキュラム学習を実施することができます。同じ環境内で、異なるエージェントが、異なるカリキュラム学習を実施することも可能です。

7. 訓練設定ファイル - 環境パラメータのランダム化

環境パラメータのランダム化を有効にするには、サブセクション「parameter_randomization」を訓練設定ファイルに追加します。

環境パラメータのランダム化の訓練設定ファイルの例は、次のとおりです。

behaviors:
  # < 上と同様 >

# 環境パラメータのランダム化
parameter_randomization:
  resampling-interval: 5000

  mass:
    sampler-type: "uniform"
    min_value: 0.5
    max_value: 10

  gravity:
    sampler-type: "multirange_uniform"
    intervals: [[7, 10], [15, 20]]

  scale:
    sampler-type: "uniform"
    min_value: 0.75
    max_value: 3

7. 訓練設定ファイルのアップグレードスクリプト

訓練設定ファイルのアップグレードスクリプトを使うには、ml-agentsフォルダ直下で、以下のコマンドを実行します。

$ python -m mlagents.trainers.upgrade_config [-h] [--curriculum CURRICULUM] [--sampler SAMPLER] trainer_config_path output_config_path

必須パラメータ
・trainer_config_path: 訓練設定ファイル(<=0.16.X)のパス
・output_config_path: 出力先のパス

オプションパラメータ
-h, --help: ヘルプ
--curriculum CURRICULUM: カリキュラム学習の設定ファイル(<=0.16.X)のパス
--sampler SAMPLER: 環境パラメータのランダム化の設定ファイル(<=0.16.X)のパス

「work/RollerBall.yaml」を変換して「config/sample/RollerBall.yaml」に出力する例は、次のとおりです。

$ python -m mlagents.trainers.upgrade_config work/RollerBall.yaml config/sample/RollerBall.yaml

・RollerBall.yaml (変換前)

default:
    trainer: ppo
    batch_size: 1024
    beta: 5.0e-3
    buffer_size: 10240
    epsilon: 0.2
    hidden_units: 128
    lambd: 0.95
    learning_rate: 3.0e-4
    learning_rate_schedule: linear
    max_steps: 5.0e5
    memory_size: 128
    normalize: false
    num_epoch: 3
    num_layers: 2
    time_horizon: 64
    sequence_length: 64
    summary_freq: 10000
    use_recurrent: false
    vis_encode_type: simple
    reward_signals:
        extrinsic:
            strength: 1.0
            gamma: 0.99

RollerBall:
    summary_freq: 1000

    batch_size: 10
    buffer_size: 100
    normalize: true

・RollerBall.yaml (変換後)

behaviors:
  RollerBall:
    trainer_type: ppo
    hyperparameters:
      batch_size: 10
      buffer_size: 100
      learning_rate: 0.0003
      beta: 0.005
      epsilon: 0.2
      lambd: 0.95
      num_epoch: 3
      learning_rate_schedule: linear
    network_settings:
      normalize: true
      hidden_units: 128
      num_layers: 2
      vis_encode_type: simple
    reward_signals:
      extrinsic:
        gamma: 0.99
        strength: 1.0
    keep_checkpoints: 5
    checkpoint_interval: 500000
    max_steps: 500000
    time_horizon: 64
    summary_freq: 1000
    threaded: true

8. Pythonでのプロファイリング

「Unity ML-Agents」では、学習プロセスでホットスポットを特定し、変更による回帰を特定するために、「軽量のプロファイリングシステム」を提供しています。

タイマーは階層的で、コードブロックで追跡する時間を、必要に応じて分割できます。すべてのタイマーは「グローバル」インスタンスを使用して動作しますが、必要に応じてオーバーライドできます(主にテスト用)。

◎ プロファイリングの追加
プロファイリングの追加方法は、2つあります。

最も簡単な方法は、プロファイリング対象とするメソッドにデコレータ「@timed」を追加することです。

class TrainerController:
   # ....
   @timed
   def advance(self, env: EnvManager) -> int:
       # do stuff

hierarchical_timer() を使用することもできます。大規模なメソッドの様々な部分、または抽象メソッドのプロファイリングには、hierarchical_timer() の方が便利です。

with hierarchical_timer("communicator.exchange"):
    outputs = self.communicator.exchange(step_input)

◎ 出力
デフォルトでは、学習の最後にタイマーが収集され、JSON形式で「{summaries_dir}/{run_id}_timers.json」に出力されます。
出力は、次のキーを持つノードオブジェクトで構成されています。

・ total (float) : 子呼び出しを含む、ブロックで費やされた合計時間(秒)。
・ count (int) : ブロックが呼び出された回数。
・ self (float) : 子呼び出しを除く、ブロックで費やされた合計時間(秒)。
・ children (dic) : ノード名をキーとした子ノードの辞書。
・ is_parallel (bool) : コードのブロックが複数の「スレッド」または「プロセス」で実行されたことを示す(以下を参照)。これはオプションであり、デフォルトはfalseです。

◎ 並列実行
・サブプロセス
複数のプロセス(たとえば、SubprocessEnvManager)で実行されるコードの場合、タイマー情報を「メイン」プロセスに定期的に送信し、そこでタイマーを集約して、サブプロセスでそれらをフラッシュします。これにより、合計時間が親の合計時間を超える可能性があることに注意してください。これは、unix time コマンドから報告される「実際の値」と「ユーザーの値」の違いに似ています。タイマー出力では、並行して実行されたブロックがis_parallelフラグで示されます。

・スレッド
タイマーは現在time.perf_counter()、費やされた時間の追跡に使用しており、複数のスレッドに対して正確な結果が得られない場合があります。これに問題がある場合は、トレーナー構成で「threaded: false」を設定 してください。

9. Unity Environment Registry [実験的]

Unity Environment Registory」は、ビルド済みのUnity環境のデータベースであり、Unity Editorをインストールしなくても簡単に使用できます。Unity Environment APIを使い始めるのに最適な方法になります。

◎ レジストリから環境をロードする
はじめに、サンプル環境で提供されているデフォルトのレジストリにアクセスできます。Unity環境レジストリはマッピングを実装しているため、[]を使用してその識別子を持つエントリにアクセスできます。次のコードを使用して、デフォルトのレジストリに存在するすべての環境識別子をリストします。

from mlagents_envs.registry import default_registry

environment_names = list(default_registry.keys())
for name in environment_names:
  print(name)

レジストリ値のmake()は、使用できるUnityEnvironmentを返します。make()に渡されるすべての引数は、UnityEnvironmentのコンストラクタにも渡されます。UnityEnvironmentコンストラクタの引数の詳細については、Python-APIのドキュメントを参照してください。たとえば、次のコードは、識別子「my-env」の下で環境を作成し、それをリセットして、いくつかの手順を実行し、最後にそれをクローズします。

from mlagents_envs.registry import default_registry

env = default_registry["my-env"].make()
env.reset()
for _ in range(10):
  env.step()
env.close()

◎ 独自のレジストリを作成して共有
作成したUnityEnvironemntを共有するには、次の手順が必要です。

・プラットフォームごとにUnity環境の実行ファイルを作成(Linux, OSX, Windows)
・各実行ファイルをzip圧縮フォルダに配置
・希望のホスティングプラットフォームに各zipファイルをオンラインでアップロード
・説明と環境へのパスを含むyamlファイルを作成
・yamlファイルをオンラインでアップロード

yamlファイルは次の形式である必要があります。

environments:
  - <environment-identifier>:
     expected_reward: <expected-reward-float>
     description: <description-of-the-environment>
     linux_url: <url-to-the-linux-zip-folder>
     darwin_url: <url-to-the-osx-zip-folder>
     win_url: <url-to-the-windows-zip-folder>
     additional_args:
      - <an-optional-list-of-command-line-arguments-for-the-executable>
      - ...

これで、ユーザーは次のコードで環境を使用できます。

from mlagents_envs.registry import UnityEnvRegistry

registry = UnityEnvRegistry()
registry.register_from_yaml("url-or-path-to-your-yaml-file")
【注意】 "url-or-path-to-your-yaml-file" には、URLまたはローカルパスを指定できます。


この記事が気に入ったらサポートをしてみませんか?