2022年7月24日日曜日

もう1つ修正を施したらちゃんと育つようになった

 前回回帰ネットワークの実装ミスの話をしたが、もう1つだけミスしていたかもしれないところがあった。今までの実装では zero_grad() メソッドをエピソードの終了時にだけ呼び出していたのだが、learn() メソッドが呼び出される度に呼び出されるように変更した。

どちらが正解かははっきりしなかったのだが、裏で回していたKangarooで、これを毎回呼び出した方が安定して成長することがわかったのでこのような変更を加えた。これでバッチサイズが小さくなっても学習が途中で止まってしまうことがなくなった。

AIガオガエンの方でもそうなっているようで、Lv3を何度か攻略してみたところバッチサイズが小さくても過去に見られたようなパフォーマンスの低下が見られなくなった。やっと実装が完了した、ということになるだろうか。まだ問題が潜在している可能性はあるものの、今のところ不審な挙動は見られない。

今は学習率周辺のベンチマークをとっている。もしうまくいくようであれば過去に一度試したGRU、未来予測型、色の見えるエージェントなども順次試していきたい。それぞれ攻略するのに数日単位でかかるので気長な作業にはなりそうだが…。

2022年7月10日日曜日

回帰型ネットワークの実装ミス

うまく成長しない原因もわからないし、Switch本体のバッテリーも壊れてしまっていたこともあり、しばらく配信を停止していた。数日前にまた再開して再度以前の成長していた時の環境を取り戻そうとするもうまくいかず停滞していた。

何か間違いが見つからないかとまたコードを眺めたり、デバッガで値を確認したりしていたところ、一つ予期しない挙動をしている部分を見つけた。

以前回帰型のネットワークのバグ取り(トレーニング中に同じネットワークを2回使ってしまい、状態を変えてしまっていたバグ)をした時、もう1つ同じネットワークを用意することで解決したかのように見えた。ここに盲点があった。

トレーニングがうまくいくためにはこの2つのネットワークは全く同じアウトプットを、時間差をつけて出さなければならない。1つのエピソードを学習する際、2つ目のネットワークに最初のnステップの状態をあらかじめ入力して、nステップ分だけ進めておく。このようにセットアップして、以後1つ目のネットワークが変更される度に2つ目のネットワークにウェイトをコピーすれば、同じアウトプットを出し続けるだろうという算段だった。

何が問題だったかというと、この1つ目のネットワークと2つ目のネットワークが受ける入力はnステップ分だけずれているので、ネットワークの内部状態の変化が必ずしも同期しないということだった。すなわち、毎回ウェイトがコピーされるとは言え、2つ目のネットワークはずれているnステップ分の状態をウェイトが更新される前のネットワークで処理することになるため1つ目のネットワークと全く同じことをするわけではない、ということになる。これによって内部状態にわずかなずれが生まれ、そのずれは蓄積されてエピソードの後半に向けて増えていく。

このバグの存在とバッチサイズを大きくすると挙動がよくなるという現象は無矛盾である。

解決方法は明快で、ウェイトをコピーするタイミングで内部状態も同時にコピーすることで対応できる。(内部状態を更新せずにネットワークを使用する、という解決方法もあり、こちらの方がリソースの節約にもなるが、コードの更新箇所が多くなるので見送った。) これが最後の実装ミスだといいのだが…。

今後は、まず今まで走らせていたLv5クリア前のモデルがパフォーマンスを改善するか確認し、それが確認されたらバッチサイズを小さな値に戻してまたLv3スタートで最初から学習をさせることにする。大幅な学習期間の短縮が見られる可能性もあるが、あまり期待しないようにする。

2022年4月27日水曜日

OSアップグレードの不具合で成長しなくなった話と別のOSアップデートで直った話

自分にコントロールできないものに大きく左右されることもある。

1月21日、AI用のMacをMonterey(12.1)にアップグレードした。ガオガエンでマルスを相手にしていたところ待ち合いが長くなって成長が鈍化したため、相手をウルフに変えた後およそ2週間後のことだった。

