2021年11月13日土曜日

順調に育つエージェントができた

とりえあずのお祝いを。

前回の記事の終わりで、さもパフォーマンスが落ちる原因がわかったかのような口を聞いたが、仮説検証のために色々と実装をしたものの結局のところパフォーマンスが落ちる原因はわからなかった。しかもコードの重要な部分にバグがあるのも見つかり、しっちゃかめっちゃかになった。バグの修正後に比較的安全なパラメータ調整をして臨んだところ安定して成長するようになったのである。今回の記事はそのあたり(10月上旬あたりから約1ヶ月程度)のまとめになる。長くなることを最初にお伝えしておく。

過学習と正則化

前回の最後に立てた仮説は「過学習によってそれまでと少しでも違う動きをする相手に対応できなくなっている」というものであった。過学習とはデータの中の一般化できない部分にまで適応してしまう現象のことである。深層学習では過学習をどのようにして避けるかが一つの大きなテーマにもなっており、様々な手法が開発されている。データの数が少なければ少ないほど過学習のリスクも高まる。こちらの記事に詳しく解説されている。

深層強化学習の場合はデータを常に作り続けるために他の深層学習の分野と比較して過学習に対する対応が薄い。このプロジェクトで使っているRainbowというモデルでも明示的に過学習を防ぐ方法は取られていない。Rainbowの論文ではAtariのゲームのシミュレータを用いているので、データ取得と学習のステップをどの程度の比にするかを選べるようになっている。ここでデータ取得の頻度を比較的大きくしておけば過学習を防ぐことができる仕組みになっている。

AIガオガエンの場合は実機を用いるためデータ取得の頻度が実時間で決めらている。一方学習は別スレッドで動いているためステップ数はCPUに可能な最大値となっている。LSTM2枚程度のモデルではだいたいRainbow論文と同程度、つまり4ステップごとに1回程度のペースで学習をする。一回の学習で32ステップを読み込むため、実時間に対して8倍程度の速度で学習をすることになる。これもRainbow論文と同程度である。

これだけ聞くと過学習の心配はなさそうに感じるがもちろん環境が違うためちゃんと成長するために必要なデータの分量も変わってくる。LSTM1枚のモデルが2枚のものより早くパフォーマンスが落ちるのを観測したとき、過学習の可能性を疑ったのである。

過学習が起こったらどうすればいいのか。先述の記事にもあるように、「正則化」を行うのが順当な手法である。このプロジェクトでは最適化の手法であるAdamにWeight Decayを加えたAdamWというものを使った。

もうお分かりかと思うが、これで問題は解決しなかった。詳細は割愛するが、Weight Decayを導入してもパフォーマンスの低下は防げず、逆にWeight Decayを弱めたところから成長を始めるエージェントなどもいて、かえって邪魔になっている印象であった。

次に試されたのが色が見えるエージェントである。Rainbow論文にならってAIガオガエンは白黒の映像を与えられていたが、ステージが緑色、ガオガエンが赤、マルスが青で、それぞれのカラーチャンネルにうまく対応していたため色が見えるエージェントは物の識別が用意になるのではないか、という仮説があったからである。色を導入するとデータ量が増えるため、今までよりも少ない数のリプレイメモリしか保存できなくなるのがトレードオフである。

これも試されたものの、白黒のエージェントに勝ることはなく、短期間で実験を終えることになった。

ハイパーパラメータチューニング

試せる案が減ってきたので、ノイズを増やす、マルチステップの数を変える、などの妙な変更を始めた。ここで試したかったことは、「パフォーマンスの低下は過学習の結果ではなく、ガオガエンが成長する上で必要なステップで、それを越えた先に成長がある」という仮説の検証であった。このエージェントでは成長速度を上げるため、裏でやっていたAtariのパラメータを一部ひっぱってきてやっていた。つまり、バッチサイズを大きく(32→128)し、学習率を上げる(1e-5→1e-4)という方法だったのだが、どういうきまぐれからかLSTMレイヤーの数は3枚にしてみた。

蓋を開けてみると、このエージェントの成長はとても遅かった。バッチサイズを大きくし、ネットワークを重くした結果、データ取得に対する学習ステップが100ステップに1,2回程度まで下がってしまい、結果Lossの現象は今までのLSTMモデルより随分ゆっくりになった。次のグラフはLSTM1枚のモデルと今回のモデルの比較である。両方Lv3スタートである。


Lossが2.0程度に戻ってくるまでに先のモデルは500エピソード程度だったが、今回のモデルは3000エピソード近くかかっている。そしてこのエージェントはその後もゆっくりと成長を続け、Lv3をクリアする直前まで来た。ここまでにおよそ5日程度かかっている。

ここで一度クラッシュしたのと、メモリ構造を書き換えるために止めたため、クリア前ではあるがLv4に移行することにした。以下がLv4の経過である。
しばらく走らせたものの、クリア目標である70%に到達するのは遠いように見えたので、クリア条件を60%に改めてクリアしたことにした。次がLv5の経過である。

ここに来て減速を始めたのである。結局駄目だったかと落胆したものである。パフォーマンスが下がるにつれてガードが増え、クラッシュするまで守るようになったのが印象的であった。パフォーマンスが落ちつつも試合時間が長くなっているあたりにその様子が間接的に伺える。

未来予測型

その次に試されたのが未来予測型のネットワークである。情報を処理するLSTMの前に未来を予測する部分を並列で作り現在の情報と予測された未来の情報の両方を使って最適な行動を選べる(はずの)エージェントである。次の図の左側の水色の線の部分が未来予測の部分である。

着想はSSBMの深層強化学習を行ったFiroiu氏のこの論文からである。AIガオガエンの約300msの入力遅延を未来予測でごまかせないかという話である。

結果から言うと、未来予測型がしっかり完成する前に、回帰ネットワークまわりのバグが見つかったので保留になった。なのでこの部分は未完成である(一応完成はしているが未検証、といったところか)。

回帰ネットワークのバグ

問題は「トレーニングの最中に同じネットワークを2回使ってしまっていた」というものであった。回帰ネットワークでなければ何度使おうが同じ入力には同じ結果を返すので問題ないのだが、回帰ネットワークは内部状態を持つため2回使うと違う結果が出るし、その次のステップ移行にも影響してくる。トレーニングにおいても同じネットワークは一度しか使ってはいけないのだ(内部状態を元に戻すという処理も可)。今回は2回使わなければいけない場面でネットワークを2つ用意するという対応をとった。

