AdvantageでActor-Criticを学習する際の注意点
Advantageを使ったActor-Criticの学習で、ちょっとはまった点があったのでそのことについて書き留めておきたいと思います。要約すると、以下のようになります。
AdvantageはActor(戦略)側の学習に使用するが、Advantageの計算過程にCritic(価値評価)の計算を使用していると、Actor側の勾配がCriticにも流れてしまう。
具体的には、以下のような実装になります(疑似的なコードです)。
policy_loss
の計算にはもちろんAdvantageが登場しますが、この計算過程でCriticの出力を使っています。そのため素直にbackpropを実行するとCritic側にまで( policy_loss
から計算された)勾配が流れてしまいます。
Actorの目的関数はCriticの目的関数と異なるため、これは意図しない挙動を生むことになります。個人的な実験ではAdvantageが極端に負の値を取ったりするので、もしAdvantageの値を観測し以下のような感じになっていたら要注意です(※これはCatcherという一つの環境でしか試していないので、別の環境では別の動きをする可能性があります)。
※本記事は当初softplusをAdvantageに適用することでこの極端な負の値による影響を軽減していましたが、これは対処療法でした。。。
対策としては、勾配が流れないよう止めるか(tf.stop_gradient)、Advantageを外(勾配が絡まない所)で計算しておくといった方法を取ります。
勾配が流れないよう止める対策は以下のようになります(Issueにて教えていただきました)。
上で掲載したコードに対策を適用した場合は以下のようになります。
外で計算してしまう対策は、以下のようになります。Advantageを外で計算しておいて、学習の時に渡す形になります。
上で掲載したコードに対策を適用した場合は以下のようになります。
いずれの方法でも、戦略(Actor)側の学習がCritic(価値評価)側に影響を与えないようにする、という点では変わりません。
以下は、対策後Catcherの環境で3回実行した結果です。きちんと報酬が獲得できています。
参考: Advantageとは?
強化学習における「戦略の学習」は様々な手法がありますが、基本は「期待値の最大化」です。期待値は、もちろん報酬x確率の総和で求められる値です。直感的には、報酬が高い行動については確率を高く、報酬が低い行動については確率を下げるようにすれば期待値を高められます。勾配法を用いて、期待値が高まるよう戦略を改善していく手法をPolicy Gradientと呼びます(リンク先はSutton先生の講義資料です)。
Policy Gradientが行いたいことは前述の通り「期待値の最大化」です。ただ、最適化の都合上「最小化」にした方が行いやすいので、値にマイナスをかけて最大化問題を最小化問題として解くのが一般的です。
Advantageは、行動価値(Q(s, a))から状態の価値(V(s))を差し引いたものになります。
なぜわざわざ状態の価値を引くのかというと、「行動のみ」の価値を得るためです。Policy Gradientは「行動の確率」に「価値」を掛けますが、その「価値」は純粋に行動のみの分の方が良いのでは、というのがAdvantageを使用する背景です。
ただ、この場合Q(s, a)の算出とV(s)の算出の2つが必要になります。そのため、Q(s, a)をV(s)で推定することにします。具体的には、「実報酬+次の状態の価値」で計算します。
これは、通常のQ学習と同じ仕組み(TD学習)となります。こうすることで、Policy Gradientを「行動の確率」と「行動のみの価値」で学習させることができます。これがAdvantageを使ったPolicy Gradientであり、A2CやA3Cといったアルゴリズムの中核をなすものです。