【深層強化学習、keras-rl】 keras-rlで連続値の行動を扱えるDDPGを試す

深層強化学習ライブラリであるkeras-rlを用いて、 DDPGを動かしてみます。
Open AI gym で提供されているPendulumという問題を解きます。
基本的にはkeras-rlのexmpleコードを用います。
適宜、日本語のコメントや学習結果を表示するためのコードを加えています。

ちなみに私の環境は

  • ubuntu 18.04
  • python 3.6.0

です。

DDPGについて

Deep Deterministic Policy Gradient(DDPG) は
モデルフリーの深層強化学習アルゴリズムです。
Actor-Critic を用いて構成されています。

https://www.tcom242242.net/entry/2019/04/02/190122

なので、ActorとCtiricの2つのニューラルネットワークを用います。
詳しくは以下の論文を参照していただければと思います。

https://arxiv.org/pdf/1509.02971v2.pdf

kears-rlのインストール

keras-rlを動かすためにいくつかインストールする必要があります。

pip install numpy
pip install gym
pip install tensorflow
pip install keras
pip install keras-rl

プログラム

Pendulumという振り子の問題を解かせます。
学習エージェントは、振り子を立たせて置くことが目的となる問題です。

問題については以下の公式サイトを確認していただければと思います。

https://github.com/openai/gym/wiki/Pendulum-v0

以下にサンプルコードを示します。
以下のコードはコピーしてそのまま実行できます。

import numpy as np
import gym
import matplotlib.pyplot as plt

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

from rl.agents import DDPGAgent
from rl.memory import SequentialMemory
from rl.random import OrnsteinUhlenbeckProcess

# 環境(タスク)の設定
ENV_NAME = 'Pendulum-v0'
env = gym.make(ENV_NAME)
np.random.seed(123)
env.seed(123)
assert len(env.action_space.shape) == 1
nb_actions = env.action_space.shape[0]

# actorの設定
actor = Sequential()
actor.add(Flatten(input_shape=(1,) + env.observation_space.shape))
actor.add(Dense(16))
actor.add(Activation('relu'))
actor.add(Dense(16))
actor.add(Activation('relu'))
actor.add(Dense(16))
actor.add(Activation('relu'))
actor.add(Dense(nb_actions))
# 出力は連続値なので、linerを使う
actor.add(Activation('linear'))
print(actor.summary())

# criticの設定。上記で設定したactorのinputを入力に含める
action_input = Input(shape=(nb_actions,), name='action_input')
observation_input = Input(shape=(1,) + env.observation_space.shape, name='observation_input')
flattened_observation = Flatten()(observation_input)
x = Concatenate()([action_input, flattened_observation])
x = Dense(32)(x)
x = Activation('relu')(x)
x = Dense(32)(x)
x = Activation('relu')(x)
x = Dense(32)(x)
x = Activation('relu')(x)
x = Dense(1)(x)
x = Activation('linear')(x)
critic = Model(inputs=[action_input, observation_input], outputs=x)
print(critic.summary())

# Experience Bufferの設定
memory = SequentialMemory(limit=100000, window_length=1)
# 行動選択時に加えるノイズ(探索のため)
# 平均回帰課程を用いている。単純にノイズが、muに収束していく。
# ここでは、mu=0に設定しているので、ノイズはゼロになっていく。つまり、探索を行わなくなる。
random_process = OrnsteinUhlenbeckProcess(size=nb_actions, theta=.15, mu=0., sigma=.3)

# DDPGエージェントの設定
agent = DDPGAgent(nb_actions=nb_actions, actor=actor, critic=critic, critic_action_input=action_input,
                  memory=memory, nb_steps_warmup_critic=100, nb_steps_warmup_actor=100,
                  random_process=random_process, gamma=.99, target_model_update=1e-3)
agent.compile(Adam(lr=.001, clipnorm=1.), metrics=['mae'])

# エージェントの学習
# visualizeで学習中のゲーム画面を表示するか。verboseで学習プロセスの表示をするかを設定できる
history = agent.fit(env, nb_steps=50000, visualize=False, verbose=1, nb_max_episode_steps=200)

# 学習曲線のプロット
history = history.history
plt.plot(np.arange(len(history["episode_reward"])), history["episode_reward"])

# 学習済みモデルのパラメータの読み込み
# agent.load_weights('ddpg_{}_weights.h5f'.format(ENV_NAME))

# 学習したモデルのパラメータの保存
agent.save_weights('ddpg_{}_weights.h5f'.format(ENV_NAME), overwrite=True)

# 評価
agent.test(env, nb_episodes=5, visualize=False, nb_max_episode_steps=200)

上述したコードを実行すると、 下記のような学習曲線をプロットします。
f:id:ttt242242:20190416140700p:plain

学習が進むにつれて、得られる報酬が向上しているのがわかります。

コメント

タイトルとURLをコピーしました