AtCoder Heuristic Contest 030

 暫定64位。

0086

考えたこと

ソフトマックス分布を使いたい

  M個ある各油田について、それぞれ左上のマス位置が i, jである確率を保持してみたい。これは i, jについてlogitを持つSoftmax分布として表現したくなった。

 この分布を持って、マップ全域について期待値を取っていけばどのマスにどの程度の量の油田がありそうかを予測することができる。

微分で分布を改善できそう

 この分布をクエリの結果から改善したい。各マスについて、予測した値と1マスクエリ結果の値の自乗誤差を損失関数として誤差を微分すれば良さそう。損失の式を考えて連鎖率を追っていくとそれっぽい値は出てくる。

 (しかし、結局Softmax関数の正しそうな勾配の式は遅いし精度も悪化するしで、謎の嘘勾配を使った。この式じゃ間違っているっけ? うーん)

0マスを確定すると大きい

 1マスクエリで0が確定すると、そこに油田の量が発生するような置き方をするのは不可能ということがわかり、かなり分布を削ることができる。それを狙っていく。

 どのマスで1マスクエリをかけるか。確定することで得られる情報が多いのは、0か1以上か不確かなところとなる。つまり、期待値が0.5くらいのマスを優先的に調べていく。この調べ方でかなりスコアが改善された。

おまけ程度に複数マスクエリの使いみちを探す

 各油田から配置パターンをサンプリングしてきて、その配置パターンでクエリをかける。やはり自乗誤差を考えるが、各マスではなくクエリマス全体の和を取ってから損失計算ということになるので精度はそこまで出ないようだった。一応最初の方にフィールドサイズの N回だけ入れた方がちょっとだけマシになったので入れた。


 ということをやると冒頭に貼ったGifのような挙動になる。

所感

 頭ニューラルネットという感じの解法しか思いつかない。

 確率的な要素が多少ある方が単に焼きなましゲームよりは得意な気がする。ここ最近のAHCで成績良かったのもAHC022で、やや近い匂いがするな?

STL-10データでFSQを試す

 最近の世界モデル系手法ではVQ-VAEが当たり前のように使われているので試してみたいが、生のVQ-VAEだとcommitment lossとかentropy lossとか、様々な工夫を入れなければいけないことが気になり、そういう工夫が要らないと主張されていて内容もシンプルなFSQを試してみた。

 公式実装がjaxで存在しているのでこれを利用した。

 タスクとしては単純な画像再構成で、CIFAR-10あたりだとちょっとトイ・タスクすぎるので、STL-10データを使った。

 STL-10データの特徴は冒頭に書いてある通り

  • 10 クラス: airplane, bird, car, cat, deer, dog, horse, monkey, ship, truck
  • 画像サイズ 96x96 pixels
  • 各クラス train500枚、test800枚の画像がある

となる。unlabeledなデータもあるが、今回はとりあえずtrain 500 x 10クラスの5000枚で学習を試した。

 VQ-VAEを使う上で、Encoder-Decoder部分のCNNも、あまり適当なものではなく実績のあるものを使いたかったため、MaskGITの実装を利用した。(両方Google Researchの研究なので)こちらもjaxでありFSQと繋げるのは簡単。

実装

 FSQをlevel3で要素数10としたので、コードブックサイズとしては 3 ^ {10} = 59049と結構大きくなっており、VQ-VAEの方は単純にコードブックサイズ1024としたので、フェアではないかもしれない。FSQのlevel2とするとnanが発生して上手く学習が進まなかった。

結果

比較実験

 まずFSQと補助損失がなにも入っていないvanilla VQ-VAEと比較した。

 再構成損失が明らかにFSQの方が良く、損失の推移も安定的だった。

FSQの長時間実験

 FSQを上記比較実験から10倍の8時間回してどの程度再構成ができるかを確認した。10倍回すとかなり損失も下がる。

学習データにあるもの
データID 結果
0
1
2
3
4

 学習データ内にあるものはまぁまぁ再現ができているといえばできているかもしれないが、No.2のチーターの画像はちょっと細かくてよくわからない感じになっている。

テストデータ
データID 結果
0
1
2
3
4

 テストデータにあるものだとまだ崩れがちである。学習データも学習量も足りていなさそうな中ではよくやっているか。

今後

  • BBFの次状態予測部分にFSQを導入してみる

余談

 FSQのLevel2だと学習が上手くいかないのは、元のコードがバグっているからのような気がした。自前で実装してみると学習は進んだ。しかし、損失の減りはLevel3(10次元)より悪かった。

 前述の通り、コードブックサイズが 3 ^ {10} = 59049 2 ^ {10} = 1024ではかなり違うので仕方がないことではありそう。

