maktopia

make-u-topia

Splatoon2 ブキ編成から勝敗を75%当てるやつを追試した

面白い話なので,適当なプログラムを書いて追試しました. 使用したコードはGitHubに公開しています. github.com

実験の結果,正答率は55%程度となり,主張を再現することはできませんでした.

以下,自分の行った実験の説明です.

注意

筆者は機械学習の専門家ではありません. もし専門家の方で,間違いがわかる方がいらっしゃれば,GitHubにPRを送っていただくとか,コメントを頂くとかでアドバイスが頂ければ幸いです.

データ集め

元ツイートを見ます. データはstat.inkから取得しているらしいです.

ガチマッチ約2万試合をAIに学習

取得した戦績データの期間等がいつか記載されていません.

とりあえず,「直近で安定したゲームバージョンであるv2.1.xのガチマッチ全てを学習データに用いた」だと解釈するのが妥当だと思われるので,その条件でデータを収集します. stat.inkのバトルIDが,210500から308238のものを集めました.*1

前処理

まず,以下の条件の戦績データを使用します.

  • 野良ガチマッチ
  • 回線落ちしているプレイヤーがいない
  • SquidTracksやsplatnet2statinkにより,自動集計されている
  • ブキやステージのデータが正しく登録されている

その上で,以下の情報を抽出します. これらの作業を行うプログラムも公開しています.

ブキ編成

元ツイートを再び見ます.

このツイートについて,自分の解釈を説明します.

味方チーム,敵チームについて,それぞれを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

と記載されています.

とりあえず,パラメータ設定も何もわからないので,いろいろ試してみることにします.記載されている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%と,あんまりうまくいってなさそうな雰囲気を感じます.

ニューラルネットワーク

特徴量の次元も大したことはないので,そんな大げさなネットワークにする必要はなさそうです.

f:id:mak4026:20180203052119p:plain

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していますが,パラメータの探索範囲がよろしくない可能性はあります.
    • しかし,ロジスティック回帰のようなシンプルなモデルでも性能がそれなりに出ることが前提だと思われます.
    • また,ブキの追加やゲームのアップデートが短いスパンで行われることを考えると,仮に繊細なパラメータチューニングを求められるならば,やはり実用上嬉しくない気がします.

余談

そもそも,ブキ編成から勝敗を予測することの意義について考えてみると,確かに編成運による有利不利の影響がどれほどかを知ることができるでしょう.

しかし,プレイヤーとしては,少なくとも自分のウデマエを賭けているガチマッチにおいて,自分のチームが編成的に有利だろうが不利だろうが,目の前の試合を勝利することを目指すしかありません.プレイヤーにとって重要な情報とは,何が自分に勝ちをもたらすかを説明するものです.

仮にSVMDeep Learningで編成から勝敗が99%予測できたとしても,現在の技術ではそこから「どのような要因がSplatoon2において重要であるか」を知ることはまだ難しいです.どちらかというと,統計分析によるデータ解析の方が,プレイヤーにとって,より有益な情報をもたらす可能性が高いような気がします.

*1:後からアップロードされたデータが存在するかもしれないので,厳密にはもう少し後のIDまで集める必要があります

*2:例えば,ヒーローシューターレプリカ→スプラシューターとして扱う

*3:02/03時点のバージョンでは,正規化が雑です(WIP)

i have no words.