このバグに間してはバッチサイズを大きくすることによってもある程度対策が可能なため、バッチサイズの大きくした時にパフォーマンスが低下しにくくなる1つの理由となり得た。

GRU vs LSTM

回帰ネットワークのバグを修正するついでに計算を軽くしたい欲求も出てきた。もし今まで成長していなかったのが回帰ネットワークのバグのせいならばLSTM1枚でもちゃんと成長する可能性がまだ残っている。

それと同時に、今までのLSTMの知見が眉唾ものになったために、少し他の事を試すいい機会になった。GRUというLSTMと同等の性能でパラメータが少なく計算と学習が少し早い回帰層があり、これとLSTMのどちらを使うか迷った結果今まではLSTMを使っていたのだが、ろえを機会にGRUを試してみることにした。以下がGRUでLv3から学習を始めたときの結果である。

最初大きなバッチサイズ(4096だったか)で始めて、2200epあたりで成長の遅さにしびれを切らしてバッチサイズを小さく(128)した。そこからしばらく走らせたものの、パフォーマンスの低下が見られたので仕方なく打ち切った。LSTM3枚のモデルがうまくいっていたため、このままここで時間を使うのは勿体ないかと思い、これも一旦保留にしてLSTM3枚のモデルに戻ることにした。

最後の変更:バッチサイズをランダムに

結局まともに動いているならいいかということでLSTM3枚でLv5で調子がよかったあたりから再開した。次のグラフの14000epあたりから修正されたLSTM(バッチサイズ大)が始まる。
バッチサイズの変更の伴って報酬は急上昇し(QもLossも)あっさりとLv5をクリアした。Lv6も同様でさほど苦労せずに攻略した。Lossはバッチサイズを大きくして以来増え続けている。
Lv7の途中で少し成長に鈍化が見られた。
上昇を続けていたLossもここで現象に転じ、過学習の様相を見せ始めた。ここで、新たな正則化の手法を導入した。バッチサイズを固定された数からランダムに変更したのである。

学習に用いるデータは1試合ずつ取り出して使われるのだが、バッチサイズを固定しておくと、同じ試合を取り出した時に切り分け方がいつも同じになる。これをランダムにすることで、同じ試合でも別の切り方になり、ネットワークにとって少しずつ違うデータに見えて、正則化が働くのではないかという算段である。

そのランダム化を3700epあたりで導入した結果、以下の図のようにパフォーマンスがまた回復してLv7をクリアすることができた。最後急激に報酬が落ちたが、あまり気にしないことにした。その後もこのエージェントは順調に成長し、ついに当初の目標であるLv8のCPUマルスを攻略した。

これで少なくとも安定して成長するエージェントができたことになり、いよいよAI同士によるセルフプレイの準備を始められる段階に入った。

確認事項1: クイックモードをやめたらどうなるのか

今までのトレーニングの大部分はデータが速くとれるクイックモードでやっていたが、通常モードと比べると入力遅延がやや大きい、フレームスキップがより頻繁に起こる、FPSが微妙に違うなどの問題があって通常モードに戻したときにどうなるかという検証が行われていなかった。人間は通常の時間でプレイしているため、通常モードで動かせないのは致命的になる。セルフプレイを本格的に始める前に通常モードに移行できるかを確かめることにした。

クイックモードでLv8マルス攻略まで鍛えたガオガエンを通常モードで戦わせた結果がこちらである。

ご覧の通り、最初こそ少しパフォーマンスを落とすものの、比較的簡単に順応することがわかる。

確認事項2: 終点から戦場にするとどうなるか

もう1つ確認しておきたかったのが台の有無にどう対応していくかである。スマブラは縦にも横にもキャラが動くゲームで、ステージ上の浮遊する台の存在によって戦術の幅が大きく広がる。もし実戦を意識するのなら、台有りでの戦いは避けられない。セルフプレイを始めるにあたって、台なしの環境で育ててしまった場合、台ありにシフトしたかったら両方のエージェントを同時に鍛えなおす必要がある。ゲーム内CPUが使えるうちに台の有無に適応できるかの確認をしておきたい。

次の図は、Lv8CPUマルスを終点で倒したガオガエンが戦場(両方エレクトロプランクトンではあるが…)を使った時の結果である。

クイックから実時間に変更した時と比べて最初のパフォーマンスの落ち込みは大きかった。ほぼ全然勝てない状態に戻ったものの、そこそこの時間で勝率を5割程度まで戻すことができた。

この挑戦中にセルフプレイ用の機材が届いたので、このエージェントを叩き台としてセルフプレイを開始することにした。

続きは次の記事で…。


2021年9月23日木曜日

回帰型ネットワーク(LSTM1枚からまた2枚へ。あれ?)


 2枚のとは違うのか?

大した違いはないんじゃないだろうか。結局のところ回帰レイヤーは自分の出力が自分に返ってくるのでNユニットの2枚のLSTMでできることは2Nユニットの1枚のLSTMでだいたい可能である。(返ってくるまでに1ステップの時間がかかるので全く同じというわけではないが。)

同じユニット数だともちろん2枚の方が色々なキャパシティが上がるとは思うが、同時に回帰レイヤーのトレーニングは時間ステップを遡りながら行うので重くなりがちである。実際に1枚のものと2枚のものではだいたい3割程度、1ステップの学習速度に違いが出る。

一方シンプルな系(Atariのゲーム)で学習成果を試したところ、1枚のものも2枚のものもだいたい同じステップ数だと同程度のパフォーマンスになる。だとすると1ステップあたりの学習が早い1枚のものの方が有利だということだ。もちろん複雑な系の場合はどうなるか不明である。

最初2枚のものから始めたのは、PyTorchのデフォルトの値が2枚だったからで、特に深い理由はなかった。その後、OpenAIのDota2のAIがLSTM1枚で行われていることなどを知って、1枚の方がよいのではないかと思うようになった。

で、1枚のものと2枚のもの、試したところ実際どちらがよかったのかという話だが、残念ながら結論が出なかった。次の2枚の図を見ていただきたい。


上が1枚のもので、下が2枚のものである。枚数以外はほぼ同じ条件である。2枚のものはゴールラインの0.5を越えたので止めたが、1枚のものは越えなかった。Rewardだけ見ると勿論2枚の方が成績がよいのだが、このあたりの数値はノイズが大きくもある。Lossの値を見ると確かに1枚のものの方が早く収束しているし、値も低く保たれている。Qの最終値も大きいし、何なら先に0に到達したのは1枚のものの方だ。どちらが先に0.5に到達したかというのは、偶然性の寄与するところが大きいように思われる。

