Unity ml-agents v0.6.0 動かしてみた

事前準備編は下記から
[Unity ml-agents v0.6.0 setup for windows - Qiita](https://qiita.com/tkmn0/items/ca68564a1475a019368f)

環境
- Windows 10
- Unity 2018.2.14f1

基本的には下記と同じです。
[ml-agents/Basic-Guide.md at master · Unity-Technologies/ml-agents · GitHub](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Basic-Guide.md)

流れ

```
1. ML-Agents Toolkitをセットアップ
2. TensorFlowSharpをセットアップ
3. 学習前のモデルを実行
4. 学習済みのモデルを実行
5. 学習させてみる
6. 学習させたモデルを実行
```

### 1. ML-Agents Toolkitをセットアップ
---
Unity 2017.4 より上のUnityを用意してください。
後で使う Unity TensorFlow Plugin が上記の条件を要求しています。
Unity で `ml-agents/UnittySDK` フォルダを開きましょう。

`Edit > Project Settings > Player`
より、PlayerSettings を開きます。
Other Settingsの ` Scripting Runtime Version` が
__.NET 4.6 Equivalent__ または __.NET 4.x Equivalent__ になっていることを確認してください。

### 2. TensorFlowSharpをセットアップ
---
学習済みのモデル（.byteファイル）をUnityから読み込むためには、TensorFlowSharpというプラグインが必要になります。
[こちら](https://s3.amazonaws.com/unity-ml-agents/0.5/TFSharpPlugin.unitypackage)よりダウンロードできます

ダウンロードした __TFSharpPlugin.unitypackage__ をダブルクリックで開いてください。
UnityEditor上でimportをクリックすれば、Unity project内に設置されます(Assets/ML-Agents/Plugins/Computer)
再度PlayerSettingsを開き、
__Scripting Define Symbols__ に `ENABLE_TENSORFLOW` と書き込んでください。

ここで、下記のエラーが発生するかと思いますが、 言われるがままに ProjectSettingsから、__Allow unsafe code__ にチェックを入れたらエラーが消えました。
`Unsafe code requires the unsafe command line option to be specified. Enable "Allow 'unsafe' code" in Player Settings to fix this error.`
ここまでで、下記の様になっているかと思います。
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/images/other_settings_LI.jpg">

### 3. 学習前のモデルを実行
---
`Assets/ML-Agents/Examples/3DBall/Scenes/3DBall`を開いてください。
ここでとりあえずPlayを押すと、ボールを落とす状態のシーンが再生されるかと思います。    
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/gifs/not_trained.gif">

### 4. 学習済みのモデルを実行
---
次に、同じシーンで、学習済みのモデルを実行してみます。
`Assets/ML-Agents/Examples/3DBall/Prefabs` 
の中にある、__Game__ オブジェクトの子オブジェクトの __Platform__ のインスペクターを開いてください。
__Ball 3D Agent__ という名前のスクリプトがアタッチされているハズですので、Ball 3D Agentの __Brain__ prorpetyを `3DBallLearning (LearningBrain)`に変更してください。    
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/images/3d_ball_agent_LI.jpg">

Prefabのプロパティを変更したので、シーン上のすべての ＿Platform__ オブジェクトのBrainが`3DBallLearning (LearningBrain)`になってるかと思います。

この状態で、再度Playボタンをクリックすると、今度はボールを落とさないようにPlatformが動くと思います。    

<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/gifs/pre_trained.gif">

### 5. 学習させてみる
---
今度は自分で学習させてみましょう。
上記手順で変更した、__Platform__ プレファブのBall 3D AgentのBrainが `3DBallLearning (LearningBrain)`になっていることを確認してください。
次に、シーン上の __Ball 3D Academy__ の、Brainsプロパティを`3DBallLearning (LearningBrain)`に設定し、
__Control__ にチェックを入れてください。
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/images/academy_LI.jpg">

Windowsの場合、学習中に途中中断するとエラーが起こり、学習結果が保存されません。
ですので、`ml-agents/config/trainer_config.yaml`を編集します。
__max_steps__ を設定するだけです。
3DBallLearningの部分を下記の様に設定してください。
今回は5000回トレーニングさせます。

```
3DBallLearning:
    normalize: true
    batch_size: 64
    buffer_size: 12000
    summary_freq: 1000
    time_horizon: 1000
    max_steps: 5000
    lambd: 0.99
    gamma: 0.995
    beta: 0.001
    use_curiosity: true
```

編集が終わったら、
コマンドプロンプト(私はpowershellを使用しました)を開き、 ml-agentsをクローンしたディレクトリ直下で、
`mlagents-learn config/trainer_config.yaml --run-id=training_5000 --train`
とコマンドを叩いてください。
mlagents-learn コマンドが無い場合は、設定が終わっていないか、pathが通っていません。
下記記事を参考にして頂ければと思います。
[Unity ml-agents v0.6.0 setup for windows - Qiita](https://qiita.com/tkmn0/items/ca68564a1475a019368f)
下記のようなログが出たら成功です。

```

                        ▄▄▄▓▓▓▓
                   ╓▓▓▓▓▓▓█▓▓▓▓▓
              ,▄▄▄m▀▀▀'  ,▓▓▓▀▓▓▄                           ▓▓▓  ▓▓▌
            ▄▓▓▓▀'      ▄▓▓▀  ▓▓▓      ▄▄     ▄▄ ,▄▄ ▄▄▄▄   ,▄▄ ▄▓▓▌▄ ▄▄▄    ,▄▄
          ▄▓▓▓▀        ▄▓▓▀   ▐▓▓▌     ▓▓▌   ▐▓▓ ▐▓▓▓▀▀▀▓▓▌ ▓▓▓ ▀▓▓▌▀ ^▓▓▌  ╒▓▓▌
        ▄▓▓▓▓▓▄▄▄▄▄▄▄▄▓▓▓      ▓▀      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌   ▐▓▓▄ ▓▓▌
        ▀▓▓▓▓▀▀▀▀▀▀▀▀▀▀▓▓▄     ▓▓      ▓▓▌   ▐▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▌    ▐▓▓▐▓▓
          ^█▓▓▓        ▀▓▓▄   ▐▓▓▌     ▓▓▓▓▄▓▓▓▓ ▐▓▓    ▓▓▓ ▓▓▓  ▓▓▓▄    ▓▓▓▓`
            '▀▓▓▓▄      ^▓▓▓  ▓▓▓       └▀▀▀▀ ▀▀ ^▀▀    `▀▀ `▀▀   '▀▀    ▐▓▓▌
               ▀▀▀▀▓▄▄▄   ▓▓▓▓▓▓,                                      ▓▓▓▓▀
                   `▀█▓▓▓▓▓▓▓▓▓▌
                        ¬`▀▀▀█▓


INFO:mlagents.trainers:{'--curriculum': 'None',
 '--docker-target-name': 'None',
 '--env': 'None',
 '--help': False,
 '--keep-checkpoints': '5',
 '--lesson': '0',
 '--load': False,
 '--no-graphics': False,
 '--num-runs': '1',
 '--run-id': 'training_5000',
 '--save-freq': '50000',
 '--seed': '-1',
 '--slow': False,
 '--train': True,
 '--worker-id': '0',
 '<trainer-config-path>': 'config/trainer_config.yaml'}
 
 INFO:mlagents.envs:Start training by pressing the Play button in the Unity Editor.
```

このまま、UnityのPlayボタンをクリックしてください。
すると、コマンドプロンプト側で下記のようなログが出て、5000回トレーニングを行った後、自動で
Unity Editorのゲームが止まります。

```
INFO:mlagents.envs:Hyperparameters for the PPO Trainer of brain 3DBallLearning:
        batch_size:     64
        beta:   0.001
        buffer_size:    12000
        epsilon:        0.2
        gamma:  0.995
        hidden_units:   128
        lambd:  0.99
        learning_rate:  0.0003
        max_steps:      5000
        normalize:      True
        num_epoch:      3
        num_layers:     2
        time_horizon:   1000
        sequence_length:        64
        summary_freq:   1000
        use_recurrent:  False
        summary_path:   ./summaries/training_5000-0_3DBallLearning
        memory_size:    256
        use_curiosity:  True
        curiosity_strength:     0.01
        curiosity_enc_size:     128
        model_path:     ./models/training_5000-0/3DBallLearning
INFO:mlagents.trainers: training_5000-0: 3DBallLearning: Step: 1000. Mean Reward: 1.234. Std of Reward: 0.641. Training.
INFO:mlagents.trainers: training_5000-0: 3DBallLearning: Step: 2000. Mean Reward: 1.363. Std of Reward: 0.805. Training.
INFO:mlagents.trainers: training_5000-0: 3DBallLearning: Step: 3000. Mean Reward: 1.454. Std of Reward: 0.901. Training.
INFO:mlagents.trainers: training_5000-0: 3DBallLearning: Step: 4000. Mean Reward: 1.829. Std of Reward: 1.090. Training.
INFO:mlagents.trainers: training_5000-0: 3DBallLearning: Step: 5000. Mean Reward: 2.263. Std of Reward: 1.552. Training.
INFO:mlagents.envs:Saved Model
INFO:mlagents.trainers:List of nodes to export for brain :3DBallLearning
INFO:mlagents.trainers: is_continuous_control
INFO:mlagents.trainers: version_number
INFO:mlagents.trainers: memory_size
INFO:mlagents.trainers: action_output_shape
INFO:mlagents.trainers: action
INFO:mlagents.trainers: action_probs
INFO:mlagents.trainers: value_estimate
INFO:tensorflow:Restoring parameters from ./models/training_5000-0/3DBallLearning\model-5001.cptk
INFO:tensorflow:Froze 20 variables.
Converted 20 variables to const ops.
```

トレーニング中の様子。
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/gifs/training.gif">
`models/training_5000-0/3DBallLearning.bytes` 


こいつが5000回トレーニングしたモデルです！

このモデルを`UnitySDK/Assets/ML-Agents/Examples/3DBall/TFModels/`に移してください。
このとき、名前が被ってしまうと思うので、新しく追加したほうを __3DBallLearning_5000__ 的な名前に変えとくとわかりやすいかと思います。

次に、Unity Editorから、
`Assets/ML-Agents/Examples/3DBall/Brains/3DBallLearning` の Modelを 先ほど追加し、名前を変更した、 __3DBallLearning_5000__ に変えてください。
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/images/Brain_model_LI.jpg">

最後に、 シーン上の
__Ball 3D Academy__ の __Control__ のチェックを外してからプレイボタンをクリックしてみてください。
5000回トレーニングした感の挙動（わかりづらいですが。。。）を見れるかと思います。
<img src="https://raw.githubusercontent.com/tkmn0/media/master/ml/001/gifs/trained_5000.gif">

あとは、先ほどのtrainer_config.yamlのmax_stepsの回数を変えて、再度学習させて確認してみて下さい。
例えば、40000回トレーニングすると、デフォルトで用意されたモデルと同じように、ボールを落とさなくなりました。


### まとめ
---
とりあえず、サンプルを動かすことと、学習させることができました。
Examplesの中には他にもいろいろなシーンがあるので試してみると面白いと思います。
- __xxAgent__  という名前のプレファブを見つける 
- ブレインを __xxLearning__ に変更する
という手順を踏んでから再生すれば、あらかた動くかと思います。

機械学習についての知識はまだありませんが、Unityでこれだけ気軽に動かせるとなると勉強しやすそうですね。

次は、自分で作った環境で学習させてみたいと思います。