Help us understand the problem. What is going on with this article?

Pythonの強化学習ライブラリKeras-RLのパラメータ設定

More than 1 year has passed since last update.

はじめに

PythonライブラリKeras-RLは強化学習のことがあまりわかっていなくても使えてしまうのですが、
細かいチューニングをしようと思うとパラメータの意味を理解していないといけません。

そうすると強化学習の数式レベルの理解がある程度必要になります
(行動価値関数などの最終的な式の意図や動作が把握できている程度でよい)。

よくわかっていないという人は個人的には以下の連載記事が一番わかりやすかったのでおすすめです。

今さら聞けない強化学習(1):状態価値関数とBellman方程式

本記事では、Keras-RLの各パラメータがどのような意味を持つのかを説明しながら、
実際の設定値などを紹介していきたいと思います。

(私も完全に理解している訳ではないので誤りがありましたらコメントいただければと思います)

想定読者

  • 強化学習の思想やKeras-RLの使い方の流れはわかったけど、細かいパラメータを適当に設定している人

Keras-RLのパラメータ

Keras-RL Documentationの Available Agentsには以下のAgentが利用可能であると記載されています。

  • DQN
  • DDPG
  • NAF
  • CEM
  • SARSA

また、DDQN(DoubleDQN)とDuelingDQNはDQNのパラメータで設定できます。

数が多いので、ここでは最もメジャーなDQNに絞ってパラメータを見ていきます。

環境、DNNモデル

まずはgymの環境とDNNモデルを作成しておきます。
環境は例としてCartPole-v0とします。

from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten, Dropout
import gym

env = gym.make('CartPole-v0')
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(Dropout(0.5))
model.add(Dense(16))
model.add(Activation('relu'))
model.add(Dense(nb_actions))
model.add(Activation('linear'))

DNNの入力層と出力層はニューロン数が固定されます。
DQNのDNNは「環境の観測値に応じた行動価値関数の近似」をするために用いられるので、
「環境で観測される値の次元=env.observation_space.shape」が入力となり、
「行動空間の次元=nb_actions」が出力となります。

その間の層は全結合(Dense)やDropout、活性化関数(Activation)を自由に積み重ねてください。

Experience Replay用のメモリ

Experience ReplayとはDNNの学習を安定させるために用いられる仕組みです。

DNNは時系列に相関があるデータをその順番のまま使うとうまく学習できないらしいので、
メモリにaction、reward、observationsなどのデータを経験(Experience)として保管しておいて、後でランダムにデータを再生(Replay)して学習を行います。

from rl.memory import SequentialMemory

memory = SequentialMemory(limit=50000, window_length=1, ignore_episode_boundaries=False)
パラメータ 必須 意味
limit メモリ(collections.deque)の上限サイズ。action(行動)、reward(報酬)、observations(観測)のそれぞれにdequeが用意される。上限を超えると古いデータが書き換えられていく
window_length 観測を何個連結して処理するか。例えば時系列の複数の観測をまとめて1つの状態とする場合に利用。
ignore_episode_boundaries エピソードの境界を無視するかどうか(別のエピソードの経験を利用する場合はTrue)。

なお、もうひとつrl.memoryにあるEpisodeParameterMemoryクラスはCEMで利用可能なメモリとのことです。

行動ポリシー

from rl.policy import LinearAnnealedPolicy
from rl.policy import SoftmaxPolicy
from rl.policy import EpsGreedyQPolicy
from rl.policy import GreedyQPolicy
from rl.policy import BoltzmannQPolicy
from rl.policy import MaxBoltzmannQPolicy
from rl.policy import BoltzmannGumbelQPolicy

# どれか選択
policy = LinearAnnealedPolicy(EpsGreedyQPolicy(), attr='eps', 
                      value_max=1., value_min=.1, value_test=.05, nb_steps=1000)
policy = SoftmaxPolicy()
policy = EpsGreedyQPolicy(eps=0.1)
policy = GreedyQPolicy()
policy = BoltzmannQPolicy(tau=1., clip=(-500., 500.))
policy = MaxBoltzmannQPolicy(eps=.1, tau=1., clip=(-500., 500.))
policy = BoltzmannGumbelQPolicy(C=1.0)

行動ポリシーとは、環境において行動を選択する基準となるものです。
上記以外にも、Policyクラスを継承して自作してもいいとのことです。

LinearAnnealedPolicyは引数に指定したポリシーについて、attrに指定したパラメータをvalue_maxからvalue_minまでnb_steps回目までに線形に変化させるというものです。
value_testについてはテスト時の固定的なパラメータ値となります。

BoltzmannGumbelQPolicyについてはトレーニング時のみに利用できるポリシーとのことです。

パラメータ 必須 意味
eps ランダムな行動を選択する確率(イプシロン)。値が大きいほど探索に重きを置いて行動を決定する。
tau ボルツマン分布を利用したソフトマックス手法のQ値を割る値。
clip Q値をtauで割った後にクリップする範囲。
C ガンベル分布の乗数betaの計算式beta = C/np.sqrt(action_counts)で利用。

エージェント

from rl.agents.dqn import DQNAgent

agent = DQNAgent(nb_actions=nb_actions, memory=memory, gamma=.99, batch_size=32, nb_steps_warmup=1000,
                 train_interval=1, memory_interval=1, target_model_update=10000,
                 delta_range=None, delta_clip=np.inf, custom_model_objects={}, 
                 model=model, policy=None, test_policy=None, enable_double_dqn=False,
                 enable_dueling_network=False, dueling_type='avg')

大量にパラメータがありますが、必須のものはごく一部です。

