Emileの備忘録

色々な事をだらだらと

A2Cの理論と実装

この記事はKyoto University Advent Calendar 2020の記事の12/21日分として書かれた物です.
adventar.org
先日のd0ra1998先輩の記事には改めて京都の四季の美しさに気付かされました.
先輩方の面白い記事が並んでいる中でこんな駄文を投下するのは気が引けますが....



A2Cってなに?

A3Cよりあとに提案された,Advantage, Actor-Criticの2つを用いる手法です.(Aが2つなのでA2C.)
experience replayを用いないので, RNN を使えるといったメリットもあります.


学習の概要は,

一つのネットワークに対して複数のAgentを準備しておいて,
(それぞれのAgentに対して)行動選択 -> 新しいState, Reward を観測 -> (規定回数まで)行動選択に戻る
-> 蓄積した行動,State,Rewardを用いて学習

を繰り返すという流れです.

Agentが共通というのがA3Cとの違いです.(とても実装が楽)
それ以外の学習自体はA3Cと全く同じ.


どういう仕組み?

Actor-Criticとは?

行動選択を行うActor関数と評価を行うCritic関数の2つを用いて学習する手法です.

今回はモデルとしてニューラルネットワークを用いて,
Actorは \pi(a|s;\theta )を近似する様に,Criticは V^{\pi}(s; \theta_v) を近似する様に学習する様にします.

一般には \theta ,\ \theta_vは別々に準備するのですが,
今回は画像を入力に用いるので,途中までは同じ層を用いて最後に分岐させるようにします.

損失関数の構造

 Value\ Loss := \frac{1}{2} \sum \{ (\sum_{i=0}^{n-1} \gamma^i r_{t+i} + \gamma^n V(s_{t+n}; \theta_v) ) - V(s_t; \theta_v) \}^2
 V(s; \theta_v )の教師信号に用います.


これはforward viewに基づいた n-step rewardを使用していて,
1つの報酬がそれより前の状態にも伝わるので,報酬に時系列的なずれのあるような環境で有効です.

( n-stepのTD誤差と同じです.)



 Policy\ Loss := - \sum \{ A^{\pi}(s) \log (\pi (a|s) ) \} + \beta H(\pi) をActorの教師信号に用います.

 A^{\pi}(s) := (\sum_{i=0}^{n-1} \gamma^i r_{t+i} + \gamma^n V(s_{t+n}; \theta_v) ) - V(s_t; \theta_v) はAdvantageと呼ばれていて,

方策勾配定理より,
 f(\theta) = \sum_{s \in \mathcal{S}}p_{s_0}(s)V^{\pi_{\theta}}(s) とした時の方策勾配が,一般の関数 b: \mathcal{S} \rightarrow \mathbb{R}について,
 \ \ \ \nabla_{\theta }f(\theta) = \mathbb{E}^{\pi}[ \nabla_{\theta} \log{\pi(a|s; \theta)(Q^{\pi}(s,a) - b(s))} ]となる事を利用しています.

この A^{\pi}は, Q^{\pi}(s,a) - V^{\pi}(s)を近似していて,行動のその状態での相対的良さを意味しています.
 \ \ V^\pi(s)を引く事で方策勾配の分散を抑えられて学習が安定するというメリットもあります.


後ろの項は,エントロピー項と呼ばれ,
 H(\pi) :=  - \sum \pi(a|s) \log \pi(a|s)と定義されます.

この項を Policy\ Lossに加える事で,局所最適解に学習初期段階で収束する事を防ぐ事が期待できます.
 \ \ \betaはハイパーパラメータで,この項の寄与の具合を調整します.


今回は共通のニューラルネットを用いて学習するので,
上記の項をまとめて,

 Loss := \alpha Value\ Loss + Policy\ Loss \\ = \frac{ \alpha }{2} \sum \{ (\sum_{i=0}^{n-1} \gamma^i r_{t+i} + \gamma^n V(s_{t+n}; \theta_v) ) - V(s_t; \theta_v) \}^2 - \sum \{ A^{\pi}(s) \log (\pi (a|s) ) \} + \beta H(\pi)

 \ \ を全体の損失関数として使用します.


実装

Open AIのBreakOutを環境に使用しました.
詳しくは下のコードを読んでください.(main2.py, model.py, env.py を使用しています.)
github.com




結果

直近50回のスコア平均が310を安定して超える様になりました.



嵌った所


1.Advantage LossのAdvantage項に勾配を流さない

2.Value LossのAdvantage項の V(s_{t+k})項に勾配を流さない

3.Adamで学習する時には,各LayerをHe normalで初期化すると良い

4.rewardのクリッピング

5.reset後の開始時にランダムな長さだけ,stateを動かした方が学習が偏らない

6.あちこちで実装をミスっていた


参考にした物

実装が綺麗で分かりやすい記事です. (本当にありがとうございました)
horomary.hatenablog.com

損失関数等がまとまってて見やすいです.
medium.com

A3Cの論文,それなりにお気持ちfullでスッキリします.
https://arxiv.org/pdf/1602.01783.pdf



お勉強につかったので.
www.kspub.co.jp


ポエム

ハイパーパラメータや細かい実装の工夫に学習が左右されるのが厄介ですね.

ここまで読んでくださってありがとうございました.