【論文読み】Large-Scale Study of Curiosity-Driven Learning

pathak22.github.io

Summary

この前の論文(Curiosity-Driven Learning)の続きみたいな感じの論文。特に外的報酬を全く利用しない場合に焦点を当て、内的な報酬のみでどれだけタスクをこなせるか・どんな挙動が観察されるかについて広範囲の実験を行なったもの。基本的に提案手法はこの前のものと同じなので数式・新しい概念はあまり出てきません。

結果についての動画が論文のランディングページ(?)に挙がっています。

Experiments

Environments

実験対象の環境(ゲーム)一覧

Feature Learning Methods

前の論文ではstateの特徴を抽出するモジュールとして、状態 s_t s_{t+1}からその差分の行動 a_tを計算するInverse Model(この論文ではIDF: Inverse Dynamics Featureと呼んでいます)を用いていたが、今回の実験ではそれに加えて

  • Pixels: 生のピクセルデータ
  • RF: Random Feature (単にランダムに初期化したネットワークでマッピング)
  • VAE: Variational Auto Encoder *4

を使って比較検証を行なった。これらはどれも a_t s_{t+1}は使わず、単純に s_tの特徴量を1対1で写像しているだけのもの。

これらの特徴抽出モデルを検討にするにあたり、以下の3要素が重要になると述べられている。

  • Compact: 状態の特徴量をどれだけコンパクトに(低次元に)圧縮できているか
  • Sufficient: 状態を表す十分な情報が保存されているか
  • Stable: 特徴量が学習中にどれだけ安定しているか。探索と並行して学習していくVAEやIDFはこの要因により学習が不安定になる可能性がある

f:id:ey_nosukeru:20190509172355p:plain:w400
特徴抽出モデルの3要素を比較した表

比較対象の4つのモデルについてそれぞれ軽くまとめ。

  • Pixels: 全ての情報を含んでいるのでSufficientで変換がないのでStableだが、無圧縮なのでCompactでない
  • RF: CompactかつStableだが、ランダムな写像なので十分な特徴を含んでいない可能性がある
  • VAE: Compact、元の状態を復元できるように学習するのでSufficientだが、学習が必要なのでStableでない
  • IDF: Compactだが、行動を予測するよう訓練するので状態に関してはSufficientでない可能性がある、Stableでない

Practical Considerations

学習にあたって行なったより具体的な調整。特徴量をいかに安定させるか(数値のスケール・分布を一定に保てるか)が、学習全体を安定化する上で非常に重要になるとのこと。

PPO*5

提案手法は内的報酬を計算する部分のみに関するものなので、Policyのアルゴリズムには自由度がある。ハイパーパラメータ*6の少なさや頑健性から実験では一貫してPPOを用いる。

Reward normalization

現在の報酬*7標準偏差で正規化することでスケールを安定化

Advantage normalization

PPOにおけるAdvantage( Q - V)を平均0, 標準偏差1に正規化

Observation normalization

状態の正規化。あらかじめエージェントを10000ステップほど走らせ、そこで得られた状態を元に正規化を行う

Feature normalization

特徴抽出部分にBatch Normalizationを使って特徴量を正規化

More actors

PPOではエージェントを並列で走らせるが、その数が増えるほどより学習が安定したとのこと (バッチサイズと同じイメージで捉えると良いかと思います)

正規化や細かい前処理がいかに大事かを思い知らされ、とても参考になります。

"Death is not the end"

探索の段階ではゲームオーバーをエピソードの終了など特別なシグナルとは見なさず、「初期状態への遷移」という単純な状態遷移とみなす。特別な処理を行わなくても、初期状態というのは何回も見る「退屈な」状態であり、好奇心がうまく働いて勝手に回避されるようになる。

言われてみれば確かに人間でも同じような心理が働いている気がして興味深いポイントです。

Results

Atari & Mario

まず外的報酬を全く使わない条件でAtari/Marioを学習させた結果。

f:id:ey_nosukeru:20190509180732p:plain
Atari/Marioでの特徴抽出モデルの比較結果

Pixelsは予想通りどのタスクでも性能が低い。その他の3つはタスクによってブレがあるが、概ね同じくらいの結果になっている。VAEは他に比べても比較的うまくいっているように見えますが、「なんとなく不安定(somewhat unstable)」であり、これ以降の検証からは外されてしまいます。