BBFで連続的に2つのゲームを実行する

 強化学習エージェントが環境の変化に対応できるかどうか、という点に興味があるため、atariゲームを連続的に切り替える設定での学習を試せるようにした。

 デフォルトのatari環境では各ゲームによって有効な行動数が異なる。たとえばBreakoutだと4種類(NOOP、FIRE、RIGHT、LEFT)だけが有効な行動である一方、Alienだと18行動が有効となる(8方向 + 停止の9通り動きがあり、FIREするかしないかで2倍の18通りになる)。ここが変わってしまうとネットワーク構造なり出力方策の処理を変えなければならなくて不便なため、必要ない行動も含めて全てを入力できるようにした。これはatariの環境を作るときにfull_action_space=Trueというオプションを入れれば良い。ドキュメント

 環境設定周りのBBFの実装がわりと複雑で、環境を作成する関数をRunnerに渡して、Runner内部でそれをAgentを作る関数に渡してAgentにActionNumを教えるという形になっているため、いろいろこねくり回す必要がある。

 簡単に実験したところ、Breakoutで行動が増えることによる性能の低下は、そこまで大きくないようだった。

 今回はまず実装を試すということで、atari 100kベンチマークで使われる26ゲームのうち、BBFが高いスコアを出せていたBreakoutとBoxingの2ゲームを選び、それをこの順番で10kずつ学習させた。

 学習中のHumanNormalizedScoreは以下の通り。

学習中のHumanNormalizedScore

 10kでゲームが切り替わったことで報酬が全然得られなくなっており、学習して持ち直していくことがわかる。

 それぞれのゲームの学習が終わったタイミングでBreakoutとBoxingの両方を100回テストした結果が以下の通り。

評価タイミング BreakoutのHumanNormalizedScore BoxingのHumanNormalizedScore
Breakout学習終了時(10k終了時点) 1.01 -0.72
Boxing学習終了時(20k終了時点) 0.18 1.12

 ある程度想定通りの結果が得られた。

  1. まず、Breakout学習終了時ではBoxingは全く学習されてないのでとても低いスコアになる。
  2. Boxingまで学習するとBoxingのスコアは良くなるが、Breakoutの学習結果が失われてBreakoutのスコアが低くなる。

 やや想定外のこととしては

  1. Breakoutのスコアの下がり方が思ったよりも大きくない
    • よく考えると20kではまだ1回目のパラメータリセットが走らないタイミングかもしれないので、その点で忘却が起きない
    • リプレイバッファは十分大きなサイズで作っており、ゲーム切り替えタイミングで特にリセットはしていないつもりなので、Boxing学習中もバッファ内にはBreakoutのデータが残っていて適宜リプレイされる

 やっていることが複雑化してくるので、各種リセットの挙動が想定通りに実装できているかどうかが不安になる。

 今後はAugmenting Replay in World Models for Continual Reinforcement Learningで示されている指標を計算できるようにして、忘却性と可塑性の評価をできるようにしてみたい。

読書メモ 西田洋平『人間非機械論』

 西田洋平『人間非機械論 サイバネティクスが開く未来』

 著者多数『未来社会と「意味」の境界: 記号創発システム論/ネオ・サイバネティクスプラグマティズム

を読み、面白かったので記録を残しておく。主に前者の本についてがメインで、部分的に後者を参照する。それぞれ有料の本なので、内容をまとめるということはしない。読んで浮かんだ疑問点・所感などを残す。興味がある人は買って読んでください。

面白かった点

 テクニカルな面として、相互再帰によって無限退行を解消できるという話は面白い。単なる再帰よりも性質的に良い点がどれくらい出てくるのだろうか。これは元論文とか、もっとの他の参考資料を辿らないとわからなさそう。場合によってはいろいろ応用が利く概念なのかもしれない。

 観測者の再帰性、あるいは説明の円環あたりも、完全に納得できているわけではないがそれらしい気もする。モデル化の中に自分を含めるかどうかというのは大きな差異になりそう。主観的な知覚刺激の中からどうやってそれを学習するのか。不思議だ。

 あとはHACSの階層性の見出し方は感触の良さを感じる。