この時はウルフはやや停滞気味だったのだが、このアップデートの直後に少しパフォーマンスを落とした記憶はある。どういう理由でパフォーマンスが落ちたのか不思議には思ったものの、トレーニングを継続させたところ再びパフォーマンスがゆるやかに上昇していったので深刻な問題とはとらえずにそのまま放っておいた。

そのウルフはガオガエンを倒せるようになることはなかった。

ここで疑問に思い、もしかしたら今のネットワークの設定に限界があるのではないかと思い、今考え得る手法でベンチマークをとってどの設定がいいか確認しようと思って、ウルフチャレンジなる企画を始めたのだが、どんな設定にしてもうまくいかない状況が3ヶ月程続いた。

この間、ネットワーク構成はおろか、ステージ、ファイターに至るまで様々な要素を変更して試したがどれもうまくいかず、結局元の設定に戻ってきてもやはりうまくいかない始末。これは何かあると思って他の原因を探ろうとしたときに、以前視聴者の方から「動画が音ずれしている」と報告をいただいたのを思いだした。

音声の方が先に来るタイプの音ずれだったのだが、音に対して映像が遅れてPCに届いているということはAIが現状をリアルタイムで捉えられていないということである。今思えば音ずれの報告があった時点で気がつくべきだったのだが、すっかり失念していた。数秒の遅延でもゲームをする上では致命的である。ましてAIでやろうとするとそこから成長できなくなるのは当然なようにも思える。

音ずれは始めてから数日で現れるようだった。実際に映像の取得が遅れることを確認するため、音ずれの訪れを待った。……。

4月22日、映像取得の遅延を確認する前だったが、配信が中断されたのを機会にOSを 12.3.1 にアップデートした。不思議なことにここから再び音ずれの症状がなくなり、AIも成長を止めなくなった。同日開始した配信で 4月26日現在まだ成長を続けている。いつものAIガオガエン対Lv3マルスだが、あと2日程度でクリアしそうな勢いだ。

いくつか気になる点もまだある。

音ずれの症状が起こる前はOBSによる配信が一定期間(およそ1週間程度)で中断されることが多かった。多くの場合CPUパニックによるものでコンピュータ自体が再起動してしまっていた。macOS 12.1になってからはその不具合はほぼ解消され、ほぼ一ヶ月程度不具合なしで連続配信できたこともあった。それがまた 12.3.1 になってから以前と同様に不安定になった可能性がある。まだデータがたくさんとれているわけではないが、22日から今までの間に既に一度CPUパニックで再起動している。全ての不具合が同時になくなることはないのだろうか。

少なくともまた何らかの実験ができる環境が手に入ったのはいいことだ。今までうまくいかなかったベンチマークの作業をまた継続したい。またルキナに戻してみるのもいいかもしれない。

2022年2月7日月曜日

ウルフチャレンジシリーズ【深層強化学習】

順調に育つエージェントができたのかと思いきや、セルフプレイの段階でやはり成長が止まってしまっているように感じたので、また一段階戻って手法のベンチマークをしてみることにする。

環境を少し変えて行う。理由は以下の通りである。
・CPUにはウルフを使う。基本的には近距離が強いファイターだが、飛び道具による待ち合い回避や牽制ができるので。
・1Pファイターにはルキナを使う。ゲームをややこしくしたり、記憶を要求するギミック等がなく、撃墜方法が豊富で多くの面で高性能なので。

最初に試すのは今までに使ってきた手法である。すなわち、
・畳み込み層の後にLSTM3枚
・並列で未来予測層LSTM2枚
・Batch size は 4から2048の間でランダムに決まる


今回試したいことがらは、
・結局LSTMは何枚必要なのか
・batch size はここまで大きくないといけないのか
・未来予測層は有用なのか
という点である。

調べるのにかなり時間はかかると思われるが、知見を貯めていきたいところである。

2022年1月17日月曜日

これからホムヒカを始めようと思っている方へ

 2021年末からほぼ毎日ホムヒカを触っていたのですが、今日魔境街道に到達したので、ここまでで理解したことを書いておきます。

この記事の対象は既にスマブラを他のファイターでやっているけれど、ホムヒカを新たに始めたいなと思っている人になります。