問題はこの後だった。2枚にしようかな、と思ってその先に進んだ結果、途中で成長が止まってしまったのだ。次の図はLv2をクリアした2枚のモデルでLv3に進んだ結果である。

まだ順調に進んでいる。Qの値がふらついているのも相手の変化に合わせて再調整したためと読みとれる。そして、Lv4である。
突然勝率を下げ始めたのである。行動にもおかしな様子が顕著に現れていた。自滅の数が極端に多くなったのである。Qも下がりっぱなしで元に戻る気配もない。このあと2枚のモデルでLv3の最後から始めたり、3ストックにしたりLv2まで戻したり、1枚のモデルでやったり学習率を上げたりしたが、結局どのモデルもある段階まで学習すると、そこからパフォーマンスを下げて戻らなくなることのが観測された。回帰ネットワークを導入する前は確かそのようなことはなかったと思うのだが、これはいったいどういうことなのだろうか…。
次の記事では、なぜそうなったかの仮説と、解決策についての議論をする。







2021年9月20日月曜日

回帰型(再帰型)ネットワーク(LSTM2枚)

 強い。

時系列予測などによく用いられる回帰型ネットワークを実装した。英語では Recurrent Neural Network (RNN) と呼ばれ、再帰型ネットワークとも訳される。出力を次のステップの自分の入力に入れることでループを形成し、原理的には無限ステップ離れた過去の情報にもアクセス可能になる。詳しい説明はこちらの記事などを参考にされたい。(英語が読める場合はこっちのブログ記事の方がいいかも。) 今回の実装ではLSTM(Long-Short Term Memory; 長-短期記憶)という型のRNNを用いる。

時系列を認識するタイプのネットワークなので、時間の流れを適切な順序で入れてやる必要がある。今までの学習方法ではランダムな時間を取り出してきてトレーニングしていたので、変更する必要があった。新しい方法では1試合のデータを丸ごと取り出してきて、それを1から試合終了まで順番に入れることになった。バッチサイズは今まで通り32でも大丈夫なようだった。これに伴ってメモリ構造を一から書き直す必要があり、更に Prioritized Memory が(実装が面倒だという理由で)失われた。一応こちらの論文を参考にして、完全にランダムにリプレイメモリから情報を取り出すのではなく、最後にやった試合を必ず一度は読み込むような形の実装にした。

裏でこっそり実験していた Space Invaders や Kangaroo などのゲームは元のRainbowと遜色ないペース(あるいはもっと早く)でクリアしてしまった。AIガオガエンで試してもその強さは健在で、1ストック制の試合だと1日も経たずにLv1やLv2をクリアしてしまう。

これはLSTMレイヤー2枚の結果である。まずはLv1から。

途中でメモリ構造を変えたのでLossとQの値がおかしくなっているが、1200エピソード程度でクリアしたことがわかる。次にLv2のデータである。
Qがおかしくなっていたので最初からやりなおしたものだが、ほぼ同じような振舞いで1600エピソードでクリアしている。ガオガエンの挙動自体も興味深く、ロープスイングから頻繁にラリアットを決めたり速い段階で復帰らしいこともするようになっている。
LSTM2枚のモデルの途中で1枚にする実験などを挟んだが、この記事では2枚の結果だけをまとめて載せる。Lv3の結果は以下の図である。
上の図のLv2からの継続で、2500エピソードほどでクリアラインの0.5に到達している。目覚ましい成果である。このあとLv4に行くのだが、そこで次のような結果を出す。
Lv3での成果はどこへやら、勝率を大幅に落としてしまい、更にQも上がっていかない。これはどうしたことかと思い、一度Lv3終了時に戻ってそこからLv3を継続してみることにする。(ここで自滅が気になったので3ストック制に戻す。)
2700エピソード目あたりからが新しいデータになるが、結局Lv3に戻ってもスコアが伸びることはなく、むしろ下降していく傾向が見られた。

もしかするとLv3に上がってしばらくすると戦術の再調整を迫られることになり、必然的にスコアが下がるのかもしれない。だとすると最適なポリシーを再評価するまで淡々とトレーニングを続けないといけないのかもしれない。もう少し早く学習ができるネットワークで長期間回す必要があるのかもしれない。

次回は1枚レイヤーのRNNについて書く。

2021年9月16日木曜日

Lv4における2週間の停滞

何が成長を阻害している…?

もちろんLv3も順調ではなかったが、無事にLv3を乗り越えて帰ってきたLv4も順風満帆とはほど遠いものだった。Lv3を終えてからの二週間の修行の結果がこちらである。

(Reward: 報酬、 Episode Length: 各エピソードの長さ、 Q: 報酬予測値、 Loss: 予想と現実の差、 それぞれ20試合分くらいの移動平均)

何か変わった? むしろ悪くなってない…? 11000エピソードあたりから少し上昇した気はするけれど、最後下がってるし…。

また何週間かすれば上がってくるのかもしれないし、このまま落ちていくのかもしれない。

この間何もなかったわけではない。このエージェントのコードが公開された。整理するのは大変だったけれど、環境を綺麗にしておくと開発が楽になるので自分のためになる。

そして開発を楽にした結果、実際に開発を始めたのである。リカレント(再帰・回帰)レイヤーを含むエージェントである。これについての詳細は次項に持ち越すことにする。

2021年9月3日金曜日

Lv4 への寄り道と Lv3 への栄光の帰還、そしてまた Lv4へ


 Lv3マルスは倒れた。

前の記事でどうしてもLv3を倒せずに停滞した話をした。作戦会議の結果、Lv4に行ってみることにした。同時にこちらの論文のFigure 4でライフが複数あるタイプのAtariのゲームだと、ゲームオーバーでエピソード終了にするよりも、ライフが1つ失われた段階でエピソード終了にする方がスコアの伸びがよい、という結果が出されていたことを思い出したので、それをスマブラに適用してストックを1つにする変更もした。

その結果がこちらである。

Rewardは微妙に上がった。QはLv3のときのものを引き継いだのでLv4に合わせて下降した。後半も振動は見られるが顕著な上昇は見られない。これが約一週間のトレーニングの成果である。

1ストック制に移行してからゴールをどこに設定していいのかよくわからなかったのだが、3ストックのときに1.5だったので、単純に計算して0.5にしてみた。Lv4では0.0に触れることもかなわなかったわけだが、一週間Lv4で修行した結果、Lv3ではどうなるのか…。その結果が次のグラフである。