完全にランダムなエージェントに対しIDFは75%のゲームで、RFは70%のゲームでより多くの報酬を獲得したとのこと。IDFとRFの比較ではIDFが55%で勝利。しかしMontezunaRevengeのように内的報酬だけではうまくいかないゲームもあったそう。

興味深いのがRFの性能で、ランダムに特徴抽出しただけなのにIDFに匹敵する性能を叩き出している。理由としては比較的ゲームが単純でありそもそもの状態の情報量が少ないこと、特徴量の安定性が学習を進める上で非常に重要でありRFはその点においてIDFより有利であることなどが挙げられる。

報酬(つまりゲームの目的)を全く与えず、多くのゲームにおいてエージェントが好奇心だけでクリアすることができた、というのは驚くべき結果です。これに対するやや否定的な見方としては、「洗練されたゲームはユーザーの好奇心がゲームと目的と一致するように作られている」という点が挙げられます。人工知能によってゲームの本質が浮かび上がるというのもなかなか興味深いですね。

またMarioでは前の論文での実験に比べ100倍(!)の時間をかけることで、11ステージものクリアを達成することができたとのこと。より多くのエージェントを並列で学習させたことで学習の安定性が向上したことが一因として考えられます。

f:id:ey_nosukeru:20190509184136p:plain:w400
並列エージェント数での比較(Mario)

Roboschool

ゲームの設定がよくわからなかったので動画のスクリーンショットだけ載せておきます。

f:id:ey_nosukeru:20190509191650p:plain:w400
┌(┌ ^o^)┐

Multi-agent curiosity in Two-player Pong

2人ピンポンでどちらもCuriosity-drivenなエージェントにしたら何が起きるか。ラリーの長さを測ったところ順調に伸びていき、ついにはゲームが崩壊して反応しなくなってしまった(笑)とのことです。

f:id:ey_nosukeru:20190509184021p:plain:w400
ピンポンのラリー数。途中でゲームがバグったのでそれ以降の数値は無意味

Skill Generalization

Marioにおいて、検証するステージを変えることでステージ依存でない一般的なプレイテクニックが獲得されたかを検証する実験。ステージ1-1であらかじめ訓練したエージェントを他のステージ(1-2/1-3)で転移学習させ、1から学習するよりも効率的に学習が進むかを調査した。

f:id:ey_nosukeru:20190509185043p:plain:w600
転移学習によるエージェントの性能比較

RFよりIDFの方が汎用スキルの獲得ではうまくいっているように見える。右側は背景色が変更され、難易度も格段に上がるため1-2に比べて苦戦しているが、1-1で獲得されたスキルが探索において役立っている証拠が(プレイの様子を観察結果から?)確認できた。

Unity Maze

Unity ML-agentsのMazeでも検証。ここでは目的地に着いたら+1、他には報酬を与えない非常にスパースな報酬のみを与えたが、好奇心による探索でうまく迷路をクリアすることができた。

f:id:ey_nosukeru:20190509185704p:plain:w450
Mazeにおける学習経過。外的報酬のみでは全くクリアできていないことに注目

Discussion

今回の実験では少なくとも、「好奇心がプレイヤーを自然と目的に導くような」人間が設計したゲームでは学習がうまく行くことを確認できた。

しかし、ゲームにランダムな要因が含まれている場合、常に予測誤差が発生するため学習がうまくいかない可能性がある。例えばMazeにおいて迷路内にランダムな動画を放映する巨大なスクリーンを設置したところ、そこに気を取られて学習が止まってしまうという現象が見られた。

f:id:ey_nosukeru:20190509191757p:plain:w300
迷路内に設置された巨大スクリーン

f:id:ey_nosukeru:20190509190124p:plain:w450
MazeにTVを設置すると学習がうまくいかなくなる

今後の研究ではこの問題を解決し、現在人手による報酬が確立されていない(unlabeled)環境での探索を、より高次元なタスクの遂行に役立てることができないかを一つの大きな目標としたいと述べられている。

感想

外的報酬を全く使わずにこれだけのパフォーマンスが学習されるというのは驚くべき結果だと思います。 筆者も述べているようにこれまで人手の報酬が確立されず研究が進んでこなかった分野についての発展が期待されます。また最後のTVの例など、人間の子供と同じような挙動が観察されているのも非常に興味深い点だと思います。

