見出し画像

メモその7. 実践ML-Agents

前回までのあらすじ

ML-AgentsことMachine Learning Agentsを導入したKato。
しかし導入はしたけど何をやってるかはよく分かっていなかったのだ!
Making a New Learning Enrivonmentからその実態を探る!

Making a New Learning Environment
https://github.com/Unity-Technologies/ml-agents/blob/release_1/docs/Learning-Environment-Create-New.md#add-the-agent-sphere

サイト通りにRollerBallを作成していきたい。

1.実践ML-Agent おしながき

ML-AgentsによるUnity projectは以下のように進んでいくらしい。

スクリーンショット 2020-05-09 20.32.33

以下ガバ和訳

1.Agentsのための環境を作ります。環境はシンプルな物理現象からゲーム、生態系まで幅広く対応してます。

2.Agentsサブクラスを実装します。(ML-AgentsにAgents.csがあるので継承する)Agentsサブクラスは調査する環境、割り当てられた行動、報酬を計算するのに使用されます。

3.AgentsサブクラスをGameObjectに追加しましょう


2.Set Up Unity Project編

まずは下準備。

スクリーンショット 2020-05-09 20.41.53

これに関しては以前掲載した"メモその6.激闘ML-Agents"内の"2.Installation Unity編"を参照されたし。

最終的にpackageにML Agentsが追加されればおっけい。

3.Create Object編

RollerBallでは以下3つのGameObjectと、空のGameObjectを1つ使用する。

・Plane(3D Object)
名称は"Floor"とする。Transformの値は以下の通り。

Position = (0, 0, 0)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

・Cube(3D Object)
名称は"Target"とする。Transformの値は以下の通り。

Position = (3, 0.5, 3)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

・Sphere(3D Object)
名称は"RollerAgent"とする。
Agentsサブクラスを付加するObject。
addComponentでRigidbodyを付加しておく。
Transformの値は以下の通り。

Position = (0, 0.5, 0)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

・整理用に空のGameObject"TrainingArea"を追加。
Transformの値は以下の通り。

Position = (0, 0, 0)
Rotation = (0, 0, 0)
Scale = (1, 1, 1)

上記3つのGameObjectをDragして"TrainingArea"の子要素にしてしまう。

スクリーンショット 2020-05-09 20.58.56

だいたいこんな感じ。

4.Implement an Agent編

エージェント夜を往くってな。
ごめんなさいなんでもないです。

スクリーンショット 2020-05-09 21.11.15

1.Inspector windowのRollerAgentを選択します
2.Add Componentを選択
3〜5.New Scriptから"RollerAgent"を作成

RollerAgentの編集

スクリーンショット 2020-05-09 21.11.20

1.RollerAgentをエディターで開く
2. MonobehaviourをAgentに置き換える(Agentクラスを継承)
     んでもって、以下のコードを追加

using Unity.MLAgents; 
using Unity.MLAgents.Sensors

3.Update()を削除

(正直公式にコード全文載ってるからコピってポンでいいんだけどね)

5. Agent三本柱

さてさて継承するAgentクラス。
以下の3つのメソッドを拡張することで色々やっていきます。

・OnEpisodeBegin()
・CollectObservations(VectorSensor sensor)
・OnActionReceived(float[] vectorAction)

ML-Agentsは様々な実行エピソードを含んでいます。

例えば、

・割り当てられた課題を解決しようとするエピソード。

(このProjectの場合、"Agent"が"Target"に向かうこと)
・失敗したエピソード
(このProjectの場合、"Agent"が"Floor"から落下すること)
・タイムアウトしたエピソード
(タスクの成否に関わらず時間がかかりすぎている)

などなど...

OnEpisodeBegin()は新たなエピソードのために、それぞれのエピソードの初期段階で呼ばれます。

何言ってんだお前?ってなるかもしれないので、サイト説明をガバ和訳しながらなんとなく掴んでいく。

6.OnEpisodeBegin()

スクリーンショット 2020-05-09 21.35.24

今回、"RollerAgent"は、毎回"Targe"tに接触するよう動く。
こうしたエピソードが終わったとき、本メソッドは"Target"を"Floor"上の新たな地点に設置する。加えて、"RollerAgent"が"Floor"から落下した場合、本メソッドは"RollerAgent"を再び"Floor"に戻す。

スクリーンショット 2020-05-09 21.40.26

"Target"に向かって動くために、"RollerAgent"は"Target"のTransform情報を必要とする。この情報を得るために、RollerAgentのスクリプトにpublic型のTransformを宣言する。
UnityのInspector Windowから、ここに"Target"をぶち込む。
やったね!

スクリーンショット 2020-05-09 21.40.25

"RollerAgent"の速度をリセットするために、Rigidbodyを付加する。
Rigidbodyの反応を得るのに最適なのは

GameObject.GetComponent<T>()

を使用することである。

なんやかんやで、現段階のコードはこうなる。

using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;
public class RollerAgent : Agent
{
   Rigidbody rBody;
   void Start () {
       rBody = GetComponent<Rigidbody>();
   }
   public Transform Target;
   public override void OnEpisodeBegin()
   {
       if (this.transform.localPosition.y < 0)
       {
           // If the Agent fell, zero its momentum
           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);
   }
}