なんと、始めてから一日も経たずにゴールラインの0.5を越えてしまったのである。Qの調整が行われてLv3用の戦い方になるのに1500から2000エピソード程度かかった節はあるが、いともあっさりと設定したゴールラインを越えてしまった。

正直なところ、統計的なゆらぎを考えると3ストックで1.5のゴールの方が1ストックで0.5のゴールよりもシビアな気はするので、実際に強くなったから攻略したのか、単純に上振れが激しく起こったからなのかはわからない。しかし、0.5を複数回越えてそのあたりでしばらく滞在している様子を見るとまあ合格点にしてもいいんじゃないかという気はする。

というわけで晴れてLv4に進むことになった。ストック数は1を維持していきたいと思う。既にある程度データがあるので今後どう伸びるのかが楽しみである。

こうなってくるともうひたすら時間をかけてトレーニングさせるより他ない気がしてきた。

トレーニングの様子はずーっと配信しているので、進捗はYouTubeの配信でどうぞ。

https://www.youtube.com/channel/UCTR4c0xE-pIFgSoE6bFVPmw
















2021年8月30日月曜日

深層強化学習AIガオガエン FAQ

Q: これは何?

A: 機械学習の一種である深層強化学習を用いて、スマブラ(ガオガエン)をプレイするコンピュータプログラムを作る実験です。

Q: 何でこんなことしてるの?

A: 趣味です。人智を越えたスマブラのスーパープレイ、見てみたくないですか…? 開発の経緯が見たければブログの過去の記事をここから辿って見てください。

Q: どうやって動いてるの?

A: Arduino をコントローラ代わりにしてスイッチにコマンドを入力し、出力はキャプチャーボードでパソコンに取り込みます。ゲームは無改造のSwitchの実機で実行されています。詳しい説明や写真などはセットアップの記事を参照してください。ダメージや撃墜の計算は取り込んだ画像を解析して行われています。

Q: どうしてガオガエン…?

A: 作成した人のメインだからです(このファイターのいい動きをよく知っている、というのが大きい)。あと、ガオガエンは強いです。

Q: どうしてマルス…?

A: 飛び道具がなく、単発攻撃が多い近距離ファイターから適当に選びました。

Q: どうしてエレクトロプランクトン(ステージ)…?

A: 一番シンプルで動きも少なかったので。グリーンバックみたいであまり見栄えはよくないかもしれません…。ピクトチャットも考えたけど背景が意外と動いたので却下しました。

Q: 右上のグラフの意味は?

A: Reward は直近20試合程度の報酬の平均値です。報酬は1ストックあたり2ポイントで、ダメージはその部分点がもらえます(100%で1程度)。どういう倒し方をしても最終的に1ストックで2ポイントになるように設定されています。Qは報酬の予測値みたいなものだと思っていただければいいかと思います。直近10000ステップ程度の平均を出しています。

Q: 最新鋭の強化学習アルゴリズム使ってんのに弱くない?

A: どんなアルゴリズムを使っても強化学習にはかなり多くのトレーニングデータが必要になります。実機でデータを出している以上、強くなるまでにはそれなりに時間がかかります。この世に生まれてからまだ1ヶ月くらい、と考えるとそれなりにがんばってる気がしませんかね…?あと、コードにバグが入ってないとも限りません。

Q: 自分もやってみたいんだけど、簡単にできる?

A: デジタル回路とプログラミングの経験が多少あればできると思います。プログラムのセットアップが少々ややこしいですが、ちゃんと数日かけてやることをやればできるはずです。実行に必要なコードと解説はこちらに置いておきました。README_ja.md が日本語での説明になっています。

Q: 本当に成長してるの? 弱くなってない…?

A: 実のところわかりません…。Rewardが上昇傾向にあれば成長していると言えますが、かなり振れ幅があるので、数日単位で見て確認するのがよさそうです。そのうち勝率の上昇の統計的優位性等も出せたらいいなとは思っています。

Q: 自滅しまくるのは何で?

A: 正直なところよくわかりません。ただ、最初よりはかなりましになっています。もしかしたら、この強化学習エージェントは一般化が苦手で、ありとあらゆる状況で自滅してみないとわからないのかもしれません。

Q: どうしてダメージの初期値が12%なの?

A: ダメージ認識を数字ではなく色を使って認識しているからです。0から12%までは色が白で変わらないので、最初から小さな変化を認識できる12%から始めています。

Q: CPUのマルスを倒せるようになったらどうするの?

A: 今のところは、他のCPUともやってみるとか、マルスも深層学習にして互いを相手に練習させるとかを考えています。いいアイディアがあれば Twitter の DM などで教えていただけると嬉しいです。

Q: 最新情報やまとめはどこで見たらいい?

A: 新しい情報は Twitter で発信しています。ここで答えられていない質問等にも答えます。こちらからどうぞ。

深層強化学習AIガオガエンはこういう感じで動いている!

 線がごちゃごちゃなのは許してくれ。


ちなみに配線図はこんな感じ。

以下、材料の詳細。
  • M1 Mac mini (2020) RAM 8GB, SSD 256GB (80,000円くらい)
    • メモリがギリギリなので余裕があれば16GBの方がいいかも。
    • たくさんのメモリとGPUを積んだLinuxが理想的とは思うけど、動作の保証はできない。
  • Elgato HD60 S+ (23,000円くらい)
    • +のないモデルはMacで読めないのでだめ。
    • UVCプロトコルを用いたモデルであればこれでなくても使用可能かも。
  • Nintendo Switch (33,000円くらい)
    • ドックが必要なのでLiteはだめ。有機ELモデルはわからない(多分OKとは思う)。
  • シリアルポートデバイス (1,500円くらい)
    • FTDIチップが乗ってれば他のでもいけるかもしれないけど、挙動が違うかも。
  • Arduino UNO R3 (3,000円くらい)
    • 互換機でもいけるかもしれないけれど挙動が違うかも。
その他インターフェイス系(モニタ、マウス、キーボード)などは多分何でもいいので適当なものを使ってください。ElgatoのOut端子から出てくる信号を表示するサブモニタがあると動作確認に便利。

2021年8月24日火曜日

Lv3マルスが倒せないよ

想像以上の強敵だった…。

Lv3のマルスは強敵であった。色々環境を整え、配信も可能にし、新しい計算機を用意して氷嚢の必要性をなくし、2週間ほど放置しても、クリアライン(報酬の移動平均 >= 1.5)を越えることはなかった…。

