どこから見てもメンダコ

軟体動物門頭足綱八腕類メンダコ科

CMA-ES(共分散行列適応進化戦略)の Python実装

実用性の高いブラックボックス最適化手法 CMA-ES(共分散行列適応進化戦略) のpython実装例を簡単なアルゴリズム解説とともに紹介します。

f:id:horomary:20210117213110g:plain:w400f:id:horomary:20210117224720p:plain:w400


はじめに

CMA-ESは連続最適化問題におけるブラックボックス最適化手法のひとつです。ブラックボックス最適化、すなわち最適化したい関数の中身がまったくわからなくてもOKなので極論どんな問題にでも適用可能で、確率的な探索を行うアルゴリズムであることから観測ノイズに強い上に、調整の難しいハイパーパラメータが存在しないので現実の問題に適用しやすい優秀な手法です。

本記事ではCMA-ESの考案者であるHansen氏らが2016年に執筆したCMA-ESのチュートリアル論文([1604.00772] The CMA Evolution Strategy: A Tutorial)に従ってPythonでの実装を行います。基本的にどう実装するかの解説がメインの記事ですので、アルゴリズムの理論的詳細についてはチュートリアル論文をご参照ください。

参考文献・実装

[1604.00772] The CMA Evolution Strategy: A Tutorial

http://www2.fiit.stuba.sk/~kvasnicka/Seminar_of_AI/Hansen_tutorial.pdf

The CMA Evolution Strategy

Evolution Strategies による連続最適化

deap/cma.py at master · DEAP/deap · GitHub

Evolution strategies - Scholarpedia

CMA-ES - Wikipedia


アルゴリズム概要

CMA-ESのアルゴリズムをざっくりと示すと下記のようになります。

1. 多変量正規分布 σN(m, C) に従ってλ個体を生成し、各個体の適合度(目的関数の値)を算出する
2. 生成したλ個体のうち目的関数の値が上位μ個体を抽出する
3. μ個体のパラメータと進化パスpσ, pcに基づいて多変量正規分布のパラメータ m、σ、C を更新する
4. 値が収束するまで1-3を繰り返す

f:id:horomary:20210117213110g:plain:w400f:id:horomary:20210117224720p:plain:w400
目的関数が超多峰性関数(右)でも問題なく最適化できている

最適化の過程を視覚化すると、多変量正規分布(この場合は2次元正規分布)がその形状を伸び縮みさせながら最小値を探索していることが理解できるため直感的にはわかりやすいアルゴリズムです。しかし、いざ実装しようとチュートリアル論文([1604.00772] The CMA Evolution Strategy: A Tutorial)の疑似コードを見ると登場するパラメータが多すぎて戸惑います。落ち着いて一行ずつ追っていきましょう。

f:id:horomary:20210117230257p:plain:w600
CMA-ES tutorial, A. Algorithm Summaryより


0. 入力次元数に依存する定数の算出とパラメータ初期化

まずは入力次元数に依存する定数の算出と正規分布および学習パラメータの初期化を行います。

f:id:horomary:20210118232114p:plain:w500

Set parameters で指定されているのは入力次元数に依存する推奨値が設定されている定数パラメータです。これらは調整すべきハイパラというよりはアルゴリズムの一部みたいなものなので強い意図がない限り推奨値を採用するのがよいでしょう。ただし、世代あたり総個体数λだけは大きければ大きいほど良いので許容できる総試行回数と相談して適切な値を設定しましょう。デフォルト値は4 + 3ln入力次元数です。

Initializationで指定されているパラメータのうち、pから始まる  \displaystyle{ p_{\sigma} , p_{c}} は入力次元数と同じ長さのベクトルである進化パス(evoluation path)です。進化パスは過去の正規分布中心の遷移情報を蓄積しておくために使用します。

多変量正規分布  \displaystyle{  \sigma \mathcal{N}(m,C) } のパラメータのうち、共分散行列Cは単位行列Iで初期化しますが正規分布中心mおよびステップサイズσは自分で問題に応じて設定する必要があります。最適化したい関数についての事前知識がない場合、中心mは適当でもあまり問題ないですが、σは小さすぎるとすぐに局所収束してしまうので様子を見て調整しましょう。


1. 多変量正規分布に従う個体サンプリング

f:id:horomary:20210118231908p:plain:w500

探索フェーズでは、多変量正規分布  \displaystyle{ \sigma \mathcal{N}(m, C) }に従う個体xをλ個体生成しそれらの適合度(目的関数の値)を評価します。

 \displaystyle{ x \sim \sigma \mathcal{N}(m, C) = m + \sigma \mathcal{N}(0, C) } であるので、多変量正規分布 \displaystyle{ \mathcal{N}(0, C) }に従うサンプルを生成することができればxを生成することができます。

 \displaystyle{ \mathcal{N}(0, C) }に従うサンプルを生成するもっとも簡単な方法はnumpy.random.multivariate_normalとかを使うことですが、ここでは多次元独立標準正規分布 \displaystyle{ \mathcal{N}(0, I) }の線形変換による多変量正規分布の生成を行います。わざわざ面倒なことをする理由は後述。

具体的には、まず共分散行列Cを \displaystyle{ C = B D D B^{T} }の形に固有値分解します。標準正規分布から生成されたサンプル \displaystyle{ z = \mathcal{N}(0, I) } の線形変換  \displaystyle{ y=BDz } はCを共分散行列とする多変量正規分布に従うため、  \displaystyle{ y \sim \mathcal{N}(0, C) } となります。

なぜこれで多変量正規分布を生成できるかは下記リンクが大変分かりやすく説明してくれていますので参照ください。
多変量正規分布にしたがう乱数の生成 - 捨てられたブログ



いちおうnumpy.randomの多変量正規分布モジュールの結果とだいたい一致することを確認しておきます。

f:id:horomary:20210119003836p:plain:w500


2. 正規分布中心mの更新

まずは正規分布中m心の更新から行います。

f:id:horomary:20210122225141p:plain:w500

 \displaystyle{ x \sim  m +\sigma \mathcal{N}(0, C) = m + \sigma y } であることから、正規分布中心の学習率  \displaystyle{ c_m } が推奨値の1.0に設定されているとき、現世代の上位μ個体のパラメータの重みづけ平均を次の正規分布中心mとする、という意味になります。

重みづけ平均のための重みwは適合度(目的関数値)の順位が良いほど大きくなるように、かつ重みの総和が1になるように設定します。 この重みwはいくつかの決め方がチュートリアル論文で紹介されていますが、順位iに応じて  \displaystyle{ w_i = \frac{\log{\frac{\lambda}{2}} - \log{i}}{\sum_{i}^{\mu}{w_i}}  \ \ ( i = 1 ... \mu ) } と設定する方法が無難かつ実装が楽です。

この正規分布中心の更新だけでも進化計算アルゴリズムとして最低限機能します。 しかし、世代ごとの探索範囲が狭すぎるため、大域的な地形を捉えることに失敗し局所地形にトラップされがちであることがわかります。

f:id:horomary:20210119011537g:plain:w500
正規分布中心mのみ更新


3. ステップサイズσの更新

正規分布中心mの更新だけでは探索範囲が狭すぎて最適化に失敗することがわかりました。そこで、探索範囲に影響するパラメータである正規分布のステップサイズ変数σ を、進化パス  \displaystyle{ p_{\sigma} }に応じて更新します。

f:id:horomary:20210120005804p:plain:w500

直感的には、進化パス \displaystyle{ p_{\sigma} }とは過去世代での正規分布中心の遷移ベクトルの重みづけ和と理解できます。
指数平滑移動平均の計算と似たような感じで、重みは最近の遷移ほど大きくなります。

もし遷移がランダムウォークしているならば付近の地形がざっくり凸であると判断できるのでσを小さくして探索範囲を絞るべきです。そうではなく遷移に指向性があるならばまだ坂を下っている途中と判断できるのでσを大きく更新する、というのがステップサイズσの更新アルゴリズムの概要です。

f:id:horomary:20210120231904p:plain:w400
http://www2.fiit.stuba.sk/~kvasnicka/Seminar_of_AI/Hansen_tutorial.pdf, 45p より

実装については、  \displaystyle{ C^{\frac{1}{2}} y_w= BD^{-1}B^{T} y_w} という定義であることに注意しましょう。定義から  \displaystyle{ C^{\frac{1}{2}} y_w = B z_w } であり、つまりこれは楕円yを正円Bzに戻す処理なのでノルム計算のための正規化処理と理解できます。※ただし、ここまでの実装だと共分散行列Cは単位行列のまま更新していないのでyもまた正円であることに留意ください。

f:id:horomary:20210121010224p:plain:w500
チュートリアル論文より

前述した多変量正規分布からの個体発生でnumpy.random.multivariate_normalを使わずわざわざ手動で共分散行列の固有値分解をしたのはこのσの更新ステップで使うからだったのです。

f:id:horomary:20210119011655g:plain:w500
正規分布中心mとスケールσを更新

探索範囲を適応的に変更することができるようになったため、なんとか最適解付近にまで到達できています。しかし、このような等方円状探索は入力次元数に指数比例して球体積が増大するので効率が良くありません。とくに目的関数に対する感度が各入力変数で著しく異なるような場合(悪スケール条件)では非常に効率の悪い探索となります


4. 共分散行列Cの更新

等方円状ではなく、目的関数への感度が高い(変化の大きい)方向について重点的に探索幅が大きくなるように共分散行列Cを更新していくことで悪スケール性の強い目的関数でも効率よく探索することができるようになります。これがCMA-ESがCMA(共分散行列適応)たる所以である共分散行列の適応的更新アルゴリズムです。

