2022年7月10日日曜日

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

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

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

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

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

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

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

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

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

0 件のコメント:

コメントを投稿