はじめに †
研究用に強化学習のプログラムを作るときには,いくつか注意点があります.
ここでは,その注意点について説明します.
乱数生成器 †
ほとんどの強化学習アルゴリズムは行動選択に乱数を用います. したがって,強化学習のプログラムは,乱数生成器(random number generator)を用いたものになります.
最初に注意が必要となる点は,システムに標準で用意されている次のような乱数生成器は,生成する疑似乱数に偏りがあることが知られています.
- C言語のrandom()関数
- JavaのMath.random()メソッドとjava.util.Randomクラス
- Excel VBAのRnd()メソッドなど
よい疑似乱数を生成するアルゴリズムとしてメルセンヌ・ツイスター(Mersenne Twister)があります.
したがって,システムに標準で用意されている乱数生成器ではなく,メルセンヌ・ツイスターを使用すべきです.
さまざまな言語で書かれた乱数生成器がここからダウンロードできます. ちなみに,Rubyでは標準の乱数生成器にメルセンヌ・ツイスターが採用されています.
乱数のシード †
研究で行う実験には再現性が求められます. つまり,同じ条件で実行したときに結果が同じにならないといけません.
しかし,乱数を用いると,これが保証されない場合があります. たとえば,JavaのMath.random()は,生成される乱数系列が毎回違うため異なる結果となってしまいます.
そこで,乱数のシード(seed)を用いて乱数生成器を初期化します. 同じシードで初期化された乱数生成器は,必ず同じ乱数系列を生成します.
乱数生成器をシードを指定して初期化し,このシードを記録しておけば,毎回同じ結果を出すことができます.
エージェント用の乱数生成器と環境用の乱数生成器 †
強化学習では,エージェントだけでなく環境も乱数生成器を用いて実装されます. なぜなら,多くの問題(環境)では,状態遷移や報酬がランダムに決められる,つまり,非決定的だからです.
このとき,エージェントが用いる乱数生成器と環境が用いる乱数生成器は独立したものにしておく必要があります. 乱数生成器が一つしかないと,アルゴリズムが異なるエージェントAとエージェントBが同じ状態で同じ行動を選択したときに異なる結果になってしまうことがあるからです.
例として,N本腕バンディット問題*1のように,状態が一つだけでどの行動を選択しても現在と同じ状態に遷移し,報酬が行動によってランダムに決まる問題で,乱数生成器を一つしか使わない場合について考えます. この乱数生成器を用いて特定のシードで生成された乱数系列をR1, R2, R3, R4, R5, ...とします.
エージェントAはアルゴリズムの中で乱数を1回だけ使って行動を選択し,エージェントBはアルゴリズムの中で乱数を2回使って行動を選択するものとします.
エージェントAを用いて実験するときは,エージェントが乱数R1を使って行動を選択し,環境が乱数R2を用いて報酬を決定します.
エージェントBを用いて実験するときは,エージェントが乱数R1, R2を使って行動を選択し,環境が乱数R3を用いて報酬を決定します.
もしエージェントAとエージェントBが選択した行動が同じだったとしても,環境によって決定される報酬が違うものになってしまう可能性があります.
エージェントが用いる乱数生成器と環境が用いる乱数生成器をそれぞれ独立に用意しておけば,同じシードで同じ行動が選択されたときには必ず同じ結果になります.
学習用の乱数生成器と評価用の乱数生成器 †
強化学習の実験では,学習がどのくらい進んでいるかを調べるために,それまでに学習した行動規則*2を用いて,評価を行います.
このとき,評価時に用いられる乱数生成器も学習時に用いられる乱数生成器と独立したものにしておく必要があります.
なぜなら,学習時と評価時に同じ乱数生成器を使用していると,評価のやり方によってその後の結果が異なってしまうことがあるからです.
上と同じ問題を考えます.
エージェントAが学習を1ステップ行うごとに10エピソードによって評価されるとき,1ステップ目の学習でエージェントがR1を,環境がR2を使用し,その後の評価でR3, ..., R22が使われます. したがって,2ステップ目の学習ではエージェントがR23を,環境がR24を使います.
同じエージェントが学習を1ステップ行うごとに100エピソードによって評価されるとき,1ステップ終了後の評価ではR3, ..., R202が使われるので,2ステップ目の学習ではエージェントがR203を,環境がR204を使います.
このように,評価のやり方を変えただけで,学習される結果まで変わってしまいます.
学習時に用いる乱数生成器と評価時に用いる乱数生成器を独立したものにしておけば,評価のやり方を変えても必ず同じ学習をすることができます.
また,評価用の乱数生成器を評価を行う度に初期化すれば,以前の評価に影響されずに同じ評価を再現することができます.
まとめ †
強化学習のプログラムを作るときには,次の点に注意しましょう.
- 乱数生成器にはメルセンヌ・ツイスターを用いる
- 乱数のシードをコマンド・ライン引数などで指定できるようにしておく
- 乱数生成器は独立に4種類用意する
- 学習時にエージェントが使用するもの
- 学習時に環境が使用するもの
- 評価時にエージェントが使用するもの
- 評価時に環境が使用するもの
- 評価用の乱数生成器は評価を行う度に初期化する
参考文献 †
- 強化学習.
Sutton, R.S., Barto, A.G. (著), 三上 貞芳, 皆川 雅章 (訳). 森北出版 (2000).