Morikatron Engineer Blog

モリカトロン開発者ブログ

CEDEC2020の補足 ー格闘ゲーム編その1ー

 お久しぶりです。モリカトロンでエンジニアをやっております、馬淵です。

 前回私がブログを書いたのがNEATに関して書いたとき*1(2020年2月24日)で、これを書き始めているのが2020年9月8日なので、私がブログを書くのは実に6ヶ月強ぶりになります。 何故これほど間隔が空いたのかですが、2020年9月4日のCEDECにおける弊社の講演を見ていただいた方には既に察しの通り、CEDEC発表に向けて色々行っていたからです。 今回の発表で出てきたWANN(Weight Agnostic Neural Network:重みを無視できるNN)ですが、実はNEATの手法を利用して実装されており、私がNEATに関して書いているときはWANNに関しての調査を行っている時期でした。 その後、WANNを手加減や調整に利用出来たらよいという理想を基に格闘ゲームAIのプロジェクトが立ち上がり、CEDECでの発表がトントン拍子で決定、発表に至るという状態です(完璧な伏線回収ですね)。そこで、今回はCEDEC2020の発表で説明しきれなかったことや、発表に至るまでの失敗例、創意工夫、苦労話などを書いていこうと思います。

 私は基本的に、格闘ゲームに関する発表の自己対戦で強くする部分、つまりpythonにかかわる部分がほとんどだったので、UE4との通信および手加減に関する部分は共同研究者の岡島さんが書いてくれることを祈っています。 尚、こちらで書く内容はCEDECでの設定とは打って変わり、具体的に使った入出力や利用したアルゴリズムなど、強化学習で使われている基本的なワードを本記事で説明しないため、初心者向けとはなっていません。 また、CEDECにおける格闘ゲームAIに関する説明を補填するという内容になっておりますので、まずは以下のスライドの方に目を通していただくことをお薦めします。

攻略、接待、変更に強いAIプレイヤー開発のためのアプローチ

*本記事で挿入されている動画ですが、研究時に資料として残しておいたものを利用しているため、音がなく動きがカクカクしています。ご容赦ください。

Gym環境開発編

 まず、ゲームの学習を行うための環境作りと設定に関してから書いていきます。 「強化学習のアルゴリズムやコードそのものを利用しやすくするために、ゲームをOpenAI Gymのように扱える環境を作る」というのはプロジェクトの最初から決まっていました。 今回は実験色が強い発表でもあり、使用するアルゴリズムの変更やハイパーパラメータの調整、ゲームへの入出力に関する設定を変更することが多かったため、最終的にはJSONで設定を変更できるようにしたのですが、結果的にこれは正解でした。 今回は、手加減のために階層型強化学習に倣って「上位方策」と「下位方策」と定義*2した2種類のAIの学習を行ったわけですが上位、下位で環境の設定が違います。 以下、主要な部分の設定です。 順に説明していきます。

下位方策 上位方策
フレームスキップ数 6 30
入力情報 ミニマップ 特徴量
出力数 72 2

フレームスキップ

 今回、発表に利用させていただいたゲームは60FPSで動作するゲームだったのですが、NNがゲーム側から入力情報を受け取ってゲーム側に出力という行為を何フレーム間隔で行うかを定めたものです。 下位方策は6フレーム、おおよそ0.1秒間隔でどのボタンを押すかの決定を行い、上位方策は30フレームでおおよそ0.5秒間隔で戦略を決定しています。 上位方策が利用するルールベースAIは下位方策の設定が使われているため下位方策の行動は5回分にまとめられていることになります。