f:id:horomary:20210120012713p:plain:w500

まず共分散行列Cの進化パス   p_{c} は、ステップサイズσの更新における   p_{\sigma} とほぼ同じ形の式であるため過去世代での正規分布中心の遷移ベクトルの重みづけ和と理解できます。唯一異なる   h_{\sigma} は、ステップサイズσが大きすぎる時には共分散行列Cの進化パス  p_{\sigma} の更新を中止する役割を持ちます。

  \displaystyle{ w_{i}^{o} } について、上位個体数μを推奨値通りに決めているならば負の重みは生じず常に   w_{i}^{o} = w_{i} なので気にしなくて大丈夫です。

さて重要なのは共分散行列Cの更新式です。第一項は学習率に応じて現在のCを縮小してるだえけの処理なのでとくにコメントはありません。


第二項の   \displaystyle{ c_{1} p_{c} p_{c}^{T} }rank-one updateと呼称される進化パス  p_{c} を用いた共分散行列Cの更新処理です。ここで   \displaystyle{ p_{c} p_{c}^{T} } は2つのベクトルの 直積 であることに注意してください。rank-one更新とはこれまでの進化パス(正規分布中心の遷移ベクトルの重みづけ和)の指向性に応じて共分散行列を更新する処理と理解できます。直感的には、(2次元入力なら)正規分布中心の遷移ベクトル方向に沿って楕円(共分散行列)の軸を伸ばしていく処理です。


第三項の   \displaystyle{ c_{\mu} \sum{w_{i} y_{1:\lambda} y_{1:\lambda}^{T}} } は、rank-μ updateと呼称される進化パス  p_{c} に依存しない共分散行列Cの更新処理です。これは現世代のmを分布中心としたうえでの上位μ個体からの共分散行列の推定であり、有望個体群から推定される共分散行列をCの更新に利用する処理であると理解できます(下図を参照)。rank-μ更新は有望個体群の数μが小さい場合は推定精度が低く効率が悪いことに留意しましょう。

f:id:horomary:20210123012105p:plain:w600
有望個体からの共分散行列Cの推定. 分布中心を有望個体の平均とする場合はEMNA(共分散行列推定アルゴリズム)の結果と一致するが、rank-μ更新では中心を現世代の平均に設定するので勾配方向に楕円の軸が伸びる。図はhttp://www2.fiit.stuba.sk/~kvasnicka/Seminar_of_AI/Hansen_tutorial.pdf, 38p より



共分散行列適応アルゴリズムにより、大域的な地形変化が大きい方向に正規分布の楕円を伸ばしていくことで効率的な探索が可能になっているということがわかります。

f:id:horomary:20210117213110g:plain:w500


実装の確認

levi関数を適当に改変した謎関数を目的関数として実装をテストします。ほぼ楕円描画とgifアニメ作成がコードの大半です。

f:id:horomary:20210117213110g:plain:w500f:id:horomary:20210117224720p:plain:w500


注意: 本稿で実装したのは (μ/μw, λ)-CMA-ES という最も王道なCMA-ESの実装ですが、CMAESはいろいろな派生手法があることに留意ください。

深層分布強化学習 ① Categorical DQN(C51)

分布強化学習(distributional reinforcement learning)の概念を深層強化学習へ導入したCategorical DQN(C51)をtensorflow2で実装します。

why restrict ourselves to the mean?
[1707.06887] A Distributional Perspective on Reinforcement Learning

f:id:horomary:20201230142636p:plain:w500


参考資料

Deep Reinforcement Learning Hands-On | Packt

https://physai.sciencesconf.org/data/pages/distributional_RL_Remi_Munos.pdf

『強化学習』(森村 哲郎)|講談社BOOK倶楽部


前提手法:Deep-Q-Network (DQN) horomary.hatenablog.com

はじめに

[1707.06887] A Distributional Perspective on Reinforcement Learning

従来の深層強化学習(Q学習)では期待割引報酬和を最大化するために、状態行動価値Q(s, a)の期待値を関数近似します。Q関数がうまく近似できているならば、Q関数に従って期待値の大きな行動(action)を選択しつづければ報酬和も最大化されます。

f:id:horomary:20210104164929p:plain:w400

Q関数の期待値が高い行動を選択しつづけること自体は問題ありません。しかし、状態行動価値Q(s, a)の期待値を直接関数近似するのではなく、状態行動価値Q(s, a)の確率分布を関数近似しそこから期待値を算出する方が、Q関数が環境をよく表現できるので学習が安定化するのではないか?というのが論文の要旨です。

この論文ではまずベルマン方程式を分布の概念を導入した分布版ベルマン方程式を提案しました。

f:id:horomary:20210105094229p:plain:w400

さらに、価値分布をカテゴリ分布で表現したQ学習をatari環境向けに実装し、分布強化学習の有用性を当時のatari環境におけるSOTAという結果で証明しました。atari環境においてはカテゴリ分布のビン数が51に設定されたことから論文内ではこの手法を指してC51と呼称しています。

f:id:horomary:20210104173641p:plain:w500
論文より

分布強化学習(distributional reinforcement learning)自体は古くから存在するアイデアだったのですが、 この手法が発表されたことにより深層学習×分布強化学習の研究が活発化し、 QR-DQN, IQN, FQF など多くの後継手法が発表されることとなりました。

※単語が似ていて紛らわしいのですが分布強化学習(distributional reinforcement learning)と分散強化学習(distributed reinforcement learning)は全く異なる概念です。javajavascriptくらい違います。

rayで実装する分散強化学習 ①A3C(非同期Advantage Actor-Critic) - どこから見てもメンダコ


分布強化学習 (Distributional Reinforcement Learning)

※論文では状態をxで表記していますがここではsで表記します。また、表記の簡単のために状態遷移は決定論的とします。

通常のベルマン方程式

通常のQ学習では下式のようにベルマンオペレータTを定義し、ベルマンエラー  \displaystyle{ \mathcal{T}Q(s, a) - Q(s, a)} を最小化するようにQ関数を更新していきます。

 \displaystyle{
\mathcal{T}Q(s, a) = E \left[{ R(s, a) }\right]  + \gamma \max_{a' \in A} Q(s', a')
}

Q(s, a)はスカラ値なのでベルマンエラー  \displaystyle{ \mathcal{T}Q(s, a) - Q(s, a)} もまたスカラ値であり、この最小化とは一般的な教師あり学習と同様にMSE(平均二乗誤差)*1 なんかを最小化するだけです。


分布版ベルマン方程式

分布版ベルマン方程式では、状態行動価値を期待リターンの確率分布Z(s, a)で表現したベルマンオペレータTを定義します。

 \displaystyle{
\mathcal{T}Z(s, a) = E \left[{ R(s, a) }\right]  + \gamma Z(s', a')
}

 \displaystyle{
a' = \text{arg} \max_{a' \in A} E \left[{ Z(s', a') }\right]
}

遷移先状態s'での行動a'は  \displaystyle{E \left[{ Z(s', a') }\right] } を最大化する行動を採用します。
 \displaystyle{E \left[{ Z(s, a) }\right] = Q(s, a) } であるので、遷移先での行動選択については通常のQ学習と同じです。

通常のベルマン方程式も分布版ベルマン方程式も見た目上はあまり変わりませんが、通常のベルマンオペレータは”スカラ値Q(s', a')に割引率を掛けて即時報酬を足す”、という非常にわかりやすい処理であるのに対して、分布版ベルマンオペレータでは”確率分布Z(s', a')に割引率を掛けて即時報酬を足す”、というやや想像しにくい四則演算を行います。

f:id:horomary:20210105011035p:plain:w600
論文Fig.1を改変して掲載

論文内fig.1 はZがカテゴリ分布として表現されている場合での分布版ベルマンオペレータ適用のイメージです。①割引率を掛けることで分布が縮み、②即時報酬が足されることで分布が横に平行移動する、 という処理が可視化されています。(③のずれたビンを直す処理については後述)

同じことをPythonでやってみます。

f:id:horomary:20210105221347p:plain:w800

コードを見ればとくに難しいことはありませんね。
ただし、 \displaystyle{ \mathcal{T}Z(s, a) } \displaystyle{Z(s, a) }ではカテゴリ分布のビンの幅が変わっていることに注意してください(後述)。


ベルマンエラーの計算(分布版)

ベルマンオペレータ  \displaystyle{ \mathcal{T}Z(s, a) } の適用方法がわかったので後はベルマンエラー  \displaystyle{ \mathcal{T}Z(s, a) - Z(s, a)} を計算するだけです。しかしZは確率分布であるので通常のQ学習のように単純な引き算をすることはできないため、2つの分布間の距離を適切に定義する必要があります。

2つの分布間の距離尺度といえばKL-divergenceやWasserstein-metricなどいろいろありますが、C51ではカテゴリ分布でZを表現しているので深層学習ではお馴染みのcategorical cross entropy を2つの分布間の距離として、これを最小化するようにネットワークを更新していきます。

しかし、上述したようにベルマンオペレータ適用後の \displaystyle{ \mathcal{T}Z(s, a) }ビンの幅が変わってしまっているため、そのままではクロスエントロピーを計算することができません。(灰線がZ(s, a)のビン幅、赤船がTZ(s, a)のビン幅)

f:id:horomary:20210105225131p:plain:w500

そこで、 \displaystyle{ \mathcal{T}Z(s, a) }の分布形状を可能な限り保ったまま、 \displaystyle{Z(s, a) }のビン幅に再割り当て(projection)を行う必要があります。この作業を数式にしたのが下式です(論文より)。

f:id:horomary:20210105225614p:plain:w500

初見では意味不明な数式ですがコードを見るとそれほど難しいことは言っていないことに気が付きます。

