tocomの調査録(機械学習、強化学習多め)

機械学習関連のことをまとめていきます。強化学習関連が多いかもしれません

【Deep Q Learning、深層強化学習】keras-rlを試してみる

今回は深層強化学習ライブラリのKeras-rl をとりあえず試したいと思います。

keras-rlとは

Keras-rlとは 深層学習用ライブラリであるkerasを用いて、深層強化学習アルゴリズムを実装したライブラリです。
比較的容易に深層強化学習を試すことができます。

github.com

install方法

Keras-rlのインストール方法は以下のようになります。

pip install keras-rl

Keras-rlを使用するために他にもいくつかインストールしておく必要があります。

pip install numpy
pip install tensorflow
pip install keras

問題設定

今回はOpen AI GymのCartpoleという問題を深層強化学習によって解いてみます。

OpenAI Gym

強化学習ベンチマーク問題を集めたOSSです。

keras-rlの強化学習エージェントに解かせる問題は、 OpenAI Gymのインターフェースに準じて作成する必要があります。

OpenAI Gymは以下のコマンドでインストールできます。

pip install gym

Cartpole問題とは

CartPoleは、 棒が設置してある台車があり、
台車を棒が倒れないように
うまくコントロールする問題になります。

f:id:ttt242242:20190428190208p:plain

出典:Leaderboard · openai/gym Wiki · GitHub

制御値、観測、報酬等について
制御値(行動)

制御値は、台を左に押す(0)か 右に押す(1)の二択になります。

操作
0 左に押す
1 右に押す
観測

観測値は、台車の位置、台車の速度、棒の角度、棒の先端の速度の4つになります。

観測情報 最小値 最大値
台車の位置 -2.4 2.4
台車の速度 -inf inf
棒の角度 -41.8° 41.8°
棒の先端の速度 -inf inf
報酬

報酬としては1を与え続けます。

エピソードの終了判定

以下のどれかの条件を満たした場合に、
エピソードが終了したと判定されます。

  • ポールのアングルが±12°以内
  • 台車の位置が±2.4以内
  • エピソードの長さが200以上

実験

ソースコード

Cartpole問題を深層強化学習で解きます。
まずコードの全体像を以下に示します。

import numpy as np
import gym

from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten
from keras.optimizers import Adam

from rl.agents.dqn import DQNAgent
from rl.policy import BoltzmannQPolicy
from rl.memory import SequentialMemory

ENV_NAME = 'CartPole-v0'

env = gym.make(ENV_NAME)
np.random.seed(123)
env.seed(123)

nb_actions = env.action_space.n # アクション数

# モデルの定義
model = Sequential()
model.add(Flatten(input_shape=(1,) + env.observation_space.shape))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(nb_actions))
model.add(Activation('linear'))
print(model.summary())

memory = SequentialMemory(limit=50000, window_length=1) # experience reply で用いるmemory
policy = BoltzmannQPolicy() # 行動選択手法の定義
dqn = DQNAgent(model=model, nb_actions=nb_actions, memory=memory, nb_steps_warmup=10,
               target_model_update=1e-2, policy=policy)
dqn.compile(Adam(lr=1e-3), metrics=['mae'])

history = dqn.fit(env, nb_steps=50000, visualize=True, verbose=2) # 学習。ここでnb_stepsは全エピソードのステップ数の合計が50000(だと思う)

dqn.save_weights('dqn_{}_weights.h5f'.format(ENV_NAME), overwrite=True)

dqn.test(env, nb_episodes=5, visualize=True)

ソースコードの解説をしていきます。

まず、以下のコードでCartpole問題を定義します。

ENV_NAME = 'CartPole-v0'

env = gym.make(ENV_NAME)

次にDeep Q Learning のQ Network$Q(s, a, \theta)$を以下のコードで定義します。
このモデルはtarget networkも兼ねています。
ここはKerasのモデルで簡単に定義できます。
入力は観測情報で、出力は各行動の期待報酬ですので、行動数(nb_actions)分になります。

# モデルの定義
model = Sequential()
model.add(Flatten(input_shape=(1,) + env.observation_space.shape))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(nb_actions))
model.add(Activation('linear'))

次にExperience Replyで用いるMemoryと、
行動選択に用いるPolicyを用います。今回はBoltzmann行動選択法を用います。

memory = SequentialMemory(limit=50000, window_length=1) # experience reply で用いるmemory
policy = BoltzmannQPolicy() # 行動選択手法の定義

ここで、Deep Q Networkを用いた深層強化学習エージェントを定義します。
先程のmemoryやpolicyなどを渡します。
そして、Q Networkのcompileを行います。compile時にtarget networkのcompileをおこないます。

dqn = DQNAgent(model=model, nb_actions=nb_actions, memory=memory, nb_steps_warmup=10,
               target_model_update=1e-2, policy=policy)
dqn.compile(Adam(lr=1e-3), metrics=['mae'])

深層強化学習エージェントの学習を行います。
fit関数を用いて学習を行います。ここで、最初に定義したenvなどを渡して学習します。

history = dqn.fit(env, nb_steps=50000, visualize=True, verbose=2) # 学習。ここでnb_stepsは全エピソードのステップ数の合計が50000(だと思う)

学習したモデルを以下のコードで保存します。

dqn.save_weights('dqn_{}_weights.h5f'.format(ENV_NAME), overwrite=True)

最後に学習し終えたモデルを用いて評価をおこいます。
ここでは学習や探索はしません。

dqn.test(env, nb_episodes=5, visualize=True)

実験結果

上述したソースコードを実行すると以下のように出力します。
以下の出力は学習し終えた深層強化学習エージェントで、Cartpole問題を解いた結果です。
各エピソードともに200ステップ、ポール立たせられているので、正しく学習出来ています。

省略

Testing for 5 episodes ...
Episode 1: reward: 200.000, steps: 200
Episode 2: reward: 200.000, steps: 200
Episode 3: reward: 200.000, steps: 200
Episode 4: reward: 200.000, steps: 200
Episode 5: reward: 200.000, steps: 200

エピソード毎の報酬の変化の推移

エピソード毎の報酬の変化の推移をプロットしてみました。(参考程度) f:id:ttt242242:20170905060828p:plain