ひょっとすると全キャラVIPを目指す一環でホムヒカを使いたい人やホムヒカ対策をしたい人にも役に立つかもしれません。

ある程度用語の理解が必要になるのでご了承ください。


既に使い手の方にはほぼ当たり前の内容になると思います。


コンボについて

できるに越したことはないですが、簡単なものから始めてもいいかと思います。

最初のうちは、下強、上強、上Bあたりをいつでも頭に置いておいて損はないと思います。

上Bで〆めますが、展開継続にならないし後隙もあるので通らない場合は無理してしない方がいいです。

上Bの着地隙はパニッシュメントレイが15F、レインボーダストが20Fなので、一段目を外した場合はパニッシュメントレイにした方が若干コンパクトになります。

もちろん崖を掴める場合は着地隙は関係ありません。

コンボについては調べれば色々出てくると思うのでここでは割愛します。



立ち回り


差し込みに有用な技

めくり空N、とりわけダッシュで近づいて小ジャンプ登り空Nをめくって出すのが比較的安全で展開も良いです。

当たったら浮いた方向を見て着地を狩りに行きましょう。

着地の位置を近くにしないとめくり空Nからコンボはありませんが、より安全になります。

クラウド、クッパ、ゲッチ等の速いガーキャンを持っている相手にはめくり空Nは控えましょう。


ジャンプで近づいてくる相手に二段ジャンプを合わせて空Nをかすめて当てるのも比較的安全でリターンが高い方法になります。


ヒカリのDAは使い易いですが、横強、下強より後隙が長いので、滑り横強(ダッシュ中に左スティック反転、右スティックを進行方向に)か滑り下強(ダッシュ中に左スティック反転、右スティックを下に。タイミングがずれると反転してしまうので要練習)をおすすめします。それぞれコンボ始動の技になります。

ステップ中は滑り強攻撃はできない(ですよね…?)のでDAでステップの範囲内の相手にはDAで妥協します。

DAはなるべく先端か密着(めくり)で当てます。半端にくっついて当てると痛い反撃をもらいます。


一度展開を取ったら相手の受け身や着地に合わせてひたすら技を合わせます。当たらなかったりガードされても次々と技を繰り出して展開を維持しましょう。連打に使う技は下強、弱あたりがおすすめです。

相手の着地はDAではなく滑り上強で取るとよりコンパクトになりますし、その後のコンボも繋がります。台上にも当たります。ダッシュの状態から台上に直接上強できるようになっておくと(ダッシュ中に左スティックを反転して右スティックを上)いいでしょう。


ホムラの立ち回りは難しいですが、リーチを押し付けたい時と、ブレイズエンドが刺さる時は使います。

先端当てを徹底して被弾を抑えるようにしましょう。

空下はリターンが高いですが、ガードされると反確が多いので、基本的に差し込みで使う技ではないと思います。使うとしても引き慣性か先端で。

みんな空下を本気でガードしてくるので、すかし掴みは通ることが多いです。例外は差し込みに上Bを安全に入れ込めるタイプのキャラ(ゲッチなど)になります。


ブレイズエンドはジャンプが低い相手(スティーブ、格ゲーキャラなど)と飛び道具キャラによく刺さります。

ほぼ全ての飛び道具を打ち消しながら飛んでいくので飛び道具相手にヒカリでも立ち回りが難しいと思ったらブレイズエンドを投げるのもありだと思います。

反射持ちの相手にはかなり反射を狙われるので注意しましょう。大ダメージを受けます。剣が横回転の時は反射されますが、縦回転になると反射できなくなるので、反射を狙っている相手には届くぎりぎりの距離で打つと反射されずに当てることができます。横Bスマッシュ入力で飛距離も変わりますので、うまく当てましょう。


いつチェンジするべきか

基本的にはヒカリで立ち回り、有利展開(崖、着地狩り)でホムラにチェンジがいいと思います。

撃墜できない%の場合はヒカリで崖狩りするのは大いにありです。



掴んだらどうするべきか

0%の時は下投げ、空後、空後、上Bのコンボを狙います。

1F暴れや回避があるファイターは抜けられることも多いと思いますので、無理せずにただ上Bでもいいかもしれません。

空前や空上で展開を取るのもありかと思います。


