2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Unity ML-Agents を試してみた

Last updated at Posted at 2020-09-01

前提

環境

  • Unity 2019.4.9f1 (LTS)
  • ML Agents 1.3.0 (Preview)
  • ML Agents Extension 0.0.1 (Preview)
  • Anaconda Python 3.8
  • Windows 10

次の記事

⇒ 「Unity ML-Agentsでターン制ゲームを作る

記事の範囲

リソース

導入

Unity

  • Unity Hubをダウンロードして導入します。
  • Unity Hubを開き、インストールから新しいLTS版を導入します。
    • 最初は2018.4.x (LTS)を試したのですが、頻繁にエディタが落ちたので、2019.4.x (LTS)にしました。

Anaconda

  • ダウンロードしてデフォルト設定で導入します。
    • パスがどうのと尋ねられるけど、何も変えずにOKするだけです。
  • Anaconda Navigatorを起動して、自動設定が完了したらNavigatorを終了します。
  • 開発では、スタートメニューのAnaconda Promptを使用します。(Windows)

ML-Agents

  • ガイダンスに従って導入します。
    • リポジトリをクローンするかダウンロードします。
      • 全体が開発環境になります。
      • 中のProjectフォルダのテンプレートをベースにUnityプロジェクトを作ります。
        • フォルダ名(Project)は変更可能です。(そのままで複数の機械学習プロジェクトを作ると、UnityHubに同じ名前が並ぶので…)
    • Unityのパッケージマネージャで、必要なUnityパッケージを導入します。
    • pip3で、必要なPythonパッケージを導入します。
      • スタートメニューのAnaconda Promptを使用します。(Windows)

入門ガイドを試す

  • まずは、「入門ガイド」を試します。
    • 再学習も試してみましょう。
      • スタートメニューのAnaconda Promptを使用します。(Windows)
        • まず、カレントディレクトリをUnityプロジェクトの親フォルダ(すなわちML-Agentsのリポジトリのルート)へ移動します。
        • 通常、初めての学習
          • mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun
        • 中断からの再開
          • mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun --resume
        • 以前のファイルに上書き
          • mlagents-learn config/ppo/3DBall.yaml --run-id=first3DBallRun --force
        • アスキーアートのUnityロゴに続きStart training by pressing the Play button in the Unity Editor.と表示されたら、エディタで再生ボタンを押します。
      • 学習を中断する場合はコンソール(Anaconda Prompt)でCtrl+Cを押します。するとエディタの再生が自動的に停止します。
        • いきなりエディタの再生を停止しても、コンソール側でセーブされるように見えますが、推奨されていないようです。
      • 学習結果の~.nnファイルをResultフォルダからAsset/TFModelsフォルダへコピーします。
        • 初めてなら、エージェントコンポーネントにファイルを設定します。
    • より多くの例が見たければ、学習環境の例をあたります。

学習環境を新たに作ってみる

  • 次に、「新しい学習環境を作るを」試します。
    • エージェントは下記のような感じになりました。
    • トレーニング構成ファイル(~config.yaml)はサンプルのまま使いました。
RollerAgent.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;

public class RollerAgent : Agent {

	[SerializeField] private Transform target = default; // ターゲット
	[SerializeField] private float forceMultiplier = 10; // 作用力係数
	private Rigidbody rBody; // エージェントの剛体
	private const float reachMargin = 1.42f; // 許容する接触誤差

	/// <summary>オブジェクトの初期化</summary>
	private void Awake () {
		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, 0.5f, 0);
		}
		// ターゲットを新しい無作為な位置へ移動
		target.localPosition = new Vector3 (Random.value * 8 - 4, 0.5f, Random.value * 8 - 4);
	}

	/// <summary>環境の観察</summary>
	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>
	public override void OnActionReceived (float [] vectorAction) {
		// 行動, size = 2
		var controlSignal = Vector3.zero;
		controlSignal.x = vectorAction [0];
		controlSignal.z = vectorAction [1];
		rBody.AddForce (controlSignal * forceMultiplier);
		// 報酬
		var distanceToTarget = Vector3.Distance (transform.localPosition, target.localPosition);
		// ターゲットへの到達
		if (distanceToTarget < reachMargin) {
			SetReward (1.0f);
			EndEpisode ();
		}
		// プラットフォームからの落下
		if (transform.localPosition.y < 0) {
			EndEpisode ();
		}
	}

	/// <summary>環境のテスト</summary>
	public override void Heuristic (float [] actionsOut) {
		actionsOut [0] = Input.GetAxis ("Horizontal");
		actionsOut [1] = Input.GetAxis ("Vertical");
	}

}

課題と対処

以下のような課題が生じ対処しました。

Windowsで実行形式での学習をしようとしても起動できないと言われる

独立実行可能な学習環境」に従って、mlagents-learnの引数--env=<env_name>にビルドしたフォルダを指定しましたが、「mlagents_envs.exception.UnityEnvironmentException ~ Couldn't launch」などと出て学習を開始できません。

対処

<env_name>に実行ファイルのフルパス(/区切り)を指定しました。
拡張子はあってもなくても大丈夫でした。

EndEpisode ()でフリーズする

エディタごとフリーズしました。

対処

EndEpisode ()は内部でOnEpisodeBegin ()を呼び出します。
そのため、OnEpisodeBegin ()の中でEndEpisode ()を呼ぶと再入が発生します。

応用できるようにさらに学ぶ

  • 紹介されている例は、いずれも3D空間上の挙動を学習するものですが、「エージェント」と「学習環境の設計」を学ぶことで、ターン制ゲームへの道筋が見えるようになりました。
  • トレーニング構成ファイル」を学ぶことで、独自の~config.yamlファイルを作れるようになります。
  • 独立実行可能な学習環境」を学ぶことで、長時間の学習の際にもエディタを占有されずに済むようになります。
  • 学習を最適化し、より良い結果を得るためには、機械学習そのものについてより深く学ぶ必要があるようです。
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?