ChainerRLとAzure Notebooksをつかって、Minecraftで深層強化学習 ハンズオン

本記事は @keisuke-umezawa さんの以下の記事を元にしています。
https://qiita.com/keisuke-umezawa/items/fcf5d00474e244217a5e

# Minecraft
みなさん、ご存知Minecraft。私は知らなかったですが、マイクラって略されるんですね。公式のPR動画としては以下のようなものもあります。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/gITUej4Tmb">https://t.co/gITUej4Tmb</a></p>&mdash; Keisuke Umezawa (Chainer Evangelist) (@kmechann) <a href="https://twitter.com/kmechann/status/1072849400458764288?ref_src=twsrc%5Etfw">2018年12月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


また、[Minecraft Japan Wiki](https://www26.atwiki.jp/minecraft/)では下記の通り説明されています。

> Minecraftは、2009年5月10日にNotch氏(本名:Markus Persson)が開発を始めた、サンドボックス型のものづくりゲームです。 
レトロゲーを想起させるドットテイストのブロックが溢れる世界で、プレイヤーは建物やその他のものを自由に創造することが出来ます。 
未開の土地を探索したり、洞窟を探検したり、モンスターと戦ったり、植物を育てたり、新しいブロックを手に入れ配置することで、様々なものを作ることができます。 
創造（想像）力次第で小さな家から、ドット絵、地下基地、巨大な城まで何でも作ることができます。
>
> マルチプレイでは、協力して巨大な建築物を作ったり、Player VS Player(PvP)で他プレイヤーと戦うことも出来ます。

この説明にあるようにいくつか、現在の強化学習に適したキーワードがあります。

* 建物やその他のものを自由に作ることできる
* 色々なゲームができる
* マルチプレイできる

このあたりの特性がMinecraftにあるからこそ、Minecraftで強化学習をしようというモチベーションが生まれたのだと思います。

# Marlo Project
このハンズオンでは、Minecraftをシミュレーター環境として深層強化学習を行います。現在、Minecraftを活用した[MARLO](https://www.crowdai.org/challenges/marlo-2018)という深層強化学習のコンテストが行われています。今回はこのコンテストで活用されいる[marLo](https://github.com/crowdAI/marLo)という[OpenAI's Gym](https://github.com/openai/gym)互換のMinecraft環境を使います。OpenAI's Gym互換のため、ChainerRLなどの強化学習フレームワークを簡単に使用することができます(完全ではないが・・・例えば動画の保存に使うwrapperが使えなかったりする)。

marLoでは下記のような環境が用意されており、例えば溶岩の上の一本道を歩くAIを深層強化学習で作ることが出来ます。今回は`MarLo-FindTheGoal-v0`で説明を行い、その後皆さんに新しい課題にチャレンジしていただきます。

|||||
|---|---|---|---|
|``MarLo-MazeRunner-v0`` ![](https://media.giphy.com/media/u45fNQxG59wfnRpzwJ/giphy.gif)|``MarLo-CliffWalking-v0`` ![](https://media.giphy.com/media/ef4lPGNqaLlKr45rWB/giphy.gif)|``MarLo-CatchTheMob-v0`` ![](https://media.giphy.com/media/9A1gHZrWcaS4AYzcIU/giphy.gif)|``MarLo-FindTheGoal-v0`` ![](https://media.giphy.com/media/1gWkQbDsHOfo4kZXZv/giphy.gif)|
|``MarLo-Attic-v0`` ![](https://media.giphy.com/media/47C7AYB3FA6kgrMiQ3/giphy.gif)|``MarLo-DefaultFlatWorld-v0`` ![](https://media.giphy.com/media/L0s9QXuR6vIJh6A0dq/giphy.gif)|``MarLo-DefaultWorld-v0`` ![](https://media.giphy.com/media/4Nx7gYiM9NDrMrMao7/giphy.gif)|``MarLo-Eating-v0`` ![](https://media.giphy.com/media/pObNMjjfcGI5tVhmX6/giphy.gif)|
|``MarLo-Obstacles-v0`` ![](https://media.giphy.com/media/5sYmFFkq7aEMKTbKP4/giphy.gif)|``MarLo-TrickyArena-v0`` ![](https://media.giphy.com/media/1g1bxw2nD3G9fz2WVV/giphy.gif)|``MarLo-Vertical-v0`` ![](https://media.giphy.com/media/ZcaMeSnzLrMY1NWM7f/giphy.gif)|||

# ハンズオンの内容
※ このハンズオンは、 https://qiita.com/keisuke-umezawa/items/fcf5d00474e244217a5e
 を元に作成しています。

## Requirement

2018/12/14時点では以下が必要です。

- Python 3.5+ environment with
    - Chainer v5.0.0
    - CuPy v5.0.0
    - ChainerRL v0.4.0
    - marlo v0.0.1.dev23

## Azureで環境設定

※ 以下の手順でGPUをつかうには、Azureの従量課金subscriptionが必要です。CPUのみで行う場合は、Azure無料試用版でも構築可能です。
※ 他の環境での構築方法の[記事](https://qiita.com/namahoge/items/ae690bdb9cee42ad9394)もあるのでご参考ください。

### 1. Azure Cloud Shell を使ってVMの作成

#### 1. https://portal.azure.com/#home にアクセス

* Microsoft のアカウントを持っていない場合は作成してください
* 今までにAzureを使ったことが無い方は、[こちら](https://azure.microsoft.com/ja-jp/free/)から無料アカウントをサインアップしてください。

#### 2. 右上を確認し、今回使うディレクトリになっていることを確認してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/0bd0e3e1-fd1f-bf93-a48d-58766efef152.png)

※ 個人でアカウントを作成されている場合は既定のディレクトリで問題ありません。

#### 3. 次に、以下をクリックし、Cloud Shellを起動してください

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/cff3384a-7edd-1242-e41a-a02525f0af26.png)

#### 4. Bash をクリックしてください（過去にCloud Shellを使ったことがある方はここはスキップになります）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/274a3fe2-230c-7ba4-7911-00803582cc89.png)

Azureへのサインアップが完了していない場合は、以下のような画面が出ます。「Azureサブスクリプションを作成します」をクリックし、無料試用版の登録をしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/c6e70c81-c63c-e83a-e83f-a5f0dcd39b88.png)

また、ストレージが無い場合は以下のように表示されます。サブスクリプションは、無料試用版をお持ちの方は、**無料試用版**を選択して、ストレージを作成をクリックしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/129fe708-e49a-9e50-6bd2-6e2229b6407f.png)

#### 5. Cloudshellのコンソールが開きます。`□`をクリックして、コンソール画面を大きくしておいてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/1d0200e2-5a8e-65ea-d8bf-221761ce0afc.png)


#### 6. リソースグループを作成（既に作成済みの場合はスキップ）

** リソースグループを既に作成していて、それを使う場合は、本項目はスキップできます。 **

リソースグループを作って、今回利用するリソース（VMやネットワークなど）をまとめることができます。
以下のようにして、"malmo"という名前のリソースグループを作成します。（他の名前にする場合は、移行、"malmo"を自身で設定した物に置き換えてください）

```bash
az group create -g malmo -l eastus
```

成功すると、以下のように表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/875e15a8-52eb-2019-1974-3fcc003263bd.png)

#### 7. パスワードを生成

以下の通り入力して、パスワードを生成してください。

```bash
echo user name: ${USER}
VM_PW=`openssl rand -base64 12`
echo VM password: ${VM_PW}
```

ユーザー名とパスワードが表示されるので、どこかにメモをしておいてください。

#### 7. VMを作成

CPUインスタンスで作成には以下の通りCloud Shellで実行してください。
**これ以降、インスタンスを起動しているときは、費用が発生します。不要になったら、停止しましょう。**
概ね、月に、4千円ぐらいです（参考：[価格](https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/linux/)）

※ なお、Cloud Shell用のストレージや、VMのストレージ等は、起動していないときも僅かながら費用がかかります。

```bash
az vm create --location eastus --resource-group malmo --name ${USER}-vm \
 --admin-username ${USER} --admin-password ${VM_PW} \
 --authentication-type password \
 --public-ip-address-dns-name ${USER}  \
 --image microsoft-ads:linux-data-science-vm-ubuntu:linuxdsvmubuntu:latest \
 --size Standard_B2s
```

<!--
```bash
az vm create --location eastus --resource-group malmo --name ${USER}-vm \
 --admin-username ${USER} --admin-password ${VM_PW} \
 --authentication-type password \
 --public-ip-address-dns-name ${USER}  \
 --image microsoft-ads:linux-data-science-vm-ubuntu:linuxdsvmubuntu:latest \
 --size Standard_D2s_v3
```
-->

**※ 以下はCPUインスタンスを起動した人は不要です**

GPUインスタンス で作成するには以下の通りCloud Shellで実行してください。

なお、GPUインスタンスのStandard_NC6は、１月動作させ続けると、**7万円以上かかりますのでご注意ください。**（参考：[価格](https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/linux/)）
また、無料試用版では使えません。

```bash
az vm create --location eastus --resource-group malmo --name ${USER}-vm \
 --admin-username ${USER} --admin-password ${VM_PW} \
 --authentication-type password \
 --public-ip-address-dns-name ${USER}  \
 --image microsoft-ads:linux-data-science-vm-ubuntu:linuxdsvmubuntu:latest \
 --size Standard_NC6
```

成功すると以下のように表示されます。以下の`publicIpAddress`はメモをしておいてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/f518ccd2-fa0a-0a39-0b35-563f0e8f0356.png)

上記IPアドレスと最初に作成したパスワードを使えば、SSHで接続できます。
本ハンズオンでは、後の作業を楽にするため、Azure Notebooksを使います（後述）

もし、ここでエラーが出る場合は以下の可能性があります。

* VMの名前（`--name ${USER}-VM`）及び、DNS name (`--public-ip-address-dns-name ${USER}`)が既に使われている（同じリソースグループ内で、ユーザー名が重複している）
    * `--name ${USER}-VM`と`--public-ip-address-dns-name ${USER}`の部分を、`--name ${USER}-VM2`及び、`--public-ip-address-dns-name ${USER}2` 等として、重複を回避してください。
* Standard_NC6 が使えないサブスクリプションを使っている（無料試用版では使えません）

#### 8. ポートをオープン

Azure Notebooks から繋ぐためと、画面を表示するためのnoVNCというウェブサーバに繋ぐため、8000, 8001 6080の３つのポートをオープンします。
以下のコマンドをCloud Shellで実行してください。


```bash
az vm open-port --resource-group malmo --name ${USER}-VM --port 8000 --priority 1010
az vm open-port --resource-group malmo --name ${USER}-VM --port 8001 --priority 1020
az vm open-port --resource-group malmo --name ${USER}-VM --port 6080 --priority 1030
```

### Azure Notebooksの接続

####  1. Notebook を Clone

以下のページを表示し、Cloneをクリックしてください。

https://notebooks.azure.com/ikeyasu/projects/marlo

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/4f1fd22c-ffc9-7d81-bde2-a6c8178cb2ff.png)

#### 2. Direct Compute の設定

先ほど作成したVMに接続するため、Direct Compute の設定をします。

左上の▽をクリックし、"Direct Compute"をクリックして設定画面を表示してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/193b9893-dad1-0401-05e3-47d28e4fc18d.png)