パラメータ 必須 意味
nb_actions 行動空間の次元数。環境により決まるためこの段階で変更することはない。
memory 事前に作ったExperience Replay用のメモリ。
gamma 行動価値関数の式に出てくる割引率。将来の価値をどれくらい考慮するかを決める(値が大きいほど将来の価値を大きく反映する)。1未満の値を設定する。
batch_size 学習のバッチサイズ
nb_steps_warmup ウォームアップステップ数。学習の初期は安定しないため、学習率を徐々に上げていく期間。
train_interval トレーニングのインターバル。train_intervalステップ毎に学習が実行される。
memory_interval Experience Replay用のメモリにデータを貯めるインターバル。memory_intervalステップ毎にメモリに経験が保存される。
target_model_update 0以上の値。1未満の値の場合はSoft updateと呼ばれ、(1 - target_model_update) * old + target_model_update * newの式で重みが更新される。1以上の値の場合はHard updateと呼ばれ、int(target_model_update)ステップごとに重みが完全に更新される。
delta_range 非推奨のパラメータ。delta_clipを代わりに使ってくれとのこと。もし値が設定された場合はdelta_clip = delta_range[1]となる。
delta_clip Huber損失のデルタ値。
custom_model_objects ターゲットモデルを生成する際のオプション。詳細はこちらを参照。
model 事前に作ったDNNのモデル。
policy 行動ポリシー。設定しない場合はEpsGreedyQPolicyが適用される。
test_policy テスト時の行動ポリシー。設定しない場合はGreedyQPolicyが適用される。
enable_double_dqn DoubleDQN(DDQN)を適用するかどうか。
enable_dueling_network DuelingDQNを適用するかどうか。Trueにすると出力層の前の層にDueling Networkを挿入してくれる。
dueling_type Duelingネットワークのタイプ(enable_dueling_networkがTrueのときに使用)。行動価値関数 Q(s,a)を状態価値関数V(s)とアドバンテージA(s,a)から計算する際の計算方法を決める。avg、max、naiveが選択できるが、avgが推奨されているとのこと。具体的な式は以下を参照。

avg: Q(s,a;theta) = V(s;theta) + (A(s,a;theta)-Avg_a(A(s,a;theta)))
max: Q(s,a;theta) = V(s;theta) + (A(s,a;theta)-max_a(A(s,a;theta)))
naive: Q(s,a;theta) = V(s;theta) + A(s,a;theta)

エージェントのコンパイル

from keras.optimizers import Adam

agent.compile(optimizer=Adam(lr=1e-3), metrics=['mse'])
パラメータ 必須 意味
optimizer DNN重み更新の最適化手法。利用可能な手法はKerasのoptimizers。更新式はこの記事に整理されている。Adamであれば学習率(Learning rate: lr)は1e-3が論文で推奨されているらしい
metrics 評価関数のリストで、Kerasの評価関数が使える。または自作のlambda y_true, y_pred: metricの形式で指定できる。指定の有無にかかわらずmean_qという評価関数が追加される。

エージェントの学習

agent.fit(env=env, nb_steps=nb_steps, action_repetition=1, callbacks=None, verbose=1,
          visualize=False, nb_max_start_steps=0, start_step_policy=None, log_interval=10000,
          nb_max_episode_steps=None)
パラメータ 必須 意味
env 事前に作った強化学習環境。
nb_steps シミュレーションのステップ数。1ステップは、1回の観測、行動、報酬の獲得。
action_repetition 行動の繰り返し回数。2以上にすると、観測なしに同じ行動をaction_repetition回繰り返す。
callbacks コールバックのリスト。rl.callbacks.Callbackを継承したコールバックが使える。ステップの開始・終了、エピソードの開始・終了、アクションの開始・終了がイベントとなる。
verbose ロギングのモード。0でロギングなし、1でlog_intervalステップ毎にロギング、2でエピソード毎にロギング。具体的にはrl.callbacks.TrainIntervalLoggerが呼ばれる。
visualize 可視化のEnable。具体的にはrl.callbacks.Visualizerが呼ばれる。環境でrender(mode='human'))が実装されていないと例外が起きる。
nb_max_start_steps この値を最大値とする乱数値回目からステップを開始する。シミュレーションの開始位置を変動させたい場合に利用。この間はExperience Replayに記録されない。
start_step_policy nb_max_start_stepsが0でない場合に有効。nb_max_start_stepsまでの間にどのような行動ポリシーとするかをlambda observation: actionの形式で指定。Noneの場合はランダムに行動が選択される。
log_interval ロギングするステップ間隔。
nb_max_episode_steps 1エピソードにおける最大のステップ数。

このパラメータを見ればわかるように、Keras-RLではエピソード数を決めるのではなく、
ステップ数と1エピソードにおける最大のステップ数で「最小のエピソード数」が決まります。
つまり、nb_steps / nb_max_episode_stepsが最小エピソード数となります。

例えばnb_steps=3000nb_maxepisode_steps=300の場合は、最低3000/300=10回のエピソードが繰り返されます。
ただし、nb_max_episode_stepsよりも少ないステップ数でエピソードが終了することもあるので、
エピソード数は最大でnb_steps回となります(ほぼありえませんが、毎回1ステップ目でシミュレーションが終了する場合)。

おわりに

今回はDQNのパラメータを見てきましたが、他のAgentでも共通する部分もあればそうでない部分もあります。
(異なる部分は例えば、SARSAはExperience Replayをしないのでメモリが不要、など)

公式ドキュメントがそれほど充実しているわけではないので、
もし他のAgentのパラメータ設定について知りたい場合はソースコードを見るのが手っ取り早いと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした