OpenAIのSpinning Upで強化学習を勉強してみた その3
はじめに
その3ということで一応Introduction to RLの最終回.今回勉強したページはこちら
Part 3: Intro to Policy Optimization
今回はpolicy optimizationの基礎理論とその実装について.
Deriving the Simplest Policy Gradient
まずはでparameterizeされた確率的なpolicy を考える.目標はexpected return の最大化で,今回はfinite-horizon undercounted return(減衰しない固定長区間の報酬の和)とする(ただしinfinite-horizon discounted returnでも結果は同じ).
基本的には次のような勾配上昇法によってpolicyを最適化していく.
はpolicy gradientと呼ばれ,policy gradientを使ってpolicyの最適化を行うアルゴリズムをpolicy gradient algorithmsというらしい.
ということでpolicy gradientを求めてみる.まずはpolicy gradientを計算するのに必要なtrajectoryの確率の微分を求める.Policy におけるtrajectory の確率は次のように与えられる.
ここで連鎖律と対数の導関数を利用して次のようにの導関数を表現.
Trajectoryの確率の対数は
となることからは次のようになる.
最後の等式はがと無関係なことから導かれる.以上から最終的に求めたいpolicy gradientは次のようになる.
最後の期待値の計算はサンプル平均として計算することで勾配を実際に計算することが可能.すなわち,trajectoryの集合がエージェントの行動の結果得られたとした時,policy gradientは次のように計算される.
ここにはpolicyの対数が微分可能であるという仮定と,trajectoryのデータを集めるために環境においてpolicyを実行可能という仮定が入っていることには注意.ただ,実際は自動微分のおかげで勝手に計算してくれるので実装に関してはめちゃくちゃ簡単にできる.
Implementing the Simplest Policy Gradient
Spinning upのgithubのrepositoryにpolicy gradient algorithmの実装例があって,わずか122行で実装可能とのこと.ただ自分はpytorch派なので,pytorchで再現実装してみました(元のコードをなるべく崩さないように書いたので不自然な記述方法があったりするので注意).以下コード.
import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym from gym.spaces import Discrete, Box def mlp(sizes, activation=nn.Tanh, output_activation=None): layers = [] for i in range(1,len(sizes)-1): layers.append(nn.Sequential( nn.Linear(sizes[i-1], sizes[i]), activation() )) layers.append(nn.Linear(sizes[-2], sizes[-1])) if output_activation is not None: layers.append(output_activation()) return nn.Sequential(*layers) def multinomial(logits, num_samples=1): return torch.distributions.Multinomial(num_samples, logits=logits).sample() def train(env_name="CartPole-v0", hidden_sizes=[32], lr=1e-2, epochs=50, batch_size=5000, render=False): if torch.cuda.is_available(): device = "cuda" else: device = "cpu" # make environment, check spaces, get obs / act dims env = gym.make(env_name) assert isinstance(env.observation_space, Box), \ "This example only works for envs with continuous state spaces." assert isinstance(env.action_space, Discrete), \ "This example only works for envs with discrete action spaces." obs_dim = env.observation_space.shape[0] n_acts = env.action_space.n # make core of policy network policy = mlp([obs_dim] + hidden_sizes+[n_acts]).to(device) optimizer = optim.Adam(policy.parameters(), lr=lr) def train_one_epoch(): # make some empty lists for logging batch_obs = [] batch_acts = [] batch_weights = [] batch_rets = [] batch_lens = [] # make obs = env.reset() done = False ep_rews = [] finished_rendering_this_epoch = False while True: with torch.no_grad(): # rendering if not finished_rendering_this_epoch: env.render() # save obs batch_obs.append(obs.copy()) logits = policy(torch.from_numpy(obs[None]).float().to(device)) act = multinomial(logits).squeeze().to("cpu").detach().numpy() obs, rew, done, _ = env.step(act.argmax(0)) # save obs batch_acts.append(act) ep_rews.append(rew) if done: # if episode is over, record info about episode ep_ret, ep_len = sum(ep_rews), len(ep_rews) batch_rets.append(ep_ret) batch_lens.append(ep_len) # the weight for each logprob(a|s) is R(tau) batch_weights += [ep_ret] * ep_len # reset episode-specific variables obs, done, ep_rews = env.reset(), False, [] # won't render again this epoch finished_rendering_this_epoch = True # end experience loop if we have enough of it if len(batch_obs) > batch_size: break # take a single policy gradient update step batch_obs = torch.from_numpy(np.array(batch_obs)).float().to(device) batch_acts = torch.from_numpy(np.array(batch_acts)).float().to(device) batch_weights = torch.from_numpy(np.array(batch_weights)).float().to(device) logits = policy(batch_obs) loss = -( batch_weights * (batch_acts * nn.functional.log_softmax(logits, 1)).sum(1)).mean() optimizer.zero_grad() loss.backward() optimizer.step() return loss, batch_rets, batch_lens for i in range(epochs): batch_loss, batch_rets, batch_lens = train_one_epoch() print('epoch: %3d \t loss: %.3f \t return: %.3f \t ep_len: %.3f'% (i, batch_loss, np.mean(batch_rets), np.mean(batch_lens))) env.env.close() if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('--env_name', '--env', type=str, default='CartPole-v0') parser.add_argument('--render', action='store_true') parser.add_argument('--lr', type=float, default=1e-2) args = parser.parse_args() print('\nUsing simplest formulation of policy gradient.\n') train(env_name=args.env_name, render=args.render, lr=args.lr)
雑に移植しただけなのでコードは元のやつが参考になるかと.
サンプルコードの問題設定はCartPoleで棒が倒れないようにするあれ.強化学習の環境についてはopenai gymを使って実装.今回のCartPoleについてはここ参照.観測としてはcartの位置と速度,poleの角度と速度の4次元が得られる.Policyは2層のニューラルネットなので観測の4次元をとすればのように表現される.行動はcartを左か右に動かすかの2択なのでpolicyの出力は2次元.出力された確率からサンプリングによって行動を選択し,poleが倒れるなどの終了条件を満たすまで繰り返しサンプルを収集.rewardは毎行動ごとに1与えられる.よって最大化すべき関数は選択された行動を示すone-hotベクトルをとすればとして計算できる.
コード内でlossを計算しているいわゆるloss functionの役割を果たしている式があるが,これは厳密にはloss functionではない.基本的にloss functionはデータ分布が固定の元で計算されるが,この場合では直近のpolicyにおいてサンプルされたデータで学習を行うためデータ分布がパラメータ(policy)に依存する.また,基本的にはloss functionは予測結果の良し悪しをはかる指標となるが,ここでのloss functionは現在のパラメータの良し悪しをはかる.要は何が言いたいかというと,強化学習においてデータはエージェントの行動の結果得られるため,行動を決めるpolicyのパラメータ次第でデータの分布が変わるのでいわゆるloss functionとしての役割とは少し違うということ.
Expected Grad-Log-Prob Lemma
ここではExpected Grad-Log-Prod (EGLP)と呼ばれる命題を解説.
・EGLP Lemma
ここではpolicy gradientsを通して使われる中間的な結果を導く. ある確率変数が従うでparameterizeされた確率分布は次を満たす.
・証明
は確率分布なので.について微分すれば.この関係を用いれば
Don't Let the Past Distract You
ここまでpolicy gradientを以下のように表現した.
この勾配を使えば報酬の和であるに比例した行動の対数確率を増加させることができるが,実はこれはあまりよくないとのこと.
エージェントは結果に基づいて行動を決めるべきだが,行動の前に得られる報酬は行動がどれくらいよかったかには全く関係がない.この問題を解決するために次のようにpolicy gradientを表現する.
何が変わったかというと,rewardの計算がもともとと行動を起こした時刻に関係なく全ての時刻に対する総和の計算だったのに対し,行動を選択した時刻以降の足し合わせに変わっている.こうすることによって,行動を起こす以前の報酬を考慮しない形になるので良いだろうということ.ちなみにこれをreward-to-go policy gradientと呼びと表す.
Implementing Reward-to-Go Policy Gradient
ということでreward-to-go policy gradientを実装.rewardの計算が変わるだけなのでさっきのコードを一部修正するだけで動く.具体的には次のreward-to-goを計算する関数(サンプルコードまんま)を用意.
def reward_to_go(rews): n = len(rews) rtgs = np.zeros_like(rews) for i in reversed(range(n)): rtgs[i] = rews[i] + (rtgs[i+1] if i+1 < n else 0) return rtgs
batch_weightsの部分を
batch_weights += list(reward_to_go(ep_rews))
に変更.これでreward-to-goバージョンのpolicy gradientになる.学習の安定性は増した気がする.
Baselines in Policy Gradients
EGLPの結果は状態のみに依存する任意の関数に対して適用可能.
なので,次のように任意の数を引いたり足したりすることが可能.
ここで使われる関数はbaselineと呼ばれ,一般的な選択肢としてon-policy value function がある.
経験的にとすることはpolicy gradientにおいてsampleのばらつきを減らす効果があるらしく,結果として学習の速度と安定性が向上するとのこと.ただ,実践的にはを正確に計算することはできないので近似計算することになる.近似計算にはニューラルネットを使うことが多く,このvalue functionを計算するvalue network はpolicyと同時に更新されていく.
を学習する最も単純なものは以下の二乗誤差を目的関数として学習する方法.
はエポック目のpolicyで,過去のパラメータからまでに複数回のパラメータの更新が行われる.
Other Forms of the Policy Gradient
今までの内容を踏まえてpolicy gradientを一般化すると次の形になる.
はここまでやってきた例で言えば,だったり,だったり,だったりする.その他の選択肢として次の2つも重要.
- On-Policy Action-Value Function
Q関数を使っても良いという証明はこちら.
- The Advantage Function
Advantage functionを使っても良いというのはQ関数を使っても良いということから言える.
曰くadvantage functionを使ったpolicy gradientsはとても一般的な方法らしく,advantage functionを推定するたくさんの方法があるそうで,Generalized Advantage Estimation(GAE)の論文を読むことを推奨していた.のでまた今度読む.
まとめ
とりあえず単純なアルゴリズムで強化学習を試すというところまで.OpenAI gymがよくできていて,実装にかかるコストがめちゃくちゃ削減されているのが嬉しい.
とりあえずspinning upのintroduction to RLはこれで終わり.後は実際に色々手を動かしたり論文読んだりして各々頑張ってくれ的な感じなのでやってみようと思う.
OpenAIのSpinning Upで強化学習を勉強してみた その2
はじめに
OpenAIが提供するSpinning Upで深層強化学習の勉強をしたのでメモその2.今回勉強した内容はこちら.
Taxonomy of RL Algorithms
RLアルゴリズムを手法ごとに分類しようというもの.Part2のページに木構造でいい感じにまとめた図がある.Part 2の目標として各アルゴリズムが何をどのように学習しているか,アルゴリズムの長所と短所,最近のアルゴリズムをここでの枠組みに当てはめられるようになることの三点.
Model-Free vs Model-Based RL
RLアルゴリズムを分類する上で最も重要な点の一つが,エージェントが環境のモデルを参照もしくは学習するかどうか.ここでの環境のモデルというのは状態遷移と報酬を予測する関数を意味する.
環境モデルを利用する方法は,エージェントが行動を選択した結果何が起こるかを見て計画を立てるというもの.有名な例としてはAlphaZeroがこのアプローチを利用している.将棋や囲碁のようなボードゲームでは指し手を数手先まで予想してから行動を決定する.これが行動の結果を見るということ.
逆にモデルを持たない方法は環境の真のモデルをエージェントは利用できない.仮に利用したいと思う場合には学習して獲得する必要がある.ただ学習することの大きな課題として,学習して得られた環境モデルのバイアスをエージェントが直に受け取ってしまうという点.そのため実環境においてパフォーマンスを大きく低下させる場合がある.基本的にモデルの学習は困難で,大量の時間と計算リソースを費やす必要があるとのこと.
モデルを利用するアルゴリズムをmodel-based methodsといい,その逆をmodel-free methodsという.model-freeはモデルから得られる潜在的な利得を諦める代わりに実装が単純という利点があり,今自分が読んでるpart2執筆時点ではmodel-free methodsが広く使われているということ.
What to Learn
もう一つのアルゴリズム分類基準として何を学習しているかという点がある.学習対象の候補としては以下の4つ.
・policies
・action-value functions (Q関数)
・value functions
・environment model(環境モデル)
What to Learn in Model-Free RL
Model-free RLには主に二つのアプローチが存在.
Policy Optimization
Policy を学習する方法.を直接または間接的に最大化することでを最適化する.この最適化はほとんどがon-policyとして行われ,実際行動した結果集められたデータを利用して最適化が行われる.また,policy optimizationは普通on-policy value function を近似するの学習も含む.
Policy optimizationの例として勾配上昇法を利用して直接最大化するA2C/A3Cやを上昇させるような代わりとなる目的関数を最適化するPPOアルゴリズムなどがある.
Q-Learning
Optimal action-value function を近似するを学習する方法.Bellman方程式に基づく目的関数を利用するのが一般的.最適化はoff-policyで行われ,エージェントの振る舞いに関わらず任意の時点で得られたデータを使って最適化が行われる.Q-learningによって選ばれる行動は次のように与えられる.
Q-learningの例としてはDQNやC51がある.
Trade-offs Between Policy Optimization and Q-Learning
Policy optimizationの強みとしては,目的に対して直接的に最適化を行うことができるという点.対して,Q-learningはself-consistency equationを満たすようにを学習することによってエージェントの振る舞いを間接的に最適化するだけで成り立っているため,学習に失敗しやすい.ただ,Q-learningはpolicy optimizationに比べサンプルを効率的に収集/再利用可能なためデータ量において利点がある.
What to Learn in Model-Based RL
Model-free RLと比べてmodel-based RLには簡単な分類手段がないとのこと.ここではいくつかの例をあげる.
Background: Pure Planning
多くの基本的なアプローチはpolicyを陽に表現することはなく,代わりに行動選択のためにmodel-predictive control (MPC)のようなpure planning techniquesを使う.MPCでは,エージェントが環境を観測するたび,モデルに従って最適な行動を選ぶ.この時,現時刻からある固定長先の時刻までの間で取ることができる全ての行動を記述することで最適な行動を選ぶ.将棋や囲碁でいうと,5手先までの選択肢を全て列挙して最適な指し手を選ぶというところ(これが俗に言う水平線効果を生じさせる原因?).
Expert Iteration
Pure planningを単純に改変しようとするとpolicy を陽に表現または学習して獲得するという方法が考えられる.エージェントはモデルを利用したplanning algorithmを使うことで現在のpolicyからサンプリングすることで行動の候補を生成する.この生成された行動はpolicyのみで選択された行動より良い行動となる.そのためこのpolicyに対して"expert"と呼ばれ,policyはplanningアルゴリズムの出力,すなわちexpartのような行動をするように学習されていく.
Data Augmentation for Model-Free Methods
これはpolicyもしくはQ関数を学習するためにmodel-free RLを使うものだが,エージェントの更新においてシミュレーション結果を現実のものとして拡張する(これがどう言う意味かはいまいちわからなかった.),もしかはシミュレーション結果のみを使ってエージェントの更新を行う.
Embedding Planning Loops
もう一つのアプローチとしてはplanning procedureをpolicyとして利用するというもの.この方法はモデルのバイアスを減らすことが可能とのこと.
まとめ
ざっくりとRLのアルゴリズムを分類.各分類ごとに手法の例が示されていたので適当に論文も読んで勉強して行きたい.
OpenAIのSpinning Upで強化学習を勉強してみた その1
はじめに
OpenAIが提供するSpinning Upで深層強化学習の勉強をしたのでメモ.ちなみに強化学習は完全素人で何も知らない状態から始めていて,とりあえずの取っ掛かりとしてSpinning Upを利用してみたと言うところ.個人的にtensorflowで書かれているのがしんどい.
Part 1: Key Concepts in RL
まず,強化学習(RL; Reinforcement Learning)とは何かというざっくりとした概念の説明.
Part 1のページはこちら.
Key Concepts and Terminology
RLはエージェント(agent)と環境(environment)という二つの主要な要素から成り立っている.環境はエージェントが存在して行動をする世界のこと.エージェントは行動のたびに世界の状態を観測して取りべき行動(action)を決定する.例えば将棋(趣味が将棋なので)の場合は,盤面の駒の配置(環境)を観測した後エージェントはどの駒をどこに動かすか(action)を決定するということ.
ただ,エージェントは闇雲に行動しても意味がないので,エージェントは行動した結果に対し環境から報酬(reward)を受け取る.報酬は行動の良し悪しによって与えられる報酬が変わり,この報酬を目安として最適な行動を取るように学習していくと言うものがRL.
以下,RLを学ぶ上で基本かつ重要な概念など.
States and Observations
状態(state)は世界(environmentとworldの違いがイマイチわからないがとりあえず環境,世界と区別して書く)の状態を記述したもので,に含まれない世界の状態の情報はない.それに対し観測(observation)は状態の一部を記述したもの.
Deep RLにおいて状態と観測はreal-valued vector, matrixまたはhigher-order tensorによって記述される.例えばロボットは観測をRGBカメラによって得るとすれば,はカメラによって得られたRGBの画像となる.この場合小さな部屋にロボットがいれば世界はその部屋の中で,観測はカメラで撮影された部屋の一部ということ.
仮にエージェントが環境の全ての状態を観測可能な場合には,その環境のことをfully observedといい,一部しか観測できない場合にはpartially observedという.
Action Spaces
異なる環境においては取れる行動の種類は異なる.車の制御ならアクセルとブレーキとハンドル操作,囲碁ならどこに石を置くかなど.逆にいえば車の制御という課題で碁石をおくという行動はできない.そのため,与えられた環境で許されている行動の集合をaction spaceと呼ぶ.このaction spaceは離散な行動のみを許すdiscrete action spacesと連続な行動を許すcontinuous action spacesがある.さっきあげた例だと車はcontinuousで囲碁はdiscrete.
このdiscreteかcontinuousかはRLの手法に大きな影響を与え,多くの場合どちらか一方にしか適用できないことが多く,もう一方のaction spacesに適用する場合にはアルゴリズムに大きな変更を要する場合があるとのこと.
Policies
Policyはエージェントがどの行動を取るか決めるのに使うルール.行動の選択が決定的な場合次のようにによって表現される.
もしくは確率的なものとしてを使って次のように表現される.
場合によってはagentをpolicyと置き換えて使うこともあるそう.
Deep RLにおいてはparameterized policiesを使い,上記のやがニューラルネットによって表されるとのこと.つまり,ニューラルネットのパラメータをと表現すれば次のように表現可能.
Deterministic Policies
Continuous action spaceにおけるdeterministic policiesの例として次のようなtensorflowのコードがあげられてた.
obs = tf.placeholder(shape=(None, obs_dim), dtype=tf.float32) net = mlp(obs, hidden_dims=(64,64), activation=tf.tanh) actions = tf.layers.dense(net, units=act_dim, activation=None)
これは先ほどの数式を使えばで表現できて,がいわゆる1層の全結合層になっている状態.
Stochastic Policies
Deep RLにおけるstochastic policiesは基本的にcategorical policiesかdiagonal Gaussian policiesを使うとのこと.
Categorical policiesはdiscrete action spacesの場合に使われ,diagonal Gaussian policiesはcontinuous action spacesの時に使われる.
Stochastic policiesでは次の2つの計算が重要となる.
・policyからの行動のサンプリング
・特定の行動の対数尤度の計算
Diagonal Gaussian policyに関してはガウス分布の平均は状態に関する関数として表現するのが一般的だが,分散に関しては2種類の表現が使われていて,一つは状態とは関係のないただのベクトルとして表現する方法で,もう一つはとする方法.
Trajectories
Trajectory は次のような世界の状態と行動の系列のこと.
つまり強化学習していく上で,環境がどのように変化したか,その時どのような行動をとったかのログ.初期の状態はstart-state distribution なる分布からサンプリングされる.
状態の遷移(時刻の状態から時刻で状態への移り変わり)は環境における自然な法則によって拘束されていて(つまりありえない移り変わりはできない),直近の行動にのみ依存する.この遷移も決定的,確率的なものがあり次のように表現される.
また,行動はpolicyから決められる.ちなみにtrajectoriesはepisodesやrolloutsと呼ばれることもあるとのこと.
Reward and Return
Reward function はRLにおいてめちゃくちゃ重要で,世界の現在の状態と選択された行動,それによって遷移した状態に依存する.
ただし,場合によっては簡単化されて現在の状態のみに依存,または状態と行動に依存する場合もある.
目標としてはtrajectoryに対してcumulative reward を最大化すること.選択肢の一つとしてfinite-horizon undisputed returnがあり,これは次のように固定ウィンドウ幅で報酬の和を取るというもの.
もう一つの選択肢としてはinfinite-horizon discounted returnで,エージェントから得られた全ての報酬の和を取るというもの.ただし,一般には適当な減衰率を使って重み付き和で表現される.
この減衰という操作には直感的な解釈と数学的な利点があって,直感的には後で受け取る報酬より直近の報酬の方が重要(出だしでつまづいたらどうしようもないということか),数学的には無限の足し合わせだと有限の値に収束しなくなって扱いにくいが,適当な減衰係数があることで収束するから嬉しいということらしい.
通常のRLだと上の二つのreturnは明確に定義されているが,ことdeep RLに関しては明確でない場合があるそう.deep RLだとしばしばundiscounted returnを最適化するアルゴリズムをセットアップするが,value functionsを推定するのに減衰係数を使うとのこと.(まだ詳しい話出てきてないのにいきなりこんなこと言われてもよくわからないが)
The RL Problem
Return functionやpolicyをどう選んだとてRLの目標はexpected returnを最大化するpolicyを選択すること(policyの選択がなんであろうとゴールは最適なpolicyを選ぶとはこれいかに).
Expected returnの説明をするために,状態遷移とpolicyが確率的な状況について考える.この時,ステップめのtrajectoryの確率は次のように与えられる.
この式は状態が以外とは独立なことから得られる.この時returnがどのようなものであれ,expected return は次のように計算できる.
これは普通に期待値の計算.するとRLの最適化問題はexpected returnの最大化なので次のように表現される.
Value Functions
Value functionsは状態または状態と行動のペアの価値を知るために使われる関数でほぼ全てのRLアルゴリズムで使われる.一般的にはexpected returnで表現され,主に次の4種類に分類される.
- On-Policy Value Function
状態から始まり,常にpolicyに従って行動する場合
2.On-Policy Actoin-Value Function
状態から始まり,最初にある行動を取り,その後常にpolicy に従って行動する場合
- Optimal Value Function
状態から始まり,その環境において最適なpolicyに従って常に行動するような場合
- Optimal Action-Value Function
状態から始まり,最初にある行動を取り,その後その環境において最適なpolicyに従って常に行動するような場合.
Value FunctionとAction-Value Functionの間には次のような関係がある.
要は取りうる行動に対してaction-value functionを周辺化すればvalue functionになる.
The Optimal Q-Function and the Optimal Action
状態における最適なpolicyはから始まるexpected returnを最大化する行動を選択する.その結果もしが得られれば,最適な行動を直接得ることができる.
ただし,expected returnを最大化する行動が複数存在する場合もあり,その時は行動はランダムに選ぶ.
Bellman Equations
実は先ほどあげた4つのタイプのvalue functionsは全てBellman equationsと呼ばれるspecial self-consistency equations(これは日本語だとなんて訳を当てるのか)に従う.
On-policy value functionsにおけるBellman方程式は次のように表現される.
はのことで,次の状態が環境の遷移分布からサンプリングされることを意味していて,は,はを表す,Bellman方程式は開始点における価値(value)はその点から期待される報酬( Reward)と次の点の価値[V^\pi(s')]の足し合わせであるという考えに基づいている.
Optimal value functionsに関するBellman方程式も同様に表現できる.
On-policy/optimal value functionのBellman方程式間の明確な違いは行動に対する最大化があるかないかのみ.
Advantage Functions
RLにおいてたまに,特定の状況下でとった行動がどれくらいよかったかではなく,ほかと比べて平均的にどれくらいよかったかを知りたい場合がある(ローカルに見るかグローバルに見るかという感じ).そのためadvantage functionの概念を作る.
あるpolicy に対応するadvantage function は,永久にに従って行動するという仮定の下,ある状態において特定の行動をとった時にどれくらいよかったかを記述するもの.数学的には次のようにかける.
Advantage functionsに関してはまた後ほど解説がある.
Formalism
文献を読んでいくとMarkov Decision Processes (MDPs)の設定に遭遇する場合があるだろうということ.ここはoptionalなので特に詳しいことはないが,MDPsは5-tuple,で定義されるもので,
・は取りうる全ての状態の集合
・は取りうる全ての行動の集合
・はreward functionで
・は遷移確率関数では状態で行動をとった時に状態に遷移する確率
・は初期状態分布(starting state distribution)
まとめ
とりあえずpart 1まで.まだここで出てきたものがどのように使われるか出てきてないので理解が進みにくいがなんとなく雰囲気はつかめた.
HOW POWERFUL ARE GRAPH NEURAL NETWORKS?を読んだのでメモ
はじめに
HOW POWERFUL ARE GRAPH NEURAL NETWORKS?を読んだのでメモ.各命題,定理の証明は今回は割愛.
2018.11.24
Openreviewにて論文で提案しているGINが定理3を満たさない(= WL testと同等の識別能力を有すると言えない)ということが示されて内容が変更されていたのでこちらのメモも少し修正.(修正抜けがあると思うので正確な内容を知りたい場合は論文を参照).
気持ち
Graph convolutional networks(GNN)がグラフデータに関する様々な課題においてstate-of-the-artを記録しているが,どの研究もヒューリスティックスに頼ったtrial-and-errorで手法が作られていることを問題視.もう少し理論的な理解とともに新しいGNNを提案するというもの.
Graph Neural networks
まずは一般的なGNNについて.を各ノードが特徴ベクトルを持つグラフとする.今回はnode classification(各ノードのラベルの予測)とgraph classification(グラフそのもののラベルの予測)の二つに焦点を当てる.
GNNは主にノードの表現ベクトルまたはグラフそのものの表現ベクトルを学習するために用いられ,基本的な戦略としては隣接ノードの情報を集約を繰り返すことでそのノードの持つ表現ベクトルを更新していく.一般的に回集約を繰り返すことで-hopの情報を得ることが可能.この集約の手続きは次のように表現できる.
は層目のノードが持つ特徴ベクトルで,.はに隣接するノード集合.の選び方によってGNNは区別される.例えば,KipfとWellingが提案したGCNは次のような関数として定義される.
は学習パラメータとなる行列.GraphSAGEは関数を要素ごとのmax-poolingに置き換えたものとして表現できる.またGraphSAGEにおいてはのステップとしてという演算が存在する(GCNにはの処理はない).
Node classificationにおいては,ノードの表現ベクトルを使って予測を行い,graph classificationにおいては次のような関数によりノードの表現ベクトルの集約が行われる.
は基本的にpermutation invariantな関数である必要がある.
Weisfeiler-Lehman test
Weisfeiler-Lehman test(WL test)は各ノードにカテゴリカルラベルが付与されていると仮定した元で,(1)ノードとその隣接ノードのラベルをaggregate,(2)集約されたラベルをユニークな新しいラベルに変換,という処理を繰り返すもので,この処理を繰り返した結果二つのグラフの各ノードが異なるかどうかでグラフの同型性を判断するというもの.この処理はGNNの処理と 似ているというのがここでの主張.
WL testを使ったGNN的な手法としてShervashidzeらが提案したWL subtree kernelがある.これはWL testの異なる繰り返し回数でのノードラベルをノードの特徴ベクトルとして使う手法で,-th iterationにおいてあるノードをルートとしたのきの高さの木構造を表現可能(Figure 1がその例).
Theoretical framework
GNNの表現力の高さを分析する.仮定としてグラフの各ノードの特徴ベクトルとしてunique labelを割り当てる.この時隣接ノードの集合の特徴ベクトルは以下で定義されるmultisetを形成する.これは異なるノードが同一の特徴ベクトルを持つため同一の要素が複数回現れることを意味する.
Definition 1 (Multiset)
Multisetは集合の一般化された概念で,その要素として複数のインスタンスを持つことを許す.すなわち,multisetは2-tuple であり,この時はの基底となる集合で個別の要素によって形成され,は要素の多様性を与える.
ここではGNNの表現力を測るため,GNNに二つのノードを同一の場所に埋め込む時を考える.直感的には,これは二つのノードが同一の特徴量,同一のsubtree構造を持つ時にのみ可能だと思える.面白いのはmultisetsな状況においてGNNはこれは不可能だと言っていて,aggregation schemeはinjectiveであるという.よってここではCNNをmultisets上の関数の集合として考え,それがinjective multiset functionsを表現できるかどうかを分析する.
Generalizing the WL test with graph neural networks
理想的にGNNの表現力の高さは異なるグラフを区別できるかどうかであるが,これはグラフの同型性の識別問題を解決したことになってしまう.ここでの分析においては少しゆるい指標を使ってGNNの表現力を分析する.
Lemma 2.
を非同型なグラフとする.もしneighborhood aggregation schemeに従うGNN がとに異なる埋め込みを与えるならば,WL graph isomorphism testを使ってとは非同型であると判別できる.
Lemma 2からaggregation-based GNNはグラフ識別においてWL testと同等の能力がある.では現状提案されてるGNNはどれもWL testと同等の能力があるのかというのが疑問.論文では次のTheoremから同等な能力があるとしている.
Theorem 3
をneighborhood aggregation schemeに従うGNNとする.十分な回数集約の操作が行われたとき,もし次の条件が満たされればはWL testにおいて非同型と判断されたとを異なる埋め込みへと写像する.
a) はノードの特徴ベクトルを次のように繰り返し集約,更新する.
b)のグラフレベルのreadout(multiset上の演算)は単射.
ここまでGNNとWL testは同等とは言いつつも,GNNはWL test以上に重要な利益をもたらす.というのもWL testでのノードの特徴ベクトルはone-hotベクトルでsubtree間の類似性などを得ることはできない.つまりGNNはWL testを連続空間に拡張かつ学習ベースにしたものと言える.これはGNNが構造の識別だけでなく埋め込みの学習やグラフ構造間のdependenciesも取得可能ということを意味する.
Graph isomorphism network (GIN)
ここではTheorem 3を満たすことで一般化されたWL testという保証のあるGraph Isomorphism Network (GIN)を提案.
Lemma 4によりsum aggregatorsが単射,特にmultisets上のuniversal functionsを表現できるということを示す.
Lemma 4
が可算であるとする.が有限のmultiset においてuniqueとなるような関数が存在する.さらに,任意のmultiset function はある関数を用いてのように分解される.
Multi-layer perceptrons(MLPs)のuniversal approximation theoremから,をMLPsでモデリングすることができる.実践的にはは一つのMLPでモデル化したとのこと.するとGINは次のような形でノードの特徴量を更新する.
は実験では0または学習パラメータとしていた(ちなみに0の場合はTheorem 3を満たさない).この演算は言ってしまえば自分自身に適当な係数をかけて全ての隣接ノードとの和をとってMLPに入力するというもの.またGINはのみでは行わない.めちゃくちゃシンプルで直感的にはうまくいかなさそうだがTheorem 3からより複雑なものと比べても同程度の性能を発揮できる保証がある.
Readout subtree structures of different depths
グラフレベルのreadoutの重要な側面としては繰り返し回数が増えるほどノードの表現はrefinementされ,かつglobalな情報を得ることができるという点.この繰り返しの回数は重要だが,稀に回数が少ない時に得られた表現が良いものである場合もある.そのためGINでは全てのdepths/iterationsから得られた情報を用いることにする.これをJumping Knowledge Networks (JK-Nets)に似た構造で実現する.すなわち次のようなreadoutの関数を用いる.
つまり全てのiterationにまたがって特徴ベクトルをconcatするというもの.Theorem 3とLemma 4に従えばこのreadoutの処理はWL testとWL subtree kernelの一般化になっている.
Less powerful but still interesting GNNs
最後にGCNやGraphSAGEを含むTheorem 3を満たさないGNNについて考える.ここではGINの集約の処理を(1)MLPsではなく単層のパーセプトロンにした場合,(2)sumの代わりにmeanまたはmax-poolingを使った場合のモデルについて掘り下げる.これらのGNNのバリエーションがWL testより劣り,単純なグラフにおいて機能しないことを示す.それでもなおsumの代わりにmeanを使うGCNはnode classificationにおいてよく機能するらしい.この理解を深めるためにGNNがグラフの何を捉えることができて何を捉えることができないかを論じる.
1-layer perceptron is insufficient for capturing structures
Lemma 4における関数は異なるmultisetsをuniqueなembeddingsに写像する役割を果たし,universal approximation theoremからMLPによってパラメタライズされる.にも関わらず多くのGNNは単層のパーセプトロンを使っている.するとグラフの学習に単層のパーセプトロンで十分かという疑問がわく.実際には単層のパーセプトロンモデルはできないことが次のLemma 5から言える.
Lemma 5
任意の線形変換に対して有限のmultisets が存在する.
すなわち違うmultisetsに対して同じ表現を割り当ててしまう(区別できなる)場合があるということ.これを後ほど実験的にも証明した.
Structures that confuse mean and max-pooling
今度はsumをmeanまたはmax-poolingに置き換えたらどうなるかを考える.基本的にmeanまたはmax-poolingはpermutation invariantなため良いmultisite functionであるが,単射でないという問題がある.Figure 2と3にmeanやmaxにした場合に非常に単純なグラフの識別に失敗する例が示されている.
Mean learns distributions
ここではmean aggregatorが区別可能なmultisetsを調べるため,という例を考える.この二つのmultisetsはmean aggregatorによって同じ埋め込みが与えられる.そのため,mean aggregatorはmultisetの要素の分布を捉えていて,正確なmultisetを捉えることはしていないと言える.
Corollary 6
が可算であるとする.もし,有限のmultisetsが同じ分布を持つならば,に関して関数が存在する.
もし解きたい問題がグラフの構造よりも統計的な情報を重視する場合にはmean aggregatorはうまく機能する.さらに言えば,ノードの特徴が多様な場合にはsum aggregatorと同程度の性能を発揮する.これがnode classificationにおいてmean aggregator (GCN)が機能する理由だと考えられる.
Max-pooling leans sets with distinct elements
Max-poolingは残念なことに正確な構造も分布も捉えることができない.ただし,代表的な要素を捉えるのが重要なタスクにおいては適していると言える.実際PointNet (point cloudのためのNN)ではmax poolingを使っていて,ノイズや外れ値に頑健な認識を可能にしている.
Corollary 7
が可算であるとする.もしが同じunderlying setを持つなら,に関してが存在する.
まとめ
個人的にめちゃくちゃ面白かった.GNNの論文は色々読んだけど確かに表現力に関して突っ込んだ論文はなかったなと.読み応えあってメモも一部和訳レベルで残してしまった.ICLR2019のレビュー中なようだけど3人目のレビュワーがしきりに"I quite liked the paper"て言っててテンション上がってたのが印象的.
Neural Nearest Neighbors Networksを読んだのでメモ
はじめに
Neural Nearest Neighbors Networksを読んだのでメモ.differentiableなKNN selection ruleを提案するというもの.NIPS 2018でgithubにコードも公開されている.
Differentiable -Nearest Neighbors
クエリとなるアイテムを,データベースの候補を,距離関数をとする.はデータベースの中にないものと仮定し,はクエリからの距離に従ってデータベースのアイテムのランキングを生成する.ここで[tes:\pi_q:I\rightarrow I]をの距離にしたがってソートを行うpermutationと定義する.
するとのKNNはpermutation において最初の個のアイテムの集合として与えられる.
KNNのselection ruleはdeterministicなため微分不可能で,距離に関する微分を伝播することができない.そこでこの問題をone-hotベクトルの連続値への緩和を使って解消する.
KNN rule as limit distribution
ここではKNN selection ruleをカテゴリカル分布の極限分布としてみなすことで緩和する.をデータベースのアイテムのインデックスに関するカテゴリカル分布とする.クエリアイテムとの距離をとし,温度パラメータを導入すれば,番目のアイテムを選択する確率は次のように与えられる.
Gumbel softmaxやconcrete distributionで見たような式だが,ここではアイテム間の距離によって決定的にサンプリングされるアイテムが決まるためgumbel分布からのサンプリングがない.の時はone-hotベクトルとなる.この式を1-NNのstochastic relaxationとしてみなすことができるため,これをの場合に拡張することでKNNを微分可能な形に緩和することができる.そのために条件付き分布へと拡張する.ここでは次のように計算される.
つまり一度選択されたアイテムは選択される確率が0に近くなるようクエリアイテムとの距離を離すというもの.実際がone-hotベクトルの場合にははにおいてになる.これによって番目のサンプルのインデックスは次のように得られる.
Index vector からのstochastic nearest neighbors を次のように定義する.
温度の時がone-hotベクトルとなり nearest neighborsと一致する.ただ基本的にはone-hotベクトルではないので多分mixup的な形になるはず(というかone-hotベクトルに近づけば近づくほど勾配が消失していくので意味がなくなる).
Neural Nearest Neighbors Block
今までの議論を踏まえてニューラルネットの一つの層としてneural nearest neighbors block ( blocks)を提案する. blocksは二つの部分からなり,一つはembedding networkで,もう一つは連続緩和されたnearest neighborsを計算する部分がある.
Embedding network
Embedding networkはでparameterizeされたCNNを使って入力から特徴ベクトルを得る部分.得られた特徴をとし,ユークリッド距離を用いてというpairwise distance matrix を得る.さらに,ここでは温度を計算するもう一つのネットワークを用意する.ただし,とは出力層以外は重み共有している.
Continuous nearest neighbors selection
距離行列,温度テンソル,入力の特徴から continuous nearest neighbors feature volumes を計算する.nearest neighborsとは入力の次元が同じなのでelement-wiseな操作によってまとめることができるが今回はチャネル方向に結合することで情報をまとめたとのこと.
block for image data
基本的に blockは入力のドメインに関係なく適用可能だが,画像データにカニsてはちょっとした修正が必要.従来画像におけるnon-local methodはパッチレベルで行われ,パッチレベルの処理には様々な利点が存在する.そのため画像に blockを適用する際にはim2colを使ってパッチレベルで計算するとのこと.
まとめ
基本的にはdeterministicなGumbel softmaxという感じ.実験ではdenoisingや超解像などの逆問題を解くのに使っていたが,いろいろなことに使えそう.ただ,複雑なことをしようとすると距離(というかembedding network)に何らかのpriorを持たせないと学習は難しそう.
Learning Laplacian Matrix in Smooth Graph Signal Representationsを読んだのでメモ
はじめに
Learning Laplacian Matrix in Smooth Graph Signal Representationsを読んだのでメモ.
気持ち
データの構造をグラフで表現する際に,一般的にはgeographicalもしくはsocial friendshipなどに基づいてグラフ構造を決定する.ただこのような決め方は常に良い方法とは言えない,またはこのようなグラフ構造の導入が常にできるとは限らない.なので観測されたデータから学習ベースでグラフ構造を決めようというのがこの論文のゴール.ただしデータサンプルからグラフ構造の決定は基本的にはill-posed problemなのでグラフの滑らかさを使ってうまく扱う方法を提案.
Smooth graph signals
まず滑らかなグラフとは何かというところから.ここではノード数の重み付き無向グラフを考える.はそれぞれグラフのノードとエッジとエッジが持つ正の重みを表す.を重み付き隣接行列,を度数行列とすれば非正規化グラフラプラシアンは次のように表現できる.
は固有値分解可能なため固有値固有ベクトルを使って次のように表現できる.
また,の最小固有値は0でその個数はグラフのconnected componentsの数に一致する.
ここでグラフ上のグラフ信号のsmoothnessは次の2次形式で測ることができる.
は頂点を結ぶエッジの重みでは各頂点の信号の値.つまりエッジの重みを使って重みづけられたノード間の信号の変化分の大きさが小さいほどグラフは滑らかであるということ.
グラフラプラシアンの細かい話は以前勉強したメモがあるのでそちらを参照.
Representation via factor analysis model
ここでは因子分析に基づくsmooth graph signalsのための表現モデルを提案する.factor analysis modelは線形モデルの一種で,今回は次のモデルを考える.
は観測されたグラフ信号の表現で,は潜在変数で固有ベクトル行列を通してをコントロールする.はの平均.ここでは雑音は等方性であるとし,平均0,分散の多変量ガウス分布を仮定する.よっての確率密度関数は次のようになる.
今回のモデルは一般的な因子分析モデルのグラフ信号への一般化になっていて,重要となるのはの固有ベクトルで表現される表現行列の選択.選び方には二つの観点があって,一つはグラフのトポロジーを反映したものを探すことで,もう一つは表現行列がグラフのフーリエ基底として解釈可能であるということ.なのでの固有ベクトルは表現行列の良い候補になる.
今回はクラシカルな因子分析モデルに従って潜在変数をガウシアンと仮定.もっと言えばここではガウシアンを平均0,精度行列をの固有値とする以下の形で定義する.
はのムーアペンローズの擬似逆行列.の固有値はグラフの周波数を表しているため,低周波ほどエネルギーを持つということを暗に仮定していること.今までの関係を用いればの条件付き確率との確率は次のように表現可能.
ただしの関係を満たす.
Learning framework
観測との事前分布が与えられたとし,のMAP推定を行う.するとのMAP推定は次のように表される.
は雑音と潜在変数の確率密度関数を表し,はが与えられた時のの条件付き確率密度関数.ここでそれぞれガウス分布を仮定すれば次のように書き直せる.
は定数でノイズの無い状況においては解は.または直交行列なのでにおいてが成り立つので以下の最小化問題へと書き直せる.
すなわちの特性からこの最小化問題はグラフの信号が滑らかになるような解を導く.
ここでグラフ構造は未知であるためこの最小化問題は潜在変数と表現行列との事前分布に対する精度行列を変数に持つ.すなわち次の最小化問題として表される.
さらにという変数変換を用いれば次のようにかける.
Learning algorithm
最終的に得られた最小化問題を行列形式で書き直すと次のようになる.
は個のデータを並べたもので,は正の正則化パラメータ.この論文ではこの最小化問題をとの交互最適化によって解く.
に関する最小化問題はinterior point methodsなどで効果的に解けるがここではADMMを使ったとのこと.またに関しては次のclosed formな解がある.
まとめ
最小化問題を解くのにグラフラプラシアンの制約が面倒な印象.この辺の話はGCNとかとは組み合わさらないのか.
ScratchDet: Exploring to Train Single-Shot Object Detectors from Scratchを読んだのでメモ
はじめに
ScratchDet: Exploring to Train Single-Shot Object Detectors from Scratchを読んだのでメモ.
気持ち
現状の物体検出器は基本的にimageNetなどのpretrainedモデルを使って学習している.この論文ではこれが精度の低下を起こすと主張.その理由として
事前学習に使ったデータと検出の学習に使うデータのドメインのギャップ
分類と検出の目的関数間のギャップ
ネットワーク構造の制約
の3つを挙げている.1に関しては別な文献で指摘があり,2に関しては分類と検出ではtranslationに対してのセンシティビティが異なる点を意味する.最後の3に関してはオリジナルのネットワークをimageNetなどで事前学習するコストが高いことから挙げている.
これらを解決するためにスクラッチから学習可能な枠組みを提案するというもの.論文通してとにかくBatchNormすごいということしか言ってない感はある.
ScratchDet
ここではSSDをスクラッチで学習することを仮定.オリジナルのSSDはBatchNormを使っていないがここではまずbackbone(VGGやresnetなどメインのネットワーク部分)に使うことを考える.理由としてはBatchNormは目的関数を滑らかにして勾配を落ち着かせる効果があると言われているのでスクラッチから学習する上では必要だろうという思いがある.これだけでとりあえずmAPが67.6%から72.8%まで上がるとのこと.さらに面白いのは学習率を大きくすればするほど精度が向上するらしい.具体的にはオリジナルのSSDでは学習率0.001だったが,BatchNormを入れて学習率を0.05にすると78%まで精度向上するとのこと.これは(実験条件をどこまで揃えているかわからないが)SSDの元の論文で報告されていた77.2%を上回っている.
次にdetection head subnetworkにBatchNormを入れることを考える.backboneに入れずdetection headに入れるだけでmAPが67.6%から71.0%に改善,さらに学習率を0.001から0.01にあげると75.6%まで改善する(さっきと違い0.05の場合は試していないよう).学習途中の勾配のノルムを確認したところbatchnormを入れると入れないものより安定していてlandscapeが滑らかになっている,すなわちフラットな解になっていることが確認できる(と言い切るのはやりすぎ感はあるけど).
Backboneとdetection head両方にBatchNormを入れた場合には最大で78.7%まで向上した.ただし,学習率が0.001,0.01の場合には両方に入れるよりbackboneのみの方がmAP的には良い.
BatchNormを使えばスクラッチからでも十分な性能が出せることが確認できたので,次はより良いbackbone networkの構造を探す.SSDで一般的なVGG-16とResNet-101を比べるとImageNetではResNet-101が良い結果を示しているが,DSSDの論文によるとSSDにおいてはVGG-16の方が良いmAPを達成している.これはResNet-101は最初の段階で一気に解像度を下げていることが原因で,これにより小さな物体の検出が難しくなる.なので入力の解像度をあげれば解決できる問題で実際論文でも解像度が大きい場合にはVGG-16よりもResNet-101が優っている.さらに言えば,cocoデータセットのように検出のカテゴリ数が増えればResNet-101の分類能力の高さが発揮されて入力の解像度が小さくてもVGG-16より良い結果を達成できる.詳細はDSSDの論文読めとのこと.
以上を踏まえて最初のdownsamplingをなくせば大体の状況でVGG-16よりいい精度を出せるだろうということで,Root-ResNetなる構造を提案.提案といっても内容は単純で最初の畳み込みのストライドを1にしてカーネルサイズを3に変更しただけとのこと(この畳み込みをroot blockと定義).
実験
BatchNormの部分は繰り返しになるので割愛.root-resnetに関してResNet-18を使って検証.ResNetの最初の畳み込みのdownsamplingをなくすだけでmAPが4%ほど改善するそう.さらに最初の畳み込みをカーネルサイズ7の畳み込みの代わりにカーネルサイズ3の畳み込み数回で代用したところ精度が向上.具体的にResNetの構造に対し,7x7を3x3に変えて層の数を3にしたところ2%ちょっと改善,さらにroot-resnetの構造(downsamplingを無くす場合)にすればやはり4%程改善.
様々なベースライン手法とPascalVOCで比較.300x300の解像度を入力としてもスクラッチから学習したroot-resnet-34がほぼ全てを上回るmAPを達成.唯一負けたのがCoupleNetでroot-resnet-34がmAP78.5%に対してCoupleNetが80.4%.またms cocoでの比較ではtwo-stage系の手法(Faster R-CNNなど)には劣る結果.ただし,multi-scale testingをした場合では一応全ての手法を大きく上回っている.
まとめ
SSDの論文書いた人たちはBatchNorm入れてうまくいかなかったとかgithubのissueに書いてた気がするけどなんだろなという気持ち.内容としては技術レポート的な感じだが実践的に役立ちそうなことは多かった.数式は出てこなかったなあ