「対戦ゲームデータ分析甲子園」(ProbSpace)で24位(上位8.3%)に入りました

2020-10-21-公開

ProbSpace開催のデータ分析コンペ「対戦ゲームデータ分析甲子園」に参加し、24位に入りました。

prob.space

対戦ゲームと言っていますが、Nintendo Switch のSplatoon2の勝敗を対戦開始時点で予測する、という課題です。

ちょうどSplatoon2に今年からハマっていたこと、ずっとデータ分析コンペに参加しないとと思っていたこともあり、データ分析コンペに初めてちゃんと参加できました。

期間は開始日2020-08-19、終了日2020-10-18です。毎日はできませんでしたが、2020-08-25に予測を初提出し、終了直前(2020-10-17深夜)まで粘っていました。

結果

  • PublicからPrivateで59th -> 24th(上位8.3%)に上がった
  • 参加ユーザー数: 555
  • 予測提出者数: 288

主にやったこと

モデル

  • モデルにはXGBoostとLightGBMを使用
    • カテゴリ変数が大量にあるため、前処理で楽をできるGDBT系のモデルを使用
  • ハイパラチューニングをoptunaで行った
  • 10FoldのCVでテスト
  • ナワバリバトル・ガチエリア・ガチヤグラ・ガチホコバトル・ガチアサリによってモデルを変えてみる
  • ナワバリバトル・ガチマッチによってモデルを変えてみる
    • ナワバリバトルではふざけてプレイしているプレイヤーも案外いるため、分けて考えた方が良いと考えたので
  • 単純なアンサンブル(予測確率を平均した後、0, 1に直す)を実行
    • 試行錯誤で生まれてきたモデルの中で、Publicスコアが高めなものをとりあえず放り込んだ
    • 放り込まれたモデル7個: ルールで分割する・しない、ブキ詳細を追加する前後、XGB・LightGBMそれぞれ、ハイパラチューニングした・していない、など設定が入り混じっている

特徴量

  • 外部データを使用し、ブキからメイン、サブ、スペシャルの列も作成
  • ウデマエを順位に変換
  • period(時間帯)を連続値に変換
  • カテゴリ変数はlabel encoding
    • カテゴリが多いため、ダミー変数化すると疎な特徴量が大量に作成され、過学習の懸念があったため
  • periodを時間帯に変換
  • periodを曜日・祝日に変換
  • levelを20区切りでbin化
  • チーム間の人数差を作成
    • 人数差が発生している試合はほとんど無かった(0.2%程度)
      • ゲームをプレイしている実感としてはもっと頻繁に人数差が発生しているのだが…謎
  • 外部データを使用し、ブキからキルフレームや前隙、最大ダメージ等の列も作成
  • 各プレイヤーに紐づく特徴量だと、A1~A4の並びに敏感になってしまうと考え、チームの集計として情報を表現できないか考えた
    • 各プレイヤーに紐づく連続変数から。チーム内平均値、最大値、最小値を作成
      • チーム内平均値、最大値、最小値のチーム間差を作成
    • 各プレイヤーに紐づくカテゴリ変数から、チームごとの該当人数の列を作成
      • ウデマエやメイン、サブ等をダミー変数化してA1-A4, B1-B4それぞれ合計をとる
        • Aチーム、Bチームで分ける
        • ABの差を取る
  • A1~A4, B1~B4に紐づく各プレイヤー特徴量を削除
    • 特徴量が増えすぎて過学習の恐れがあったため

上位陣の解法を勉強

  • ターゲットエンコーディングが人気?
  • (2nd) 個人の特定が効いたらしい
  • (13rd) プレイヤーごとの勝敗予測をまず作った人も
  • (10th) 各ブキを前衛・中衛・後衛に振り分け、各チームの射程の組み合わせとステージの広さとをカテゴリ変数として結合する
  • (7th) A-1プレイヤー以外をレベル順でソートし、それらのブキ等をそのまま特徴量に使う + 同一時間帯でA1プレイヤーを特定したうえで、StratifiedKFoldを実行
    • GBDT系のobjectiveは二値分類でもbinaryよりregressionの方が若干精度が良いことが多いらしい
  • (6th) LightGBMのみ、10分割のCVで予測・平均した結果を0, 1に割り振るモデルで6位とは驚異的
    • チームの統計量を追加してみても過学習したとのこと。個人の特徴量を増やしていくのが重要だったか、という感想を書いている

感想

  • 目標だった上位10%に入れて嬉しい
  • PublicとPrivateでそれほどスコアが変わらなかった
    • PublicからPrivateで59th -> 24th に上がったので、ライバルと比べるとそこそこ汎化性能を保ったモデルが作れたのではないか
  • アンサンブルの強さを思い知った
    • 最後の最後に出したアンサンブルモデルのPrivateが一番良かった
    • 諦めずに粘ってよかった
  • 各プレイヤー情報をうまく使って上位に入っている方もいるようなので、各チームの集計のみを使用するという戦略が若干外してしまった?
  • 多数の人がこれだけ取り組んでもなお誰もaccuracy0.6に到達しない状況に鑑みると、そもそもこれだけの情報では予測できないようなタスクだったと…
    • 仕事だったら辛い経験になっただろうなと遠い目になる
    • そういう「どこまで性能を求めうるのか」を、他の方の様子などから感じられてとても良かった
  • 落ち着いて取り組めたので、試行錯誤の記録をドキュメントに残す、ドキュメントを書いてからコード書く、各処理を関数化して修正等を行いやすくする、パイプラインを整理する、といった良さそうな習慣が少し洗練されたと思う