Splatoon2 ブキ編成から勝敗を75%当てるやつを追試した
AIによって75%の正解率で試合結果を編成の差から的中させることができました。ガチマッチ約2万試合をAIに学習させました。
— スプラ研究所(SpLab) (@splalab) January 28, 2018
ガチマッチの勝敗の要因には実力の占める割合が低く、運の占める割合が高いことが分かりました。 pic.twitter.com/kgynDg4vWG
面白い話なので,適当なプログラムを書いて追試しました. 使用したコードはGitHubに公開しています. github.com
実験の結果,正答率は55%程度となり,主張を再現することはできませんでした.
以下,自分の行った実験の説明です.
注意
筆者は機械学習の専門家ではありません. もし専門家の方で,間違いがわかる方がいらっしゃれば,GitHubにPRを送っていただくとか,コメントを頂くとかでアドバイスが頂ければ幸いです.
データ集め
元ツイートを見ます. データはstat.inkから取得しているらしいです.
ガチマッチ約2万試合をAIに学習
取得した戦績データの期間等がいつか記載されていません.
とりあえず,「直近で安定したゲームバージョンであるv2.1.xのガチマッチ全てを学習データに用いた」だと解釈するのが妥当だと思われるので,その条件でデータを収集します. stat.inkのバトルIDが,210500から308238のものを集めました.*1
前処理
まず,以下の条件の戦績データを使用します.
- 野良ガチマッチ
- 回線落ちしているプレイヤーがいない
- SquidTracksやsplatnet2statinkにより,自動集計されている
- ブキやステージのデータが正しく登録されている
その上で,以下の情報を抽出します. これらの作業を行うプログラムも公開しています.
ブキ編成
元ツイートを再び見ます.
Q編成をベクトルにする方法をkwsk
— スプラ研究所(SpLab) (@splalab) January 29, 2018
A
1.武器ごとに次元を作ります。
敵味方についても加味します。
例(味方スシ次元、味方マニュコラ次元、敵スシ次元、....)
2.1試合毎に武器毎の存在数によって数値を付与してベクトルにします。
例(味方スシ:1、味方マニュコラ:0、敵スシ:2,....)
このツイートについて,自分の解釈を説明します.
味方チーム,敵チームについて,それぞれをone-hotベクトル風味の表現に落とします.
例えば,ブキがスプラシューター,スプラローラー,スプラチャージャーの3種類のみ存在するとします. このとき,それぞれのone-hot表現を
ブキ | one-hot表現 |
---|---|
スプラシューター | [1,0,0] |
スプラローラー | [0,1,0] |
スプラチャージャー | [0,0,1] |
と表すことができます.ここで,あるチームが,
スプラシューターx1, スプラローラーx2, スプラチャージャーx1
の編成だったとき,この編成はブキごとのone-hot表現の和 [1, 2, 1] と表現できます.チーム編成とこのベクトル表現は,自明に1対1に対応します.
SVMを使ったらしいので,入力として用いる特徴量は正規化( 0 <= x <= 1)を行うことが望ましいと考えられます.自分のプログラムではこのベクトルを4で割っています. つまり,先の例では [0.25, 0.5, 0.25] になります.
v2.1.x終了時点でブキは,レプリカ武器を除いて66種類存在しますので,ブキ編成の特徴は66*2次元のベクトルとして表現できます.
前処理の時点でレプリカ武器は,元ブキとして処理します*2.
勝敗
味方チームが勝利した場合は1.0, 敗北した場合は0.0とします.
ステージ,ルール,ガチパワー
追加実験に使えるように,ステージやルール等も抽出して,one-hotベクトルにしておきます. ガチパワーも取得しておきます*3.
アンダーサンプリング
これらの処理を経て,大体24000件のデータが集まりました.
前処理が終わった後のCSVファイルを読み込んで,勝敗の数を確認してみます.
>>> import pandas as pd >>> x = pd.read_csv('csvs/v21x.csv',header=None) >>> x[154].value_counts() 1.0 12535 0.0 11474 Name: 154, dtype: int64 >>>
少し勝利数が多く,これは元ツイートの主張と合致します. 学習時に勝ち試合のデータをアンダーサンプリングして,ラベルの数を揃えています.
学習
前処理が終わったので,学習をしましょう. この課題は,勝ち(1.0)か負け(0.0)かを判別する2クラス分類問題です.
学習アルゴリズムやパラメータ設定は何を使っているのでしょうか. 元ツイートを見ますが,
SVMや多層NN等のAI
と記載されています.
Qアルゴリズムの詳細とか、使ったコードの公開予定は?
— スプラ研究所(SpLab) (@splalab) January 29, 2018
A研究を発展してくれる方はありがたい存在で、公開を予定しています。
しかし、あまりスプラをプレイしていない方々は建設的考察に向かないと思うので、ウデマエに制限を設けるかもしれません。
とりあえず,パラメータ設定も何もわからないので,いろいろ試してみることにします.記載されているSVM, ニューラルネットワークに加えて,ロジスティック回帰とXGBoostで実験を行います.
以下の実験では,前処理したデータを
学習データ : 検証用データ : テストデータ = 6:2:2
に分割しています. 性能評価は,学習データで学習を行った後,予測器にテストデータを入力し,その正解率(accuracy)を見ています.
詳しい実装はGitHubのリポジトリを参照してください.
SVM
ハイパーパラメータのチューニングが重要らしいので,scikit-learnのGridSearchCVをありがたく使わせて頂きます.
実装はこちらを参考にしました. qiita.com
# Tuning hyper-parameters for f1 Best parameters set found on development set: {'C': 1000, 'gamma': 0.0005, 'kernel': 'rbf'} ... The scores are computed on the full evaluation set. precision recall f1-score support 0.0 0.54 0.55 0.54 2293 1.0 0.54 0.52 0.53 2297 avg / total 0.54 0.54 0.54 4590 test accuracy: 0.5370370370370371 confusion_matrix: [[1267 1026] [1099 1198]]
53.7%と,あんまりうまくいってなさそうな雰囲気を感じます.
ニューラルネットワーク
特徴量の次元も大したことはないので,そんな大げさなネットワークにする必要はなさそうです.
EarlyStoppingをかけて学習していきます.
... Epoch 7/100 13768/13768 [==============================] - 3s 190us/step - loss: 0.6761 - acc: 0.5769 - val_loss: 0.6853 - val_acc: 0.5471 4590/4590 [==============================] - 0s 29us/step Test loss: 0.688756134307 Test accuracy: 0.543572984801
54.3%なので,あまり当てられてません.
Denseレイヤーのユニット数を増やしたり減らしたり,層を積んだり,Dropout層を抜いたりしましたが,特に性能は改善しませんでした.
ロジスティック回帰
かなり早めに学習が終わってしまったので,もしかするともっと単純なモデルでも良いのかもしれません. ロジスティック回帰は,隠れ層のない単純パーセプトロンとして実装できます.
... Epoch 8/100 13768/13768 [==============================] - 2s 141us/step - loss: 0.6823 - acc: 0.5650 - val_loss: 0.6878 - val_acc: 0.5373 4590/4590 [==============================] - 0s 22us/step Test loss: 0.686071637357 Test accuracy: 0.547058823503
54.7%...あまり変わりませんね.
XGBoost
XGBoostというすごいやつがあるという噂を聞いて,実装が難しくなさそうだったのでついでに実装しました. qiita.com
実装はこちらを参考にして,パラメータ探索のためにGridSearchCVしました. qiita.com
Best parameters set found on development set: {'learning_rate': 0.01, 'max_depth': 2, 'n_estimators': 100, 'su bsample': 1.0} ... The scores are computed on the full evaluation set. precision recall f1-score support 0.0 0.55 0.29 0.38 2349 1.0 0.50 0.75 0.60 2241 avg / total 0.53 0.52 0.49 4590 test accuracy: 0.516557734204793 confusion_matrix: [[ 685 1664] [ 555 1686]]
51.6%と,こちらもあまり予測できていません.
追加実験
ルールやステージといった特徴量を増やした実験も行いましたが,いずれの手法でも,正解率の改善は見られませんでした.
まとめ
追試を試みましたが,75%の正解率には辿り着けませんでした.そもそも,パラメータ設定などが公開されていないので,難しいものがありましたが・・・
本当は75%当てられると仮定して,正解率がよくなかった理由について,考えうるものを挙げていきます.
- 実験の手法が間違っている?
- 後学のために,間違いがわかる方はアドバイスを頂けるとありがたいです.
- 入力データが元ツイート主と異なる?
- 情報が元ツイート主から得られないため,致し方ない部分です.
- 入手可能なデータのうちで,可能な限り公正にデータを取得しましたが,このデータでうまくいかないとなると,データに対してロバストでない手法ということになって,実用上あまり嬉しくない気がします.
- 繊細なパラメータチューニングが要求される?
- SVMやニューラルネットワークはパラメータチューニングで性能が変わるとされます.
- 今回の実験で,SVMではGridSearchCVしていますが,パラメータの探索範囲がよろしくない可能性はあります.
- しかし,ロジスティック回帰のようなシンプルなモデルでも性能がそれなりに出ることが前提だと思われます.
- また,ブキの追加やゲームのアップデートが短いスパンで行われることを考えると,仮に繊細なパラメータチューニングを求められるならば,やはり実用上嬉しくない気がします.
余談
そもそも,ブキ編成から勝敗を予測することの意義について考えてみると,確かに編成運による有利不利の影響がどれほどかを知ることができるでしょう.
しかし,プレイヤーとしては,少なくとも自分のウデマエを賭けているガチマッチにおいて,自分のチームが編成的に有利だろうが不利だろうが,目の前の試合を勝利することを目指すしかありません.プレイヤーにとって重要な情報とは,何が自分に勝ちをもたらすかを説明するものです.
仮にSVMやDeep Learningで編成から勝敗が99%予測できたとしても,現在の技術ではそこから「どのような要因がSplatoon2において重要であるか」を知ることはまだ難しいです.どちらかというと,統計分析によるデータ解析の方が,プレイヤーにとって,より有益な情報をもたらす可能性が高いような気がします.