ChainerRL を Colaboratory で動かす

# TL;DR

* (英語版) https://colab.research.google.com/github/chainer-community/chainer-colab-notebook/blob/master/hands_on_en/chainerrl/quickstart.ipynb
    *  (日本語版) https://colab.research.google.com/github/chainer-community/chainer-colab-notebook/blob/master/hands_on_ja/chainerrl/quickstart.ipynb
* Colaboratory で、ChainerRLで動かした。
    * ChainerRL は、Chainerを使った深層強化学習ライブラリ。
    * Colaboratory は、Google が公開している無料で Jupyter notebook が使える環境。GPUも無料で使える。
* Colaboratory の Notebook 内で、結果をアニメーションで確認できるようにした
![anim1.gif](https://qiita-image-store.s3.amazonaws.com/0/38555/b9bee231-f2ca-729b-3b04-9731cdc407e3.gif)

# Colaboratory について

Colaboratory はGoogleが提供している、秒速でGPUマシンとJupyter Notebook実行環境が手に入る夢のようなサービスです。
もちろん、無料なので、いくつか制限があります。（制限については、[こちらが詳しいです](https://qiita.com/tomo_makes/items/b3c60b10f7b25a0a5935)）それでも、Colaboratory 出現以前の世界では、[AWSで動かして12時間で1000円ほどかかったり](https://aws.amazon.com/jp/ec2/instance-types/p2/)、[17万円のPCを組み立てたり](https://qiita.com/ikeyasu/items/db16a5d9fc68fa21b3d5#%E3%81%8A%E5%80%A4%E6%AE%B5)していたのを考えると、本当に夢のようなサービスです。
Colaboratory の基本的な使い方は、Jupyter Notebookと同じです。（参考：[Jupyter事始め](https://qiita.com/taka4sato/items/2c3397ff34c440044978)）

# ChainerRLについて

ChainerRL は、Chainerを使った深層強化学習ライブラリ。DQN・DDRLなどの著名な強化学習アルゴリズムを簡単に扱うことができたり、学習を行う環境である ALE ([Atariの古いゲーム](https://gym.openai.com/envs/#atari))や [OpenAI Gym](https://gym.openai.com/) を簡単に扱う事ができます。

公式リポジトリ： https://github.com/chainer/chainerrl

# ChainerRL を Colaboratory で動かすための準備

https://colab.research.google.com/drive/1XQaqLeUpn299ZdDDJ7CtGtJkZ0A-Tgii
を開いて下さい。開くためには、Google のアカウントでログインしている必要があります。ログイン済みの場合は、以下のように、Colaboratory で Notebook が開かれます。

![スクリーンショット 2018-03-03 20.15.18.png](https://qiita-image-store.s3.amazonaws.com/0/38555/77dbfbd8-b41f-b825-90ed-7171dbf611b9.png)

次に、"PLAYGROUND で開く"をクリックします。すると、以下のように、実行可能な形で開くことができます。

![スクリーンショット 2018-03-03 20.17.47.png](https://qiita-image-store.s3.amazonaws.com/0/38555/782d6853-6db5-d939-b44e-e59b4aad6bb8.png)

このままだと、実行結果の保存ができないので、「ドライブにコピー」をクリックします。

![スクリーンショット 2018-03-03 20.19.09.png](https://qiita-image-store.s3.amazonaws.com/0/38555/02f5dd7d-87d3-42b8-6691-d06e2e1dccb4.png)

これで、現在ログイン中の Google アカウントの Google Drive にノートがコピーされました。


# ChainerRL を Colaboratory で動かす

上から、コードのセルを実行していきましょう。SHIFT + ENTER で実行できます。
この Notebook は ChainerRL の [Quick Start Guide](https://github.com/chainer/chainerrl/blob/master/examples/quickstart/quickstart.ipynb) をベースにしていますが、Colaboratory で動かす為に、一部変えた部分があります。ここでは、違うところを説明します。

### Chainer と ChainerRL のインストール

最初にあるコードセルでは、Chainer と ChainerRL、OpenAI Gym等をインストールしています。
以下の通り、apt が使える、かなり自由に環境を構築できます。また、Chainerのインストール方法（正確には、Copy）は、@kmaehashi さんの[こちら](https://github.com/kmaehashi/chainer-colab)を元にしています。
なお、この Notebook はGPUランタイムでないと動きません。実行前に、念のため、メニュー→「ランタイム」→「ランタイムタイプの変更」から、ハードウェアアクセラレーターが、GPU になっている事を確認してください。

````
# Install Chainer, ChainerRL and CuPy!

!apt-get -qq -y install libcusparse8.0 libnvrtc8.0 libnvtoolsext1 > /dev/null
!ln -snf /usr/lib/x86_64-linux-gnu/libnvrtc-builtins.so.8.0 /usr/lib/x86_64-linux-gnu/libnvrtc-builtins.so
!pip -q install https://github.com/kmaehashi/chainer-colab/releases/download/2018-02-06/cupy_cuda80-4.0.0b3-cp36-cp36m-linux_x86_64.whl
!pip -q install 'chainer==4.0.0b3'
!apt-get -qq -y install xvfb freeglut3-dev ffmpeg> /dev/null
!pip -q install chainerrl
!pip -q install gym
!pip -q install pyglet
!pip -q install pyopengl
!pip -q install pyvirtualdisplay
````

ChainerとChainerRLのインストールが終わったら、その後は基本的に、ChainerRL の Quick Start Guide
 と同じで、環境作って、Q関数のモデルを作って、Optimizer を作って、Agent 作って、学習する、という流れです。

### matplotlib のアニメーション機能を使った結果確認

学習が終わったら、その結果を確認します。Loss や Reward の進捗を見ても良いですが、せっかく強化学習なので、動作結果を見たいものです。通常ですと、`env.render()`するとウインドウが表示され、結果がみれます。が、Colaboratory ではウインドウを表示する方法がありません。そのため、matplotlib のアニメーション機能や Open AI Gym の録画機能を使って確認します。

matplotlib のアニメーション機能は、以下のような流れで実行します。

1. `env.render()`の戻り値として返ってくる画像を配列に保存
2. `matplotlib.animation.FuncAnimation` でアニメーションを作成
3. `HTML`で表示

ここで、`env.render()`を実行する必要がありますが、そのためには、画面を表示できる必要があります（Xセッションが必要となります）。 ダミーのXセッションを起動する場合、通常は、Xvfb を使えば良いのですが、Colaboratory ではバックグランドプロセスの起動はできないため、通常の方法では使えません。そこで、Python の`pyvirtualdisplay`というモジュールで起動して、環境変数を`os.environ`で設定します。

```python
# Start virtual display
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1024, 768))
display.start()
import os
os.environ["DISPLAY"] = ":" + str(display.display) + "." + str(display.screen)
```

そして、以下のように、`env.render()`を実行し、アニメーションを表示します。

```python
frames = []
for i in range(3):
    obs = env.reset()
    done = False
    R = 0
    t = 0
    while not done and t < 200:
        frames.append(env.render(mode = 'rgb_array'))
        action = agent.act(obs)
        obs, r, done, _ = env.step(action)
        R += r
        t += 1
    print('test episode:', i, 'R:', R)
    agent.stop_episode()
env.render()

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from IPython.display import HTML

plt.figure(figsize=(frames[0].shape[1] / 72.0, frames[0].shape[0] / 72.0), dpi = 72)
patch = plt.imshow(frames[0])
plt.axis('off')
animate = lambda i: patch.set_data(frames[i])
ani = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=len(frames), interval = 50)
HTML(ani.to_jshtml())
```

こうすると、以下のようにアニメーションが表示されます。

![anim1.gif](https://qiita-image-store.s3.amazonaws.com/0/38555/b9bee231-f2ca-729b-3b04-9731cdc407e3.gif)

### OpenAI Gym の録画機能を使う

これでも問題無いのですが、もう一つ、Open AI Gym には、録画機能があります。
そのため、`gym.wrappers.Monitor`を使って、env を Wrap して、`env.render()`します。

ここでも、Xセッションが必要となるので、以下の実行の前に、先ほどの`pyvirtualdisplay`を使って、Virtual Display を起動しておいてください。

```python

# wrap env for recording video
envw = gym.wrappers.Monitor(env, "./", force=True)

for i in range(3):
    obs = envw.reset()
    done = False
    R = 0
    t = 0
    while not done and t < 200:
        envw.render()
        action = agent.act(obs)
        obs, r, done, _ = envw.step(action)
        R += r
        t += 1
    print('test episode:', i, 'R:', R)
    agent.stop_episode()
```

そして、以下のようにダウンロードします。Episode毎に録画されるため、複数ファイル、ダウンロードされる事があります。

```python
from google.colab import files
import glob

for file in glob.glob("openaigym.video.*.mp4"):
  files.download(file)
```

[![Colaboratory で実行した Open AI Gym の実行結果を録画](https://qiita-image-store.s3.amazonaws.com/0/38555/3c07f247-0afe-a27f-f937-622bde32c7ed.png)](https://www.youtube.com/watch?v=-Hn7pq6_cQo)

# まとめ

強化学習は、Image classification や GAN などのタスクと違って、環境構築が難しかったり、Jupyter Notebookで確認しずらいという課題がありました。ここで、紹介した方法では、Colaboratory を使って、秒速で環境を構築でき、簡単に結果を確認でき、強化学習に取り組む際のハードルを下げる事ができると思います。

# Chainer Colab Notebook リポジトリ

[Chainer Community](https://chainer.connpass.com/)では、Colaboratory を使った Hands-on 資料を作成しています。Contribution も受け付けていますので、Github の Pull-requestからお願いします！

@keisuke-umezawa さんによる紹介記事： https://qiita.com/keisuke-umezawa/items/4e99c2a4f5f07567444c

Google drive: https://drive.google.com/drive/u/0/folders/1GdwW9HmKfKfo6E-K81YKuURh-XheCGDR

Github: https://github.com/chainer-community/chainer-colab-notebook