ChainerRL + Minecraftで深層強化学習 ハンズオン [MineRL version]

前回の[Qiita記事](https://qiita.com/keisuke-umezawa/items/fcf5d00474e244217a5e)に引き続き、今回もMinecraftで深層強化学習する記事を書きます。

# 目的
なぜ、改めて書き直すかというと、前回使用した[Malmö](https://github.com/Microsoft/malmo)に比べて、より取り扱いのしやすいMinecraft環境「[MineRL](https://github.com/minerllabs/minerl)」が開発されたからです。MineRLとChainerRLを使って簡単に深層強化学習を試してみましょう。

# MineRLについて

<img src="http://www.minerl.io/docs/_images/survival1.mp4.gif" width=20%> <img src="http://www.minerl.io/docs/_images/survival2.mp4.gif" width=20%> <img src="http://www.minerl.io/docs/_images/survival3.mp4.gif" width=20%> <img src="http://www.minerl.io/docs/_images/survival4.mp4.gif" width=20%>

MineRLは、Malmöを利用したMinecraftの強化学習環境で、Malmöに比べて同期・安定・高速化などが実現しています。特に、Malmöでは同期性能が低く毎stepごとに行動をできない場合がありましたが、MineRLではそこが改善しています。タスクとしては以下などが用意されています。

* MineRLTreechop
  * 64個の「原木 (log)」を集める
  * 森で、 鉄の斧を持った状態からスタート
  * log を入手するごとに +1 reward

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111482/6dd9cc23-e89d-c75a-d894-a122ac81a08d.gif" width=25%>


* MineRLNavigate
  * 指定されたゴール地点へ向かう
  * “compass” を観測可能；ゴール方向を指示してくれる
  * ゴール到達で +100 reward
  * “Dense” 版では更にゴールにとの距離に応じて毎ステップ報酬を貰える (遠ざかると負の報酬)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111482/d37ed3ca-da6a-057b-d4c6-385975e79a3a.gif" width=25%>
 
* MineRLObtainDiamond
  * ダイヤモンドを入手する
  * 多くの中間アイテムが必要となる
  * ダイヤモンド入手で +1024 reward
  * 中間アイテム入手でも (小さめの) 報酬
  * デフォルトではアイテムの1回目の入手時のみ報酬が貰える “Dense” 版では何度でも貰える

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111482/36e83ec3-9a01-d28e-8790-44c5d64063c8.gif" width=25%>

# ベースライン実装
## Requirements
- git、makeをインストールしていること。
- Dockerをインストールしていること。

## 動かし方
ハンズオンのためのコードをフォークしたレポジトリ[baselines](https://github.com/keisuke-umezawa/baselines)で管理しています。

まずはcloneして、chainerrlのディレクトリに移動してください。

```bash
$ git clone https://github.com/keisuke-umezawa/baselines.git
$ cd baselines/general/chainerrl
```

次にDockerfileをビルドしましょう。Makefileに必要なコマンドが定義されているので、`make build`とコマンドを打てば良いです。

```bash
$ make build
```

次に、実行してbashでログインしましょう。それもMakefileにコマンドが定義されているので、以下で大丈夫です。

```bash
$ make run
$ make bash
```

すると、環境設定されたDockerコンテナ内にbashでログインすることができます。
以下のコマンドで動かしたいスクリプトを動かすことができます。今回は試しに、`dddqn.sh`を動かしてみましょう

```
# cd baselines
# APP="lxterminal -e 'bash -c /opt/baselines/dddqn.sh'" /usr/bin/graphical-app-launcher.py
```

実はこのコンテナ内には、VNCサーバーが動いており、ブラウザから`localhost:6080`にアクセスすると、コンテナ内のGUI環境にアクセスすることができます。

<img width="644" alt="スクリーンショット 2019-09-28 15.23.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111482/3a099bbe-97d8-0023-ae9f-97e2fdc1064b.png">

上記のコマンドを実行して10分程度待つと、以下のようにMinecraftの画面も出てくるはずです。

<img width="809" alt="スクリーンショット 2019-09-23 20.14.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111482/941a58eb-b7d1-1520-6039-a142d518dac8.png">

## 学習済みモデルを使った場合の動かし方
[リンク先](https://github.com/keisuke-umezawa/baselines/releases)にそれぞれのタスクとモデルに対して、複数のモデルを用意しています。

例えば、Treechopをdddqnで解きたい場合は、リンク先`https://github.com/keisuke-umezawa/baselines/releases/download/v0.0/dddqn1.zip`のモデルを使用するといいでしょう。

```bash
$ wget https://github.com/keisuke-umezawa/baselines/releases/download/v0.0/dddqn1.zip
$ unzip dddqn1.zip
```

そうすると、`8000000_finish`のようなディレクトリができているはずです。

dddqn.shを以下に書き換え、上記と同じように動かしてみましょう。

```bash
python3 dqn_family.py \
  --gpu -1 --env MineRLTreechop-v0 --outdir results/MineRLTreechop-v0/dddqn \
  --final-exploration-frames 1000000 --final-epsilon 0.02 --arch dueling --replay-capacity 800000 --replay-start-size 1000 \
  --target-update-interval 1000 --update-interval 1 --agent DoubleDQN --monitor --lr 0.001 --gamma 0.99 --batch-accumulator mean \
  --always-keys attack --reverse-keys forward --exclude-keys back left right sneak sprint --load ./8000000_finish
```

# Reference
- https://github.com/minerllabs/baselines
- https://www.slideshare.net/pfi/minerl-competition-tutorial-with-chainerrl-156927429