f:id:horomary:20210105230948p:plain:w800

ビン幅を再割り当てした \displaystyle{ \mathcal{T}Z(s, a) }を論文では \displaystyle{ \phi\mathcal{T}Z(s, a) }と表記しています。ここまで理解できればあとは普通にクロスエントロピーを計算するだけです。


Categorical DQN(C51)のtensorflow2実装

上述した分布版ベルマンオペレータの適用とビンの再割り当て処理(projection)を除くとほぼDQNと同じなので実装の要点だけ掲載。

実装全体はgithubへ:

github.com


カテゴリ分布Q関数

ネットワーク構造は基本DQNですが、最終Dense層が"action_space×カテゴリ分布のビン数"のunitsを出力したうえでこれを(バッチサイズ, action_space, n_atoms)にreshapeし、各action軸でsoftmaxをとることで確率分布を表現します。

ちなみに論文ではカテゴリ分布のビンのことをatoms、およびそのビンに割り当てられた確率をsupportと呼称しています。英語だとそういう表現なんですね。


ネットワーク更新

 \displaystyle{ \mathcal{T}Z(s, a)} \displaystyle{Z(s, a)}のcategorical cross entropyをロスとしてSGDするだけです。

クロスエントロピーの計算はlogをとる前に微小量を加えておかないと打切り誤差でLog(0)を計算してnanを吐くことがあるので注意。(実際2Mstepくらい進んだあたりでnan吐いて学習失敗した)

分布版ベルマンオペレータの適用

上述のコードとやってることは同じですが、ミニバッチ単位での処理のためにややコードの見通しが悪くなっています。

またdoneのときの処理、つまり \displaystyle{ \mathcal{T}Z(s, a)}= R(s, a) のときの処理が追加されています。


BreakoutDeterminisitc-v4 での結果

4000エピソードちょいでおよそ400万stepを学習した結果です。
論文の結果(fig.3)を見ると1000万stepくらい学習すればスコアがサチるみたいです。

f:id:horomary:20210106214232p:plain:w500


マシンはGCPのn1-standard-4(4-vCPU, 15GBメモリ) + GPU K80 のプリエンティブルVMインスタンスを使って24時間学習しました。プリエンティブルVMは激安な代わりに24時間で自動シャットダウンされます。費用はざっくり計400円くらい?


付録

分布ベルマン方程式の理論的保証

 \displaystyle{
\mathcal{T}Z(s, a) = E \left[{ R(s, a) }\right]  + \gamma Z(s', a')
}

本文では価値分布をカテゴリ分布で表現し、categorical cross entropy(※論文ではKL divergenceのクロスエントロピー項と言っている)を分布間の距離尺度とする分布版ベルマンオペレータを天下り的に正しいもののように紹介しましたが、実際はこのような方法の理論的保証はされておらず”APPROXIMATE DISTRIBUTIONAL LEARNING”と明記されています。

[1707.06887] A Distributional Perspective on Reinforcement Learning の前半は分布ベルマン分布の理論的保証に割かれているのですが、ここで保証されているのは固定方策かつZ(s, a)を連続な分布で表現した場合にZ(s, a)とTZ(s, a)の累積分布関数の逆関数のLp-Wasserstein距離を分布間の距離尺度としたときに分布ベルマンオペレータが縮小写像となる(収束する)ということです。

続報でもこのあたりの議論が深められています。
[1902.03149] Distributional reinforcement learning with linear function approximation

しかし、分布版ベルマンオペレータの収束性の話は当然通常のベルマンオペレータの収束性の議論の理解が前提なので、そもそもこのあたりの知識に自信がない人(私です)は、強化学習の青い本『強化学習』(森村 哲郎)|講談社BOOK倶楽部)2章 プランニング
を読みましょう。

こちらの記事も大変参考になりました。Thank you!
Wasserstein Distance, Contraction Mapping, and Modern RL Theory | by Kowshik chilamkurthy | Medium


経験分布からのWasserstein LossはBiased

上述の通り、論文ではWasserstein距離を分布間距離尺度としたときに分布ベルマン方程式が収束するということを証明したのに、CategoircalDQNの実装ではカテゴリ分布のKL距離を採用しています。これは経験分布のWasserstein距離はBiasedであるためです。

これについてはLemma 7, Proposition 5で説明されていますが、私は理解に時間がかかったので同じような方のために解説しておきます。

具体例として2つの分布PとQの間のwasserstein距離を考えます。分布Pは表(=1)と裏(=0)がどちらも0.5の確率で出るコインの分布(ベルヌーイ分布の確率質量関数)とします。一方、分布Qは表(=1)がpの確率で、裏(=0)が 1-p の確率で出る歪んだコインの分布とします。

この分布Pと分布Qの1-wasserstein距離 d(P, Q)= |0.5 - p| であることは視覚的にも容易にわかります(下図)。

f:id:horomary:20210331020557p:plain:w500
PとQのwst距離の視覚的理解

分布Pは無限のコイントス試行によって得られる真の分布であることに注意してください。もし分布Pが経験分布である場合、極端にはコイントス試行1回行って表が出たという結果からの経験分布の場合、経験分布Pと分布QのWST距離は 1-p となります(下図)。同様に裏が出た場合のWST距離はpとなります。

f:id:horomary:20210331021733p:plain:w500
経験分布Pと分布QのWST距離

ここで、PのコインについてN回の試行を行い、各サンプルから得られるPの経験分布と分布QのWST距離のサンプル平均を考えます。表が出る確率は0.5でありこの場合のWST距離は1-p, 裏が出る確率も0.5でありこの場合のWST距離はpであるので、このサンプル平均 E[d(Pi, Q)]は 0.5×p + 0.5×(1-p)= 0.5 となります。上述の通り、分布間の真のWST距離は |0.5 - p| であるので、よってp=0 or 1の場合を除いて経験分布からのWasserstein距離にバイアスがかかることが理解できます。

SGDにおいてミニバッチを構成する各サンプルはまさに報酬分布R(s)および遷移分布P(s' | s, a)からの1回のサンプリングから得られた経験分布であるため、各サンプルのWST距離のミニバッチ平均もまた同様にBiasedとなります。


なぜ分布の推定が学習を安定化させるか?

atari2600環境で当時のSOTAを達成し単体のDQN拡張手法としては最良の結果を示したCategorical DQNですが、状態行動価値分布を推定することでなぜ学習が安定するのかについてはdiscussion項で考察されているものの明確な結論は示されていません。

強化学習の青い本『強化学習』(森村 哲郎)|講談社BOOK倶楽部)8.2.1.4 カテゴリDQN法 でも、

性能改善の要因として、マルチタスク学習のように目的タスク(期待リターン推定)の学習と並行して関連する多数のタスク(リターン分布推定)を学習することによる効果などが考察されていますが、いまだ議論の段階で、今後さらなる解析が期待されます。

と、述べられています。

他にはこちらの記事も参考になりました。
https://clarelyle.com/posts/2019-02-08-aaai.html


マウスの脳は分布強化学習を行うか?

最近出たDeepmindハーバード大のNature論文。マウスのドーパミン細胞における神経活動の測定から分布強化学習っぽさを示す結果が得られたらしい。興味ある方はどうぞ。

www.nature.com


次:② QR-DQN

horomary.hatenablog.com


*1:DQNだと huber loss

rayで実装する分散強化学習 ②A2C(Advantage Actor-Critic)

GPUが一つしかなくても効率よく訓練できる分散強化学習手法A2Cをrayで実装します。

前記事:

horomary.hatenablog.com


f:id:horomary:20201224012126j:plain


A2Cとは

A3C論文: [1602.01783] Asynchronous Methods for Deep Reinforcement Learning

A2CはA3C(Asynchronous Advantage Actor Critic) の派生手法です。 A3Cでは並列化された各agentが自律的にrollout → 勾配計算し勾配情報だけをパラメータサーバに送付、という流れで分散学習を行います。この方法では各agentがそれぞれ勾配計算を行うためGPUの数=agentの数のときパフォーマンスが最大となります*1。これはGPUリソースに乏しい一般人にはなかなか辛いアーキテクチャです。

f:id:horomary:20210204231842p:plain:w600
A3C型の分散強化学習は各agentがネットワークのコピーを持つ

そこで、①中央指令室がすべてのagentに対してアクション指示を出す→②並列化された各agentは指示されたアクションで環境のstepを進める→③各agentは蓄積した遷移情報を中央指令室へ送信→④中央指令室が集められたトラジェクトリから勾配計算しネットワークを更新する、という流れで学習を行う派生手法が考案されました。これなら推論、勾配計算をするのは=GPUを使うのは中央指令室だけなのでGPUは1つでOKとなります。

f:id:horomary:20200530150556p:plain:w600
A2C型の分散強化学習は中央指令室だけがネットワークを持つ

この分散学習アーキテクチャA3Cの最初のAである Asynchronous(非同期) の要素が削られているのでA2Cと呼ばれます。ちなみに、A3CとA2Cでパフォーマンスに大きな差は無い*2、とのことです。

A3Cの非同期並列アーキテクチャ、およびA2Cの同期並列アーキテクチャはその後のさまざまな手法で転用されているので実装できるようになっておくと便利です。たとえば openai/baselinesppo1はA3CアーキテクチャでのPPO(Proximal Policy Optimization)実装、ppo2A2CアーキテクチャでのPPO実装です。


rayによるA2C型同期並列アーキテクチャの実装

A3Cの非同期並列学習とは違い、A2Cの同期並列学習についてはmultiprocessingなんかでの実装もそれほど難しくありませんが、rayを使うことですっきりシンプルに実装できます。