最後の確率的要因への対応というと確率的モデルを取り込んだネットワークなどが使われていくのでしょうか。関連する話題としてWeight Uncertainty in Neural Networksも読んだので近いうちに投稿したいと思います。

最後までお読み頂きありがとうございました。

*1:コンソールゲームが色々入ったゲームセット。強化学習界隈の標準的なベンチマークになっています。OpenAI Gymで簡単にPythonからプレイできます。

*2:https://github.com/Unity-Technologies/ml-agents

*3:こちらもOpenAI Gymからプレイできるようです。

*4:通常のオートエンコーダーの中間層を確率モデル化し、標準ガウス分布に近づけるような制約をつけたもの

*5:参考: https://towardsdatascience.com/proximal-policy-optimization-ppo-with-sonic-the-hedgehog-2-and-3-c9c21dbed5e

*6:学習で変化しない、手動で与えるパラメータ

*7:並行して動かしているエージェント全体での報酬という意味だと思われます

DgraphのORマッパー"graphor"を作りました

こんにちは。nosukeruと申します。

趣味(?)でやっているアプリ開発の方で、バックエンドをGoとDgraphというグラフデータベース(https://dgraph.io/)を使って構築しているのですが、如何せんDgraphが新しいサービスなために日本語文献が少なく、またライブラリもあまり充実していない状況で、Go公式のDgraphクライアントも素のGraphQL+-*1を書いて投げるものしかなかったので、自分でGo用のORM(Object Relational Mapper)を実装してみました。PHPのLaravelを以前触ったことがあったので大部分を参考にして仕様などを決めました。

元々は自分用に使うつもりしかなかったのですがせっかく作って置いておくのももったいないので公開しようと思います。もしグラフデータベース、Dgraphに興味がある方がいましたらぜひフィードバック等頂ければ大変助かります。Issue/PRも歓迎です。

github.com

(注意)現在まだベータ版です。特にセキュリティ面(QLインジェクション)には不安があるので使用の際はご注意ください。

以下おまけ(開発で感じたこと)

  • Goのインターフェース・モデル管理が難しい。Modelというインターフェースで統一的に扱えるようにしつつSave()などのモデル共通の機能をどうやって実装するかに相当悩んだ。結局Modelインターフェースとそれを実装するModelPropertyを定義して、ユーザー定義のモデルにModelPropertyを組み込んでもらうことで実現した。ただクエリ結果をそれぞれのモデルにキャストする部分はジェネリクスなしでは厳しく、クエリ結果をそれぞれのモデルとして取得するAsUser()AsUsers()をユーザーに定義してもらうしかなさそうという結論になった。

  • エラー処理がめんどくさい。データベースにクエリ投げるたびにエラーが発生しうるので実行系は結局全部エラーが返り値についてくる。panic("DataBaseError")したい気持ちをグッとこらえて頑張ってエラー処理を書いた。ただエラーの粒度をどの程度にしたらいいのかよくわからなかった。

  • QueryとRelationにQueryBuilderとしての共通の処理を持たせるところはinterfaceとstructを使い分けてうまく書けたと思う。やったぜ。

  • シングルトン(graphorInterface)をどのように外部に公開したらいいのかがわからなくて、結局 1. graphorInterfaceを定義 2. 準拠するgraphorStructを定義 3. NewGraphor()で作成したgraphorInterfaceをパッケージ変数としてもつ というよくわからん実装になった。もうちょっとスマートな実装法がないか考えたい。

  • ORMを実装したことでQuery Languageへの理解が嫌というほど身につきました。SQL文わからないよお><って方はぜひ一度自分でORMを実装してみましょう!(崖から突き落として生き残った奴を選別するタイプのオタク)

*1:SQLに当たるデータベース言語

【強化学習入門】PolicyGradientでOpenAI GymのCartPoleをクリアする

こんにちは。nosukeruです。

今回は強化学習アルゴリズムを実際に実装し、この分野で一般的なベンチマークとして用いられるOpenAI Gymを使って遊んでみました。

コードはここに置いています(今後も追加予定)。深層学習のライブラリにはPyTorchを使っています。

github.com

Introduction to RL

強化学習ではエージェントがある環境下に置かれた状態で、環境とのやりとりを行いながら状況に応じた良い行動を習得することを目指します。時刻 tにおけるエージェントの状態(state)*1 s_t \in S、そこでエージェントが取る行動(action) a_t \in Aと表します。*2

エージェントが行動を起こすことにより環境とのやりとりが行われ、エージェントの状態が s_{t+1}に変化するとともに、報酬(reward)  r_t \in Rを得ることができます。報酬は正とは限らず、負の場合にはペナルティとみなすことができます。このプロセスを繰り返してエージェントはゲームを進めていきます。

f:id:ey_nosukeru:20190504104131p:plain:w360
エージェントと環境の関係. 引用元: http://ainow.ai/2016/11/07/104056/

エージェントの目的はこの報酬の和を最大化することなのですが、単純な和を取るだけだと行動を先送りにして「明日から本気出す」的なダメダメエージェントができてしまうことが考えられるので、割引率 \gammaを導入し、近い将来の報酬により大きな価値を与える重み付け和が用いられることが多いです。

\begin{align} R = \sum _ {t=0} ^ {\infty} \gamma ^ t \end{align}

エージェントはこの報酬を最大化するため、自身の置かれている状態に対して適切な行動 a_tを選択する必要があります。この基準となるのが方策(policy)  \pi(s, a) = P(a|s)で、状態sのもとで行動aを取る確率を表します。環境の状態遷移も確率的に定義されていることが多く、また確率的な方策の方がより幅広い戦略を取ることが可能になるため、このように確率的に定義しています。

その他、状態 sで行動 aを取った時次の状態 s'に遷移する環境の確率を P _ {s s'} ^ {a}と書き、状態や行動の潜在的な価値を表すものとして

