社内AIプログラミングコンテストで優勝したゲームプレイAIの紹介

こんにちは、応用人工知能チームの辻本です。

最近は計算リソース、データ量、アルゴリズムの改善によって簡単に精度の高いAIが利用できるようになりつつあります。しかし、現状では全てのタスクにおいてAIを利用すればいいわけでもありませんし、リソースの制限もあるため、特性を理解して上手に応用することが重要です。そこで、社内ではAI応用のための知見や環境を積み上げていく機会を増やす取り組みを行っています。

先日、取り組みの一環でゲームプレイAIのプログラミングコンテストが開催され、約20チームが参加して盛り上がりました。このコンテストで優勝したゲームプレイAIについて紹介します。

AIによるゲームプレイ動画です。

コンテスト概要

AIにアクションゲームなどのデバッグの一部を任せられるかどうか検証したいという考えもあったので、ゲームプレイAIが対象として選ばれました。ゲームをAI用に変更せずに画面情報だけを使ってプレイさせたかったので、ゲームプレイのためのフレームワークにUniverseを利用しました。NeonRaceというFlashゲームのステージ6のスコアで順位を決定します。

Universeは様々なゲームやアプリケーションをAIにプレイさせるためのフレームワークです。ゲームはdockerコンテナで実行され、AIはゲーム毎に用意された報酬サーバとVNCを通じて、画面情報および報酬の取得とマウスやキーボードによる操作ができます。利用者は、取得した画面や報酬から次のアクションを決定するAIを作ることになります。 似たようなプロジェクトとしてSerpent AIもあります。

ゲームの起動

まずはゲームを起動してみます。

上記コードを実行するとNeonRaceのステージ6が開始され、VNCクライアントでlocalhost:5900に接続すると実際にゲームをプレイできます。5900番ポートで接続できなかった場合は、docker psなどで待ち受けポートを調べてください。

初めてのプレイでも70000点前後は出せると思うので、70000点を最初の目標にしました。

サンプルコードの実行

A3Cのサンプルコードが提供されているので、これをベースにして改良してくことにしました。16並列で実行すると12時間程度で収束するようです。

AIが選択可能な操作から無駄なものを除いて学習させた結果は10000点程度、壁との衝突回数を減らすためにコース外を走り続けるようになりました。

性能改善の取り組み

ここからは性能改善のために取り組んだ方法をいくつか紹介します。

罰則の追加

コース内を走らせるために、コース外に出た時に罰則を与えました。

コース外に出たことを検出するために、ゲームを手動でプレイして画面のキャプチャを用意して、CNNでコース内・コース外判定を行います。98%程度の精度でコース内・コース外の判定ができるようになり、AIがコース内を走り続けるようになりました。スコアも改善して20000点です。

キャプチャは以下のコードで用意できます。同じような画像だらけになってしまうので画面のキャプチャは5フレームに1回にして、コース内・コース外それぞれの画像を2000枚ずつ用意しました。

CNNは最後に掲載するコードと同じです。

状態空間の単純化

サンプルコードのモデルでは画面情報から特徴を抽出できていないように思えたので、画面情報から役に立ちそうな特徴を抽出して状態空間を単純化してみました。事前に特徴を抽出するので、サンプルコードをCNNから全結合ネットワークに変更しています。

OpenCVによる画像処理やCNNを利用して以下の特徴を抽出しました。

  • コース内の自機の位置
  • 妨害車両の位置
  • ポイントアップアイテムの位置

これらの特徴を利用することで、壁との衝突の回避、妨害車両の回避、ポイントアップアイテムの取得を学習することを期待しましたが特に改善は見られませんでした。ネットワークを改良すると性能が向上するとは思いますが、学習に時間がかかるので後回しにした結果、コンテスト期間中にネットワークの改良には着手できませんでした。

行動を一定時間固定

AIはフレームごとに操作を決定するので、曲がっている途中に1回だけ直進してからまた曲がり始めるなどの無駄な行動が多いことが分かりました。NeonRaceではフレームごとにキー入力を変化させる必要がなかったので、操作を一定時間固定することによってカーブが曲がれるようになり、スコアが40000点に改善しました。

ルールベースAI化

AIの学習を待っている間に、自機位置を判定して壁に近づくと反対側に曲がるだけの単純なルールベースAIを作ってみると50000点が出るようになりました。

ここからは強化学習を捨てて、AIの行動ルールのチューニングに注力しました。以下のルールを調整すると、最終的に初心者と同程度の80000点を出すAIが完成しました。

  • コースの曲がり具合によって、早めに曲がり始める
  • ポイントアップアイテムを取得できるようにブレーキをかける

所感

今回対象としたゲームを強化学習で学習させるためには報酬の設計、特徴エンジニアリング、行動を一定時間固定するなどの対応が必要でした。しかし、手間をかけた割には学習が進みません。画面情報からの学習のためにはゲーム毎のチューニングが必要で、1つのAIで様々なゲームに対応させることは難しそうです。また、AIの学習のためにAWSのc4.4xlargeインスタンスを利用したのですが、パラメータの変更やモデルの変更のたびに12時間ほど実行させる必要があり、人間と同等の性能のAIを作るまでには大量の計算リソースが必要だと思われます。現状では性能面でもコスト面でもAIにプレイさせるデバッグよりも人間によるデバッグのほうが良さそうでした。単純なゲームであれば、簡単なルールベースAIでもそれなりの性能がでることが実感できたので、まずはルールベースAIで要件が満たせるのか検討するのも良いと思います。

コンテスト課題の選択としては反省点がありました。今回のテーマである強化学習に馴染みのない人が多く、参加者の半分くらいはサンプルコードを動かすだけで終わってしまっているようでした。幅広い人にAIを利用する機会を与えるためには少しずつステップアップしていくような課題を選ぶべきかもしれませんが、AIを利用できるタスクの知見を貯めるためには同じような課題ばかりを選ぶわけにもいきません。これからも試行錯誤しながらちょうどいい課題設定を考えていきたいと思います。

おまけ

単純なルールベースAIのコードを掲載します。本文中に掲載したキャプチャ用コードで用意した画像を自機のコース中の位置で左・中央・右に分類してleft.txt center.txt right.txtにファイルパスを保存してから、python sample.py trainで学習させてください。学習後、python sample.pyを実行すればルールベースのAIがゲームプレイを開始します。

このAIはそれほど性能を要求しないので、手元のCore i7 2.8GHz、16GBのメモリを搭載したMacBook Proで動作させていました。