(1) オートポイエーシスがどこまで成立するのかよくわからない

 細胞が、タンパク質等を構成素(正確には構造らしいが)オートポイエティック・システムであるというのは納得感がある(生物学について詳しくないので機序を説明せよと言われたら全く自信はないが)。また、生物個体が細胞を構成素とするオートポイエティック・システムであるというのも納得できる。

 一方で神経システムがオートポイエティック・システムであるのかどうかは(書内でも注意書きがあったように)、すぐにはよくわからない。構成素としてはやはり細胞レベルのものを考えるのか、それとも抽象的な神経ネットワーク的なものを考えるのだろうか。また心的システムがオートポイエティック・システムであるかどうかもさらによくわからない。構成素が何に相当するのか、あまり見当がつかない。

 HACSを前提とすると全て構成素はコミュニケーションになるはずなのだろうか。抽象度がかなり高まり、解釈にブレが生じてしまいそうな気がする。会議の例はわかりやすいが、その他に自分で応用して考えてみようとすると恣意的になんでも当てはめてしまうか、全然当てはめられないか、ということになる。

 工学的に、細胞レベルでオートポイエーシスを再現するのは難しそうなので、一歩抽象的な段階で実現できるかどうかというのが争点になりそうだというのはわかる(未来社会と「意味」の境界 第3章)。が、上の通り、それがオートポイエティック・システムなのかどうかそもそもよくわからないので、目指すべきものなのかも不明。正直、工学レベルとしては、とても複雑なノン・トリビアルマシンであるか、オートポイエティックなシステムであるか、という区別にはあまり意味がないのではないか、という方に同意したい。

(2) 性質は明確な違いがあるのか

 オートポイエーシスについても、閉鎖性・自律性についても、非連続な変化というよりも中間を考えたくなった。オートポイエティックである/ないといったものが、完全に非連続的な2つの極であると、応用を考えにくい気がする。

 たとえば、生物も無限に生きられるわけじゃないのでオートポイエーシスも完全な形式では成立していない。なので、オートポイエーシスが成立する時間的長さがあるわけで、それが十分に長いと生物っぽく見えるが、成立時間を徐々に短くしていくとどこかで非生物へ切り替わる瞬間が生じるだろうか。そのオートポイエーシスが成り立つ時間の長さで「オートポイエーシスらしさ」を連続的に考えたくなる。

 閉鎖性・自律性についても、結局構造は外部とやり取りするというのを考えて、どの程度意味が構造的になった情報を受け取るかというのは段階があるのではないかという気がした。「自律性」という言葉を身近なレベルで捉えて卑近な例を考えると

  • 手取り足取り全て教えなければいけない
  • 言葉でやってほしいことを伝えるだけで良い
  • なにも言わずにやる

などの段階が考えられる。相互作用(入力)される情報がリッチであるか、そういう連続的な段階で自律性を考えられないか、とは思った。

 入力から情報を希薄化していく。有益な情報自体も自分で獲得してくださいとなる。それは結局表現学習の一つでしかないということになってしまうか。

その他

 結局こういう考えを知って、では工学的にどうしますかというと、別にそこまでやることは変わらなくて、ある程度妥当そうなモデルを考えてあとは性能次第、というようにも感じる。その「妥当そうなモデル」が厳密な確率的生成モデルになるのか、ちょっと妥協していろいろ近似の入ったニューラルネットワークいろいろになるのかはよくわからないが。

 全然別の方向性としては、ライフゲーム的なものが超高度に進歩して、外界とも接点を持ち、かつ、意味があると錯覚するような振る舞いをできるようになると、それはオートポイエティックなシステムだしハッピー、ということになる道もあるのだろうか。やっぱりそのレベルのオートポイエーシス性は別にあまり興味ないなぁとは思ってしまう。

Bigger, Better, Faster: Human-level Atari with human-level efficiencyを読んだメモ

 実験の結果が

  • Atari 100k ベンチマークで、Human Normalized ScoreのIQM(26ゲーム中の上位25%と下位25%を除いた中間50%ゲームについての平均スコア)が1.045
  • 学習時間は6 hours on single GPU

とのことであり、魅力的。

 Max Schwarzer氏(Google DeepMind)が筆頭著者として関わっている一連の研究があるようだ。

  1. SPR(Self-Predictive Representations)
  2. SR-SPR(Scaled-by-Resetting SPR)
  3. BBF(Bigger, Better, Faster):この論文
    • SR-SPRに細かい工夫を詰め込んでネットワークサイズを大きくすることに成功し、性能向上

