ころがる狸

ころがる狸のデータ解析ブログ

【強化学習】方策勾配法の仕組みと学習のワークフロー

こんばんは。今日のテーマは方策勾配法です。前回の記事では強化学習の基礎から深層強化学習(DQN)までを扱いました。そこでは状態や行動の価値Qの見積もりをいかにして最適化するかという考え方が根底にありましたが、方策勾配法では価値ではなくエージェントの方策(≒エージェントの行動確率)を最適化することが目的です。本記事では学習のワークフローをまじえながら方策勾配法を解説します。

【参考資料】強化学習の入門記事はこちら。
dajiro.hatenablog.com

【目次】
(式の展開をすっ飛ばしたい人は、方策勾配法のワークフローからご覧ください!)

方策勾配法の仕組み

方策勾配法は、エージェントの行動確率をニューラルネットワークで表現するためのテクニックです。そのことを数式ベースで見ていきましょう。行動確率はネットワークに含まれるパラメータ\theta(重みやバイアスに相当)を用いて

\pi(a|s, \theta)

のように表されるとします(aは行動、sは状態です)。例えば、行動が4通り(上、下、右、左)ある場合には、状態sを入力としてa = (0.2, 0.5, 0.1, 0.2)のように行動を確率で出力してくれる関数をイメージして下さい(ここでは行動が離散的に表現できることを前提にします)。これ自体がニューラルネットワークなので、パラメータ\thetaは確率的勾配降下法によって以下のように更新できます。

 \theta_{t+1} = \theta_{t} + \alpha\nabla J(\theta)

\alphaは学習率、J(\theta)は最適化したい目的関数で、自乗誤差やクロスエントロピーなどの損失関数に対応します。普段ニューラルネットワークを扱う際には損失関数を最小化することが多いと思いますが、ここでの私たちのミッションはエージェントが獲得する報酬を最大化するということです。ならば、目的関数J(\theta)として1つのエピソードで得られる報酬の期待値を設定しても良いでしょう。

J(\theta) = v_{\pi\theta}(s_{0})

_{0}はエピソードの初期状態で、v_{\pi\theta}はパラメータ\thetaに依存する真の価値関数です。極めてシンプルですが、ここには将来得られる価値が織りこまれています。さて、パラメータ更新をする際にはこの微分値が必要なわけですが、これは以下のように表されることが方策勾配定理によって知られています。

\nabla J(\theta) \propto \sum_{s\in{S}}\mu(s)\sum_{a\in{A}}\nabla \pi_{\theta}(a|s)Q^{\pi\theta}(s, a)

ここで\mu(s)は状態sに遷移する確率、\pi_{\theta}(a|s)は状態sで行動aをとる確率、Q^{\pi\theta}(s, a)はその価値です。式が一気に飛びましたが、安心してください。以下の著作に方策勾配定理の証明が載っているので興味のある方はご参照下さい。269ページです。
http://incompleteideas.net/book/bookdraft2017nov5.pdf

あと一息です。最終的な表現を得るために、以下の式変形を利用します。

\nabla \pi_{\theta}(a|s) = \pi_{\theta}(a|s)\frac{\nabla \pi_{\theta}(a|s)}{\pi_{\theta}(a|s)}=\pi_{\theta}(a|s)\nabla {\rm log}\pi_{\theta}(a|s)

これを用いると、\nabla J(\theta)は期待値として以下のように表現することができます。

\nabla J(\theta) \propto E_{\pi\theta}(\nabla {\rm log} \pi_{\theta}(a|s)Q^{\pi\theta}(s, a))

お疲れさまでした!この微分値をもとに行動確率\pi(a|s, \theta)のパラメータを更新することで、報酬を最大化するような行動確率が得られる目途が立ちました。以下では、これを実装する際のワークフローを確認してみましょう。

学習のワークフロー

おさらい

