LoginSignup
0
0

More than 1 year has passed since last update.

ML-Agents Python Low Level API入門:Pythonによる環境操作その3

Posted at

はじめに

今回もPythonによる環境操作の理論的な側面について理解を深めていきます。

DecisionStepsとTerminalSteps

DecisionStepsおよびTerminalStepsmlagent_envs.base_envパッケージで定義されている、エージェントの収集した情報を報告してくれる通信用のクラスです。これらは非常に似た機能を持っているので、一度に解説します。まずは、どちらのクラスにも含まれる有用なフィールドについて解説します。

obs

obsフィールドは観測を表すNumPy配列のリストです。1次元目(最初のインデックス)はエージェントのインデックスを示しており、2次元目以降でUnityで設定した情報がNumPy配列として保存されています。このNumPy配列の内容は、Unityで指定したものになります。Behavior ParametersコンポーネントのVector ObservationVector Sizeの数だけの要素が含まれた配列で、その格納順序は、Agentクラスを継承したコンポーネントのCollectObservationメソッドで指定した順番と一致します。

reward

rewardフィールドは単数形ですが、すべてのエージェントの直前のステップでの報酬を表すNumPy配列です。エージェントは直前のステップでも決定を受け取って行動し、OnActionReceivedメソッドが呼ばれているはずです。そこで指定された報酬が帰ってきます。このように書くと単純に思えますが、実際はDecision Requesterコンポーネントの効果により、Decisionを要求しないActionが複数回行われているので注意が必要です。(ここは調査した結果を書く。おそらく、何もしないフレームはRewardは消化されずに、Decisionを要求したときに一度に開放されるはず)

agent_id

agent_idフィールドも単数形ですが、中に入っているのはNumPy配列です。int32型が保存されていて、エージェントIDが保存されています。この情報を使うことで、rewardおよびobsが、どのエージェントから収集した情報なのかが分かります。
前回の記事で解説しましたが、get_stepsメソッドは、そのステップの開始時点での決定待ち状態のエージェントをすべて収集してくるという機能を持つだけであり、すべてのエージェントの情報を1ステップ分集めてくるものではないのです。したがって、obsrewardsに入っている情報は0個のエージェントについての情報である可能性も十分にあるわけでし、並んでいる順番が常に一定であることも保証してくれません。agent_idはそのときのためのフィールドです。agent_idの数値は、そのインデックスに保存されているエージェントのIDを示します。例えば、以下のような場合を考えます。

agent_id == [0, 1, 4]
reward == [-1, 1, 0]
obs == [[1, 1, 0], [0, 0, 0], [-1, 0, -1]]

このとき、エージェントIDが1のエージェントは報酬1を受け取っており、現在の状態は[0, 0, 0]であるということが識別できます。これは、最初から2番目に1がある、というagent_idからの情報から、rewardおよびobsの同じ最初から2番目の情報を集めたエージェントのIDが分かる、という仕組みです。

action_mask

action_maskフィールドは、Agentを継承するコンポーネントでWriteDiscreteActionMaskをオーバーライドした場合に使うことができるもので、離散的アクションの一部の選択を禁止することができます。禁止することができる、といっても、mlagents-envsにその機能があるわけではなく、決定を作成するときにそれを使わない決定をするようにPython側が実装しないといけないというものです。あくまで環境側からのリクエストを示す値になります。ちなみに、mlagents-learnの場合にはこのフラグをいい感じに解釈してくれるという仕組みになっています。注意点として、Trueが使用できないフラグになっています。これは、actionMask.SetActionEnabledとはです。Unity側でfalseを設定すると、対応するaction_maskはTrueになっています。

BehaviorSpec

Spec系クラスの存在価値

ここまででobsrewardなど、Behavior Parametersコンポーネントの設定によって形状が変化する引数を扱いました。そのような引数の形状は、事前に把握しておくだけでなく強化学習の環境に問い合わせて取得することができます。そうすることで、より汎用的なプログラムを書くことができます。例えば、得られる観測のベクトルを増やすという変更を行ったときにも、Python側がニューラルネットワークの入力層の入力の数を観測ベクトルの個数を取得してから設定するようにプログラムをかいておけば、Python側の変更は不要になります。

BehaviorSpec

Unityで環境を作成するときにも解説しましたが、ML-Agentsにおける"Bahavior"とはひとつの強化学習モデルで表現されるエージェントというような意味を持っています。したがって、BehaviorSpecクラスには、Behaviorについての情報が保存されています。UnityにおけるBehavior Paramatersコンポーネントに対応するような存在です。詳しくは次回の記事で解説しますが、BaseEnv.behavior_specsメソッドで取得することができます。主要なフィールドは以下の2つです。

  • observation_specs:ObservationSpecのリストを返す。リストに格納されている順番と、obsフィールドで取得できる順番は一致している
  • action_spec:ActionSpecを返す

ActionSpec

特定のBehaviorがとることができる行動についての情報を取得することができます。Behavior ParametersコンポーネントのActionsの設定に対応しています。

  • continuous_size:連続的な行動の個数
  • discrete_size:離散的な行動の個数
  • discrete_branches:それぞれの離散行動が何個の選択肢を持っているのかのタプル。例えば、Branch 0 Sizeが2で、Branch 1 Sizeが3の場合は、int型のタプル(2, 3)が得られる。discrete_sizeが大きくなれば、discrete_branchesの長さも大きくなる

ObservationSpec

あるひとつの観測の情報を取得することができます。前提としてセンサーなどの知識が必要なので、ここでは深く触れませんが、プロパティについて簡単に概要を述べておきます。

  • shape:入力の形状をint型のタプルで表す。例えば、6つの値を取得する場合は(6,)となる。
  • dimension_property:入力の種類を表す列挙型を形状に従ったタプルで表す。例えば(DimensionProperty.NONE,)ならば通常のベクトルであることを示す。

おわりに

今回まで実際のコードに触れずに解説してきたので、実感がわきにくかったとおもいます。しかしながら、理論面を分かっておくと実際のコーディングでも色々な応用・予測が聞くようになるのでその2およびその3の内容についてはしっかりと把握しておきましょう。

0
0
0

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
0
0