並列agentでトラジェクトリを収集するコードはこれだけ!

以前openai/baselinesの SubprocVecEnvを参考にしたmultiprocessingモジュールでのA2C実装を紹介しましたが、それと見比べるとシンプルさがよくわかります。rayではクラスごと並列化できるので状態を保持するサブプロセスを実装するときに本当に便利です。

horomary.hatenablog.com


A2Cでのネットワーク更新

更新アルゴリズム自体はA3Cと全く同じですので解説については前記事を参照ください

horomary.hatenablog.com

A3Cでは各agentごとにミニバッチを作成し更新していましたが、A2Cでは各agentから取得したtrajectoryを集約してminibatchとします。


CartPole-v1での学習結果

とくに問題なし

f:id:horomary:20201229171459g:plain:w600


次:Apex-DQN

horomary.hatenablog.com

*1:バッチサイズがある程度大きい場合

*2:OpenAI曰く

rayで実装する分散強化学習 ①A3C(非同期Advantage Actor-Critic)

Pythonの分散並列処理ライブラリであるRayとTensorflow2を使って分散強化学習の主要な手法を実装していきます。 まずは分散強化学習の草分け的な手法であるA3C (Asynchronous advantage actor-critic、非同期アドバンテージアクタークリティック) です。

f:id:horomary:20201224012126j:plain


はじめに

主要な強化学習手法の多くが分散並列学習を前提にしている一方で、Pythonは並列処理もノード分散処理もそれほど得意ではなく、とくに非同期並列処理のPython実装にはプログラミング的な高い障壁が存在していました。

しかし、近年 rayライブラリが救世主的に登場したことにより、Pythonでの分散並列処理の敷居は大きく下がることとなりました。

Ray provides a simple, universal API for building distributed applications.
- Rayは、分散アプリケーションを構築するためのシンプルでユニバーサルなAPIを提供します。

rayは素晴らしく使いやすいのに日本ではまだまだ認知度が低いライブラリですので、応援の意味も込めてrayによる分散強化学習の実装例を紹介していきます。※rayは強化学習だけでなく並列分散処理が必要なすべての処理で便利なライブラリです。


Rayとは

github.com

rayはpip install可能なpythonパッケージであり、rayライブラリを使用することで既存のライブラリよりもはるかにシンプルでPythonicなコードで分散並列処理を実装できるようになります。マシン内での並列処理が簡単に記述できるのも良いところですが、さらに素晴らしいのはマシン内並列処理そのままのコードでクラスタ間での分散並列処理にスケールアップできることです。ただし、rayライブラリは並列処理の開始時のオーバーヘッドがわりと大きいので軽いタスクの並列化には向かないことには留意ください。

rayライブラリの基本的な使い方については本記事では省略しますので、公式ドキュメントや過去記事を参照ください。

Tips for first-time users — Ray v2.0.0.dev0

horomary.hatenablog.com


A3C(Asynchronous advantage actor-critic)

[1602.01783] Asynchronous Methods for Deep Reinforcement Learning

A3Cは深層強化学習において分散並列学習の有用性を当時のatari26000環境のSOTAという結果で示した重要な手法です。その一方で(当時の)Pythonでは実装するのがクソ面倒くさい手法でもありました。これはA3Cに非同期(Asynchronous)並列処理という言語特性上の理由でPythonと非常に相性の悪い処理が入っていることが原因です。

f:id:horomary:20200523222229p:plain:w600
A3Cでは各agentが自律的にゲームをプレイ(rollout)する

A3Cでは並列化されたagentが自律的にrolloutを行い、好き勝手なタイミングで勾配計算してその勾配情報をパラメータサーバに送り付けてきます。この好き勝手なタイミングというのが本当にPythonと相性が悪く、過去記事ではthreadingモジュールを使用して非同期処理もどきの実装で妥協しました。そこで、本記事ではrayによる実装でA3Cにリベンジを行います。

horomary.hatenablog.com


1. 非同期処理(Asynchronous)

非同期処理の実装

参考:Asynchronous Advantage Actor Critic (A3C) — Ray v2.0.0.dev0

A3Cの最初のAである非同期(Asynchronous)とは上述の通り、並列化されたagentが自律的にrollout → 勾配計算し、勾配計算が終わった順に勾配情報をパラメータサーバに送付してくるような処理です。この勾配計算が終わった順に処理する実装が既存ライブラリでは本当にめんどくさいポイントだったのですが、rayのray.waitを使用するとシンプルに記述できます。

たとえば、ray.waitを使って処理が終わった順に結果を取得してまた新たな処理を追加する流れは下のように記述できます。

Agentクラスインスタンスごと並列プロセスにしているのが重要なポイントで、これは状態をもつ並列プロセスを容易に実装できるということです。これは強化学習をするうえで超便利です。

この例ををそのままA3Cに転用したのが下のコードです。

tf2で実装する場合の注意:
tensorflow2(tensorflow.keras.Model)で実装する場合は、ネットワークを別ファイルに定義しないと TypeError: can't pickle _thread.lock objectを吐きます。rayは並列化プロセスの開始時に同一ファイル内のオブジェクトはpickle化して分岐させるのに対して、tensorflow.keras.Modelは簡単にpickle化できないことに原因があるのではないかと想像しています*1。ゆえに別ファイル内に定義してimportする、あるいはAgentクラス内にtensorflow.keras.Modelを定義することでエラーを回避できます。


分散学習の効果

並列分散学習を行うことは単純にCPUリソースに応じて学習が高速化するという恩恵もありますが、経験の自己相関を低減し学習を安定化する効果が期待できます。経験の自己相関による学習の不安定化は強化学習が長く抱えてきた課題です。例えば、DQN (2013)では オフポリシー手法であることを生かしたExperience Replay (経験再生) 機構 でバッファに蓄積した経験をランダムに取り出しミニバッチを作成することで経験の自己相関を低減しています。

これに対してA3Cではサンプルを集めるAgentを並列化することで自己相関を低減するという手段をとりました。この並列化アプローチは非常に効果的である上、他手法でも容易に転用可能なアイデアであるのでA3Cの発表後には強化学習分野には分散並列化ブームが到来することとなります。


2. アドバンテージ関数 (Advantage)

参考: Vanilla Policy Gradient — Spinning Up documentation

A3Cの2つめのAであるAdvantageとはアドバンテージ関数を使用して方策勾配を計算することを指します。

 \displaystyle{
\nabla_\theta J( \pi_{\theta} ) = E_{\pi_{\theta} } \left[{ \sum_{t=0}^{T}{ \nabla_\theta \log\pi_{\theta}(a_{t} | s_{t}) A^{\pi_{\theta}}(s_{t}, a_{t})  }}\right]
}
ここで、  \displaystyle{ A^{\pi_{\theta}}(s_{t}, a_{t}) = Q^{\pi_{\theta}}(s_{t}, a_{t}) -  V^{\pi_{\theta}}(s_{t}, a_{t})
}

アドバンテージ関数を使用しない場合はQ(s, a)を使用して方策勾配を計算するのに対し、アドバンテージ関数を使用する場合はA(s, a) = Q(s, a) - V(s, a) を 使用して方策勾配を計算します。V(s, a)とは すべてのaについてのQ(s, a)の期待値であるはずなので、どちらの方法で計算しても勾配の平均値には影響ありませんが、アドバンテージ関数を使うと勾配の分散が小さくなり学習が安定化します。


アドバンテージ関数の実装

※簡単のため割引率γは表記無し

上述のように、アドバンテージ関数とは状態行動価値 Q(s, a)からベースラインである状態価値V(s, a)を引いた値と定義されています。

アドバンテージの定義
 \displaystyle{ A^{\pi}(s_{t}, a_{t}) = Q^{\pi}(s_{t}, a_{t}) -  V^{\pi}(s_{t}, a_{t})
}

このアドバンテージの算出には様々な選択肢が存在していることがA3Cの理解をややこしくしている理由のひとつです。例えば、もっともシンプルなアドバンテージ関数は、1step先までの即時報酬の情報(1step return)を使用した下記のような実装です。

1-step return advantage
 \displaystyle{ A^{\pi}(s_{t}, a_{t}) = r_{t} + V^{\pi}(s_{t+1}, a_{t+1}) -  V^{\pi}(s_{t}, a_{t})
}

あるいは、n-step先までの即時報酬の情報(n-step return)を使用することもできます。

N-step return advantage
 \displaystyle{ A^{\pi}(s_{t}, a_{t}) = \sum_{n=0}^{N-1}{ r_{t+n} } + V^{\pi}(s_{t+N}, a_{t+N}) -  V^{\pi}(s_{t}, a_{t})
}


A3CではこのN-step returnが混合されたものが使われます。
たとえばミニバッチとして連続する5stepを切り出してきた場合、1step目では5-stepアドバンテージを、2step目では4-stepアドバンテージを、・・・、5step目では1-stepアドバンテージを計算します。ゆえに論文では mix of n-step return と表現されています。

正直コード見るのが一番わかりやすいかと思います。


3. Actor-Critic

パラメータ共有型ネットワーク

Actor-Criticでは、一般的には*2 方策関数(Actor)と状態価値関数V(Critic)*3を別々に関数近似します。これに対してA3CではCNNを使用するドメイン(つまりatari2600環境)に限って、方策関数と状態価値関数を一部のパラメータを共有する分岐型ネットワークとしてまとめて実装します。

今回はCartPoleなのでCNNは使わないのですがせっかくなのでパラメータ共有型のモデルで実装してみます。

CNNのときのみ分岐型ネットワークで実装するとなぜ良いのかは論文内では明言されていません*4が、CNNにおいて入力に近い層は表現抽出の役割を担っていると言われるので、方策関数と価値関数でネットワークを共有した方が学習が安定するだろう、という一般論的な考察ができます。


