DonkeyCar3シミュレーターで強化学習してみる

# はじめに

[DonkeyCar 3.0 is Released!](https://mailchi.mp/e7afb3c2a154/announcing-donkeycar-30)でいろいろと新しくなったらしいのでそろそろやってみようと思いました。ラジコン等を買うお金を貯めるまでとりあえずシミュレーターで学習などの予行演習をやっておきます

レポジトリを漁っているうちにシミュレーターで強化学習するのが簡単になってるっぽかったのでやってみることにしました

# 環境をセットアップする

macOS Mojave 10.14.5

pyenvで専用の環境をつくります

```shell
pyenv virtualenv 3.7.3 donkeycar

pyenv activate donkeycar

python -V
Python 3.7.3
```

後で重複するものもあるが以下のモジュールをインストールしておきます

```shell
pip install python-socketio flask eventlet pygame numpy pillow h5py scikit-image opencv-python gym
```

[donkeycar](git clone https://github.com/wroscoe/donkey donkeycar)のレポジトリをクローンします

```shell
git clone https://github.com/wroscoe/donkey donkeycar
```

必要なモジュールをインストールします

```shell
pip install -e donkeycar
```

[self-driving sandbox](https://github.com/tawnkramer/sdsandbox/tree/donkey)のレポジトリをクローンします

```shell
git clone https://github.com/tawnkramer/sdsandbox.git
```

必要なモジュールをインストールします

```shell
pip install -r sdsandbox/requirements.txt
```

次に[donkey_gym](https://github.com/tawnkramer/donkey_gym)をクローンします

```
git clone https://github.com/tawnkramer/donkey_gym
```

必要なモジュールをインストールします

```
pip install -e donkey_gym
```

[Releaseページ](https://github.com/tawnkramer/donkey_gym/releases)から現行最新版のシミュレーターバイナリ[DonkeySimMac_10_13.zip](https://github.com/tawnkramer/donkey_gym/releases/download/v18.9.1/DonkeySimMac_10_13.zip)をダウンロードして展開し`donkey_sim`を /Applications に配置します

# シミュレーターを起動して強化学習する

`reinforcement_learning`のディレクトリに移動します

```shell
cd donkey_gym/examples/reinforcement_learning/
```

シミュレーターのパスを指定して`ddqn.py`を実行します。[Deep Reinforcement Learning with Double Q-learning](https://arxiv.org/abs/1509.06461)の実装のようです

```shell
python ddqn.py --sim=/Applications/donkey_sim.app/Contents/MacOS/donkey_sim
```

実行すると以下のようになってシミュレーターの起動画面が表示されます

```
/Users/user/.pyenv/versions/donkeycar/lib/python3.7/site-packages/skimage/viewer/__init__.py:6: UserWarning: Viewer requires Qt
  warn('Viewer requires Qt')
WARNING: Logging before flag parsing goes to stderr.
W0706 22:06:32.471105 4405204416 deprecation_wrapper.py:119] From ddqn.py:26: The name tf.keras.initializers.normal is deprecated. Please use tf.compat.v1.keras.initializers.normal instead.

W0706 22:06:32.475600 4405204416 deprecation_wrapper.py:119] From ddqn.py:218: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead.

W0706 22:06:32.475827 4405204416 deprecation_wrapper.py:119] From ddqn.py:220: The name tf.Session is deprecated. Please use tf.compat.v1.Session instead.

W0706 22:06:32.508859 4405204416 deprecation_wrapper.py:119] From ddqn.py:221: The name tf.keras.backend.set_session is deprecated. Please use tf.compat.v1.keras.backend.set_session instead.

starting DonkeyGym env
donkey subprocess started
binding to ('0.0.0.0', 9091)
waiting for sim to start..
2019-07-06 22:06:33.317 donkey_sim[38189:2539567] Could not find image named 'ScreenSelector'.
waiting for sim to start..
waiting for sim to start..
waiting for sim to start..
```

画面下の Play! ボタンをクリックします

![スクリーンショット 2019-07-06 22.07.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/2e15b2ac-10f0-5755-b259-2e735604cdbe.png)


シミュレーターが起動し自動的にコースが選択されて学習がはじまります。動画のように何度も運転が繰り返されます

![donkeycar-dqrl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/5c723f46-e629-1b9c-6a01-fbf42c6fa5bb.gif)

ログをみると学習が繰り返されているのがわかります

```shell
got a new client ('127.0.0.1', 59824)
W0706 22:07:47.631042 4405204416 deprecation.py:506] From /Users/user/.pyenv/versions/donkeycar/lib/python3.7/site-packages/tensorflow/python/ops/init_ops.py:1251: calling VarianceScaling.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
Episode:  0
EPISODE 0 TIMESTEP 30 / ACTION [-0.08891889, 0.3] / REWARD 0.9979240885446676 / EPISODE LENGTH 30 / Q_MAX  0
fps 14.380368140227569
EPISODE 0 TIMESTEP 60 / ACTION [-0.31381074, 0.3] / REWARD 1.22906461238042 / EPISODE LENGTH 60 / Q_MAX  0
EPISODE 0 TIMESTEP 90 / ACTION [-0.46118185, 0.3] / REWARD 1.283182117658 / EPISODE LENGTH 90 / Q_MAX  0
fps 19.979947188928957
episode: 0   memory length: 107   epsilon: 0.9895139999999955  episode length: 107
Episode:  1
episode: 1   memory length: 108   epsilon: 0.9894159999999954  episode length: 1
Episode:  2
 episode: 2   memory length: 116   epsilon: 0.9886319999999951  episode length: 8
Episode:  3
episode: 3   memory length: 117   epsilon: 0.988533999999995  episode length: 1
Episode:  4
EPISODE 4 TIMESTEP 120 / ACTION [0.5056638, 0.3] / REWARD 0.6079470236506799 / EPISODE LENGTH 3 / Q_MAX  6.9752893
episode: 4   memory length: 126   epsilon: 0.9876519999999946  episode length: 9
Episode:  5
episode: 5   memory length: 131   epsilon: 0.9871619999999944  episode length: 5
Episode:  6
episode: 6   memory length: 142   epsilon: 0.986083999999994  episode length: 11
Episode:  7
episode: 7   memory length: 149   epsilon: 0.9853979999999937  episode length: 7
Episode:  8
EPISODE 8 TIMESTEP 150 / ACTION [-0.971151, 0.3] / REWARD 0.90009812538202 / EPISODE LENGTH 1 / Q_MAX  13.961587
episode: 8   memory length: 155   epsilon: 0.9848099999999934  episode length: 6
```

ディレクトリに学習済みモデル`rl_driver.h5`が生成されています

```shell
ls -1
README.md
ddqn.py
ppo_train.py
rl_driver.h5
unitylog.txt
```

# おわりに

シミュレーターで簡単に強化学習できました。しばらく学習させてみて、ちゃんと走るようになるかみてみようと思います