これがその戦いの歴史である。

1エピソードあたり2,3分かかるので6500エピソードとなるとざっと270時間程度か。空き時間もあったが、約二週間分のデータでこれである。4000エピソード目くらいまでは成長を感じていたが、その後無慈悲にも下降した。3500くらいまではLossとQが並んで増加していたが、4000あたりから乖離が見られるような気もする。これがまずかったんだろうか…?
ガオガエン自体は別段特に壊れた様子もなく、復帰も徐々にうまくなっているし、ロープスイングのラリアット(タイミングよくボタンを押さないといけないやつ)もだんだん出せるようになってきているので、成長自体はしているのかもしれない。しかしやはり自滅が治らないのである…。明らかに復帰できる状況で復帰しなかったり、余計な入力を入れて落ちていったりしてしまう。

今後どうやってマルスと付き合っていくか考えようと思い、生放送で意見を募ることにした。こちらの放送である。
内容をざっとまとめる。まず上記のような問題を説明し、こちらから色々案を出した。

  1. ネットワーク・アルゴリズムをいじる
  2. Lv3をとばしてLv4にしてみる
  3. ファイターを変えてみる(自分、あるいは相手)
  4. 何もしないでこのまま続ける
  5. 入力を変える(画面のサイズ、HD振動の情報、音声など)
  6. 報酬関数を変える(自滅にさらにペナルティなど)
いつも来ていただいている視聴者さん達からさらに、「生存点を与える」等のアイディアを頂き、まずは簡単にできそうな案2から始めてそれでも駄目なら案5、6(生存点も含む)へと進む提案をいただいたので、そうすることにした。

配信の後にAtariのゲームの場合だとゲームオーバーをエピソードの終わりにするのではなく、ライフを1つ失った時点で終わりにした方がエージェントの成長が早いといデータがあったことを思い出した。これをスマブラにあてはめると、3ストック制ではなく、1ストック制にした方が成長が早まるかもしれないと思いそれも同時にやることにした。

Lv3を倒せないまま飛び級をしたようなものだが、果たしてどうなることか…。
ガオガエンの今後はなるべくライブ配信していこうと思っているので、気になる方は気が向いたときに時々見に来ていただけるとありがたい(コメント欄でのご意見等も歓迎)。

チャンネルはこちら。

2021年8月11日水曜日

Mac を カフェイン漬けにしてフレーム落ちを防ぐ

人も計算機も怠ける。

Lv3マルスは手強く、学習も進展が見えづらい。そんな状況で兼ねてから懸念していた事に取り組んだ。取得しているビデオフレームが具体的にどうなっているかの検証である。

キャプチャーカードのフレームレートは基本的に60Hzなのだが、開発初期の検証によって、ビデオフレームが均一のタイミングで来ているわけではない事がわかっていた。具体的にはだいたい12msの整数倍の間隔で、最終的に60Hzになるようなタイミングで来ている。例としては (12, 12, 24, 12, 24, 12, 12, 24) といった間隔である。周期性もわかりづらく、12msが1回だけ挟まる回もあれば2回挟まる回もある。24msが連続で来ることは(たぶん)ない。20Hzでの動作を目的としているので、3フレームごとに画像を取得したいのだが、その間隔は48ms から 60 ms (実測した時もだいたいこの間隔になる。23msのやつが2回くるか1回来るかで変わってしまう)と、安定しないものになる

今まではあまり気にせずに1ステップごとにタイマーを設定して、「一周したあとで46ms経っていない場合は46msになるまで待つ」というアルゴリズムでやっていて、大体平均して20Hzのデータを作り出していた。しかし、この方法だと実際に何フレームスキップしたのかもよくわからないし、遅延でフレームドロップがあった際に認識することもできない。

もし全てのフレームが問題なく読めるのであれば、3フレーム取得して2フレーム分は捨てる、という選択もできるかもしれないが、今までの実装ではコントローラへの出力も同時に行うと60Hzで画面を読み込むことができない、という問題があった。

そこで、コントローラの方をコードを見てみると、コマンドを出力したあと、スイッチ側からの入力を確認するようにできている。これがだいたい一周期あたり16msで、ビデオ出力の60Hz (16.666...Hz)と微妙に異なる値になっていた。この周期に一致しないとコマンド出力が完了しないことになっていたのでビデオフレーム取得と同時にやると双方が干渉して60Hzの取得は不可能、という形になっていた。

少し検証してみた結果スイッチ側からの入力を無視してもコントローラ操作は可能らしく、フレームレートが十分に遅ければほぼコマンド入力を落とすことなく操作できることがわかった。(本来はスレッドを立ててやるべきなのかもしれないが…)これでスイッチ側からの入力を待つ時間を削除できるので、コマンド入力の時間が最大16msかかっていたものを1ms以下に抑えることができた。

コントローラ操作の時間を削減できたので、他の障害がなければビデオフレームをだいたい60Hzで入力できるようになった。他の障害がなければ、と書いた。障害になるものがいくつかあったのである。

まずは学習を行うスレッドである。CPUを100%近く使う計算を常時行っているので、これが稼動しているときは60Hzが厳しくなる時もある。これについては60Hzで取得するのを諦めて、タイミング測定とビデオフレーム取得を繰り返すことで解決した。具体的にはフレームを取得できた時点で前回取得時の時間と比べて、40ms以下だった場合はまだ3フレームスキップされていないと判断してもう一度取得し、そうでなければ受け入れる、というものである。そのときに時間を記録しておき、もし65ms経過していた場合はフレーム落ちの可能性があるとして報告するようにした。この処理をすることで、前よりも強く3フレームごとに取ることの保証が可能になり、問題がある際も認識できるようになった。

もう1つ問題になったのが、Macの謎の挙動である。スクリーンセイバーや、ディスプレイをオフにする設定に関係なく、1、2分ユーザからの入力がないと勝手にフレーム落ちを初めるのである(怠けモードと呼ぶことにする)。この現象があることは以前から気がついていたのだが、落としたフレームの数を数え始めたことによってより顕著に問題視されるようになった。怠けモードに入る前はフレーム落ちは0.1%以下程度(一試合3000ステップで最大2フレーム程度)なのに対し、怠けモードに入ると10%程度も落とすようになる(一試合100-500フレーム!)。これはまずいと思い対策を考えることにした。