A3Cのロス関数

共有型ネットワークでは当然ロスも共有なので、方策ロスと価値ロスをまとめて、”-1×(アドバンテージ方策勾配項 + 方策エントロピーボーナスH(π) ) + 価値関数ロス” としたものがロス関数となります。※方策勾配と方策エントロピーは最大化したいので×-1しています。

ここで突然出てきた方策エントロピーボーナスH(π)とは方策のランダムさの指標です。ランダム性の高い方策(=エントロピーの大きい方策)にボーナスを与えることで早すぎる方策の収束による局所解への停滞を防ぐ効果があります。カテゴリ分布の方策エントロピーは下式で計算します。

 \displaystyle{
H(\pi(\cdot | s)) = - \sum_{a} \pi(a | s) \log\pi (a | s)
}

例えば、[π(a1|s), π(a2|s), π(a3|s)] = [0.1, 0.1, 0.8 ] の方策と [π(a1|s), π(a2|s), π(a3|s)] = [0.3, 0.3, 0.4 ] の方策であれば後者がよりエントロピーの大きい方策となります。*5

価値関数ロスについてはシンプルに1step returnを使って  \displaystyle{
(r_{t} + V(s_{t+1}, a_{t+1}) - V(s_{t}, a_{t}) )^{2}
} と計算してもよいのですが、アドバンテージ方策勾配法のためにn-step returnを計算済みなので、n-step return と現在状態価値 \displaystyle{V(s_t, a_t)}の二乗誤差、つまりAdvantageの二乗を価値関数のロスとします。

アドバンテージ方策勾配項については上述した通りです。ただし方策勾配においてアドバンテージは定数項の扱いなのでtf.stop_gradientして勾配が流れないようにする必要があることにだけ注意してください。



CartPole-v1での学習結果

f:id:horomary:20201228212049g:plain:w500

次:A2C

horomary.hatenablog.com


付録:Agentクラスの実装

実装全文はgithubへ: https://github.com/horoiwa/deep_reinforcement_learning_gallery

*1:詳細なメカニズムが分かる人教えてください

*2:少なくともA3Cの発表当時は

*3:あるいは状態行動価値関数Q

*4:見落としかも

*5:連続値行動制御によく使われるガウス分布方策であれば標準偏差σの大きさがそのままエントロピーの大きさと相関します。

Soft Actor-Critic (SAC) ②tensorflow2による実装

連続値制御で大人気の強化学習手法であるSoft-Aactor-Criticのtensorflow2実装を解説します。
対象タスクはPendulum-v0とBipedalWalker-v3。

前記事: horomary.hatenablog.com

f:id:horomary:20201209001757j:plain:w800

SAC論文 ①: [1801.01290] Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor

SAC論文 ②: [1812.05905] Soft Actor-Critic Algorithms and Applications

SAC論文 ③: https://arxiv.org/pdf/1812.11103.pdf


前提手法:DDPG, DQN

horomary.hatenablog.com

horomary.hatenablog.com


ここまでの概要

SAC(Soft Actor Critic)はSoft-Q学習のactor-criticへの適用であり、累積報酬和と同時に方策エントロピーの期待値の最大化を目的関数としてます。

 \displaystyle{
J_{soft}(\pi) = E_{\pi} \left[{ \sum_{t=0}^{T}{(R(s_t, a_t)} -  \alpha \log\pi(a_{t} | s_{t}) )}\right]
}

SACの理論的根拠となっているSoft-Q学習は最大エントロピー強化学習に基づくQ学習であり、Q学習の課題である探索力の弱さを方策エントロピー項を目的関数に組み込むことによって解決する自然なアプローチです。また、SAC(およびSoft Q学習)はオフポリシー強化学習手法であり高いサンプル効率が期待できます。

SACの実装はDDPGおよびその改良であるTD3に非常によく似ていますが、Soft-Q学習に由来する探索力の高さから致命的なハイパーパラメータが少なく安定したパフォーマンスを期待できます。

【TF2】DDPGでPendulum-v0【強化学習】 - どこから見てもメンダコ

【強化学習】TD3の解説・実装【TF2】 - どこから見てもメンダコ


全体的なアルゴリズムの流れはDDPGとほぼ同じであり、環境から得た経験をReplayBufferに蓄積しそこからミニバッチを作成してネットワークの更新を行うというループを繰り返します。DDPGと同様にSACは方策とQについてニューラルネットワークによる関数近似を行いますが、状態に基づくアクションの決定は方策関数が担いQ関数は方策関数の更新のためにだけ使用されます。


Soft-Q関数について

SACはsoft-Q関数をニューラルネットワークによって関数近似します。連続値制御のために、QはDQNスタイルではなくDDPGスタイルの実装になります。すなわち、状態Sと行動Aを入力とし、単一のQ値を出力するように実装します。これに対してDQNスタイルのQは状態Sを入力とし、行動Aの次元数分のQを出力します。

f:id:horomary:20200626002801j:plain:w400
Qの関数近似:DDPGスタイル(左)とDQNスタイル(右)の違い

soft-Q関数の更新

Soft-Q学習におけるベルマン方程式通りに更新していけばOKです。 通常のQ学習における価値関数Vが、  \displaystyle{
V(s_{t}) = E_{\pi}\left[ Q(s_{t}, a_{t})\right]
} であるのに対して、 Soft-Q学習における価値関数Vは  \displaystyle{
V_{soft}(s_{t}) = E_{\pi}\left[ - \alpha \log\pi(a_{t} | s_{t}) + Q(s_{t}, a_{t})\right]
}というように状態に方策エントロピーがボーナスとして付加されています。

