DockerでUnity ML-Agentsを動作させる(v0.5.0対応)

これは[cloudpack あら便利カレンダー 2018](https://benri2018.rnd.cloudpack.jp/)の記事です。

## 追記

### 2019/09/20

v0.9.1で動作させる方法をまとめました。

DockerでUnity ML-Agentsを動作させる(v0.9.1対応) - Qiita
https://qiita.com/kai_kou/items/0c2f3c7d22363fd91e4e


### 2018/12/27

2018/12/15にv0.6.0がリリースされたので、そちらでも確認してみました。

DockerでUnity ML-Agentsを動作させる(v0.6.0対応) - Qiita
https://qiita.com/kai_kou/items/157e91312c2c0115376d

### 2018/09/13

**記事投稿時はバージョンがv0.4.0でしたが、2018/09/11にv0.5.0がリリースされたので、v0.5.0を利用した手順に更新しました。**

https://github.com/Unity-Technologies/ml-agents/releases


## 概要

Unity ML-Agents(v0.5.0)をDocker上で動作させてみました。

UnityやUnity ML-Agentsの環境構築などは下記をご参考ください。

Macでhomebrewを使ってUnityをインストールする(Unity Hub、日本語化対応)
https://qiita.com/kai_kou/items/445e614fb71f2204e033

MacでUnity ML-Agentsの環境を構築する(v0.5.0対応)
https://qiita.com/kai_kou/items/6478fa686ce1af5939d8


## 手順

基本的には公式のドキュメントに沿えばよい感じです。

Using Docker For ML-Agents
https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Using-Docker.md

### Dockerのインストール

Dockerがインストールされていない場合、インストールします。

```sh
> brew cask install docker
(略)

> docker --version
Docker version 18.06.0-ce, build 0ffa825

> open /Applications/Docker.app
```

Dockerを初回起動すると初期設定のためにパスワード入力が求められます。


### UnityにLinuxビルドサポートコンポーネントを追加する

- Unity Hubアプリを起動する
- [Installs] > [On my machine]からUnityリスト右側にある[...]から[Add Component]を選択する
- [Add components your install]ダイアログの[Platforms]にある[Linux Build Support]にチェックを入れて[Done]ボタンをクリックする

<img width="1003" alt="Unity Hub" src="https://qiita-image-store.s3.amazonaws.com/0/48549/da5fa78f-8c55-e2a7-65da-5a8b40142a1a.png">

<img width="1000" alt="Add components to your install" src="https://qiita-image-store.s3.amazonaws.com/0/48549/9a75bb19-c45f-5239-3cc2-7941bd65c719.png">


### 学習用のappをビルドする

- Unityを起動して、[open]から以下のフォルダを開く
    - v0.5.0
        - ml-agents/UnitySDK
    - v0.4.0
        - ml-agents/unity-environment
    - ml-agentsリポジトリを```git clone``` していない場合は下記を参考にしてください
        - https://qiita.com/kai_kou/items/6478fa686ce1af5939d8

Unityエディタのバージョンによって、再インポートするか、確認ダイアログが立ち上がります。
<img width="422" alt="UnitySDK.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/30fd2547-6066-86e6-a52a-f7fca2191654.png">

「Continue(続行)」ボタンをクリックして進めます。

再インポート処理すると初回、プロジェクトが開くまでに時間がかかります。

<img width="1679" alt="スクリーンショット 2018-09-13 10.50.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/3b9869f9-6c07-86e9-94aa-4f85bc1d9a10.png">

起動しました。

今回は、サンプルとして含まれている[3DBall]Scenesを利用します。

- Unityの下パネルにある[Project]タブから以下のフォルダまで開く
    - [Assets] > [ML-Agents] > [Examples] > [3DBall] > [Scenes]
- 開いたら、[3DBall]ファイルがあるので、ダブルクリックして開く
<img width="557" alt="スクリーンショット 2018-07-28 13.32.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/c1bdb0d3-81cb-d050-e394-e7d6749715d3.png">


#### Scenes(シーン)の設定

- Unityの[Edit]メニューから[Project Settings] > [Player]を開く
<img width="560" alt="学習のための設定" src="https://qiita-image-store.s3.amazonaws.com/0/48549/0485c977-bd34-6b60-3cc4-d9caa04377ab.png">

- [Inspector]ビューで以下の設定を確認する。
    - [Resolution and Presentation]の[Run In Background]がチェックされている
    - [Display Resolution Dialog]がDisableになっている
<img width="477" alt="ResolutionAndPresentation.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/3969581a-eb97-348c-485b-3f7974bb2ad0.png">

- [Hierarchy]ビューから[Ball3DAcademy] > [Ball3DBrain]を開く
    - [Inspector]ビューで[Brain Type]を[External]に変更する
<img width="475" alt="学習のための設定" src="https://qiita-image-store.s3.amazonaws.com/0/48549/37d21892-4706-fd7c-6239-b911e519e195.png">

- [Ctrl] + [s]キーでシーンを保存する

設定変更後、しっかりと保存しないとビルド時に設定が反映されなくてハマります。(1敗)


#### ビルド設定

- Unityの[File]メニューから[Build Settings]を選択する
- [Build Settings]ダイアログで[Platform]で[PC, Mac & Linux Standalone]が選択されていることを確認する
- [Target Platform]を[Linux]に変更する
- [Architecture]を[x86_64]に変更する
- [Headless Mode]にチェックを入れる
- [Build Settings]ダイアログで[Build]ボタンをクリックする
- ファイル保存ダイアログで以下を指定してビルドを開始する
    - ml-agents\unity-volume\3DBall
<img width="631" alt="Build Settings" src="https://qiita-image-store.s3.amazonaws.com/0/48549/447cee56-11e5-df56-a317-06e7e6feb1b8.png">


すると、unity-volumeに以下フォルダ・ファイルが出力されます。

```sh
> ll unity-volume/
3DBall.x86_64
3DBall_Data
```

### ハイパーパラメーターの用意

ハイパーパラメーターファイルをunity-volumeフォルダにコピーしておきます。

```sh
> cp config/trainer_config.yaml /unity-volume
```

### Dockerコンテナを構築する

Dockerが起動していることを確認してから、ml-agentsリポジトリ直下でdockerコンテナを構築する。
すでにDockerfileが用意されているので、buildするだけ。楽々ですね。

```sh
> cd 任意のディレクトリ/ml-agents
> docker build -t 3dball_ml_docker .
(略)
Successfully built db0b82f60411
Successfully tagged 3dball_ml_docker:latest
```

### Dockerコンテナの実行

Dockerコンテナが構築できたら実行してみます。

```sh:bash
# unity-ml-docker-3dball: コンテナ名(任意)
# 3DBall: Unityでbuild時に付けたアプリの名前(拡張子なし)
# 3dball_ml_docker: Dockerでbuild時に付けた名前
# docker_first_run: 機械学習結果を保存する際の名称(任意)

> docker run --name unity-ml-docker-3dball \
           --mount type=bind,source="$(pwd)"/unity-volume,target=/unity-volume \
           -p 5005:5005 \
           3dball_ml_docker:latest \
           trainer_config.yaml \
           --docker-target-name=unity-volume \
           --env=3DBall \
           --train \
           --run-id=docker_first_run
```

fishシェルで実行する場合は、```"$(pwd)"```を```"$PWD"```に置き換えます。

```sh:fish
> docker run --name unity-ml-docker-3dball \
           --mount type=bind,source="$PWD"/unity-volume,target=/unity-volume \
           -p 5005:5005 \
           3dball_ml_docker:latest \
           trainer_config.yaml \
           --docker-target-name=unity-volume \
           --env=3DBall \
           --train \
           --run-id=docker_first_run
```

Unity ML-Agents公式にある```docker run``` コマンドがおそらく動作検証してなくて、パラメータ指定エラーとなります。
v0.4.0とv0.5.0でパラメータ指定方法が変わったので、ご注意ください。
以下はv0.5.0の```mlagents-learn``` コマンドのヘルプです。
Dockerで実行する場合には、Dockerイメージ名```3dball_ml_docker:latest``` の後からが、```mlagents-learn``` のパラメータ指定になります。

```sh:mlagents-learn　help

    Usage:
      mlagents-learn <trainer-config-path> [options]
      mlagents-learn --help

    Options:
      --env=<file>               Name of the Unity executable [default: None].
      --curriculum=<directory>   Curriculum json directory for environment [default: None].
      --keep-checkpoints=<n>     How many model checkpoints to keep [default: 5].
      --lesson=<n>               Start learning from this lesson [default: 0].
      --load                     Whether to load the model or randomly initialize [default: False].
      --run-id=<path>            The directory name for model and summary statistics [default: ppo].
      --num-runs=<n>             Number of concurrent training sessions [default: 1]. 
      --save-freq=<n>            Frequency at which to save model [default: 50000].
      --seed=<n>                 Random seed used for training [default: -1].
      --slow                     Whether to run the game at training speed [default: False].
      --train                    Whether to train model, or only run inference [default: False].
      --worker-id=<n>            Number to add to communication port (5005) [default: 0].
      --docker-target-name=<dt>  Docker volume to store training-specific files [default: None].
      --no-graphics              Whether to run the environment in no-graphics mode [default: False].
```

実行すると、学習が始まります。
trainer_config.yamlの```max_steps``` で指定されているステップ数が完了するか、ctrl+cキーで学習が終了します。

```sh
> docker run (略)

INFO:mlagents.trainers:{'--curriculum': 'None',
 '--docker-target-name': 'unity-volume',
 '--env': '3DBall',
 '--help': False,
 '--keep-checkpoints': '5',
 '--lesson': '0',
 '--load': False,
 '--no-graphics': False,
 '--num-runs': '1',
 '--run-id': 'docker_first_run',
 '--save-freq': '50000',
 '--seed': '-1',
 '--slow': False,
 '--train': True,
 '--worker-id': '0',
 '<trainer-config-path>': 'trainer_config.yaml'}


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


INFO:mlagents.envs:
'Ball3DAcademy' started successfully!
Unity Academy name: Ball3DAcademy
        Number of Brains: 1
        Number of External Brains : 1
        Reset Parameters :

Unity brain name: Ball3DBrain
        Number of Visual Observations (per agent): 0
        Vector Observation space size (per agent): 8
        Number of stacked Vector Observation: 1
        Vector Action space type: continuous
        Vector Action space size (per agent): [2]
        Vector Action descriptions: ,
2018-09-13 05:46:26.591642: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
INFO:mlagents.envs:Hyperparameters for the PPO Trainer of brain Ball3DBrain:
        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:      5.0e4
        normalize:      True
        num_epoch:      3
        num_layers:     2
        time_horizon:   1000
        sequence_length:        64
        summary_freq:   1000
        use_recurrent:  False
        graph_scope:
        summary_path:   /unity-volume/summaries/docker_first_run-0
        memory_size:    256
        use_curiosity:  False
        curiosity_strength:     0.01
        curiosity_enc_size:     128
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 1000. Mean Reward: 1.128. Std of Reward: 0.664. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 2000. Mean Reward: 1.230. Std of Reward: 0.738. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 3000. Mean Reward: 1.410. Std of Reward: 0.783. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 4000. Mean Reward: 2.055. Std of Reward: 1.344. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 5000. Mean Reward: 2.943. Std of Reward: 2.283. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 6000. Mean Reward: 4.099. Std of Reward: 3.570. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 7000. Mean Reward: 6.653. Std of Reward: 5.869. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 8000. Mean Reward: 10.990. Std of Reward: 11.771. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 9000. Mean Reward: 21.031. Std of Reward: 21.568. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 10000. Mean Reward: 37.852. Std of Reward: 35.298. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 11000. Mean Reward: 46.157. Std of Reward: 35.978. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 12000. Mean Reward: 69.453. Std of Reward: 35.353. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 13000. Mean Reward: 80.013. Std of Reward: 34.485. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 14000. Mean Reward: 91.069. Std of Reward: 21.826. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 15000. Mean Reward: 84.494. Std of Reward: 24.379. Training.
INFO:mlagents.trainers: docker_first_run-0: Ball3DBrain: Step: 16000. Mean Reward: 80.660. Std of Reward: 26.725. Training.
(略)
```

### 学習結果をアプリに組み込む

学習結果は、```unity-volume``` フォルダ内に保存されます。
学習結果をUnityアプリに組み込む方法は下記をご参考ください。

MacでUnity ML-Agentsの環境を構築する(v0.5.0対応)
https://qiita.com/kai_kou/items/6478fa686ce1af5939d8

## 参考

Using Docker For ML-Agents
https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Using-Docker.md

Docker for Macをインストールしてみた
https://qiita.com/scrummasudar/items/750aa52f4e0e747eed68

Macでhomebrewを使ってUnityをインストールする(Unity Hub、日本語化対応)
https://qiita.com/kai_kou/items/445e614fb71f2204e033

MacでUnity ML-Agentsの環境を構築する(v0.5.0対応)
https://qiita.com/kai_kou/items/6478fa686ce1af5939d8