ここに、先ほどメモしたIPと、ユーザー名、パスワードを入力してくだし。
Name は何でも構わないので入力して、Validate を押してください。（Portは変更できません。）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/f0d3d03b-b721-333b-14ac-522149ff6970.png)

ここで、以下のようにエラーが出る事があります。この場合は、何度かValidateを押してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/ac6d8f27-ebce-f7c0-73f8-6cecd2121607.png)

うまくいくと以下のように表示されるので、Runを押してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/57065ba2-e8b5-8db9-701f-afeb26e3d349.png)

#### 3. Notebook を開く

以下のように表示されるので、marlo.ipynb を押してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/5742d3c9-6f42-f8d3-4735-9e013155cc15.png)

すると、以下のような画面が表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/2c9936ba-84d2-048a-32ca-a618d8b42f91.png)

### Notebook の実行

上記で開いた画面は、Jupyter Notebookというシステムです。
一つ一つの四角は、「セル」と呼ばれ、SHIFT + ENTER で実行できます。
いちばん上のセルを実行してみましょう。

左の `In [ ]` の部分が、`In [*]`となります。これは、実行中を意味します。
`In [1]`のようになり、出力が表示されると、実行完了です。

**以降は、Notebookの解説をご覧下さい。**

**作業が終わったら、VMを停止または削除するのを忘れないでください。**