\begin{align} Q ^ {\pi} (s, a) &= r + \gamma E _ {s' \sim P _ {s s'} ^ {a}} [V ^ {\pi} (s')] = r + \gamma \sum _ {s'} P _ {s s'} ^ {a} V ^ {\pi} (s') \\ V ^ {\pi} (s) &= E _ {a \sim \pi(s) } [Q ^ {\pi} (s, a)] = \sum _ {a} \pi (s, a) Q ^ {\pi} (s, a) \end{align}

を定義します。これらは価値関数(Value Function)と呼ばれ、方策 \piに従って行動した時に現在の状態や行動によってどれくらいの将来的な報酬が見込めるかというのを表しています。

Policy Gradient

強化学習の手法は、大きく次の2つに分けられます。

価値反復法(Value-Based Algorithm)

価値関数をモデル化し、 Q(s, a)を最大化するような行動 aを選ぶ方法

方策勾配法(Policy-Gradient Algorithm)

方策をモデル化し、報酬に対する方策の勾配を使って最適化する方法

今回は後者の方策勾配法を用います。価値反復法に比べると学習が遅いというデメリットがありますが、学習が安定している、確率的な振る舞いを取り込めるなどのメリットも多くあります。

PolicyGradientでは方策 \piをパラメータ \thetaでパラメータ化します。つまりパラメータ \thetaを持つモデルで表現しようということです。勾配やパラメータ最適化と聞くとニューラルネットが思い浮かベる人が多いと思いますが、今回の実装でも例に漏れずニューラルネットを用います。勾配を自動で計算してくれるのはやはり大きなポイントですね。

問題の目的は報酬の最大化なので、目的関数は

\begin{align} J(\theta) = V ^ {\pi} (s) = E _ {a \sim \pi(s; \theta)} [Q ^ {\pi} (s, a)] \end{align}

となります。 *3 この関数を最大にするように方策 \piもといパラメータ \thetaを最適化します。

目的関数が設定できたので、とりあえず微分してみます。

\begin{align} \frac{\partial J} {\partial \theta} &= \frac{\partial} {\partial \theta} E _ {a \sim \pi(s; \theta)} [Q ^ {\pi} (s, a)] \\ &= \frac{\partial} {\partial \theta} \sum _ {a} \pi (s, a; \theta) Q ^ {\pi} (s, a) \\ &= \sum _ {a} (\frac{\partial} {\partial \theta} \pi (s, a; \theta)) Q ^ {\pi} (s, a) \end{align}

ここで、 \piに関してサンプリングを行いたいので、 \pi \times (何か)という形にしたいです。そこで対数微分の式

\begin{align} \frac{\partial} {\partial \theta} (\ln f) = \frac{1}{f} \frac{\partial f} {\partial \theta} \iff \frac{\partial f} {\partial \theta} = f \frac{\partial} {\partial \theta} (\ln f) \end{align}

を使うと、

\begin{align} \frac{\partial J} {\partial \theta} &= \sum _ {a} \pi (s, a; \theta) (\frac{\partial} {\partial \theta} \ln \pi (s, a; \theta)) Q ^ {\pi} (s, a) \\ &= E_ {a \sim \pi (s; \theta)} [(\frac{\partial} {\partial \theta} \ln \pi (s, a; \theta)) Q ^ {\pi} (s, a)] \\ &\simeq \frac{1}{N} \sum _ {a \sim \pi (s; \theta)} (\frac{\partial} {\partial \theta} \ln \pi (s, a; \theta)) Q ^ {\pi} (s, a) \end{align}

となり、状態 aに対して現在の方策に基づいて aをサンプリングし、中の式を評価して平均を求めることで目的関数の勾配を得ることができました。実装上はさらに、

\begin{align} (\frac{\partial} {\partial \theta} \ln \pi (s, a; \theta)) Q ^ {\pi} (s, a) = \frac{\partial} {\partial \theta} (\ln \pi (s, a; \theta) Q ^ {\pi} (s, a)) \end{align}

なので、誤差関数を L = - \ln \pi (s, a; \theta) Q ^ {\pi} (s, a)とおけば普通の教師あり学習と同じように学習させることができます。誤差が最小化なのに対し今回の問題は報酬の最大化なのでマイナスをつける必要があることに注意です。

最後に「価値関数 Qが計算できない」というあまりにも重大な問題が残っているのですが、一番ナイーブなPolicyGradientの実装ではこれをなんと1回のエピソード*4で得られた実際の報酬で近似してしまうという豪快な解決法をとります。一応 Qは考えられる全ての状態遷移列に対して報酬和の平均を取ったものなので、試行回数1のサンプリング・精度の荒い近似という形で正当化することはできそうです。

ちなみに、Actor-Critic系のアルゴリズムは、この Q関数の近似部分にValue-Basedな手法を取り入れることで、より近似精度を挙げて効率的に学習されるようにしたハイブリッド型のアルゴリズムです。

さて、以上をまとめると、PolicyGradientのアルゴリズムは次のようになります。

  1. 現在の方策 \pi(s, a; \theta)に基づいて行動し、状態・行動・報酬の列 \tau = (s_0, a_0, r_0), (s_1, a_1, r_1), ..., (s_n, a_n, r_n)を得る。

  2.  \tauのそれぞれについて、その状態以降の報酬和 R = \sum _ {t'=t} ^ {n} \gamma ^ {t' - t} r_{t'} \pi(s_0, a_0; \theta)から誤差 Lを計算( Q Rで近似)。

  3.  Lをもとにモデルを学習、 \thetaを更新。

  4. 1~3を繰り返す。

3の学習のタイミングには1回ステップごと/1エピソードごと/複数エピソードごと など任意性がありますが、今回は1エピソードごとに誤差を足し合わせて重みを更新するようにしました。

CartPole

OpenAI Gymには環境として様々なゲームが用意されていますが、今回扱うゲームは一番シンプルなCartPoleというゲームです。幼少期誰でも一度はやったであろう、手のひらの上でほうきを立てた状態をどれくらいの間キープできるかというあれです。友達の中に一人は暇を持て余してこのゲームを極め、悟りの境地に入った状態で永遠にやってる奴がいるあれです。

https://i.gyazo.com/2f212b0440a51a293f502d9bf0505ba6.gif

このゲームの目的は車を左右に動かしながら出来るだけ長い間棒を立った状態でキープすることになります。棒が右に倒れそうになったら車も右に移動し、といった具合にバランスを保つのが重要になります。棒と地面の角度が一定以下になったり、画面外に出てしまったりするとゲームオーバーとなります。

エージェントの取れる行動としては「車を左に動かす」「車を右に動かす」の2つしかなく、とてもシンプルです。

また、状態(観測)としては4つの数字からなる配列が与えられます。これらはそれぞれ車の位置、車の速度、棒の角度、棒の角速度を表しているそうです。

なお、実装上はこれらの数値・行動の意味を知る必要はありません。優れた強化学習アルゴリズムは、事前知識を一切必要とすることなく、環境とのやりとりの中で物理法則なども含めたゲームの仕組みを学習することができます。

報酬としては、出来るだけ長い間ゲームオーバーにならないことが目的なので、1回アクションを起こすごとに一定値1の報酬が与えられ、プレイ時間がそのまま報酬になります。なお、CartPole-v0では200フレーム、CartPole-v1では500フレーム維持できれば自動的にクリアとなり、ゲームが終了します。

Implementation

コードの主要な部分だけ抜き出しています。全体はレポジトリを参照してください。

モデルの定義

class PolicyNet(nn.Module):
    def __init__(self, nInput: int, nHidden: int, nOutput: int):
        super(PolicyNet, self).__init__()
        self.fc1 = nn.Linear(nInput, nHidden)
        self.fc2 = nn.Linear(nHidden, nOutput)

    def forward(self, x):
        l1 = F.relu(self.fc1(x))
        return F.softmax(self.fc2(l1), dim=1)

学習

    env = gym.make('CartPole-v1')
    policyNet = policy.PolicyNet(nState, 20, nAction)
    optimizer = optim.Adam(policyNet.parameters())

    for episode in range(nEpisode):
        state = env.reset()
        steps: List[Step] = [] # step info for calculating loss

        # Exploration loop
        done = False
        while not done:
            env.render()

            # Make decision
            x = Variable(torch.Tensor([state]))
            probs = policyNet(x)

            action = np.random.choice(range(nAction), p=probs.detach().numpy()[0])
            nextState, reward, done, _ = env.step(action)

            steps.append(Step(probs[0][action], reward))
            state = nextState

        # Training
        loss = Variable(torch.tensor(1, dtype=torch.float32))
        for i, step in enumerate(steps):
            reward = sum([(gamma ** j) * s.reward for j, s in enumerate(steps[i:])])
            loss += -torch.log(step.confidence) * reward

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

GymとPyTorchの基本的な機能だけを使って上のアルゴリズムをシンプルに実装することができました。

Results

学習初期(~100epoch)

https://i.gyazo.com/88ca85a2a60e34da4b2d448eff481db2.gif

まだ仕組みをうまく学習できておらずすぐにゲームオーバーになってしまい、かくついて見えます。

学習中期(~500epoch)

https://i.gyazo.com/c0e668598dcf71ca156784ef8800a00d.gif

かなりうまくなってきましたが棒を立てたまま画面外に飛んで行ってしまうパターンが多い印象です。

学習末期(~3000epoch)

https://i.gyazo.com/a1d2c0e044f655b89255053079ff6a41.gif

かなりの割合でクリアできるようになってきました。

学習グラフ

f:id:ey_nosukeru:20190504145857p:plain
訓練回数(エピソード)とその報酬

f:id:ey_nosukeru:20190504145811p:plain
直近100エピソードの報酬平均と標準偏差

前半は順調に学習が進んでおり、後半は目に見えてクリアの回数が増えていることもわかりますが、依然として低スコアで終わってしまう場合があり、分散は高いままです。この分散が高くなりやすいという性質はPolicyGradientの欠点の一つであり、 Q関数を1回のサンプリング値で大雑把に近似していることに起因しているのですが、Actor-Critic系の派生アルゴリズムで改善されていくことになります。

おわりに

今回はGymの中でも一番簡単なCartPoleを使いましたが、今後もDQN/Actor-Critic/PPO/Curiosity-Learningなど近年の強化学習の手法を勉強しつつ、より難易度の高いゲームにもチャレンジしていきたいと思います。

最後までお読み頂きありがとうございました。

参考文献

Gym

OpenAI Gymの公式チュートリアル。これだけでGymの基本的な使い方は大体わかります。

ライトニングpytorch入門 - Qiita

ライトニングにPyTorch入門できます。

An introduction to Policy Gradients with Cartpole and Doom

英語ですが、近年の強化学習の手法を一通り学ぶことができ、とてもわかりやすいです。

強化学習入門 Part2 - TensorflowとKerasとOpenAI GymでPolicy Gradientを実装してみよう! - Platinum Data Blog by BrainPad

実装上でかなり参考にさせて頂きました。

https://papers.nips.cc/paper/1713-policy-gradient-methods-for-reinforcement-learning-with-function-approximation.pdf

PolicyGradientの元論文です。

*1:観測(observation)と呼ばれることもあります。

*2: A s_tに依存すると考えることもできますが、ここではどの状態でも取れる行動は一定であるとします。

*3:スタートとゴールが明確に決まるゲームだと s_0の方が適切なようにも思えますが、状態を限定してしまうよりもあらゆる状態に対してパフォーマンスを上げるようにした方が効率よく訓練できるので、この定義を採用することにします。またこの式ではsが束縛されておらず、厳密に書くと sに関する期待値を取らなければいけませんが、 sの分布を考えると複雑になってしまう( sの分布が \piに依存しているなど)ので、ここでは「 \piに従って現れる sに対して平均的に J(\theta)を最適化する」ぐらいのニュアンスで捉えてもらえれば良いかと思います。厳密な証明については元論文を参照。

*4:ゲームオーバーまでの1回のプレイ

【論文読み】Curiosity-driven Exploration by Self-supervised Prediction

次の論文を読んだので内容をまとめます。

pathak22.github.io

Summary

強化学習においてはエージェントに目的を認識させ、正しく学習を進めさせるために報酬(reward)が必要になる。この報酬は通常人間が手動で与える必要があるが、好奇心(curiosity)という形で自発的な報酬を導入することで、人間が報酬を与えることなくエージェントが正しく学習を進め、ロバストなプレイスキルを習得することができることを確認した。

Background

強化学習では与えられる報酬を元に、得られる報酬の合計(行動価値)が最大になるような行動の指針(方策, policy)を探索することが学習の目的になる。ここでの報酬について、大規模な問題を扱う上で次のような問題点が発生する。

  • 通常報酬は非常に疎(sparse)なものになる。例えば多くのゲームではゴールに到達する、敵を倒す、ブロックを破壊するなど特定の達成条件に応じて報酬が設定されるが、それ以外の行動については良い行動なのかどうかが判定しづらく、通常0になる。
  • 人間が手動で与える必要があり、エージェントを正しく目的に導くような密(dense)な報酬を与えるのは自明ではない。

エージェントが内的な報酬によって能動的に探索を行うことが可能になれば、人間が明示的に報酬を与える必要がなくなり(もしくは、主要な達成条件に対する疎な報酬だけで済む)、大規模な問題に対しても強化学習的なアプローチを適応することが可能になる。

Proposed Method

人間にとって行動のモチベーションの一つになるのが好奇心である。この好奇心を強化学習のタスク上で定式化し、うまくエージェントに組み込んだのが今回の論文のポイント。

鍵となるのは、好奇心を「エージェントにとっての結果の予測のしづらさ」と定義したところ。具体的には、状態 s_tにおける行動 a_tに対する報酬を、その結果としての遷移先 s_{t+1}の予測と実際の遷移先との誤差によって定義する。

ただし、素の状態そのものを予測し、その誤差を用いるのはいい方法とは言えない。例えば最新の強化学習ではゲーム画面そのものの数フレームを状態として用いてCNNに突っ込むことが多いが、木が風に揺られている時の1つ1つの葉っぱの動きを人間が予測することが難しいように、ゲーム内のピクセルそれぞれを予測することは難しく、またそれを予測することに大きな意味はない。そこでエージェントが注目すべき要素を

  • エージェントがコントロール可能な要因
  • エージェントに影響を与えうる要因

の2つに絞り、この要素のみを素の状態から特徴量として抽出する。この論文では、エージェントの行動に関係する要素のみを状態から抽出する方法として、状態 s _ t , s _ {t+1}を入力として、その差分の行動 a_tを予測するような逆推定(inverse)モデルを訓練することで、その中間層に本質的な特徴が学習されるとしている。この特徴 \phi (s_t) a_tを元に \phi (s_{t+1})を正予測(forward)モデルで予測し、その誤差を報酬 r^ i_tとする(iはintrinsic、内的報酬であることを表している)。

まとめると、報酬としての好奇心を計算する手順は次のようになる。

  1. 探索により状態 s_tと行動 a_t、その結果としての状態 s_{t+1}の組を得る。
  2.  s_t s _ {t+1}から a_tを予測するinverse modelを訓練し、その中間ベクトル \phi (s_t), \phi (s_{t+1})を状態の特徴として用いる。
  3.  \phi (s_t), a_tを入力としてforward modelに与え、遷移先の状態の特徴量の予測値 \hat{\phi} (s_{t+1})を得る。
  4.  \hat{\phi} (s _ {t+1}) \phi (s_{t+1})の二乗誤差を報酬 r^ i_tとして計算する。
  5. 内的報酬 r^ i_tと通常の外的報酬 r^ e_tを合計した r_t = r^ i_t + r^ e_tを最終的な報酬とし、従来の手法(DQN, A2C/A3C, PPOなど)を用いて方策決定を行う。

これを表したのが次の図。本論文では好奇心を計算する一連のモジュールをICM(Intrinsic Curiosity Module)と呼んでいる。

f:id:ey_nosukeru:20190502133719p:plain
報酬計算と行動決定を含む全体の構成図

Evaluation

性能比較

f:id:ey_nosukeru:20190502134441p:plain
迷路ゲームでの性能比較。右に行くほどゴールが遠く、外的報酬がより疎になるが、提案手法はそのような条件でも正しく学習できている。
f:id:ey_nosukeru:20190502134747p:plain
ホワイトノイズを入れた画面状態に対する頑健性の検証

汎化性能(generalization)の比較

f:id:ey_nosukeru:20190502135020p:plain
マリオを用いた検証で別のステージにおいてもfine-tuningを行うことで1から学習するよりも早く高い性能を発揮できている。
f:id:ey_nosukeru:20190502135336p:plain
一部fine-tuningが失敗しているが、一般的なゲームスキルを習得できていることが確認できる。

Discussion

curiosityによって自発的に学習するエージェントを構成できることを確認した。今回の検証のようにステージを変えて汎化性能を調べることは重要。 Future workとしてゲームで習得した一般的なスキル(壁にぶつからず歩くなど)を他のタスクに応用することなどが考えられる。環境とのインタラクションが限定されているような場合(環境の変化の少ない場合?)の調査は今後の課題。

感想

多くの報酬を与えることなく自発的に学習できるエージェントということで、いよいよ人間に近いAIの開発が現実味を帯びてきたように感じて非常にワクワクする論文でした。提案手法についてもなぜ今までなかったのかと思うほどシンプルで、洗練されている印象を受けました。

一点、せっかくICMで学習した状態の特徴を行動決定で使わず、わざわざ別のモデルを用いて素の状態から計算を行なっている点が気になりました。今後ICMの状態特徴量を方策に用いるようなモデルも出てくるかも?

今後の展開として、報酬の定義が難しい会話エージェントのような分野でも、Curiosity-Basedな手法は広く用いられていくのではないでしょうか。人間の赤ちゃんと同じように会話を繰り返しながら少しずつ会話できるようになっていくエージェントを作るのも夢ではないように思います。今後ともぜひ注目していきたいホットな分野になりそうです。

最後に

こういう記事を書くのは初めてなので何か疑問点・ご指摘などあればぜひお願いします。最後までお読み頂きありがとうございました。

はじめましてのごあいさつ

はじめに

初めまして。京都でエンジニアをしているnosukeruと申します。

普段の開発におけるアウトプットの場としてこのブログを開設しました。開発や研究で躓いたこと、興味を持ったことのメモ書きになるかと思います。少しでも有意義な情報を発信できるよう努めていきたいと思います。

やってること・やりたいこと

バックエンド・インフラ関連

仕事の関連で

といった環境で開発をさせてもらっています。DDDライクな設計を考える上で悩むことが多いのでDDD関連の記事が多くなるかもしれません。インフラ系も勉強中の身なので躓いたことを中心にメモしていきます。

SwiftでのiOS開発

コードベースなiOSの開発もちょくちょくやっています。Swift関連で調べてもストーリーボードを使う例がほとんどで困ることが多いのでコードベースな開発の一助になる情報を発信できればと思います。

機械学習関連の研究

知能情報系の研究室で研究をしています。強化学習、GAN、ベイズ推定など中心に読んだ論文や研究内容について共有していきたいです。

デザイン

全くの初心者なのですが最近興味を持ち始めました。CocodaDailyUIなどに挑戦してみたいと思っています。

こんな感じの内容で更新していければいいな〜と思っています。よろしくお願いします。