まずはソフトウェアでの対処を考え、無理なようならUSBの疑似HIDを作って一定間隔で何か入力をしてもらうようにしようと思い、まずはソフトを探してみた。どうやら caffeinate というコマンドが元々 Mac に入っているらしく、これが一時的にスクリーンセイバー、ディスプレイの消灯、ディスクの回転停止などの電源関係の機能を抑制してくれるらしいことがわかった。

試した結果、caffeinate では怠けモードは解消されないことがわかった。他にも色々調べた結果、怠けモードは他の省エネ機能 (App Napやら何やら)とも関係ないこともわかった。次に試そうと思ったのがマウスやキーボード入力を勝手に定期的にしてくれるソフトで、 Caffeine がそれに該当するらしいことがわかった (少なくとも昔は、「本来存在しない F15 というキー」を押し続けるソフトだったらしい)。導入し、Karabiner Element のインスペクタで確認しても、F15なるキーの入力がなかったので、不安に思いながらもしばらく放置した結果、無事に怠けモードに入るのを回避できたのである!

これらの試行錯誤の結果、フレーム落ちは合計で0.1%以下にまで抑えることが可能になり、今までよりもずっと綺麗なデータを取得することが可能になった。データのクオリティは学習に直接影響を与えるので、これは大きな変化かもしれない。今まで配信ソフトが起動しているときどんだけフレーム落としてたんだ…? 検証の必要がある…。

色々直した結果、現在の学習状況はこんな感じである。

上のグラフが報酬(青、左Y軸)とロス(橙、右Y軸)で、下がQ値(青、左)と試合の長さ(橙、右Y軸)である。X軸は共通して試合数である。報酬もロスも一定のパターンが見えづらい変化をしているが、Q値はある時期(400試合目くらいか)から着実に伸びてきている。このパターンはLv2の時も見られたので、勝ちパターンだと思いたい。グラフを用意したのが途中からで、これはLv3の最初からではないのだが、ここまででもだいたいLv2のときの2倍くらいの時間がかかっている気がする。ちなみに本稿の修正を施したのはグラフの1000試合目くらいである。

これで直すべきところは直した。あとはAIガオガエンを信じて練習を続けてもらうだけだ。

2021年8月9日月曜日

冷凍庫の安堵の溜息

冷凍庫は安心したかもしれない。

Mac Miniを買ってしまった。ベースモデルで、M1, RAM:8GB, SSD:256GB という構成である。$699で、現状これより安いMacはない。現行のMacはどうせ全部M1だし、強化学習専用マシンにするつもりだったので、今のMacbook Airと同じベースモデルで十分だろうと思いこのモデルにした。オンラインのアップルストアで注文してから1時間半で届いたのには驚いた。将来もっとパワフルなMacが出る際にはこれを売ってアップグレードするかもしれない。

TimeMachineで今の環境を移したところ、ほぼ全てのソフトが作業することなくそのまま動いた。neovimがちょっとだだをこねたのと、USBシリアルポートデバイスのデバイス番号が変わったこと以外は何事もなく、強化学習環境の移行は2時間程度で終わった。

Mac Miniには排熱ファンがついている。MacBook Air の時はパフォーマンスの低下を抑えるために筐体を氷嚢の上に置いていたが(1日3回変える必要がある。アンパンマンのシステムに似ているかもしれない)、もうその必要はない。冷凍庫は毎日3つのなまぬるくなった氷嚢を再冷凍する必要がなくなったのだ。(なお、冷凍庫が冷却の再に排出する熱を溜息にたとえるのなら、溜息の回数は減ることになる。)

余も強化学習のために奪われていたパソコンを返してもらえて御満悦である。やはりパーソナルな計算機は手近なところに必要である…。

Lv2クリア!

 まっすぐな道ではなかった。

レベル1のマルスと比べて動きの種類は増えたものの、まだ何もしない時間も長くスマッシュに勝手に入ってくるため、最初のうちは難なく勝っているように見えた。目標とする報酬の移動平均を1.5に設定したが、開始間も無く1.46程度まであがり、そこからしばらく0.5付近をさまよってから1M(学習)ステップ後に到達した。かかった時間は1日半程度だったか。多少雑だがLoss, Q値, 報酬のグラフを下に掲載する。



いつでも上がれそうな雰囲気でもあったが、そうでなかったのは偶然なのだろうか。最初上がった報酬が下がったときはネットワークが壊れたのかとも思ったが、どうやらそうではなく単純にLv1とLv2の違いに合わせようとしただけなのかもしれない。Lossが増えていったのは多少不安だったが、Q値がほぼ線形に伸びていっていたのでこれはおそらく正しい変化をしているのだと信じて先に進んだ結果、無事到達することができた。

Lv3への到達がなんと配信中に起こったのでアーカイブを残すことができた。クリアするのは動画の最後の方である。

次はLv3…。ここからCPUも少し強くなってくる。

2021年8月5日木曜日

The cat is under training...

 AIガオガエンは成長を始めた。

前回投稿した時から小さな変更(学習率を小さくし、変化幅も狭めた)を加えたが、それ以外はそのままでしばらくトレーニングを続けている。どうやら学習は無事に行われているようだ。変更を加えてから半日程度でLv1のマルスと五分の勝負をするようになり、もう半日程度で7割程度勝つようになった。自滅の頻度も減った。

復帰はLv1マルス相手だと練習する回数が少ないためまだちゃんとできるわけではない。攻撃もスマッシュを溜めて相手が入ってくるのを見て殴るという、Lv1にしか効果がないような戦術をとっているが、これは想定内だ。Lv1を相手にしているのでそれに最適な行動をとるようになったのはむしろ喜ばしい。相手のレベルに応じて適応していく可能性を秘めている。

これがLv1マルスを倒すようになった時の記録である。


勝率が高すぎても低すぎても学習の効率が悪くなるだろうからマルスのレベルを上げることにした。前回の反省をふまえて今回は1つずつ上げていく。今はLv2のマルスと戦っている。Lv1とは違いジャンプ、ダッシュ、DA、掴み、ガードなどを使ってくる。(今思えばLv1はこれらのどれもしなかった…。)攻撃の頻度はまだ低いので似た戦術が通用しなくはないはずだ。

初期の勝率は五割弱。丁度よさそうである。これがまた上がってきて、報酬の移動平均が1.5程度になったら再度レベルを上げるつもりである。

2021年8月3日火曜日

変化する学習率と exploration-exploitation balance

昨日淡々と学習させると言ったが、あれは嘘だ。