Soft-Q学習における更新式(ベルマンエラー)
 \displaystyle{
L = r(s, a) + \gamma V(s')  - Q(s, a) = r(s, a) + \gamma \left[-\log\pi( a' | s' ) + Q(s', a')  \right] - Q(s, a)
}
※a'は実際に行ったアクションではなく毎回の更新時に方策関数からサンプリングして決める


さらに、この更新式にTD3で提案されたClipped-Double-Qトリックを適用します。Clipped-Double-QとはQ学習のmax演算子(soft-Q学習ではsoftmax)に由来するQ値の過大評価を軽減するための手法であり、Double Q learning (https://arxiv.org/pdf/1509.06461.pdf) と同様のコンセプトの手法です。具体的には2つのQ関数を用意して小さい方の評価値を採用することでQ値の過大評価を打ち消します。

Soft-Q学習における更新式 with Clipped-double-Q
 \displaystyle{
L = r(s, a) + \gamma \left[-\log\pi( a' | s' ) + \min(Q_1(s', a'), Q_2(s', a')) \right] - Q(s, a)
}
※a'は実際に行ったアクションではなく毎回の更新時に方策関数からサンプリングして決める


プログラミング的にはClipped-Double-Qトリックのために実際に2つのQ関数インスタンスを作ってもよいのですが、コードをすっきりさせるためひとつのQ関数インスタンス内に(self.dualqnet)2つのq関数を内包させることにしました。


2つのq関数を内包するQ関数はtensorflow2で下記のように実装しました。レイヤー構成などはDDPG論文に準拠しています。


ソフトターゲット更新

※Soft-Q学習の”ソフト”とソフトターゲット更新の”ソフト”はとくに関係ありません

Target Networkは、DQN(2013)で提案されて以降、Q学習では標準的に使用される学習安定化のためのテクニックです。

DQNでは10000stepごとくらいの頻度でtarget Q関数とメインQ関数の重みを同期していましたが、この同期頻度の程度がそれなりに重要なハイパーパラメータになってしまっていました。これに対して、DDPGでは1-8step程度の高頻度で少しずつ重みを同期していくことによりtarget Q関数がメインQ関数をゆるやかに後追いするようにさせるSotf-Targetという手法を提案しました。SACでもこのSoft-Targetを使用します。

f:id:horomary:20201220230900p:plain:w500
Deep Deterministic Policy Gradient — Spinning Up documentation

Q関数をtensorflow.keras.Modelで作成しておけばget_weightsおよびset_weightsが使えるので実装上とくに難しいことはありません。


方策関数について

確率的方策は任意の形式が使用可能ですが、論文で単ガウス方策が使用されているのでこれに倣います。SAC論文の初期versionでは混合ガウス分布を使っていましたがmujuco環境では単ガウスでも混合ガウスでもあまりパフォーマンスに影響が無いようです。

https://openreview.net/pdf?id=HJjvxl-Cb


方策関数の更新

前記事(Soft-Actor-Critic (SAC) ①Soft-Q学習からSACへ - どこから見てもメンダコ)では、 方策関数はsoft-Q関数のSoftmax方策に似せていく、つまりKL距離を最小化することにより最適方策が得られるということを解説しました。

これを数式で表現するとSAC論文③ https://arxiv.org/pdf/1812.11103.pdfより

方策関数の更新:Qのsoftmax方策に似せる
f:id:horomary:20201220233643p:plain:w400
f:id:horomary:20201220233652p:plain:w300

この数式は一見難しそうに思えますが、式を書き下していくとそうでもないことがわかります。

 \displaystyle{
D_{KL} ( {\pi( \cdot | s) || \frac{\exp{\frac{1}{\alpha}Q(\cdot, s) } }{Z(s)} } )
}

について、まずはKL距離の定義通りに式変形して、

 \displaystyle{
=  \int \pi(a | s) \log \frac{\pi(a | s)}{ \frac{\exp{\frac{1}{\alpha}Q(\cdot, s)}}{Z(s)} }  da
}

ここで、 \displaystyle{p(x)} がxの確率密度関数であるとき、 \displaystyle{\int p(x)f(x) dx = E_{x \sim p}\left[ {f(x) } \right] } であることから、

 \displaystyle{
=  E_{a\sim\pi} \left[ {  \log \frac{\pi(a | s)}{ \frac{\exp{\frac{1}{\alpha}Q(\cdot, s)}}{Z(s)} }  } \right]
}

 \displaystyle{
=  E_{a\sim\pi} \left[ { \log\pi(a | s) - \frac{1}{\alpha}Q(a, s) + Z(s) } \right]
}

とすっきり変形できました。

よって、

 \displaystyle{
\underset{\pi}{\text{argmin}} \, D_{KL} ( {\pi( \cdot | s) || \frac{\exp{\frac{1}{\alpha}Q(\cdot, s) } }{Z(s)} } )
}

 \displaystyle{
=  \underset{\pi}{\text{argmin}} \, E_{a\sim\pi} \left[ { \log\pi(a | s) - \frac{1}{\alpha}Q(a, s) + Z(s) } \right]
}

ここで、Z(s)はπに依存しない規格化定数((softmax方策の規格化定数、統計力学で言えば分配関数)) なので \displaystyle{\underset{\pi}{\text{argmin}}}の中では無視できます。温度パラメータαもまたπに依存しない正の定数なので-αを掛けることで式を整理しつつ、最小化問題を最大化問題に変換します。

 \displaystyle{
=  \underset{\pi}{\text{argmax}} \, E_{a\sim\pi} \left[ { Q(a, s) -\alpha\log\pi(a | s) } \right]
}

というわけで結局のところ、Q値を最大化しつつ方策エントロピー \displaystyle{ H(\pi) = -\log\pi(a | s)} を最大化するというSoft-Q学習の定義通りの式が出てきました。更新式が単純なので実装も簡単です。


方策関数の実装

モデル構造自体はなんの変哲もないガウス方策ですが、状態sからの行動aのサンプリングにおいて”Reparameterization Trick” と "Squashed Gaussian Policy"という2つのテクニックが用いられています。


Reparameterization trick

上述の方策関数の更新を見れば明らかなように、SACでは方策ロスの計算において

  1. 状態sをガウス方策関数に与えてアクション分布の平均(μ)と標準偏差(σ)を得る
  2. 正規分布 N(μ、σ)からのサンプリングにより確率的にアクションaを決定する。
  3. 決定したアクションaと状態sをQ関数に与えてQ(s, a)を計算する

という処理があります。確率的な処理が誤差逆伝搬の通り道にいるとそこで自動微分が止まってしまうため、方策関数の重みを更新できません。*1

f:id:horomary:20201224002641p:plain:w800

この問題はVAE(Variational Auto Encoder)なんかでもお馴染みの Reparameterization Trick を使用することで解決します。 と言ってもやるべきことは簡単で、確率的処理を誤差逆伝搬の通り道から追い出すだけです。

f:id:horomary:20201224003944p:plain:w800

N(μ, σ) からのサンプリングと μ+σz (zは標準正規分布からサンプリングしたノイズ)は同じ結果になりますので確率的処理を通り道から追い出すことができます。いちおう実験しておきましょう。

f:id:horomary:20201224004808p:plain:w400


Squashed Gaussian Policy

ガウス分布は-∞から∞まであらゆる値をとりうる分布である一方で、たとえば今回のターゲットであるBipedalWalker-v3ではアクションの値を-1から1の範囲に制限する必要があります*2。このような場合にはガウス方策からサンプリングされたアクションにtanhを適用することで-1から1に出力されるアクションの数値範囲を制限することができます。

平均0.8, 標準偏差0.3のガウス分布からサンプリングされた値へtanh関数を適用したのが下図です。まさにガウス分布が-1から1の範囲に押しつぶされた(Squashed)ような分布になっていることがわかります。*3

f:id:horomary:20201224233659p:plain:w500

通常のガウス鵜方策の場合には、ロスの計算に必要な \displaystyle{\log\pi(a | s)}ガウス分布確率密度関数をそのまま使用すればよいですが、tanhによるガウス分布の押し潰しを行った場合  \displaystyle{\log\pi(a | s)} は下記のように計算します。

f:id:horomary:20201224230339p:plain:w400
SAC論文①より

数学強い人なら上の式みただけで理解できるのかもしれませんが私の数学力はハムスターレベルなので困惑しました。

まず、ガウス分布tanhで押しつぶされただけなので*4、破線区間での積分が等しくなるということが直感的にイメージできるでしょうか。

f:id:horomary:20201225002628p:plain:w600

 \displaystyle{ 0.54 = \tanh^{-1}(0.6) = 0.5 \log\frac{1+0.6}{1-0.6}}
 \displaystyle{ 1.09 = \tanh^{-1}(0.8) = 0.5 \log\frac{1+0.8}{1-0.8} }

これを数式で表現すると、tanhを適用されたガウス分布確率密度関数 \displaystyle{P_{\text{squash}}}ガウス分布確率密度関数 \displaystyle{P_{\text{gauss}}}として

 \displaystyle{ \int_{0.6}^{0.8} P_{\text{squash}}(a) da }

 \displaystyle{ = \int_{0.54}^{1.09} P_{\text{gauss}}(u) du }

ここまでイメージできればあとは下記の参考リンクを見れば大丈夫(丸投げ)。

normal distribution - Change of variables: Apply $\tanh$ to the Gaussian samples - Mathematics Stack Exchange

sinhx, coshx, tanhxの逆関数 | 高校数学の美しい物語


温度パラメータαの自動調整

SAC(というかSoft-Q学習)の目的関数では累積報酬和と方策エントロピーの期待値の最大化という多目的最適化問題を、単純な和をとることで一つの式にまとめ単目的最適化問題のように表現しています。しかし、Q値およびエントロピーのスケール感はタスクおよび学習の進み具合によって変わるため、エントロピー項の係数αを適切に設定することによって累積報酬和と方策エントロピーのバランスをとる必要があります。

 \displaystyle{
J_{soft}(\pi) = E_{\pi} \left[{ \sum_{t=0}^{T}{(R(s_t, a_t)} -  \alpha \log\pi(a_{t} | s_{t}) )}\right]
}

※αは論文では温度(temperature)パラメータと表現されています。これはSoft-Q学習における最適方策が統計力学におけるボルツマン分布と同じ形であり、αはボルツマン分布における温度Tに対応するためです。

最初のSAC論文ではこの係数αはハイパーパラメータとして調整されるべき値とされましたが、SAC論文② では係数αの自動調整手法が提案されています。具体的には下式に示すように、エントロピー下限値の制約付き報酬累積和の最大化問題と捉えることで適切なαを決定します。

f:id:horomary:20201226033442p:plain:w500
SAC論文②より

この双対問題を解くことによりαの更新式が得られます。しかし、真面目に最小化問題を解くのはpracticalでないので実際は右辺のEの中身をlossとしてSGDでαを更新していきます

f:id:horomary:20201226034212p:plain:w500
αの更新式

実装はこんな感じ。tf.Variableを直接定義してSGDって案外やる機会がないのでちょっと焦る。


直感的にはエントロピーが目標値Hより小さくなったらαを大きくし、逆に目標値Hより大きくなったらαを小さくして、というように適応的にαを更新していくと理解することができます。ただしエントロピーの目標値Hはやはりハイパーパラメータであり、"-1×アクションの次元数" が推奨値として提案されているものの、とくに理論的根拠があるわけではないのである程度ハイパラチューニングした方がよいと思われます。


結果

コード全文はgithubへ: https://github.com/horoiwa/deep_reinforcement_learning_gallery

Pendulum-v0, Bipedalwalker-v3ともにハイパラ調整の試行錯誤なしで良いパフォーマンスを得ることができました。

*1:実装が似ているDDPGは決定論的方策を用いるため、当然ではあるがこの問題が生じない

*2:ただし、BipedalWalker-v3は-1から1という制約はあるがこれに違反しても勝手にClippingされるのでエラーは吐かない

*3:Squashはレモンスカッシュのスカッシュ

*4:1対1写像であるので

Soft-Actor-Critic (SAC) ①Soft-Q学習からSACへ

連続値制御のための有力手法である Soft Actor-Critic (SAC) の解説と、tensorflow2での実装例です。実装するだけならDDPGやその後継であるTD3とたいして変わりませんが、しっかり理解しようとするとなかなか苦労する手法です。

注意
Soft-Q学習および最大エントロピー強化学習に興味がない場合は ②tensorflow2での実装 だけで十分です。

次:②tensorflow2での実装 horomary.hatenablog.com


Soft-Q Learning論文: [1702.08165] Reinforcement Learning with Deep Energy-Based Policies

SAC論文 ①: [1801.01290] Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor

SAC論文 ②: [1812.05905] Soft Actor-Critic Algorithms and Applications

SAC論文 ③: https://arxiv.org/pdf/1812.11103.pdf


前提手法:DDPG, DQN

horomary.hatenablog.com

horomary.hatenablog.com


Sergey Levineの講演
youtu.be


はじめに

Soft Actor Critic (SAC) は 確率的方策*1を利用可能にした DDPG と実装的には理解することができます。

DDPGはオフポリシー学習に由来するサンプル効率の良さというメリットの一方で、決定論的方策ゆえの探索力の弱さに由来するハイパラ調整の困難さと高次元行動空間の不得手さという課題を抱えていました。そこで、SACはDDPGへSoft-Q学習確率的方策を導入することによってDDPGの探索の弱さの問題を自然に解決しました。

Soft-Q-learningでは報酬r(s, a)に方策エントロピー項を組み込むことにより、”報酬最大化”も”探索”も目的とすることでQ学習で自然に探索を行うことを可能にします。

※DDPGとTD3については過去記事を参照

DDPGでPendulum-v0(強化学習, tensorflow2) - どこから見てもメンダコ

TD3の解説・実装(強化学習) - どこから見てもメンダコ


Q学習における探索促進テクニック

方策が局所最適に陥らないために探索と活用(Exploration vs. Exploitation)のバランスをうまくとることは強化学習において重要な課題の一つです。 しかし、もっともシンプルなQ学習では常にQ関数を最大化するアクションを採用する決定論的方策である”貪欲方策 (Greedy policy)”を使用するので、探索力の弱さという問題を抱えることとなります。

貪欲方策
 \displaystyle{
\pi(a) = \underset{a} {\text{argmax }} Q(s, a)
}


このQ学習の探索力の弱さを補うためによく使われるアプローチがε-Greedy方策です。この方法はDeepmindDQN (2013)でも使用されています。このアプローチはごく単純で、行動の決定時にεの確率で完全にランダムなアクションを採用し、1-ε の確率で貪欲方策でアクション決定を行うことで貪欲方策を確率的貪欲方策へ拡張し探索力を高めようというものです。

ε-Greedy方策
(1-ε) の確率で:貪欲方策  \displaystyle{
\pi(a) = \underset{a} {\text{argmax }} Q(s, a)
}
εの確率で: ランダムなアクションを選択


Greedy方策のように推定Q値を最大化(hard-max)するアクションを採用するのではなく、推定Q値の指数分布に応じた選択確率で各アクションを採用する方策をSoftmax方策あるいはボルツマン方策*2 と言います。

Softmax方策
 \displaystyle{
\pi(a|s) = \frac { e^{ \frac{1}{\beta} Q(s, a)} }{\sum_{i}{ e^{ \frac{1}{\beta} Q(s, a_{i})} }}
}

softmax方策が効果を発揮するのは取りうる選択肢に似たようなQ値のアクションが並ぶ時です。たとえば状態sにおける選択肢にa1, a2があったとしてそのQ値がQ(s, a1)=100, Q(s, a2)=101 という拮抗した場合であっても貪欲方策では常にa2が選ばれてしまいます。一方でsoftmax方策の場合はa1とa2のQ値が似ていれば同じ程度の確率でa1, a2が選択されます。また、softmax方策は微分可能な確率方策であることも重要なポイントです。


詳細は説明しませんが、他にもQ関数の出力に確率的なノイズを追加する NoisyNet のようなアプローチもあります。また、分散並列強化学習手法であるApex-DQNではε-Greedyの拡張として並列agentのそれぞれに異なる探索率εを設定するというようなテクニックを採用しています。

このようにQ学習における探索促進手法はさまざまありますが、ここまでで紹介したものはすべて アクション選択に確率的なノイズを乗せることによって探索を促進するアプローチである、とまとめることができます。


Soft-Q学習:探索 ”も” 目的とするQ学習

※簡単のため割引率=1.0の場合かつP(s' | s, a) = 1の決定論的な挙動をする系の場合で考えます

[1702.08165] Reinforcement Learning with Deep Energy-Based Policies

ここまで紹介した探索促進テクニックはあくまで確率的ノイズの追加によって探索を促進する手法でした。これに対して、報酬に方策エントロピー項を組み込むことにより、”報酬最大化”も”探索”も目的とすることでQ学習で自然に探索を行うことを可能にする、というのがSoft-Q学習の中心的なコンセプトです。

具体的にはSoft-Q学習では期待総報酬に加えて、方策エントロピーの期待値も最大化することも目指します。

一般的な強化学習では総報酬の期待値を最大化することを目的関数とする
 \displaystyle{
J(\pi) = E_{\pi} \left[{ \sum_{t=0}^{T}{R(s_t, a_t)} }\right]
}


Soft-Q学習では総報酬の期待値と方策エントロピーを最大化することを目的関数とする
 \displaystyle{
J_{soft}(\pi) = E_{\pi} \left[{ \sum_{t=0}^{T}{(R(s_t, a_t)} + \alpha H(\pi( \cdot | s_t)) )}\right]
}
 \displaystyle{ H(\pi( \cdot | s_t)) } は方策のエントロピー, αはハイパーパラメータ


方策エントロピーとは

強化学習における方策のエントロピーとは直感的にはアクション選択におけるランダムさの尺度であると表現できます。
たとえばガウス方策であればσの大きさでエントロピーの大きさが決まります。

数式で言えば、方策のエントロピーHとはアクションの対数選択確率  \displaystyle{\log\pi(a | s)} の期待値です。
期待値ですので方策に従ってアクションが生成されているサンプルの場合、つまり普通に強化学習エージェントが方策に従ってサンプルを収集している場合は \displaystyle{\log\pi(a | s)}のミニバッチ内での単純平均を計算すればOKです。*3

 \displaystyle{
H(\pi( \cdot | s_t)) = \sum_{a} {-\pi(a | s)\log\pi(a | s)} = E_{a\sim\pi} \left[ {-\log\pi(a | s)} \right]
}

方策エントロピーが大きいということは同じ状態Sを入力しても異なるアクションAが採用される可能性が高いということです。よってこの方策エントロピー項が目的関数に組み込まれることにより、Q学習における探索の問題を自然に解決することが期待できます。

また、エントロピー最大化を目的関数に組み込むことは他にも転移学習が楽になるなどいろいろメリットがあります。このあたりの詳細は下記リンクによくまとまっているので参照ください。 bair.berkeley.edu


Soft Q 関数の更新 *4

まずは上述のエントロピーの定義に従ってSoft-Q学習の目的関数を書き直しました。

Soft-Q学習の目的関数
 \displaystyle{
J_{soft}(\pi) = E_{\pi} \left[{ \sum_{t=0}^{T}{(R(s_t, a_t)} -  \alpha \log\pi(a_{t} | s_{t}) )}\right]
}

この目的関数を最大化するためのQを考えると、soft-Q学習におけるベルマン方程式は下記のように書けます。

Soft-Q学習におけるベルマン方程式
 \displaystyle{
Q_{soft}(s_{t}, a_{t}) = R(s_{t}, a_{t}) + E_{\pi}\left[ - \alpha \log\pi(a_{t+1} | s_{t+1}) + Q_{soft}(s_{t+1}, a_{t+1})\right]
}

普通のQ学習における価値関数Vが、  \displaystyle{
V(s_{t}) = E_{\pi}\left[ Q(s_{t}, a_{t})\right]
} と表現できるのに対して、
Soft-Q学習における価値関数Vは  \displaystyle{
V_{soft}(s_{t}) = E_{\pi}\left[ - \alpha \log\pi(a_{t} | s_{t}) + Q(s_{t}, a_{t})\right]
}となるので、状態Vにエントロピーという価値が追加されています。

ちなみにこの式は ”SoftQ学習における即時報酬 = 通常の即時報酬 + 遷移先でのエントロピーボーナス” と捉えると普通のQ学習におけるベルマン方程式と同じと見ることもできます。

備考:Q学習とのつながり
 \displaystyle{
Q_{soft}(s_{t}, a_{t}) = R_{soft}(s_{t}, a_{t}) + E_{\pi}\left[ Q_{soft}(s_{t+1}, a_{t+1})\right]
}
 \displaystyle{
\text{where}\quad R_{soft}(s_{t}, a_{t}) = R(s_{t}, a_{t}) + E_{\pi}\left[{ - \alpha \log\pi(a_{t+1} | s_{t+1})  }\right]
}


Soft-Q学習における方策更新

Soft-Q学習における方策関数は出力するアクションの確率分布がSoft-Q関数の指数分布(つまりsoftmax方策)に比例するように更新することで最適方策に収束します。つまりQ関数から得られるsoftmax方策を近似する関数を方策関数として実装します。

ここで、もし離散行動空間であれば方策を関数近似する必要はなくDQNスタイルで実装したQ関数の出力からsoftmax方策を実行すればOKです。そうではなくわざわざ近似関数を別に実装するのは連続行動空間でQ関数からSoftmax方策を得るのは簡単ではないためです。Soft-Q学習における方策関数はQを扱いやすくするための近似関数でしかないため、著者は後のSAC論文でこの実装はactor-criticっぽくはあるが真のactor-criticフレームワークでは無いと述べています。


※図はhttps://bair.berkeley.edu/blog/2017/10/06/soft-q-learning/より

”方策関数の出力するアクションの確率分布がSoft-Q関数の指数分布に比例するように更新”、を実現するためには十分に表現力の高い形式で方策関数(論文ではdeep-energy based policyと呼ばれている形式)を用意し、方策関数の出力する確率分布とSoft-Q関数から得られるsoftmax方策とのKL距離を最小化するように更新していけばOKです。とまあ言うだけなら簡単なのですが、連続値制御でこれを実現しようとしたらとんでもなく実装が煩雑になってしまった、というのがSACの理論的根拠になっているSoft-Q学習([1702.08165] Reinforcement Learning with Deep Energy-Based Policies)です。


Soft Actor Critic(SAC)

Soft-Q学習の理論的貢献は素晴らしいのですがあまりに実装が煩雑で実用性がイマイチという欠点がありました。また、表現力が非常に高い形式の方策関数を使用したために学習が潜在的に不安定になるという問題もあります。

そこで[1801.01290] Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic ActorではSoft-Q学習を理論的根拠にしつつも、Soft-Q学習における方策関数はSoft-Q関数から得られるsoftmax方策の厳密な近似器である必要がなく、任意の形式の方策(例:ガウス方策、混合ガウス方策 など)を使用してよい ことを新たに証明し、シンプルなactor-critic型のSoft-Q学習を提案しました。これがSoft-Actor-Criticです。

ちなみに最新のSACの実装はDDPGおよびその改良手法であるTD3と非常によく似ており、TD3に多少の改変を加えるだけで実装できてしまいます。


混合ガウス方策について

いくら任意の方策関数の形式でもよいとは言え、Soft-Q学習の流れから考えればdeep-energy based方策とまでは言わずとも混合ガウス分布方策のようにある程度表現力が高い方策関数のが良いのだろうと思います。

実際、初期versionのSAC論文(OpenReview版, 下記リンク)では混合ガウス分布方策を前提にしているのですが、同じ論文内の HalfCheetah-v1における検証実験では単ガウス方策でも16-混合ガウス分布方策でもほぼ性能が変わらないということが示されています。

https://openreview.net/pdf?id=HJjvxl-Cb

これを受けてなのか、後の版の実験セクションでは何も言わずに単ガウス方策での結果を示しています。だからと言って必ずしも混合ガウス方策が無意味と決まったわけではなく、mujoco環境程度ではそこまで複雑な表現ができる方策関数は必要ないというだけで今後再評価されるときが来るかもしれません。


SAC実装の変遷

The SAC algorithm has changed a little bit over time. An older version of SAC also learns a value function V_{\psi} in addition to the Q-functions; this page will focus on the modern version that omits the extra value function.
Soft Actor-Critic — Spinning Up documentation

と書いてある通り、SACの実装は初期から少し変化しています。

大きな違いは下記の2点です
・初期の実装はQ、V、π を関数近似していたが、最新の実装はQ、πのみ関数近似する
・温度パラメータαは初期はハイパラとして与えていたが最新の実装では訓練の中で自動調整する

実装の詳細については ②tensorflow2での実装 にて

horomary.hatenablog.com


参考リンク

OpenAI Spinning up: Soft Actor-Critic — Spinning Up documentation

UCバークレーBAIR:
Learning Diverse Skills via Maximum Entropy Deep Reinforcement Learning – The Berkeley Artificial Intelligence Research Blog

Soft Actor Critic—Deep Reinforcement Learning with Real-World Robots – The Berkeley Artificial Intelligence Research Blog

カーネギーメロン大講義資料:https://www.andrew.cmu.edu/course/10-403/slides/S19maxentRL.pdf

マギル大講義資料: https://www.cs.mcgill.ca/~cs526/roger.pdf

南京大講義資料:http://www.lamda.nju.edu.cn/yanggy/slide/Maximum_entropy_RL_Guoyu_Yang.pdf

Maximum Entropy Reinforcement Learning (Stochastic Control)


*1:たとえばガウス分布の平均と分散を出力する方策ネットワーク

*2:ちなみにボルツマン方策といわれるのは、統計力学などで用いられる気体などにおける系内の各分子のエネルギー分布を示すボルツマン分布と同じ形だからです。βを温度パラメータと言うのもこれに由来します。βが小さいほど=温度が低いほどエントロピーの寄与が小さくなるためエネルギー=Q値の重要度が高まっていきβ=0のときhardmax方策(貪欲方策)に一致します。

*3:サイコロを2個振ったときの和の期待値を計算するために2×1/36+2×2/36+... と各事象ごとの確率から期待値を計算するか、実際にサイコロ2個振る試行を100回繰り返して単純平均をとるかの違い

*4:Soft-Q学習の説明はSoft-Q learningの論文である"Reinforcement learning with deep energy based policies" よりも "Soft Actor-Critic Algorithms and Applications"に掲載の説明の方が分かりやすいので後者をベースに説明

ハムスターでもわかるProximal Policy Optimization (PPO)②TF2による実装

PPOをTensorflow2で実装しBipedalWalker-v3を攻略します。手法解説は①を参照ください。

[PPOシリーズ]

【強化学習】ハムスターでもわかるProximal Policy Optimization (PPO)①基本編 - どこから見てもメンダコ

ハムスターでもわかるProximal Policy Optimization (PPO)②TF2による実装 - どこから見てもメンダコ


f:id:horomary:20200909231745p:plain


PPO論文: [1707.06347] Proximal Policy Optimization Algorithms

コード全文はgithubへ:

github.com


1. Surrogate Objective Clipping による方策更新

PPOのコアアリゴリズムであるSurrogate objective clipping (代理目的関数クリッピング) で方策を更新する場合、方策関数と価値関数がパラメータを共有するA2C型モデル か 方策関数と価値関数を別に定義するTRPO(というか普通のActor-Critic)型モデルのどちらを採用するかで更新式が異なります。前者は離散値コントロールのaratiドメインで、後者は連続値コントロールのmujokoドメインで良好な性能を発揮することが論文中で示されています。

今回は連続値コントロールタスクであるBipedalWalker-v3をターゲットとするので、コードはパラメータ共有をしないTRPO型のモデル、すなわち典型的なActor-Criticモデルの場合のみを示します。


パラメータを共有するA2C型モデルの場合

方策ネットワークと価値ネットワークがパラメータを共有するA2C/A3C型のモデルでは”ロス関数=方策勾配ロス+価値ロス+方策エントロピーボーナス” としてパラメータ更新します。この方策勾配ロスをSurrogate objective clipping に置き換えるだけでPPOとなります。したがってA2C/A3Cの実装をわずかに変更するだけで実装完了です。この実装はAtari環境での良好なパフォーマンスからA2Cの改良手法と位置付けることができます。

【強化学習】A3CでCartPole【TF2】 - どこから見てもメンダコ


パラメータを共有しないTRPO型モデルの場合

一方でPPOをTRPOの改良手法として位置付ける場合は、価値関数と方策関数を別に定義する典型的なActor-Criticモデルを実装します。

この場合、tensorflow2での方策関数の更新コードは以下のようになります。

tensorflow2系のtf.GradientTapeではwithコンテクスト内での計算のみ勾配が流れます。この仕様はPPOと大変相性が良く、上のようなシンプルな実装が可能になります。advantagesold_logprobtf.GradientTapeの外で計算しておくのがポイント。


また、収集したサンプル群から2048step分をランダムサンプリングし、ポリシーを更新することを20回繰り返すという、 オンポリシー強化学習なのにオフポリシー強化学習のような一見違和感のある実装をしています。

これは重点サンプリング(Importance Sampling)という関心のある分布とは異なる分布から生成されたサンプルから別の分布の特性を推定する計算トリックが可能にしている実装なのですが説明すると長いのでTRPOの過去記事をご覧ください。

horomary.hatenablog.com

更新を20回でなく100回あるいは200回繰り返したとしても、clippingはold_policyを参照するためポリシーの過学習を回避できるというのも重要なポイントです。


2. Advantage(GAE)の計算

advantageの計算にはさまざまな方法がありますがPPOではGeneralized Advantage Estimation (GAE) で実装することが論文内で明言されています。

[1506.02438] High-Dimensional Continuous Control Using Generalized Advantage Estimation

f:id:horomary:20201021011908p:plain:w600
PPO論文より

なんでこの式になるかの説明も長いので省略しますが、とりあえず実装すると下のようになります。

rewardを過去のrewardから算出した標準偏差で割ることによりスケーリングしていることに注意してください。報酬のスケーリングは連続値環境においては強い学習安定化効果があることが知られています。
※running_statsの算出はbaselinesのコードを転用しています。
baselines/running_mean_std.py at master · openai/baselines · GitHub

ただし、今回のターゲットであるBipedalWalker-v3は通常時の報酬が-1から1程度なのに対して転倒時が-100という非常に大きな負報酬が設定されておりrunning_statsを狂わせます。そこで、転倒時報酬は-1に変更しています(後述のwokerクラスを参照)。


3. 非同期/同期並列化

PPO論文ではトラジェクトリの収集で並列化agentを使用することが明言されています。

強化学習におけるAgentの並列化では、A3Cのような分散非同期並列化とA2Cの同期並列化のどちらかがよく採用されます。GPUが一つしかない場合には後者の同期並列化の方が効率がよいので、今回はbaselinesのSubprocVecEnv( baselines/subproc_vec_env.py at master · openai/baselines · GitHub

)をベースに、pythonの分散並列処理ライブラリであるRayで再実装しました。

※ちなみにbaselinesのppo1は非同期並列、ppo2は同期並列実装です。

rayを使うことで並列化をとてもシンプルに記述することができました。

github.com

この同期並列環境は以下のように動かします。


学習実行と結果

ここまででPPOに必要な要素はすべて揃いました。さっそくBipedalWalker-v3をターゲットに学習を開始します。

コード全文: RL_TF2/PPO/Bipedalwaker-v3 at master · horoiwa/RL_TF2 · GitHub


ポリシーの標準偏差は固定値かつ大きめで実装したところ、コケやすいドジっ子walkerになってしまいました。 f:id:horomary:20201022233244p:plain:w500


しかし、trajectoryの総報酬(=1000stepごとの報酬和)で見ると単調増加しておりPPOがうまく実装できていることがわかります。 f:id:horomary:20201022233543p:plain:w500


実装のための備考

  • PPOでは報酬を方策更新に直接使用するので、Bipedalwalker環境の転倒時-100という大きすぎるペナルティは学習を阻害します。よって学習時は転倒時ペナルティを-1に変更していることに留意ください。DDPGやTD3なんかだとこの問題が生じないのは得た報酬を方策更新に直接使用しないからでしょう。

  • 連続値コントロール環境では、trajectoryサイズおよびポリシー更新時のバッチサイズどちらも大きめにとる方がよさそうに感じます。

  • Value Clippingは効果の有無がよくわからなかったので実装すれども紹介せず