言われてみれば確かにそうなっている。
次行ってみよう。

7.CollectObservations(VectorSensor sensor)

Agentは、Brainに対し、行動を決断するための情報を送っている。
Agentが学習中、データはニューラルネットワークに送られる。
Agentには正しい情報を提供しなくてはならない。

今回の場合、"RollerAgent"は"Target"の位置と自身の位置、速度という情報を集める。
こうした情報を集めるのがCollectObservations(VectorSensor sensor)である。
これらの情報は"RollerAgent"が、"Target"に対して行き過ぎたり、"Floor"から落下しないようにするために使用される。

結果以下のようなコードになる

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);
}

読んで字のごとく、CollectObservations(調査結果収集)


8.OnActionReceived(float[] vectorAction)

このメソッドはAgentの行動(action)と報酬(reward)を提供する。

・Actions
本Projectにおいて、平面"Floor"に位置する"RollerAgent"が取り得るactionは二つである。
・x軸方向への移動
・z軸方向への移動
すなわちこうなる。
x軸への移動、z軸方向への移動を行列で確保している。

Vector3 controlSignal = Vector3.zero;
controlSignal.x = action[0];
controlSignal.z = action[1];
rBody.AddForce(controlSignal * speed);


・Rewards
割り当てられた課題が達成された時、Agentに大して報酬を与えなくてはならない。
今回、"RollerAgent"と"Target"の距離を計算し、"RollerAgent"が"Target"に触れたと判断した時、値1.0を報酬として与えている。

float distanceToTarget = Vector3.Distance(this.transform.localPosition, Target.localPosition);
// Reached target
if (distanceToTarget < 1.42f)
{
   SetReward(1.0f);
   EndEpisode();
}

んで持って、もし"RollerAgent"が落下した時はEndEpisode()で次のエピソードへ切り替えるのだ。

// Fell off platform
if (this.transform.localPosition.y < 0)
{
   EndEpisode();
}

最終的にOnActionReceived()はこうなる

public float speed = 10;
public override void OnActionReceived(float[] vectorAction)
{
   // Actions, size = 2
   Vector3 controlSignal = Vector3.zero;
   controlSignal.x = vectorAction[0];
   controlSignal.z = vectorAction[1];
   rBody.AddForce(controlSignal * speed);
   // Rewards
   float distanceToTarget = Vector3.Distance(this.transform.localPosition, Target.localPosition);
   // Reached target
   if (distanceToTarget < 1.42f)
   {
       SetReward(1.0f);
       EndEpisode();
   }
   // Fell off platform
   if (this.transform.localPosition.y < 0)
   {
       EndEpisode();
   }
}

終わりが近い。

9.Final Editor Setup

スクリーンショット 2020-05-09 22.17.00

以下ガバ和訳
1.Inspector windowからRollerAgentを選択
2.add Componentから""Decision Requester"をRollerAgentに追加
3."Decision Period"を10に変更
4.TargetオブジェクトをInspector window内RollerAgentのTargetフィールドにドラッグ。
5.add Componentから"Behavior Parameters"をRollerAgentに追加
6.Behavior Parametersの各種値を修正
・Behavior Name to RollerBall
・Vector Observation > Space Size = 8
・Vector Action > Space Type = Continuous
・Vector Action > Space Size = 2

10.Training the Environment

ML-Agentsを使うには、拡張子yamlのファイルがいる。
詳しい理由は知らないがとにかく必要っぽい。

ということでダウンロードしたml-agentsファイルにrollerball_config.yamlファイルを作成しましょう。
私の場合は、ターミナルから Desktop/MLA/ml-agentsに移って、touch rollerball_config.yamlしました。

作成したら中身をこんな感じに弄るらしい。

RollerBall:
 trainer: ppo
 batch_size: 10
 beta: 5.0e-3
 buffer_size: 100
 epsilon: 0.2
 hidden_units: 128
 lambd: 0.95
 learning_rate: 3.0e-4
 learning_rate_schedule: linear
 max_steps: 5.0e4
 normalize: false
 num_epoch: 3
 num_layers: 2
 time_horizon: 64
 summary_freq: 10000
 use_recurrent: false
 reward_signals:
   extrinsic:
     strength: 1.0
     gamma: 0.99

あとは前回とおんなじですね
MLA/ml-agents内で、、、、

mlagents-learn config/rollerball_config.yaml --run-id=RollerBall


いっけええええええええええええええええええ!!!!!!!!!


で、出来上がったのがこちらになります。
--run-id ={}の、{}の中とおんなじ名前のディレクトリがmodels直下にできます。
んで、そのディレクトリの中に、"Behavior ParametersのBehavior nameで決めた名前.nm"が生成されます。

スクリーンショット 2020-05-09 22.32.23

やりました。
流石に気分が高揚します。

この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
3
頭は文系。心は理系。明日はどっちだ。

こちらでもピックアップされています

ガバガバ情報系メモ
ガバガバ情報系メモ
  • 7本

中身はペラッペラなので参考サイトリンクを見るべし。 己が理解するための手段、再確認的な意味合いで書いてます。 早い話が備忘録。

コメントを投稿するには、 ログイン または 会員登録 をする必要があります。