結局翌日になっても何の成果も挙げられなかった素振りを見せるガオガエン。このあいだ学習率を下げたときにはすぐに勝率を上げていったのだが、今回はまた同様に停滞した後で学習率を下げても何もおこらなかった。まあ、色々変更があったし、前回よりも学習したステップの数が少なかったので、そのせいかもしれないが、よくなることを期待していたためにがっかりした。

結局試行回数を稼がないといけないのかもしれないが、ここでまた別のアイディアを着想してしまう。学習率が正しいのかよくわからないのであれば、時間変化させてしまえばいい。学習率を周期的に変動させる方法は実は一般的に使用されていて、成果も出しているのだが、失念していた。AtariのKangarooで試してみたところ、学習が劇的に早まったので、とりいれてみることにした。値は広くとって基本の値の10倍から1/10まで、周期はとりあえず5万ステップにしてログスペースでcosで周期振動させてみる。長く停滞する期間があるようならこの方法は有効なはずだ。

というのも強化学習には長く exploration-exploitation balance (探索と収束のバランス)の難しさというものがある。探索をしすぎると解答に収束できないし、収束を早くしすぎると最適解に辿りつけなくなる可能性がある。そのバランスをとるにはいい妥協点を見つけないといけないのだが、これが難しいのである。

周期的に変化する学習率は高いときは探索を促進し、低いときは収束を促進する。うまくやればいいとこどりになりうる。失敗する可能性があるとすれば、低いときに収束した点から遠ざかってしまうことが考えられるが、これが起こっている場合は報酬やQ値に反映されるだろうから、少なくとも観測は可能と考える。

さて、明日からは淡々と学習させる日々が続くはずだ。

2021年8月2日月曜日

マルチスレディングと氷嚢

 ガオガエンはまだLv1のマルスと戦っている。前回戦わせた時よりも成長速度が速い気がする。明日くらいまでには勝率5割程度になっているかもしれない。

昨日は本質的なところではいところに変更を加えた。学習を別スレッドで実行することによって学習のために割かなければいけない時間でもデータ集めに使えるようにした。これによってCPU使用率をほぼ常時最大にできる。一応の欠点は、学習のステップ数がデータ収集のステップ数と合わなくなってくることか。特に大きな問題ではないだろう。

昨日は実験的に配信もした。https://www.youtube.com/watch?v=b5iezNghvoE 配信をするとOBSがリソースを食うので学習効率が落ちるのだが、これに放熱の問題が絡んでいることが発覚した。M1 の Macbook Air には排熱ファンがなく筐体内部に熱がこもるようになっている。M1の消費電力は低いので通常の使用には問題ないが、強化学習のようにCPU使用率を常に高い状態にするようなものだとこれが問題になることもある。配信中の学習は氷嚢なしのときは 3.5 it/s 程度だったが、氷嚢の上にMacbookを乗せると9.5 it/sまで上昇した。約3倍である…。想像以上の効果だった。

できることの大半はやった。ここからしばらくは淡々と学習を続けることになるだろう。次に変更があるとしたらリカレントネットワークか。

Lv8のマルスは強すぎたのか…?

学習率を下げて挑んだものの、その後ガオガエンがLv8のマルスを倒すことはなかった…。 正確には1%程度の確率で勝利することはあるものの、その状態がずっと続き、成長が見られなかった。 

いくつか気になる点があったので変更してみた。 まずは報酬の遅延。画像認識のアルゴリズムの関係上、ダメージを認識するまでに遅延が生じる。ダメージが入っている間、数字が動くアニメーションがあってダメージ部分を読みとれないのだ。通常のダメージのときはおそらく15フレーム(強化学習エージェントのフレームなので20Hzで1フレーム50ms)程度、撃墜の際は30フレーム程度の遅延があるものと思われる。エージェントとしては、この間に入力したどのコマンドに報酬を関連づけてよいのかわかりにくくなっているはずだ。これに加えて、コントローラの入力遅延(測定すると6フレーム程度であった)もあるので、問題は更に深刻である。

これを修正するために、ダメージ部分がどの時点で変わり始めたかを記録しておき、各試合が終わった後に記録を書き変えて報酬のタイミングをダメージが入る入力をした瞬間に近づけるという措置をとった。具体的にはダメージ変更アニメーションの開始部分から6フレーム前に報酬を入れることにした。これでエージェントが報酬と関連づけるコマンドの数をぐっと減らせるはずだ。

もう1つ気になったことは、エージェントが自分の過去の入力を認識していないことである。入力遅延や硬直がある都合上、コマンド入力は即座に画面に反映されない。エージェントは画面の情報しかアクセスできないため、自分がどのようにコマンドを入力したのかわからずに次のコマンドを入れることになる。これでは適切なコマンドが入れられるとは思えないので、入力情報に過去のコマンドも含めることにした。この変更はかなりプログラム面ではかなり大規模なものとなり、パフォーマンスも低下してしまったので、後に最適化の必要があるかもしれない。

パフォーマンスの低下にともなって試合中に直接学習するとフレーム落ちするようになってしまった。これを修正するため、学習時間を試合時間とは別に設けることにした。こうすることによって、報酬の遅延の書き換えが行われていないメモリ区間を学習に使用することもなくなった。他の利点は、試合中のリソース消費が大幅に削減されたことによって配信ソフトなどもフレームを落とすことなく同時に起動できるようになったこと、より大規模なネットワークが使えるようになったこと。欠点は、学習時間中に試合ができないためにデータ取得の効率が落ちることである。この欠点に関しては適切なスレッディングをしてバックグラウンドで学習をさせることで解決できる可能性がある。

より大規模なネットワークを使えるようになったので、 data-efficient の Rainbow から canonical の Rainbow に戻すことができた。大体のパラメータは canonical のものを用いるようにして、history-length と multi-step だけを長めに(10)とるようにした。これによって入力遅延の問題もある程度緩和されるのではないかと思われる。

様々な変更があったのでまたしばらくは様子見をしてどのようにふるまうかを確認する必要がある。またLv1マルスからやりなおしである。一晩かそこらのテストでは結果は出なさそうなので気長に考えていきたい。

2021年7月26日月曜日

学習率は高すぎるといけない

