この記事は何
せっかく Pythonで学ぶ強化学習 をざっと読んだので、手を動かしてみる大作戦です。
FlappyBird という数年前に話題になったゲームがあり、それを強化学習を用いて学習していきたいと思います。
のんびり動かしてみつつ、色々やったことを記録していこうと考えています
- FlappyBird で強化学習の練習 その0: 環境編 ← これ
- FlappyBird で強化学習の練習 その1: DQN
- FlappyBird で強化学習の練習 その2: Double DQN
- FlappyBird で強化学習の練習 その3: DQN + Dueling network
この記事は、環境構築です。JupyterLab で動画を見るのに少し手間取ったため、残しておきます。
自分のローカルマシンである mac と、リモート環境である ubuntu で動作確認しています。
目次
- FlappyBird を Python (gym) で動かす
- FlappyBird を JupyterLab 上で動かす
FlappyBird を Python で動かす
コマンドでインストール一発打つだけかと思ってたんですが、そんなことはなかった。
↓を使います。
-
gym
- ゲームを強化学習で学習できるような環境を提供する、 OpenAI によるプラットフォーム
-
ple (pygame learning environment)
- pygame (Python でゲーム作るライブラリ)のゲームで強化学習環境を用意してくれるやつ
-
gym-ple
- ple を gym のインターフェースで動かせるやつ
- 使わなくても良いけど gym ライクにやりたかったので
環境構築
※ 私の環境ではこれで動きましたが、人によっては追加でライブラリなど必要かと思います。
ubuntu
$ sudo apt-get install ffmpeg libav-tools
mac
$ brew install ffmpeg
その後
$ mkdir flappybird; cd flappybird
$ touch Pipfile
$ pipenv install --python 3.6.5
$ vi Pipfile
出来た Pipfile
を開いて、必要そうなライブラリを記述。なぜか pipenv install [libname]
で ple が入らなかったが、 Pipfile
に書くと入った(後々使う TensorFlow や matplotlib も入れてます)。
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
tensorflow = "*"
gym = "*"
jupyterlab = "*"
ipython = "*"
ple = {editable = true, git = "https://github.com/ntasfi/PyGame-Learning-Environment.git"}
pygame = "*"
gym-ple = "*"
matplotlib = "*"
[requires]
python_version = "3.6"
ライブラリをインストールする。
$ pipenv install
動作確認のサンプルコード
こんな感じにとりあえず gym を通じて動くサンプル (gym-ple からとってきて少し修正) を動かしてみます。
https://github.com/cfiken/flappybird-try/blob/master/00_environment.py
実行すると render = True
だと(ローカルだと)画面が出て動きます。 render = False
だと /tmp
以下に json のログと mp4 が保存されます。
import logging
import os, sys
import gym
from gym.wrappers import Monitor
import gym_ple
# random agent!
class RandomAgent(object):
def __init__(self, action_space):
self.action_space = action_space
def act(self, observation, reward, done):
return self.action_space.sample()
render = True # 画面表示したい場合は True, そうでない場合は False にしてください
if __name__ == '__main__':
logger = logging.getLogger()
logger.setLevel(logging.INFO)
env = gym.make('FlappyBird-v0' if len(sys.argv)<2 else sys.argv[1])
if not render:
outdir = '/tmp/random-agent-results'
env = Monitor(env, directory=outdir, force=True)
# This declaration must go *after* the monitor call, since the
# monitor's seeding creates a new action_space instance with the
# appropriate pseudorandom number generator.
env.seed(0)
agent = RandomAgent(env.action_space)
episode_count = 100
reward = 0
done = False
for i in range(episode_count):
ob = env.reset()
while True:
action = agent.act(ob, reward, done)
ob, reward, done, _ = env.step(action)
if render:
env.render()
if done:
break
# Dump result info to disk
env.close()
logger.info("Successfully ran RandomAgent")
$ pipenv run python 00_environment.py
# render = False の場合は実行が終わるまで待ちます
render = True
なら、ディスプレイにゲーム画面が表示されます。 render = False
なら、 /tmp/random-agent-results
以下にログと mp4 の動画が保存されています。
JupyterLab で動かす
こちらのサイト を参考にしました。
Jupyter Notebook だとチュートリアルがあったりして楽に動くっぽいですが、JupyterLab だと下記の理由で大変みたいです。
- JS をうまく使えない?
- nbagg がエラーになる
最終的に HTML5 を使ってアニメーション再生することで動くようにしました。リアルタイムではなく、一度実行したものの最終エピソードを後で再生するようにしています。長いので github へのリンクで。
https://github.com/cfiken/flappybird-try/blob/master/00_environment.ipynb
スクリプト版との差分としては、
-
%matplotlib inline
にする from IPython.display import HTML
-
env.render()
で取得できる frame をリストに保存しておく -
animate
であとから保存したリストをHTML5アニメーションにする
です。アニメーションを表示する部分は次のようにしています。
def animate(frames):
anims = []
fig = plt.figure()
plt.axis('off')
for f in frames:
im = plt.imshow(f)
anims.append([im])
plt.close()
ani = animation.ArtistAnimation(fig, anims, interval=50)
return HTML(ani.to_html5_video())
一度 plt.close()
を呼んでいるのは、途中段階の画像が表示されてしまうためです(もっと良いやり方があるかも)。
以上です。
何か間違いやもっと良い方法あればコメントなどいただけると助かります