手法

 まずこれらの手法はQ値ベースの方策オフ型であり、Atari 100kベンチマークをやるに際しても、リプレイバッファに経験を溜めて定期的にサンプリングして学習をする。

 環境との相互作用1回(行動選択1回)に対して、「リプレイバッファからランダムサンプリングして損失計算して勾配法でネットワークのパラメータ更新」を何回やるか、というReplay Ratioを考える。これは一般的な手法だとRR = 0.25とか、せいぜい1とかになる。しかし、ネットワークの定期的なパラメータリセットを入れるとRR = 8とか16まで伸ばせるようになる。まずここまでがSR-SPRの主張。

 これに加えてBBFでは

  • Harder reset : SR-SPRでは最終層だけ完全リセット、それ以外はランダムパラメータと20%で線形補間、という形でリセットしていた。BBFではもっとリセットを強めて50%で線形補間する
  • Larger network : Impala-CNNを持ち出してきて、CNNのchを4倍などにする
  • Receding update horizon : 価値関数の学習でnステップTD誤差を計算するときのnを10から3まで小さくしていく。これはネットワークがリセットされてから最初の10kステップで行う。リセットは40kステップごとに行うので、要するに最初の学習の25%分で下げていく
    • これはhttps://www.learningtheory.org/colt2000/papers/KearnsSingh.pdfで主張されているらしい
    • nが大きいほど収束は速くなるが、最適価値関数に対して漸近誤差が大きくなるので、最初だけ大きくしておいてから下げて学習を速めることが狙い
    • nは大きければ大きいほど良いと思っていたのでこれは意外な話
  • Increasing discount factor:割引率を0.97から0.997まで上げていく。これもnと同じく学習の最初25%でやる [1512.02011] How to Discount Deep Reinforcement Learning: Towards New Dynamic Strategies
  • Weight decay:0.1という大きな値でAdamWを使って重み減衰を入れる
  • Removing noisy nets:SPRやSR-SPRではNoisy netを使っていたがこれを削除する

ということを行う。

 各工夫がどれだけ効いているか。

Figure 5

 Replay Ratio2と8で実験されている(横軸の範囲が揃っていないの見にくい……)

自分がグラフを見た印象では

  • とにかくNo Resetは論外。ネットワークのリセットは大事
    • しかもSR-SPRのリセットでも結構性能が落ちているので、強めのリセットが重要らしい
  • nを10に固定する場合でもかなり性能が落ちている。びっくり
  • その他はまぁほどほどか

 なので、「ネットワークのリセット」と「nステップTDのnの影響」について調べる。

ネットワークのリセット

 これについては一つ前の論文SR-SPRにいろいろ書かれている。

 どうもニューラルネットワークは学習を進めてしまうと一般化する能力を失うらしい。滑らかに2つのタスクを切り替えていくマルチタスク学習の設定でも、最初のタスクで長く学習しすぎると次のタスクでの性能が上がらないらしい。 ([1910.08475] On Warm-Starting Neural Network Training; [2106.00042] A study on the plasticity of neural networks)

 (確かに、学習によって全く可塑性を失わないのならばもっとFine-Tuningが大幅にできるようなことを意味するはずなので、そういう意味では当たり前なのかもしれない。しかし100kの定数倍程度の学習ステップ数でもそれが大きく効いてくることは意外)

 オンライン強化学習というのは、学習が進めば振る舞いが変わっていくので、ある意味では滑らかに連続したマルチタスク学習と言える(極端な例としてステージ制のゲームだったりすると明確)。Replay Rateを上げてしまうと、学習が進んでいない段階のもので長時間学習してしまうのと同じことになり、その結果次のタスク(それ以降のデータ)での性能が上がらなくなってしまうと捉える。そして一般化能力を回復させる手法がネットワークのリセットである。

 リセットタイミングでの精度低下が嫌な場合は、リセット直後にある程度(ほぼオフライン強化学習として)学習してしまえば良いらしい。なるほどではある。

 その他参考文献

nステップTDのnの影響

https://www.learningtheory.org/colt2000/papers/KearnsSingh.pdf

 だいぶ話が難しくてあまり理解はできていない。phased TDという解析用の条件設定(ただしそんなに非現実な設定というわけでもない)の下で、誤差の上限 \Delta

 
\Delta _ t \le \frac{1 - \gamma ^ k}{1 - \gamma} \sqrt{\frac{3 \log (k/\delta)}{n}} + \gamma ^ k \Delta _ {t - 1}

となるらしく、この右辺第一項はk(ややこしいが、この論文ではnステップTDのnをkとしている)が大きくなると大きくなる。右辺第二項はkが大きくなると小さくなる。なのでkがいい感じのところでトレードオフのバランスが取られるはずということになるらしい。

 若干自信はないが、直感的な解釈としては、nステップを大きくとれば当然nステップ分は実報酬を使うことになり、たいていその分散は大きいのでそれに影響されるということなのだと思う。分散が大きいだけでバイアスではないので長い目で見ると漸近誤差には影響ないのかと思っていたが、確率的な収束を考えると理論的にも考えられるのか。

 理解は浅いが、まぁそうかなという気分にはなってきたので、nをいじるのは必要なことだと感じられてきた。