前回エージェントがゆっくりだが成長しているかもしれないと書いた。 実際のところ、成長しているかどうかはもっと長期間トレーニングをしてみないとわからない気がする。 スマブラとは別によくわかっている系での強化学習で、data-efficient Rainbowの学習率を変えて実験してみた。 結果、与えられた0.0001という学習率では、10万ステップ以降の学習が困難になり、0.000025あたりだと学習することがわかった。 この数字をガオガエンに適用した結果、ほどなくしてLv1のマルスを倒すようになった(半分強程度の確率で)。 小さいが重要な変更である。深層学習の教科書にも学習率は最も大事なハイパーパラメータだと説明されている。 よりよい値があるかもしれないが、とりあえずしばらくこれでいこうと思う。 この結果に気をよくし、Lv8のマルスと戦わせることにした。もしLv8にも勝てるようになったらまた動画を上げよう。

2021年7月24日土曜日

不可解な自滅の理由は Catastrophic forgetting ではなかった

 昨日立てた仮説は、リプレイメモリの容量が足りないために途中でどのように自滅をしていたかを忘れて再度自滅をしてしまう、ということだった。(Catastrophic forgetting としてフォーラムで解説されている。) これを検証するためにリプレイメモリを30万回分から100万回分に増やしてLv1のマルスと再度戦わせた。その結果がこちらである。

リプレイメモリ30万回のとき

リプレイメモリ100万回のとき
となった。50000ステップごとに評価モード(Greedy Policyになる)で報酬を5回計算し、その平均をとっている。1ストックにつき2ポイントでダメージには部分点が入る。勝利者には+1ポイントされる。一見して言えることは、ノイズが大きくて結論が出しにくいという点である。おそらくリプレイメモリ30万回の最初の方で結果の上ぶれもあり、それがその後の成長を隠していた可能性もある。両方の図を見ると双方今後もっとゆっくりとしたペースで成長を続け、いずれはコンピュータマルスLv1を難なく倒す日が来る可能性も考えられる。
リプレイメモリが多くて困ることはないので、リプレイメモリ100万のまましばらくトレーニングを続けることにする。可能であればトレーニングを加速したい。今のところアイディアは2つある。1つはより深い(多層の)ネットワークを使うこと。深いネットワークはより強い可塑性を与えるのでパフォーマンスがよくなる可能性がある(強化学習においてはその効果があまり聞かれないので注意は必要だが)。もう1つはコントローラ出力をスティックとボタンに分離すること。今は9 x 6の54通りのどれかという形で出力しているが、分離するとスティック部で9つ、ボタンで6つとなり、出力しなければいけない数字の数が15まで減少する。この単純化はトレーニングの上で役に立たないだろうか。今のトレーニングを継続しつつコードを書き始めてみることにする。

ちなみに今のガオガエンの動きはこんな感じである。





2021年7月23日金曜日

スマブラは育成ゲームになった

残念ながらAmiiboの話ではない。

この手記は最強無敵のガオガエンをスマブラに産みだすための工程の備忘録のようなものである。まだちゃんと動いていないし成功するかどうかはわからないが、研究することに価値はあるだろう。

まずは手法を簡単に説明する。ガオガエンと他のファイターを戦わせ深層強化学習を行う。強化学習はパソコンで行われるので、スイッチから映像を読み出す装置(キャプチャーボード)とスイッチにコントローラ入力をする装置が必要になる。

映像の読み出しは一般的に広く行われている方法で可能である。今回は Elgato HD60 S+ を用いる。一般のビデオキャプチャーデバイスとして扱うことができるので(Webカメラなどと同じ方式)、MacやLinuxでも使用でき、後述のOpen CVからも読み出しがしやすい。

コントローラ入力はArduinoとシリアルポートを用いて行う。ArduinoにUSB接続のプロコンのふりをさせてスイッチに繋ぎ、Arduino本体のシリアルポートからの入力で操作できるようにする。パソコン側にはUSB接続のシリアルポートデバイスを接続し、Arduinoに結線する。このような仕様でスイッチを動かす手法は既に確立されており、GitHubにリポジトリが存在するので、それを用途に合うように少々改変して使用させていただくことにする。Arduinoは家に転がっていたUno R3を用いることにした。

これらの手法をとることによって、スイッチとの入出力を外部機器で行うことができる。すなわち、本体やソフトに改造を施すことなく、強化学習の環境が構築できる。もちろん入出力の遅延を考慮しなければいけなかったり、実行時間が実時間以上にならないことを考えるとよいことばかりではない。しかし、現行機のゲームに強化学習が使えるようになるのは画期的といえるだろう。

強化学習エージェントは DeepMind の開発した Rainbow を用いる。GitHub に PyTorch での実装があるのでそれを適当に改変して使わせていただく(data-efficientの設定を用いる)。 Environment の部分はほぼ全面的に書き直さなければならないが、なんとなくうまくいくように適当にやった。

少々手をこまねいたのがダメージや撃墜の認識の部分で、これは取得した映像から読み出さないといけない。数字の部分の色(具体的には小数点の色)を見て判断することにした。報酬関数も適当に書いた。このあたりの詳細はそのうちコードを公開するときにでも解説できたらと思う。

紆余曲折あって強化学習っぽいことをするようになった。映像取得はほぼ20Hzで行い、その全フレームに対してコマンド出力を行う。コマンドはスティック8方向+中心の9パターンに、ボタン操作6つ(A, B, ガード、ジャンプ、つかみ、押さない)を掛けた、54通りの出力とした。この組み合わせだと、強攻撃がとっさに入力できない等の不完全性はあるが、まずはパターンを減らすことを優先した。手法の詳細は先行研究(スマブラDX+DQN強化学習)に依存するところが大きい。

とりあえずLv9のマルスと一晩戦わせてみたが、あるところから成長をしなくなってしまった。相手が強すぎたかと思いLv3やLv1のマルスに変えてみたが、やはり成長を途中でやめてしまうようだった。Lv1で試したときは約30万ステップ(5時間程度)の時点で成長をやめ、自滅をするようになってしまった。これが、その時使用していたリプレイメモリのサイズと一致していたので、リプレイメモリの最初の部分(自滅が多い)が失われると、どんなときに自滅になるかを忘れてしまい、また自滅をするようになる、と仮説を立て、検証することにした。

今晩は同じ設定のLv1のマルスを相手に、リプレイメモリのサイズを100万にして戦うことにする。これによって30万を越えて成長するようになるのであれば仮説は正しいことになる。次の懸念は100万を越えたときにどうなるかだが、越えたときにまた成長を止めてしまうようであればリプレイメモリの更新の方法を考慮する必要がありそうだ。

とりあえず今日のメモはここまでにする。今回は動画もなにもなく説明ばかりになってしまったが、翌日以降は興味深い動作などがあったら記録していきたいと思う。