【ML-Agents】UnityとPythonのTensorFlowをつかって機械学習させてみた(v0.11β対応)

##はじめに
v0.11.0の日本語記事が見当たらなかったので、備忘録がてら。

この記事は、__初心者向け__です。
Unity初学者が[ML-Agentsの公式チュートリアルの1つ](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Learning-Environment-Create-New.md)を模倣して
機械学習の一つ、__強化学習(Reinforcement Learning)をしてみた__というものになります。


![Rollerball.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/c9bdcfba-7fd5-af00-caf1-259d9ccb219e.gif)
__こんなのを作ります。:arrow_up:__


Unityの簡単な動かし方ならわかるけど、機械学習をまだやったことないという人向けです。
理論重視というより、手を動かしながら体験できるようザックリと紹介しています。

<b>＊この記事は2019年11月13日時点でのものです。</b>
ML-Agentsはバージョンアップがめまぐるしいので、常に最新の情報を確認してください。 
~~[去年出たばかりの教科書](https://amzn.to/38l6fJa)が役に立たなかった~~
（ちなみに今年の推移 ⇒19年1月: *v0.6* ➡ 4月: *v0.8* ➡ 10月: *v0.10* ➡ 11月現在: *v0.11*）

#要点をざっくり

Unityで機械学習を行う際に必要不可欠なワードがあります。
それが__「Academy」、「Brain」、「Agent」の３つ__です。

基本的にUnity内の「Academy」で定義した環境の中で「Brain」が「Agent」の起こすアクションを制御する、といった流れになります。
今回は外部のTensorFlow(Pythonフレームワーク)を介して強化学習を行い、生成されたニューラルネットワークのモデルをUnityで読み込んで実行させる、ということを行います。
(今回は簡易チュートリアルなので、あまりAcademyには触れません。)

 ![ML-Agents](https://blogs.unity3d.com/wp-content/uploads/2017/09/image4.png)

##バージョン0.10.0からの主な変更点
__初めての方は読み飛ばしてOK。__
v0.8xやv0.9xを使ってたけどBrain Parameters見つかんなくてよくわかんないんだけど、、っていう人はここだけ見れば大丈夫かも。

- *BroadcastHub*の廃止。
- *Brain ScriptableObjects*の廃止。 ⇒ <b>*Behavior Parameters*</b>項目に変更
- *Visual Observation*の大幅なセットアップ変更。
- gRPCの定義刷新。
- オンラインBCトレーニングの廃止。

##実行環境
 - Windows10
 - Unity 2019.1.4f1
 - ML-Agents Beta 0.11.0
 - Python 3.6（Anaconda）

##下準備
まず以下のものをインストールしてください。

 - <b>[Unity5](https://store.unity.com/ja#plans-individual)</b>(verは2017.4以降であれば問題ないと思います)

 - <b>[ML-Agents v0.11.0](https://github.com/Unity-Technologies/ml-agents)</b>
 - <b>[Anaconda 2019.10](https://www.anaconda.com/distribution/#download-section)</b> (__PythonのVersionは3.7__を選択してください)

##プロジェクト作成
１．Unityを立ち上げ`RollerBall`というプロジェクトをつくります。
２．*File -> Build Settings... -> Player Settings... -> Other Settings -> Configuration*にて
*<b>Scripting Runtime Version</b>*と*<b>Api Compatibility Level</b>*がそれぞれ、*<b>.NET 4.x Equivalent</b>*と*<b>.NET 4.x</b>*になっていることを確認します。
![YHN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/6dd98e24-7537-b246-a864-70aae8f13ee4.png)

３．ML-Agentsのアセットをプロジェクトに読み込みます。
ダウンロードした`ml-agents-master\UnitySDK\Assets`内にある
`ML-Agents`フォルダをプロジェクト内に*D&D*します。
![ooop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/f7c4c4ff-c8a0-fb62-6bcb-529c59296219.png)

##ステージ作成
###床(Floor)の作成
 - *3D Object > Plane* で平面を出します。
 - 作成した*Plane* の名前を`Floor`にします。
 - `Floor`の*Transform*を
   - `Position = (0, 0, 0)`
   - `Rotation = (0, 0, 0)`
   - `Scale = (1, 1, 1)`
  にします。
 - *Inpector* > *Materials*の*Element*をいじって好きな見た目にします。
![ppppp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/5363e781-9210-28e4-abe5-d5c50065f8d6.png)

###箱(Target)の作成
- *3D Object > Cube* で立方体を出します。
 - 作成した*Cube* の名前を`Target`にします。
- `Target`の*Transform*を
   - `Position = (3, 0.5, 3)`
   - `Rotation = (0, 0, 0)`
   - `Scale = (1, 1, 1)`
  にします。
- `Floor`と同様、見た目をお好みで変更します。
 ![box.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/c7046fbd-01bd-473c-0b43-55cc3b90ecfa.png)

###サッカーボール(Agent)の作成

- *3D Object > Sphere* で球体を出します。
 - 作成した*Sphere* の名前を`RollerAgent`にします。
- `RollerAgent`の*Transform*を
   - `Position = (0, 0.5, 0)`
   - `Rotation = (0, 0, 0)`
   - `Scale = (1, 1, 1)`
  にします。
- これまでと同様、見た目をお好みで変更します。
 ボールっぽくしたいなら、`CheckerSquare`マテリアルを選択しましょう。
 - *Add Component*より*Rigidbody*を追加します。
 ![kkkkk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/f8da6cc1-4267-95d0-c27f-9b4d4c62c148.png)

###空のオブジェクト(Academy)の作成

- *Create Empty*で空の*GameObject*を出します。
-  作成した*GameObject*の名前を`Academy`にします。
![oooiiiii.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/474b49fc-f6fe-ca15-a899-ac906dc56286.png)

さて、お次はC#で内容を記述していきます。

##Academyの実装(Implement an Academy)

-  *Hierarchy*ウィンドウで`Academy`を選択したまま*Add Component -> New Script*で`RollerAcademy.cs`という名のスクリプトを作成します。
-  `RollerAcademy.cs`の内容を以下に書き換えます。元の内容は消してしまって構いません。


```c#:RollerAcademy.cs
using MLAgents;
public class RollerAcademy : Academy{ }
```
この記述では、
「観測-意思決定-行動」などの基本的な機能（ここでは割愛）を*Academy*クラスから*RollerAcademy*クラスに継承しています。
なので、2行でオッケーです。


##Agentの実装(Implement an Agent)
*Hierarchy*ウィンドウで`RollerAgent`を選択し、
*Add Component -> New Script*で`RollerAgent.cs`という名のスクリプトを作成します。
###ベースの継承(Inheritance the *Base*)

`RollerAgent.cs`の内容を以下に書き換えます。


```c#:RollerAgent.cs
using MLAgents;
public class RollerAgent : Agent{ }
```

*Academy*と同じように名前空間*MLAgents*を読み込んで、ベースクラスに*Agent*を指定して継承させています。

ここまでが、__UnityにML-agentsを組み込む基礎的な手順__です。
次は、強化学習によるボールが箱に向かって突撃していく仕組みを追加します。

###初期化とリセット(Initialization and Resetting)

`RollerAgent.cs`の内容を以下に書き換えます。

```c#:RollerAgent.cs
using unityEngine;
using MLAgents;

public class RollerAgent:Agent
{
    Rigidbody rBody;
    void Start(){
        rBody = GetComponent<Rigidbody>();
    }

    public Transform Target;
    public override void AgentReset()
    {
        if (this.transform.position.y < 0)
        {
            //回転加速度と加速度のリセット
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            //エージェントを初期位置に戻す
            this.transform.position = new Vector3( 0, 0.5f, 0)
        }
        //ターゲット再配置
        Target.position = new Vector3(Random.value * 8 - 4, 0.5f,
                                      Random.value * 8 - 4);
    }

}
```

ここでは、

 - `RollerAgent`が箱（`Target`）に到達したときに行う、次への__再配置と初期化__
 - `RollerAgent`が床（`Floor`）から落ちた時の__復帰__
 
の処理を行っています。

`Rigidbody`はUnityの物理シミュレーションでつかうコンポーネントですね。
今回はエージェントを動かす為に使用します。
`Transform`には*Position,Rotation,Scale*の値が記録されます。
`public`に定義することで、*Inpector*で*Target*の`Transform`を渡せるようになります。

###環境の観測(Observing the Environment)

`RollerAgent.cs`のクラス内に以下を追加します。

```c#
public override void CollectObservations()
{
    // ターゲットとエージェントの位置
    AddVectorObs(Target.position);
    AddvectorObs(This.transform.position);

    //エージェントの速度
    AddVectorObs(rBody.velocity.x);
    AddVectorObs(rBody.velocity.z);
}
```

ここでは、
__観測したデータを特徴ベクトルとして集める処理__
を行っています。


*Target*と*Agent*それぞれの3次元座標と、*Agent*の速度*x*、*z*の合計8次元のベクトルをニューラルネットワークに渡していきます。~~8次元って表現かっくいいよね~~

###行動と報酬(Actions and Rewards)
`RollerAgent.cs`に以下の`AgentAction()`関数にまつわる処理を、追加します。

```c#
public float speed = 10
public override void AgentAction(float[] vectorAction, string textAction)
{
    //行動
    Vector3 controlSignal = Vector3.zero;
    controlSignal.x = vectorAction[0];
    controlSignal.z = vectorAction[1];
    rBody.AddForce(controlSignal * speed);

    
    //報酬
    //ボール（エージェント）が動いた距離から箱（ターゲット）への距離を取得
   float distanceToTarget = Vector3.Distance(this.transform.position, 
                                             Target.position);

    //箱（ターゲット）に到達した場合
    if (distanceToTarget < 1.42f)
    {
        //報酬を与え完了
        SetReward(1.0f);
        Done();
    }

    //床から落ちた場合
    if (this.transform.position.y < 0)
    {
        Done();
    }
}
```

ここでは、
__X方向、Z方向に加える2種類の力（連続値）を読み取って、エージェントを動かしてみるという「行動」と
エージェントが無事、箱に到達できたら「報酬」を与え、落ちたら「報酬」を取り上げるという学習アルゴリズムの処理__  をしています。

`AddForce`関数は*Rigidbody*コンポーネントを持つオブジェクトに物理的な力を加え、移動させる為の関数です。
ターゲットに到達したかを判断する基準値以下の距離が算出された場合のみ、報酬を与えリセットさせます。

より複雑なシチュエーションで十分な学習を得るには、報酬を取り上げるだけでなく罰を与える記述も効果的です。~~（v0,5x時は床から落ちた場合に`-1`されていたが、最新版では必要ないと判断されたらしい）~~



#####まとめると、RollerAgents.csは以下のようになります。

```c#:RollerAgents.cs
using unityEngine;
using MLAgents;

public class RollerAgent:Agent
{
    Rigidbody rBody;
    void Start(){
        rBody = GetComponent<Rigidbody>();
    }

    public Transform Target;
    public override void AgentReset()
    {
        if (this.transform.position.y < 0)
        {
            //回転加速度と加速度のリセット
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            //エージェントを初期位置に戻す
            this.transform.position = new Vector3( 0, 0.5f, 0)
        }
        //ターゲット再配置
        Target.position = new Vector3(Random.value * 8 - 4, 0.5f,
                                      Random.value * 8 - 4);
    }

    public override void CollectObservations()
    {
        // ターゲットとエージェントの位置
        AddVectorObs(Target.position);
        AddvectorObs(This.transform.position);

        //エージェントの速度
        AddVectorObs(rBody.velocity.x);
        AddVectorObs(rBody.velocity.z);
    }

    public override void AgentAction(float[] vectorAction, string textAction)
    {
        //行動
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        rBody.AddForce(controlSignal * speed);

    
        //報酬
        //ボール（エージェント）が動いた距離から箱（ターゲット）への距離を取得
        float distanceToTarget = Vector3.Distance(this.transform.position, 
                                                 Target.position);

        //箱（ターゲット）に到達した場合
        if (distanceToTarget < 1.42f)
        {
            //報酬を与え完了
            SetReward(1.0f);
            Done();
        }

        //床から落ちた場合
        if (this.transform.position.y < 0)
        {
            Done();
        }
    }
}
```

##Unityエディタ上で仕上げ

 - *Hierarchy* ウィンドウで`RollerAgent`を選択し、`RollerAgent(Script)`の項目を2点変更します。
`Decision Interval = 10`
`Target = Target(Transform)`
![sct.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/3788c9c1-5603-c443-639f-cde54104b4a3.png)


 - *Add Component > Behavior Parameters* を追加して、以下のように設定を変更します。

`Behavior Name = RollerBallBrain`
`Vector Observation  Space Size = 8`
`Vector Action  Space Type = Continuous`
`Vector Action  Space Size = 2`

![Be.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/d00f8d5d-1b9f-5346-d64f-9e27a5f687e4.png)

また、[公式ドキュメント](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Learning-Environment-Create-New.md)によると、このままデフォルトのパラメータを使用すると30万ステップも学習を行い、時間がかかってしまうようです。
今回はそれほど複雑な学習ではないので、パラメータの一部を書き換えて試行回数を2万ステップ未満まで減らしましょう。

 - *ml-agents-master-0.11 > config >* にある`trainer_config.yaml`をエディタ（VS codeやメモ帳）で開き、以下の項目の値を書き換えます。


![aaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/e79f09f1-ba8b-ac25-3e1f-9509b005200f.png)

```yaml
batch_size: 10
buffer_size: 100
```

これで、トレーニングをする準備ができました。

##手動テスト
ここまできたらあと少しです。
強化学習の前に、今までつくった環境がちゃんと動作するか人の手で確認してみましょう。
`RollerAgent.cs`のクラスに、以下のメソッドを追加で実装します。

```c#
public override float[] Heuristic()
{
    var action = new float[2];
    action[0] = Input.GetAxis("Horizontal");
    action[1] = Input.GetAxis("Vertical");
    return action;
}

```

`Hotizontal`で水平（横）の入力軸、
`Vertical`で垂直（縦）の入力軸を受け付けるようにします。

これで「W」「A」「S」「D」または矢印キーによる操作が可能になりました。

最後に`RollerAgent`の*Inspector*にある、
*Behavior Parameters*の*Use Heuristic*のチェックボックスをオンにします。

![he.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/08a8c612-ad33-930a-0cbb-067e3c11afcb.png)

Playを押して、実行してみましょう。
キー入力で動くことが確認できたら、成功です。

##TensorFlowで学習させる
では、いよいよ学習のステップに入っていきます。
###環境構築・ライブラリのインストール
まずAnaconda Promptを立ち上げます。
スタートメニュー（Winキー)から検索をかけるとすぐ出ます。
![an.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/faa056b1-f10d-615f-998f-d44821c95125.png)


```
conda create -n ml-agents python=3.6
```
と入力して、仮想環境を構築します。[^1]
![on.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/1739c589-73b7-6fff-9d40-dd4d07897ea0.png)

```
Proceed([y]/n)?
```
インストールするか、と聞かれるので`y`を入力。続いて、

```
activate ml-agents
```
と入力して仮想環境に移ります。[^2]
コマンドラインの先頭に`(ml-agents)`と付いたのを確認してください。
![aaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/fb45672f-f888-85e7-550c-9828d8589569.png)


```
cd ＜ml-agentフォルダ＞
```
に移動します。[^3]

```
pip install mlagents
```
でML-Agentsが独自に使うライブラリのインストールを行います。（2，3分かかります）
このインストールで、TensorFlow/Jupyterなどの依存関係が行われます。


少し時間がたって、
こんな感じの画面が出ればOKです。
![wewe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/62e5c9cf-ba9f-983e-3585-7135de3a02b7.png)

```
cd ＜ml-agentsフォルダ＞\ml-agents-envs
```
に移動します。

```
pip install -e .
```
と入力して、パッケージをインストールします。
![konnna.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/060daa62-421e-5afb-8562-961d5493ff16.png)
こんな画面になればOKです。
そして、

```
cd ＜ml-agentsフォルダ＞\ml-agents
```
に移動します。

```
pip install -e .
```
と入力して、パッケージをインストールします。
![www.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/6c0d804e-81da-9fe6-b3f2-85fd6c4707d6.png)

これでPython側の準備も完成です。

__\:collision:【注意】：TensorFlowSharpプラグインは、v0.6.x以降では使われていません。__古い書籍などを参考に進めていた方は、新たに仮想環境を作り直すことをオススメします。
>ML-Agents ver0.5.0 までは TensorFlowSharp を使って Pythonと通信していましたが、最新版では使わないようにしてください。もし使うと以下のようなエラーが発生したりします。

>No model was present for the Brain 3DBallLearning.
UnityEngine.Debug:LogError(Object)
>MLAgents.LearningBrain:DecideAction() (at Assets/ML-Agents/Scripts/LearningBrain.cs:191)
>MLAgents.Brain:BrainDecideAction() (at Assets/ML-Agents/Scripts/Brain.cs:80)
>MLAgents.Academy:EnvironmentStep() (at Assets/ML-Agents/Scripts/Academy.cs:601)
>MLAgents.Academy:FixedUpdate() (at Assets/ML-Agents/Scripts/Academy.cs:627)

>[（引用元）](https://www.fast-system.jp/unity-ml-agents-version-0-9-0-howto/)

---
###強化学習(Reinforcement Learning)
さて、いよいよ学習に入っていきます。夢のAI体験まであと少しです。頑張りましょう。

```
cd ＜ml-agents＞フォルダ
```
と入力して、ダウンロードしたフォルダ階層へ移ります。

```
mlagents-learn config/trainer_config.yaml --run-id=firstRun --train
```
を実行します。[^4]
![aaaaw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/b83e3998-d01c-d3d3-ffb6-754428a5f6ce.png)
コマンドラインの最下部に、
__INFO:mlagents.envs:Start training by pressing the Play button in the Unity Editor.
（Unityエディタに戻ってPlayボタンを押して、トレーニングを開始してください。）__
と表示されたのを確認します。

Unityの画面に戻って、__*Behavior Parameters*の*Use Heuristic* のチェックを外し__、:arrow_forward:ボタンを押してみましょう。

ボールが箱を追いかけ始めたら、正常に学習が開始されました。

__しばらくPlayボタンを押さないでいると、タイムアウトエラーが発生するようなので、もう一度同じコマンドを実行してください。__

コンソールのログには1000step毎にログが出力されていきます。
途中で中断したい方はCtrl+Cで中断できます。（敢えて早期に終えることで、『弱いAI』が作れたりします）
![おー！！！！.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/c45f8742-acfa-9d91-c033-408674821109.png)

__Stepが試行（学習）回数、__
__Mean Rewardが獲得した報酬の平均値、__
__Std of Rewardが標準偏差__（データのばらつきを表す値）
を表します。

学習を終えると`＜ml-agentsフォルダ＞\models\＜id名~＞`の下に、`RollerBallBrain.nn`ファイルが生成されています。

![hyhy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/5b667d39-c067-8d01-f073-0dd80872454d.png)


#学習反映
さあ、いよいよ生成されたニューラルネットワークのモデルを試す時がやってまいりました。

先程の`RollerBallBrain.nn`ファイルを、UnityのProject内にある*Assets*フォルダにcopyします。
（場所はプロジェクト内であればどこでも構いません）
![wwqqqq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/7fd0ca95-b559-72eb-460e-4bba8b962187.png)

そして、`RollerAgent`の*Inspector*にある*Model* 項目の右端の:radio_button:ボタンをクリックして取り込んだ`.nn`ファイルを選択しましょう。（*この時、同じ名前の`.nn`拡張子ファイルがある場合は混同しないように注意してください。）

また、*Behavior Parameters*の*Use Heuristic* にチェックが入ったままだと、うまく動きません。
__テストが終わったら必ずチェックは外すようにしましょう。__
![aaaqqqq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/195798ed-a538-0a9e-694c-648cd090e6da.png)

それでは、:arrow_forward: Playを押してみましょう。

__無事ボールが追い回し始めたら、成功です。__
![30fps.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/4d380e12-c9a9-e5b2-cc6b-f1f9eb4e95c5.gif)



#（おまけ）TensorBoardで推移グラフを観察
Anaconda Promptで、以下を実行します。

```
tensorboard --logdir=summaries --port=6006
```

ブラウザで[localhost:6006](http://localhost:6006/)を開くと、__学習の推移をグラフで見る__ことができます。
![ほほう、TensorBoardですか。（ﾆﾁｬｱ・・・.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/883056a1-8900-5e5f-2346-83f6e72f7293.png)

#まとめ

 - もっとゴリゴリC#を読めるようになると、__自分でアルゴリズムを微調整できそう__
 - 強化学習では、学習回数で__AIの賢さを弱・中・強などに分類できる__
 - Verの刷新が頻繁にあって、__情報が劣化しやすい__
 - ~~やっぱ人間より学習が遥かに速い。科学の力ってすげ―！！~~

初心者でもアセットを使えば、シンプルな機械学習であれば1日で模倣できる便利な世の中になりました。
実際に触ってみて、如何だったでしょうか。
機械学習に興味を持っていただくキッカケになってくれると嬉しいです。

何か気になる表現や誤表記など見受けられましたら、ご指摘頂けると幸いです。
また、この記事参考になったという方は__いいね！くれると__励みになります。

以上、ありがとうございました。

##参考
以下、非常に学習の手助けになった先人の方々の記事です。この場を借りて、__謝辞__を述べさせていただきます。

[Unity-Technologies公式ドキュメント（GitHub）](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Learning-Environment-Create-New.md)
[ml-agents移行ガイド（GitHub）](https://github.com/Unity-Technologies/ml-agents/blob/0.11.0/docs/Migrating.md)
[Unity：ML-Agents 2019年09月(ver0.9.0 /0.9.1/0.9.2)での使い方](https://www.fast-system.jp/unity-ml-agents-version-0-9-0-howto/)
[【Unity】強化学習のチュートリアルをやってみた(ML-Agents v0.8.1)](https://qiita.com/VeyronSakai/items/bae72c43f4680a388431)
[UnityのML-Agentsで、新しい学習環境を作成する(0.6.0a版)](http://am1tanaka.hatenablog.com/entry/2019/01/18/212915#%E5%AD%A6%E7%BF%92%E5%8A%B9%E6%9E%9C%E3%82%92%E9%AB%98%E3%82%81%E3%82%8B%E3%81%8A%E3%81%BE%E3%81%91)

[^1]: *" ml-agents"*の部分は好きな名前に変更して構いません。
[^2]: 自身で設定した仮想環境名でアクティベート
[^3]: [下準備](#下準備)で*ml-agents-master*をダウンロードしたディレクトリ
[^4]: *" firstRun"*の部分は好きな名前に変更して構いません。