Bigger, Better, Fasterのコードを動かす

 コードが公開されているので動かしてみる。

 venvで行ったので、おおよその手順は

git clone https://github.com/google-research/google-research
cd bigger_better_faster

python3 -m venv .env
source .env/bin/activate

pip3 install -r requirements.txt

export PYTHONPATH="$(readlink -f ../):$PYTHONPATH"

python3 -m bbf.train \
    --agent=BBF \
    --gin_files=bbf/configs/BBF.gin \
    --base_dir=./bbf_result \
    --run_number=1

という感じ。しかし途中途中でいろいろ直さないと動かなかった。

(1)dopamine_rlで落ちる

 BBFは内部的にdopamine_rlというライブラリのNoisyNetworkを読み込んでいるところがあるが、その読み込み時に

AttributeError: module 'jax.interpreters.xla' has no attribute 'DeviceArray'

で落ちる。これは最新のGitHubコードだと直っているのでこれと同じ修正をローカルのものに入れることで回避できる。

[JAX] Replace uses of jax.interpreters.xla.DeviceArray with jax.Array. · google/dopamine@a9a8fc0 · GitHub

 試行錯誤中だと上手くいかなかったが、単純にpipでdopamineライブラリのバージョンを上げても回避できるかもしれない。

(2)spr_agent.pyで落ちる

 dopamine_rlを直したら次はspr_agent.pyのところで落ちた。

ValueError: Custom node type mismatch: expected type: <class 'flax.core.frozen_dict.FrozenDict'>, value {Pythonの辞書形式}

というエラーが出る。要するにdictとFrozenDictの違いで型があってないということらしいので変換を入れると良い。

 その他、get_default_device_assignmentというやつも削除されたせいかエラーが出る。

Remove use of get_default_device_assignment(). · google/jax@3ce5cb6 · GitHub

 なんだかよくわからないが、これらを勘で次のように直した。(コピペ後に微修正したのでパッチファイルとしては機能しないと思われる。該当行を手動で修正する)

diff --git a/bigger_better_faster/bbf/agents/spr_agent.py b/bigger_better_faster/bbf/agents/spr_agent.py
index 25306dcb6..56c696091 100755
--- a/bigger_better_faster/bbf/agents/spr_agent.py
+++ b/bigger_better_faster/bbf/agents/spr_agent.py
@@ -45,9 +45,7 @@ def _pmap_device_order():
   if jax.process_count() == 1:
     return [
         d
-        for d in xb.get_backend().get_default_device_assignment(
-            jax.device_count()
-        )
+        for d in xb.get_backend().local_devices()
         if d.process_index == jax.process_index()
     ]
   else:
@@ -177,6 +175,13 @@ def interpolate_weights(
   if keys is None:
     keys = old_params.keys()
   for k in keys:
+    old_params = FrozenDict(old_params)
+    new_params = FrozenDict(new_params)
     combined_params[k] = jax.tree_util.tree_map(combination, old_params[k],
                                                 new_params[k])
   for k, v in old_params.items():
@@ -1309,6 +1314,10 @@ class BBFAgent(dqn_agent.JaxDQNAgent):
         optax.masked(optimizer, self.head_mask),
     )
 
+    self.online_params = FrozenDict(self.online_params)
     self.optimizer_state = self.optimizer.init(self.online_params)
     self.target_network_params = copy.deepcopy(self.online_params)
     self.random_params = copy.deepcopy(self.online_params)

(3)JaxがGPUを使っていない

 実験が動き出したようなログが流れ続けるが、nvidia-smiで見てもプロセスが乗っておらず、GPU利用率も低かった。

python3 -c "import jax; print(jax.devices())"

で確認したところ

An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.
[CpuDevice(id=0)]

 と出た。公式のインストール手順https://jax.readthedocs.io/en/latest/installation.html#pip-installation-gpu-cuda-installed-via-pip-easier:titileを見て、自分の環境はCUDA-12が入っているので

pip3 install --upgrade "jax[cuda12_pip]" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html

とした。これでpython3 -c "import jax; print(jax.devices())"の表示は

[cuda(id=0), cuda(id=1)]

となった。(2枚挿さっているPCなので2枚分ちゃんと出た)