入力情報

 NNへ入力する情報は当初、下位方策、上位方策ともに特徴量を利用する予定でした。具体的には各キャラクターのXY座標、お互いの距離、残り時間、体力、ダウンや気絶などの状態(bool)、必殺技ゲージ、どの攻撃を繰り出しているかといった数値を全結合層を入力に持つNNに直接入力していました。 また、学習ができることの確認としてルールベースで実装されたCPUを対戦相手に下位方策の学習を行っていました。 しかし、この特徴量を使った下位方策の学習が上手くいかなかったため、様々な試行錯誤をした結果、特徴量から格闘ゲームのステージ全体のミニマップのようなものを作り、それを畳み込みNNを利用することで学習させました。 ではどのようにミニマップを作成しているのかなのですが、まずステージ全体を41x41の2D画像のように表現し、敵および敵の飛び道具は負、プレイヤー及びプレイヤーの飛び道具は正として41x41の座標にプロットすることで作成しています。

 特徴量を利用していた際は、明らかに位置関係が学習できておらず、その場で同じ攻撃を繰り返すという結果になっていました(下の動画を参照)。 今回の研究では途中で利用する学習アルゴリズムをA3CからApe-Xへと変更しているため、アルゴリズムやその実装に不備があった可能性もありますが、この位置関係を覚えないという問題に対処するためにとった方法です。 これによって残り時間や体力、必殺技ゲージといったいくつかの情報が下位方策から抜け落ちてしまっているため、今回の「戦略を状況に応じて使い分ける上位方策」というのはこれを補っている面もあります。 また、この方法はその他のゲーム、特に3D格闘ゲームでは使えない可能性が高いので特徴量だけで学習させるというのも今後の課題の一つだったりします。

youtu.be

出力数

 上位方策に関しては、攻撃、防御の2択がNNの出力になっています。 下位方策の出力は移動の9方向と移動以外の行動8種*3の掛け算、つまり9x8=72種類を出力をするようにしています。また、先述の通り下位方策は6フレームごとに入力を決定していますが、そのうち5フレームはキーを押しっぱなしにし、最後の1フレームは移動のキーだけを押しっぱなしにすることで、長押しに対応させています。

自己対戦編

 自己対戦でAIを強くするのが今回の発表で一番難易度が高い部分でした。 発表時にも説明しましたが対戦相手を一般化するために様々な報酬設計で並列に学習させる必要があるため、実装の難易度やハイパーパラメータの調整が非常に難しい場所だったと思います。

学習コストの高さ

 自己対戦での学習にはRyzen3900とGeForce RTX 2070superが搭載されたPCを2台利用しています。 それぞれ攻撃型、防御型の学習のために利用しました。 実際は3台使用し、3つのスタイルを並列で学習させていたのですが、1つのスタイルは学習が上手くいかず、今回の発表では断念しました。 用意した環境ではUE4の描画を切ることが出来ず(その辺りの話は岡島さんが書いてくれると思います)、また敵味方の両方のNNを処理しなければならない、1つのスタイルを学習させるために分散学習させているといった要因が重なりGPUの処理能力が足りないという状況に陥りました。 そのため、マシンを2台利用しスタイルごとにマシンを分割、さらにWebsocketを利用した通信を使って対戦相手候補リストを共有するという方法で対策をしました。

ハイパーパラメータの調整

 私が参考にさせていただいた論文*4では対戦相手候補を更新するタイミングはNNが「一定のステップ分」学習した際に対戦相手候補を追加するという方法をとっていました。 この「一定のステップ」なのですが、下位方策にはミニマップ特徴量を利用している影響なのか学習が非常に遅く、調整しても不可解な動きになりやすく学習が安定しませんでした(下の動画を参照)。 最終的には、学習エージェントが100試合平均報酬を一定以上得られるようになったらそれを対戦相手候補リストに追加するという対策をとりました。 これによって学習はかなり安定するようになったのですが、100試合した際の平均報酬を出さなくてはいけなくなり結果的に学習には時間がかかるようになっています。 この対戦相手候補リストをどの程度学習が進んだら更新するべきなのかという問題も今後の課題の1つです。

youtu.be