中%の時は下投げ後、基本的には二段ジャンプ空前を狙いながらベク変を確認して内側ならジャンプの二段目を合わせて空上をしています。

確認が速い人にはもっといい方法があるかもしれません。


70%前後で相手のラインに余裕がある場合は前投げからダウン展開が狙えます。弱で止めて横スマでも下スマでも好きな方をどうぞ。残念ながらベク変ミスでもないと撃墜はできません。相手がうまくなってくると受け身を取られるかジャンプで逃げられますので、読み合いをする形になります。


高%ではOP回復の掴み打撃継続か前投げが基本になります。横移動が乏しく着地の弱い相手なら上投げもありかもしれません。


ホムラは低%で下投げから空前 or 空上のコンボがあります。空前の方が若干威力が高いですが、台がある場合は空上が2回当たるのでそちらを優先します。



撃墜手段の変化

だいたい中くらいの重さのファイターを基準に書きますので相手によって適当に加減してください。


ホムラの空下絡みだけでかなりの数の撃墜方法があり、状況に応じて適切な選択肢をとらないといけないので実は結構厄介です。

ホムラの空下は持続4Fで、1F目が弱メテオ、2F目が強メテオ(剣はほぼ真下)、3,4F目は斜め上に飛ばします。

メテオからのコンボで広い%帯での撃墜が可能です。


約45%

ホムラ空下最低空→横スマ

空下が先端で当たった場合か、ホムラに相手から離れる慣性が付いている場合は横スマが確定します。

確定の条件が厳しい上、崖から離れていると撃墜しないのであまり狙いませんが、どうしても早期撃墜したい場合に使う可能性があります。


約65%

ホムラ空下最低空→微ホールド上スマ

早期撃墜のメインの択になります。

どのくらいホールドできるのかはトレモで確認して感覚を身につけておくといいと思います。

若干%が上がると微ホールドなしで撃墜できる帯域がありますので、その帯域では振り向きや、位置調整も可能になります。


約85%

ホムラ空下→プロミネンスリボルト

このあたりから上スマが確定しなくなってきますのでプロミネンスリボルトに繋げます。

台がある場合は台上でプロミネンスリボルトが当たるので撃墜力が上がります。

相手がちゃんと外ベク変した場合は撃墜しません。


約100%

ホムラ空下→大ジャンプ空後

位置調整が必要になります。振り向いて空後しても、前に慣性をつけて飛んで空後しても当てることができます。

空前でも撃墜可能な位置なら空前でもOKです。


そろそろホムラの着地狩りDAで撃墜が可能になるあたりです。DAでの撃墜は意外と使えますが、先端を当てないと飛ばないし反撃も多いので先端を当てられる距離感を掴んでおきましょう。

このあたりからヒカリの横スマが崖端で撃墜可能になります。崖つかまりっぱなしに対して下強横スマが確定したりします。


約120%

ホムラ空下→二段ジャンプ空上

ここまで来るとかなり当てにくくなってきますが、最低空でメテオすればまだ確定する攻撃があるはずです。

このあたりから空中で空後を当てると撃墜になります。


約140%あたりから

空下をメテオで当てても何も繋がらなくなります。空下より空後を振りましょう。空下、空後は小ジャンプ登りで出した場合急降下しなければ着地隙が発生しない(オートキャンセル)ので、着地隙の消せる撃ち方をあらかじめトレモで確認して練習しておくといいと思います。

ヒカリの上スマ(発生9Fのガーキャン可能な撃墜方法)がこのあたりから撃墜できるのでチェンジも考えます。

崖外に出した場合はホムラの弱でも撃墜が可能です(後述)。

各種空中攻撃、とりわけ空中で空Nを当てても撃墜できます。

ホムラ上強での撃墜も可能になりますので、空上などでの着地狩りを匂わせて回避を誘い、上強で撃墜するという流れも可能です。上強はよく飛びますが、ガードされると反確が多いので注意しましょう。横強はなぜかガード硬直が長いので先端なら反撃はあまりありません。


約160%あたりから

ブレイズエンドでの撃墜が可能になります。数ある撃墜方法の中でもかなり安全な方なのでここまで来てしまった場合は被弾しないように立ち回りながらブレイズエンドを当てられる隙を伺いましょう。