動作結果

 設定はデフォルトのままで実行してみた。configをよく見ると、BBFAgent.replay_ratio = 64となっている(https://github.com/google-research/google-research/blob/4da7251308decf0a61807c09a8f4c087cbd06310/bigger_better_faster/bbf/configs/BBF.gin#L33)。

 ChopperCommandという、他の手法だとあまりスコアが伸びないゲームでHuman Normalized Scoreが1を超える結果を得られた。

 実験時間も3090GPUを1枚だけ使って2.6hだったため、かなり短い。

Transformer系世界モデル手法IRISとTWMの比較

 以下の2つの論文を比較する。

 共通点としてどちらも

となっている。

 提案手法に沿って、呼称は以下のようにする

手法

IRIS

IRIS Figure 1

TWM

TWM Figure1

 まず手法の概要として共通点は

  • 観測を離散AutoEncoderで複数の離散トークンにする
  • 観測の離散トークンと行動などをTransformerに入力する

大雑把には似ている。以下違いを見ていく。

Transformerへの入力

  • IRISの入力は「観測の離散トークン + 行動」
  • TWMの入力は「観測の離散トークン + 行動 + 報酬」

Transformerの使い方

  • IRISは自己回帰的に次状態の離散トークン・報酬・終了判定を予測する
  • TWMは行動に相当する位置のトークンの変換結果を hとして、そこに情報が集約されていると考え、 hから各種次の予測を行う

離散化Encoder

要素 IRIS TWM
入力サイズ 64x64x3(スタックしているかは不明。たぶんしているのでは) 64x64x4 (直近4フレームをスタック・グレースケール化)
離散化トークンのクラス数 512 32
1観測を何個のトークンにするか 16 32
損失の工夫 Perceptual Lossあり consistency lossというものを提案・導入

 離散化クラス数などはやや異なるが、概ね一致。

Transformer

要素 IRIS TWM
ベース実装 minGPT Transformer-XL
次元 256 256
層数 10 10
head数 4 4
入力する最大タイムステップ数 20 16

 Transformerパラメータはかなり近い。

方策の入力

  • IRIS:復元した観測
  • TWM:観測の表現(離散トークン)

 TWMの方で良し悪しについては記述がある。

  • 観測そのまま or 復元した観測:画像での学習なので方策が安定しやすい
  • 観測の表現:遷移予測の学習によっても変更が加えられていくので方策モデルがその変化にも追従しなければいけない。エントロピー正則化と一貫性損失を入れると安定する
  • 観測の表現 + 遷移の履歴(Dreamer形式):推論時に遷移モデルも実行するコストが発生する

 IRISの方策はさも各ステップ独立で推論できそうだが、Appendixを見るとLSTMを使っているとあり、過去系列も見ていそう。

実装

実験にかかる時間

  • IRIS
    • 実験全体は8基のA100で実行
    • 1枚のGPUで2つのAtari環境を実行して、おおよそ7日かかる。つまり1環境あたりだと3.5日
    • おそらく上記が5シードまとめての時間なので、1環境1シードだと0.7日 = 16.8時間
  • TWM(おそらく1環境・1シードあたりについての記述)
    • A100を1台だと約10時間
    • 3090を1台だと約12時間
    • Transformer-XLのメモリ機構を使わないVanilla Transformerを使うと約1.5倍かかる

 IRISの方が若干遅いのは、(1) TransformerがVanillaのもの (2)Actor-CriticにLSTMセルが使用されている というところがありそう。とはいえそこまで大差ではない。

評価

 どちらもDeep Reinforcement Learning at the Edge of the Statistical Precipiceに従っている。(おそらくAtari 100kベンチマークについての評価用OSSツールが利用されているのだと思われる。良さそう)

 比較手法もだいたい同じ。

IRIS Figure 5

TWM Figure 3

 どちらもMedianは幅広い。MeanとInterquantile Meanでは良い。

 各ゲームでのスコア表をマージすると以下のようになった。色付けは各行ごとに緑が最小、白が最大。

 (スプレッドシートhttps://docs.google.com/spreadsheets/d/1B1gMkAqUhcmGdsDui7_1lHjne3E3sOvXSg_4fIovNw4/edit?usp=sharing

 得意/苦手なゲームの傾向もやや似ていそう? ちょっとよくわからないか。EfficientZeroが強い。

その他・実験考察など

  • IRIS
    • Frostbite と Krullというステージ遷移がある場合に苦労する
    • フレームあたりの観測離散化トークン数を64に増やすと改善するゲームもある(もちろんその分世界モデルが重くなる)
    • 学習量を10Mに伸ばすと性能も伸びる
  • TWM
    • Actorのエントロピー正則化についても閾値を導入して、下回った場合のみ有効になるようにする
    • 過去のデータを何度もサンプリングして学習に利用しすぎないようにBalanced Dataset Samplingを行う
    • Attentionのヒートマップを見ると、報酬が1になるようなタイミングに重みがあったりするので、そういうタイミングへの学習が行われていそう
    • 世界モデルの学習系列を16から4に減らすと明確に性能が落ちる

所感

  • 細かい差異はともかく、Transformerに入れて世界モデルとして使うとこれくらいできますというのが確度の高い情報として提示された印象
  • それぞれの手法について、予測部分で行動まで出してそれをPolicyにするというのは不可能なんだろうか

強化学習における自分の興味範囲

 強化学習と一口に言ってもその範囲はとても広いので、自分はどこに興味があるのかを絞って考えたい。その点について改めて整理する。手法や工夫ではなく問題設定の方に着目する。

 まず、究極的な目標としては「実世界で動作できる知性を実現したい」となる。しかし、現実的に役に立つものを作りたいというよりも、知性を機械的に再現する手法を知りたいという気持ちの方が強い。

 現実的に有用なものを目指す場合、実世界と相互作用するボディの作り込みや、MLOpsのようなデータ収集と学習の仕組み作りを整備することが近道になりそうで、それは個人でやるには難しく、有益なことはどうせ企業がやるだろうとも思う。個人の趣味としてやるなら、実用性よりも納得を優先したい。

 生物は「他のマシンで学習したパラメータを脳内にコピーしてくる」ということはできず、個体として振る舞う独立したこの脳だけで学習する必要があると思われる。それを完全再現することはとても難しいだろうが、「この技術が洗練されていけば実現できそうだな」と納得できるようなものがわかると良い。

 環境準備の手軽さを鑑みて、題材自体はAtari等々のようなゲームとするのが現実的だろう。ゲームではやりつつも、先を見据える意味で以下のような4つの要素を念頭に置きたくなる。

オンライン強化学習

 データを予め収集しておいた中で学習するオフライン設定ではなく、探索のことも考える必要があるオンラインの強化学習に興味がある。探索以外にも、環境と相互作用をしていて今起こった失敗を(理屈上の最短で)いつ学習で取り込めるかという問題意識や、学習中も同じFPSで動き続けられるかといった話題もありそうだが、とりあえずはオンラインで学習できていれば良いとする。

非分散学習

 強化学習手法の中には、環境を並列でたくさん生成して相互作用の効率を上げるものがあるが、最終的な目標が現実世界との相互作用ということになると現実世界は一つしかないのでそのような手法には頼れなくなる。もちろん、シミュレータで並列的に事前学習してから現実世界に持ち込むというのは有力な手段なのだろうが、興味の範囲からは外れる。環境のモデル自体を学習して、それを内部的に並列に動かして学習するのは良い。最終的に相互作用する真の環境が一つだけであることが重要になる。

非エピソディック

 現実世界での振る舞いを考えると、明確なエピソード区切りはないものと考えた方が自然に思える。擬似的な再現としては、ゲーム系の環境として1回終わったらすぐ次が始まると想定するだけで良い。ただ、連続的にクリアできるような環境だと、報酬の割引率を適切に設定しないと報酬和自体がかなり大きくなっていってしまい学習に悪影響が出そうだ。このあたりの報酬の大きさの不安定性にも興味がある。

非定常環境

 結局、オンライン学習が求められるのは環境が非定常だからという側面が大きそうなので、評価する上ではそのような設定を準備するのが良さそう。この場合、環境が切り替わっても得られる報酬が落ちにくい、あるいはすぐ高い報酬に行けることが重要になるので、単純に最高スコアが高いことだけでなくサンプル効率が良いものが重要になる。


 上記を念頭にやっていけたらなという所存。

週記 20231225~20231231

 今週は実装を進めようとしていたが、思ったようには進まなかった。

 目標としている変更は、DQNをベースとして

  • ネットワークを過去系列を入力に含むTransformerに変える
  • 上に伴って、ReplayBufferも系列として情報をサンプリングできるものに変える
  • そうするとReplayBufferで管理するもの、返り値が変わる
  • 学習が終わってテストするときも、毎回の状態をReplayBuffer(的ななにか)に溜めておく必要がある

となることが実装を進めてみてわかってきた。最初はStableBaselines3のDQNをベースにして実装していこうとしていたが、これの実装がかなり継承を駆使した作りになっており、ReplayBufferやテスト時の動作を変更しようとしたときに結構つらいことになってしまった。ちゃんと理解していれば修正するべき点は意外と少ないのかもしれないが、そもそもどこを理解するべきかが難しい。

 なのでcleanrlのdqnから出発するように方針転換した。こちらの方が見通しがよく、またそもそものベースDQNの収束も早かった(ハイパーパラメータのちょっとした違い?)ので一石二鳥だった。

 現状はまだこのdqnでどうやればネットワークとかReplayBufferをいじれるかという見通しを立てたところで止まっている。

 一応先週の目標は「見通しを立てる」ところまでではあったので想定通りの進み具合ではあるが、まぁ実際に実装までできないものだなという学びでもある。

その他

 Sutton & Bartoの強化学習(第2版)の翻訳されたものをようやく読み始めている。非エピソディック設定とか、従来的なQ学習(から派生するDQN)に触って、読む準備が多少できてきたか。

 しかし内容はかなり難しい。テーブルベースのところはなんとか、くらいではあるけど、関数近似が入ったところから完全に置き去りにされている。

 最後の章で課題として挙げられていたところは

  • 一つ目はオンラインでの学習。これはやっていきたい。深層学習がオンラインに向いてないと言及されているが、もっと良い手法があるとも感じられていないのでとりあえずこれでやるしかなさそう
  • 二つ目は汎用性を見据えた表現学習。これについても深層学習でについて悲観的な見方をされているが、なんとかなるんじゃないかな
  • 三つ目はプランニングのためのモデル(モデル自体の学習も含む)。明らかに難しい話だが、モデルの学習も現状は深層学習以外道が見えていない
  • 四つ目はタスク選択の自動化。これは初めて聞いた話でまだピンと来ていない
  • 五つ目は好奇心の導入。これは環境モデルの学習と近いところで行われるのではないかという予想。環境をできるだけ少ない労力で説明できるようになることを目指すのが、好奇心の学習と関連するのではないか
  • 六つ目は安全性。これに関しては粛々とやりましょう

という印象。

 とりあえず一周目としては丁寧に数式を追いかけるというよりも書かれているトピックを把握する程度の雑な読み方をしたので、ここから気になったところをまた数式手書きして辿ってみたい。

週記 20231218~20231224

読んだ本

  • 今井 むつみ,秋田 喜美『言語の本質-ことばはどう生まれ、進化したか』

 言語学には特に詳しくないし思想も持っていないのでオノマトペについて語られるあれこれは素直にそう思える。個人的に興味を惹かれたのはアブダクション推論部分についての仮説で、ちょうどLLMは同じ知識を逆転した形式で問うと精度が落ちるという話とリンクするのではないか。外れているかもしれなくとも勝手に外挿して当てはめてみようとした方が学習効率が高そう。でもそれをどうやって機械で実現する?

書いたもの

 補足としては、「対策3:入力系列を圧縮する」というものもある。たとえば将棋の盤面を9x9 = 81トークンとしてずっと扱うのは流石に無駄が多い。もっと少ないトークン数で局面を十全に表すことができそう。おそらく、ここでのトークンは直接Policy, Valueを計算できるほど抽象化された分散状態じゃなくて良いので、局面を一意に指定・復元できる情報があれば良い(?)

やっていること

 強化学習の実装周りは、強化学習が想像以上に難しくて撤退戦という趣になっている。とにかくちゃんと学習できることを確認できる地点まで戻るために、グリッド世界をGym形式環境として書き直し、Stable Baseline3の既存実装を使って学習ができるかどうか、というところまで戻ってきた。強化学習をやるならGymから逃げられない!

 一応学習はできるらしい。上手くいくPPOとDQNのデフォルトパラメータで10回回して、安定性も問題なさそうなことを確認した。

 グラフ化している指標としては、単に収益ではなく最適行動を取る確率にしている。ターゲット位置が離れた位置に生成されるとどうやっても収益1にすることは不可能なので、細かい最善を考えるのが面倒くさい。最適な行動とは、今がターゲット位置ならクリック行動だし、今がターゲット位置でないならターゲット位置に近づくものとなる(相対位置関係によっては2方向が正解になることがあり得る)。これだと正しく100%が上限となる。

 DQNではかなり安定した収束を見せているのだが、それでも理想的な行動を取る確率が100%にはなりきらず96%ほどで止まってしまうことが気になる。どういう状態で失敗しているのか、確認してみなければいけない。まだライブラリの操作に慣れていないので少し調べながら進める必要があるのが面倒だ。

 とはいえDQNの方は収束した後に崩壊することも少なさそうなので、グリッド離散行動に適しているのは性質からいってもこちらだろうし、とりあえずはDQNの改造という方針で考えてみたいところ。

来週の目標

 Stable Baseline3の互換形式で、エピソードをまたいだ系列を入力とするモデルを実装する目処をつける。