手加減編

 手加減に関しては実装の多くを岡島さんに対応していただいたので、私から説明することは少ないのですが一点だけ、WANNに関する説明をしようと思います。 WANNは論文*5と共にコードが公開されている*6のですが、そのままだと学習に必要な計算量が大きく、CartPole問題でも結果が出るようになるまでにおよそ1日半程度かかっていて使いづらかったため、ある程度使えるものにするためにした工夫を紹介します。

WANN(Weight Agnostic Neural Network)

 先述したように、WANNはNEAT(NeuroEvolution of Augmented Topology)という手法の応用といった形で実装されます。 NEATに関しては弊社の以前の記事をご参考ください。

tech.morikatron.ai

 WANNは乱暴に解説してしまうとNEATから突然変異のみを利用して最適なNNの構造を探索する手法です。論文では1つのNNに対して複数の重みを適用した状態で適合率を計算し、その平均を最終的な適合率としていますが今回は最適-ランダムの間だけあれば良いので、適合率の計算は1種類のみに限定するようにしています。 また、論文では突然変異のみで探索をしていますが、このままだとNNの構造が急激に変化しやすく局所解に陥りやすいため、それぞれの個体に重みを持たせ、それを遺伝情報として交叉させることで構造が急激に複雑になることを防いでいます。 WANNは教師あり学習も可能であるため、一度強化学習で学習させたNNに教師信号を作成させ、それをWANNに教師あり学習で学習するようにしています(いわゆる蒸留)。

 これらの工夫によって上位方策の学習+教師信号の生成+WANNの学習をおおよそ4日程度に収めることが出来ました。 また、セッション中での質問に「softmaxを使った推定やQ値に乱数を加えてランダム性の高いモデルを作るよりも自然な手加減ができるのか?」といった質問がありましたが、これに関しては検証していないため、分からないです。 しかしWANNを使うことの利点として重み一つでコントロール可能であり、最適値から0に近づくにつれてランダム性が増していくという点があります。 今回、接待プレイという目標を達成出来るように設計するのは最終的に人間であることを想定しているため、機械学習で制作されたAIをコントロールしやすいという点で自然な手加減が出来るのではないかと考えています。

まとめ

 いかがだったでしょうか?久々のブログということで書き方を忘れ、CEDEC発表という大舞台のあとということで、とりとめのない気の抜けた記事になってしまったかもしれません。振り返ってみると課題は多く、まだまだこれからといった部分も多いです。 ですが、今回の発表で機械学習とゲームという組み合わせの可能性を少しでも示すことができ、これからゲームに機械学習を利用していこうと少しでも思って頂けたならこれほどうれしいことはありません。

おまけ

 自己対戦時にランダムにボタンを押す対戦相手に学習を続けると、攻撃型は非常にスマートな戦い方を覚えます(下の動画を参照)。 実際にはしゃがみガードをされると反撃を当てられてしまうのですが、CPU対戦の場合はほとんど一方的に敵を追い詰め、観ていて非常に爽快なので公開します。

youtu.be

*1:https://tech.morikatron.ai/entry/2020/02/26/100000

*2:不勉強ながら、私は階層型強化学習の定義を知らないため、この呼び方が実際の階層型強化学習における下位方策と上位方策に当てはまるのか分かりません。ここにおける上位方策、下位方策は便宜的な呼び方です。これもいつかちゃんと調査して記事に出来たら良いと思っています。

*3:強パンチ、強キック、弱パンチ、弱キック、投げ、スウェイ、リバーサル、何もしない

*4:Creating Pro-Level AI for a Real-Time Fighting Game Using Deep Reinforcement Learning,
I. Oh et al. 2020. https://arxiv.org/abs/1904.03821

*5:Weight Agnostic Neural Networks,
A. Gaier et al. 2019. https://papers.nips.cc/paper/8777-weight-agnostic-neural-networks.pdf

*6:https://github.com/google/brain-tokyo-workshop/tree/master/WANNRelease