約200%あたりから

最も速い投げバとしてホムラの下投げで撃墜可能という噂です。


ホムラの空下2F目(強メテオ)を台の下の相手に当てる場合

かなり広い範囲(60%〜110%くらい?)で上スマが確定し、位置も高いのでほぼ撃墜になります。

積極的に狙ってもいいですが、台下の相手に隙を晒すことになるので上スマなどで撃墜されないように注意しましょう。


70%くらい?で後ろ投げが台上ダウン展開になったりします。

ホムラの上スマで全狩りできるようなので狙ってみてもいいかもしれません。(あまり使ったことはありません)



ホムラの空下による低%での撃墜が有名なファイターなので狙いたくなりますが、有名すぎて空下を厳重に警戒されるためそうそう当たりません。狙いすぎて被弾するよりはさらにヒカリで地道に%を稼いで他の方法で撃墜した方が被ダメが安く済むことも多いので、相手の動きを良く見て判断しましょう。


復帰阻止について

基本はホムラの空前

相手が高い位置にいる時に復帰阻止に行くと、失敗しても展開が悪くなりません(そのまま崖展開に移行)

深く行く場合はホムラでしっかり高度を合わせてついていって当てます。

ホムラの空中機動は悪くないですが、技を振ってから行動できるまでにかなり時間がかかるので、どこまで行けるのかを事前に確認しておきましょう。特に空下は当たると強いですがジャンプせずに崖を降りて撃つ場合、ほぼ最速にして一切急降下しないようにしないと戻れなくなります。


崖の真下に対してフレイムノヴァをする手もあります。


ヒカリでする場合は空前、ライトニングバスター、上Bなどでも復帰阻止できますが、ジャンプを潰せるかよほど高%でもない限り撃墜につながることは少ないです。


崖下の内側にいる相手にヒカリで上Bすることで崖メテオを狙うこともできます。剣が当たった場合は回避暴発も狙えるレインボーダストの方が倒せる可能性が高そうです。



崖狩りについて

ヒカリの方が狩れる確率は高いですが、リターンはホムラの方が高いです。

ヒカリでやる場合は、崖端への空N置きでジャンプ上がりをケアしながら相手の行動を見ます。

回避上がりにも空Nのランディングフォースが当たることがあるので、位置どりは適当にばらすといいと思います。

空Nが当たったらあわよくばもう一発何か当ててもう一度崖外に出します。

単調にならないように、空N連打だけでなくその場上がりを掴める位置でガードしたりしてもいいかもしれません。

相手の崖上がりの択に合わせて行動を変えましょう。



ホムラの場合は120%くらいから横強での撃墜が狙えるので、横強先端が当たる位置で待機してその場上がりに合わせるというのが1つ。しかし横強先端で当てようとすると攻撃フレームの最後を当てないといけないので、その場上がりに対しては無敵が切れる1Fにぴったり合わせる必要があり、難易度は高いです。

より丸い択はガードしながら掴める位置で待って、上がるのを見て掴む。です。こうやって135%くらまで溜めると次の崖で弱での撃墜が可能になります。


135%くらいのホムラでの弱撃墜は、ジャンプ上がりとその場上がり(あと状況によっては崖離しジャンプも)をケアする択になります。比較的安全で本命択であるこの2つを同時にケアできるのは強いですが、もちろん読まれると回避上がりされてラインも失うので注意しましょう。

位置は掴みが届くギリギリよりも少し前で、相手が上がってきそうだなと思ったらAを押しっぱなしにするだけです。

ホムラの弱1段目は10Fでループし、持続が3Fあるのでその場上がりでガードを入力されても30%の確率で当たります。ガードをされたらこちらにも弱を1段か2段でやめる選択肢があるので、最悪読み合いです。ジャンプ上がりはほぼ狩れると思っていいと思います(当たる位置によってすっぽ抜けることはあります)。


撃墜に貪欲になりたい場合は60-80%あたりからホムラで崖狩りをして、一点読みの空下を当てるのも手です。わざと近づいて回避上がりや攻撃上がりを誘ったりすると成功率が上がります。