ここから読み始める人のために、もう一度整理しておきましょう。私たちは、エージェントが得る報酬の期待値を最大化するような行動確率\pi(a|s, \theta)が欲しいのでした。そのためにパラメータ\thetaを持つニューラルネットワークで行動確率を表現し、パラメータを \theta_{t+1} = \theta_{t} + \alpha\nabla J(\theta)によって更新することにしました。報酬の期待値に相当する目的関数J(\theta)の微分値は以下のように表されることを学びました。

\nabla J(\theta) \propto E_{\pi\theta}(\nabla {\rm log} \pi_{\theta}(a|s)Q^{\pi\theta}(s, a))

これを計算することで、報酬を最大化するような行動確率が得られるというのが方策勾配法の概要です。余談ですが、私は最初この式を見て面喰らいました。ニューラルネットワークといったら予測値と正解値の差分で損失関数を定義し、それを最小化するようにパラメータを最適化すると思い込んでいたからです。しかしここでは、行動確率は直接使わずに報酬を目的変数としてネットワークのパラメータを最適化しています。このような間接的な方法もあるのだということを初めて学びました。

ワークフロー

さて、これを実装する際には以下のようなワークフローに従うことになります。1エピソードごとに指定したサイズの学習データが溜まるまでエージェントが環境に対して働きかけます。(状態、行動、報酬、次の状態)を経験としてメモリに保持しておき、それを用いて学習を行います。これをエピソードの数だけ繰り返します。

f:id:Dajiro:20200519170236p:plain
方策勾配法のワークフロー。

方策勾配法による学習の実施

ワークフローは複雑ですが、方策勾配法を用いるのは最後のニューラルネットワークによる学習部分だけです。学習には\nabla J(\theta)の計算が必要になりますが、ここが方策勾配法を実装する上での難所でしょう。ポイントは3つあり、価値の計算(Q^{\pi\theta}(s, a))、行動確率の計算(\pi_{\theta}(a|s))、そして勾配の計算です(\nabla J(\theta))。これらの計算に、学習データを活用します。

1.価値の計算

価値の見積にはモンテカルロ法を採用します。エージェントが実際に行動して得られた報酬を元に、エピソード終了時点での各状態の割引価値を以下の式に従って計算します。

 G = r_{t+1} + \gamma r_{t+2} + ・・・ +\gamma^{T-1}r_{T}

 r_{n} は報酬で、蓄積した学習データから読み込みます。ここで計算されるGが上の\nabla J(\theta)の表式に出てくるQ^{\pi\theta}(s, a)に対応しています。

2.行動確率の計算

これは、実際にその行動が選択された確率を意味しています。上のワークフローで経験を蓄積する際に行動を記憶しますが(配列としてメモリに格納するということ)、ここで取り出して\pi_{\theta}(a|s)に代入します。

3.勾配の計算

Kerasなどの機械学習フレームワークを活用し、[状態、行動、割引報酬]を入力、J(\theta)を出力とする目的関数を定義してニューラルネットワークのパラメータを最適化します。平均自乗誤差などを使ったニューラルネットワークの学習方法と異なるのでしっくりこないかもしれません。この辺の巧みな実装方法は以下のテキストに記載されているのでぜひ読んでみてください。非常に参考になります。

このようにして、得られた経験(学習データ)をもとに行動確率を予測するニューラルネットワークの学習を行います。これをエピソードの数だけ繰り返すことで、報酬を最大化させられる行動確率が得られるというのが方策勾配法の一連の流れになります。かなり複雑な技術ですが、よくよく勉強してみるとモンテカルロ法やニューラルネットワークなどの既に知っている技術の集積によって成り立っていることが分かります(よくもまぁ巧みに組み合わせたと感心してしまいますが)。
方策勾配法を用いた応用は非常に多く、ゲームはもちろんのこと最適な物性を持った化合物の生成などにも活用されています。学習が安定化しづらいという問題もあるようですが、メリットも大きいため確実にモノにしておきたい技術の一つです。