以前にRL policy networkを学習する際の報酬に応じた勾配の実装方法について記述したが、計算方法に誤りがあった。
softmax_cross_entroyを修正して、backwardの際の勾配に重みを掛けていたが、lossを計算する際に重みが掛けられていないため、間違ったlossを使用していた。
Twitterでアドバイスを頂いたので、その方法で実装し直した。
v1.24.0からsoftmax_cross_entropyにreduceという引数が追加されてスカラーではなくバッチのまま値を取り出せるようになりました。またそれ以前にもF.log_softmax(logits)[:, actions]のように書くこともできます。
— mooopan (@mooopan) 2017年5月27日
softmax_cross_entroyは出力がスカラー値になっているが、オプションにreduce='no'を指定すると、平均される前のバッチの状態でlossが取得できる。
そのlossに対して重みを掛けた後に、平均をとることで、正しいlossが計算できる。
Chainerでは以下のように実装する。
loss = F.mean(F.softmax_cross_entropy(y, t, reduce='no') * z) loss.backward()
※zはバッチごとの報酬
この実装で計算される損失は、出力と報酬により以下の関係になる。
出力 | 報酬 | 損失 | |
---|---|---|---|
正解 | 正 | 正の小さい値 | 〇 |
正解 | 負 | 負の小さい値 | |
誤り | 正 | 正の大きい値 | |
誤り | 負 | 負の大きい値 | 〇 |
※出力正解は選択された行動の遷移確率が高い場合で、誤りは遷移確率が低い場合
上記表の〇のデータが増えるように学習される。
つまり、損失の期待値を最小化する。
RL policy networkの学習
勾配計算を修正後、RL policy networkの学習をやり直した。
前回は途中で値が発散して学習できなくなったが、とりあえず1000イテレーション分学習ができた。
500イテレーション置きにパラメータを保存して、保存したパラメータと自己対戦するようにしている。
500イテレーションまではわずかに勝率が上がって、それ以降は勝率が落ちている。
学習が成功しているとは言い難い。
モデルの精度が低いと、対戦相手のミスで勝利することもあり、意味ある勝敗にならないことが原因と思われる。
あるいは、まだ学習方法に誤りがあるかもしれない。
elmo_for_learnの教師データで強化学習
自己対戦の結果の精度が低いと思われるので、elmo_for_learnで生成したデータの勝敗データを使用してRL policy networkの学習を行った。
学習率0.001、ミニバッチサイズ64で試したところ、はじめ順調にlossが低下していたが、途中で値が発散してしまった。