復帰について

ホムヒカの一番の弱点になります。特に今まで復帰力のあるファイターを使っていた人は要注意です。

崖外で二段ジャンプを使った場合、ちょっと小突かれると撃墜されます。

上から帰ろうとしてすぐにジャンプを切るのは基本悪手になります。代わりに移動回避で崖を掴んだり早めの上Bで掴んだりしましょう。

ヒカリは上Bの光弾が出てしまうとほぼ頭が崖上に丸出しになってしまうので、高さを調整して光弾が出る前に掴むか、高さが足りない場合は逆に低めにしてなるべく頭が出ないようにします。

崖に近い高さで上Bを出すと振り上げの判定が崖上に出るので相手を追い払いたい時に便利です。ただし、カウンター持ちには注意しましょう(特にソラ、ジョーカー、ガオガエン)。

それでも2Fを狩られることはあるので、可能ならジャンプを温存してダイレクトに上Bすることをおすすめします。ジャンプさえあれば帰れます。


ホムラの上Bは攻撃判定が崖上に出ないかわりに、ヒカリより頭が出にくいので崖に掴まりやすいです。崖上で狙われている場合はホムラで帰るのが若干安全かもしれません。


チェンジは何度でも使えますので、2回目以降の回避として使います。ホムヒカにはあらゆる復帰阻止がバンバン飛んでくるので、どのタイミングで無敵が発生するのか確認しておいて合わせられるようにします(下Bの後、6-18Fが無敵なのですがこれを合わせられるように感覚で覚えます)。


低く飛ばされた時は内側斜め上回避してジャンプを残し、二段ジャンプと一緒に一回チェンジして上Bをするのが最も距離が稼げると思っています。

大きく飛ばされた時はジャンプを残した方がいいのか回避を残した方がいいのか相手に応じて考えて決めます。


ホムラの上Bは横入力をすると少し動けます。高度ちゃんと合わせると意外と遠くで撃ってもふわっと掴めたりするので、これもどのくらいの距離で掴めるのか確認しておきましょう。


ブレイズエンドを崖端に投げてジャンプと回避で崖を掴むのも比較的安全な帰り方の1つです。




崖上がりの択について

崖離しジャンプはハイリスクだということは常に頭に置いておきましょう。

ヒカリはジャンプ上がりとその場上がりの読み合いをするのが一番安全かと思われます。

相手が掴みを狙っている場合はジャンプが本命になります。ジャンプができてしまえば機動力で逃げられる事が多いです。


ホムラの崖上がりは若干大変ですが、崖から少し離れている相手には崖離しジャンプからブレイズエンドを投げながら上がる択も使えます。(ただし飛び道具には注意!)


攻撃上がりのリーチはかなり長いので結構使える時もあります。



因果律予測について

各回避行動の2Fあたりから3-4Fの間(回避の種類によります)に攻撃判定を受けると相手がスローモーションになります。スマッシュなどが確定します。相手の飛び道具にも使え、その場合は相手本体もちゃんとスローになります。飛び道具に前回避を合わせて相手に近づいてスマッシュすることもできますので、対飛び道具の1つになります。

因果律予測の受付時間中は、掴みを回避することができませんので、ヒカリは他のキャラより殴りの回避は速く、掴みの回避が遅いということになります。強い掴みを持っている相手(クッパ、ガオガエン等)には要注意です。掴みを狙われている時はその場回避(7F)より弱暴れ(2F)の方がいいでしょう。

因果律予測中は崖を掴みません。崖に掴まろうとして回避した時に殴られて因果律が発動しそのまま落ちることもあります。

因果律予測は強いですがヒカリの回避の後隙は他のファイターより長いので、相手に隙を晒す形での回避はかなり危険だということも覚えておきましょう。

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枚のモデルでやったり学習率を上げたりしたが、結局どのモデルもある段階まで学習すると、そこからパフォーマンスを下げて戻らなくなることのが観測された。回帰ネットワークを導入する前は確かそのようなことはなかったと思うのだが、これはいったいどういうことなのだろうか…。
次の記事では、なぜそうなったかの仮説と、解決策についての議論をする。