Keras を勉強します。
keras-rl でオリジナルの強化学習タスク・オリジナルのDQNモデルを学習したという記事が本日 Qiita に投稿されていましたが(参考記事)、まず keras-rl と gym がわからないので example コードを実行することにします。
参考記事
以下の記事を参考にさせていただきましたが、やったことは記事内容のトレースよりはるか低みです。
qiita.com
やること
強化学習で伝統的なポールバランシングタスクをエージェントに学習させます。
小学生のとき掃除の時間に、手のひらに箒をのせて倒れないようにバランスを取るのをよくやったと思います。
今回のタスクのポールの動く範囲は2次元平面内に制約されています。台車も直線上を動きます。
gym でのタスク設定は以下のページ参照。
OpenAI Gym CartPole-v0
- その時間ステップにポールが直立していれば +1 の報酬がもらえます。
- 選択できる行動は台車に +1 の力を加えるか、-1 の力を加えるかのどちらかです。
- ポールが15°以上傾くか、台車がスタート位置から所定の距離以上右か左へ外れてしまったらゲームオーバー(エピソード終了)です。
これを行動価値関数 のパラメタライズされた関数で近似し最適パラメータを解くんですが、今回は関数というかディープネットにしてしまい、ディープネットの重みの最適化を図ります。
手順
keras はもう導入済みなので、参考記事通りに keras-rl と gym を導入します。
そして今回は以下のコードをそのまま実行するだけです。
https://github.com/matthiasplappert/keras-rl/blob/master/examples/dqn_cartpole.py
# -*- coding: utf-8 -*- import numpy 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 if __name__ == "__main__": # 強化学習タスクの環境を構築する ENV_NAME = 'CartPole-v0' env = gym.make(ENV_NAME) numpy.random.seed(123) env.seed(123) nb_actions = env.action_space.n # DQNモデルを準備する 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()) # DQNモデルを最適化する上での目的関数の設定 memory = SequentialMemory(limit=50000, window_length=1) 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']) # トレーニング dqn.fit(env, nb_steps=50000, visualize=True, verbose=2) # トレーニングした重みの保存 dqn.save_weights('dqn_{}_weights.h5f'.format(ENV_NAME), overwrite=True) # テスト dqn.test(env, nb_episodes=5, visualize=True)
print(model.summary()) で以下のようにモデルの姿を出力してくれます。パラメータ数などわかりやすいです。
当たり前ですが、各層で最適化すべきパラメータ数は、前の層のアウトプットの数 + 1(定数項) に、その層のアウトプットの数を乗じたものになっています。
最終的な出力2は、「+1 の力を入れることの価値」「-1の力を入れることの価値」になっているはずです。
[2017-01-15 23:06:20,720] Making new env: CartPole-v0 __________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ========================================================================================== flatten_1 (Flatten) (None, 4) 0 flatten_input_1[0][0] __________________________________________________________________________________________ dense_1 (Dense) (None, 16) 80 flatten_1[0][0] __________________________________________________________________________________________ activation_1 (Activation) (None, 16) 0 dense_1[0][0] __________________________________________________________________________________________ dense_2 (Dense) (None, 16) 272 activation_1[0][0] __________________________________________________________________________________________ activation_2 (Activation) (None, 16) 0 dense_2[0][0] __________________________________________________________________________________________ dense_3 (Dense) (None, 16) 272 activation_2[0][0] __________________________________________________________________________________________ activation_3 (Activation) (None, 16) 0 dense_3[0][0] __________________________________________________________________________________________ dense_4 (Dense) (None, 2) 34 activation_3[0][0] __________________________________________________________________________________________ activation_4 (Activation) (None, 2) 0 dense_4[0][0] ========================================================================================== Total params: 658 Trainable params: 658 Non-trainable params: 0 __________________________________________________________________________________________
そして訓練の結果を5エピソード分テストすると、こんなに長い時間ステップの間ポールを倒さず、部屋の中央からも離れずにいることができました。最初がどうだったのか並べないとこれが長いのか短いのかよくわからないですが、トレーニング中はなんかもっとよく倒れていました。
Testing for 5 episodes ... Episode 1: reward: 21734.000, steps: 21734 Episode 2: reward: 7434.000, steps: 7434 Episode 3: reward: 5168.000, steps: 5168 Episode 4: reward: 13027.000, steps: 13027 Episode 5: reward: 22779.000, steps: 22779
感想
gym のサイトにあるように、実際にポールの動画が出てきて楽しい。