## VMの停止・再開・削除

VMは不要の時は必ず停止してください。後で同じVMで再開できます。
停止しないと、費用がかかります。
停止・削除等は、Cloud Shellでやる方法と、ポータルサイトを使う方法があります。

### Cloud Shellを使う

#### VMの停止

VMは不要の時は必ず停止してください。後で同じVMで再開できます。
停止しないと、費用がかかります。

```bash
azure vm deallocate --resource-group malmo --name ${USER}-vm
```

#### 停止したVMの再開

以下のようにして、VMを再開できます。**IPアドレスは変わりますのでご注意ください**

```bash
azure vm start --resource-group malmo --name ${USER}-vm
```

以下のようにしてIPを確認できます

```bash
az vm list-ip-addresses --output table --name ${USER}-vm
```

#### VMの削除

削除は、ポータルを使った方が便利です。以下を参照してください。

### ポータルを使って停止・開始
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/3fc55f29-fb2f-3bd0-3773-0d05a3616c29.png)

以下をクリックして、VM一覧を表示してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/c60a91a6-8839-09bf-e48c-7230b2f24c1b.png)

一覧から、自分のVMをクリックしてください。数が多い場合は、「名前でフィルター」に自分のVMの名前を入れてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/4acb0a5e-cab1-1cec-8225-8e3a8fed385c.png)

ここから、停止・開始を選べます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/6237fe08-83fd-0718-395a-44571fac1dc6.png)

### VM の削除

VM を作成すると、ディスクなど複数のリソースが作成されています。
「全てのリソース」をクリックしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/7723dd56-5bce-5f65-fdfa-14dcec32dfce.png)

「名前でフィルタ」をクリックして、自分のVMの名前を入力して、自分のVMに関連するリソースを表示してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/6d8b76eb-f382-fee1-d3f5-c1b71d84c276.png)

名前の横の□をチェックして全て選択肢、削除を押してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38555/9f4c16a0-493e-a15e-e72c-6110427bb28b.png)

確認があるので、はいと入力して、削除してください。

** 関係の無いリソースを削除しないようにご注意ください！ **