KaggleのNFLコンペに参加してみた

## コンペの概要
- 2019年10月10日〜2019年11月27日に渡って開催（https://www.kaggle.com/c/nfl-big-data-bowl-2020/
）
- アメリカンフットボールのランプレイにおいて、攻撃側が進むヤード数を予測する

## 利用できるデータ

- 1回のランプレイごとに、全体情報とプレイヤー別情報が与えられる
    - 全体情報：
        -  天候、気温、風速、風向き
        -  スタジアム、場所、芝の状態
        -  開始時刻
        -  ホーム/アウェイのスコア
        -  ダウン数（4回で攻撃終了 ※1）
        -  攻撃継続に必要なヤード数
        -  進んだヤード数 ← これを予測
        -  etc...
    -  プレイヤー別情報 ※2
        -  NFL ID 
        -  位置情報（X, Y）
        -  移動情報（S: 速度、A: 加速度）
        -  向き(Dir：体の向き、Orientation：顔の 向き) 
        -  生年月日 
        -  身長、体重 
        -  ホーム/アウェイ
        -  ジャージ番号
        -  ポジション 
        -  etc...

※1：4ダウン以内に10ヤード以上前進すれば、攻撃を継続。できなければ攻守が入れ替わる。
※2：1プレイにつき、攻撃/守備それぞれ11人、合計22行のデータが存在する。

## チームについて
- チーム名「Griffin Series」は[AI RUSH](https://ai-rush.com/)のものを引き継ぎ
- 今回のチームメンバは，光野（tenyaf <img width=30 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/96e4a688-d095-2bf1-1881-53bc4ae3f055.png">）と佐藤（foo_foo<img width=30 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/5dcf2163-faec-6886-6531-5058073adae4.png">）
- やり取りとタスク管理はSlackを利用（タスク管理にTrelloなどを使えばよかったと反省）
- コード管理はKaggle notebookを互いにForkし合う
- 2人ともアメフトの事前知識は皆無

## 結果

- Public47位（2,038チーム中）※1stステージ終了(11/28)時点
- 銀圏に入ることができました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/bfc316f2-baf0-4811-34cd-121c12fcd76e.png)

## チーム解法の紹介
### 解法の概要
- プレイヤーの位置や速度等を中心に特徴量エンジニアリング
- 0.5、1.0秒後の状態を推定（速度・加速度から算出）し、 特徴量を倍増させた
- モデルは単純なMLP
- 取り得ないヤード数を取り除く後処理の追加

<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/9c6b503a-2949-dd82-f7be-555683fcad1f.png">

### 前処理
- 攻撃する方向が「左に攻撃」と「右に攻撃」の2種類あるため、方向を統一
- チーム名の名寄せ
- 天候/風速/身長の加工 
    - 天候：あるキーワード(sunny)を含むかでカテゴライズ
    - 風速：”mph”などの単位を除いて値を抽出
    - 身長：フィート・インチ表記に統一

### 特徴量エンジニアリング
- 各プレイにおける統計量
    - X, Y, S, Aのmin, max, ave, std, var
    - SのX方向、Y方向それぞれ のmin, max, ave, std, var
<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/7129e394-695f-47e6-c5e4-98b0c6125eed.png">

- ラッシャー（※1）の情報
    - X, Y, S, Aのmin, max, ave, std, var
    - X方向のSの大きさ, Y方向のSの大きさ
    - 攻撃/守備チームメンバーとの距離(min, max, ave, sum, var) 
    - 守備チームfメンバーと最短で衝突する時 間(min, max, ave, std) 
    - 最も距離的に近い守備メンバーとの速度比 
    - 攻撃/守備チームメンバーの重心との距離
    - スクリメージラインからの距離
    - その他プレイヤーの情報

<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/eeec38a4-beb3-a9ca-5477-9747cee31be3.png">

- ワイドレシーバー（※2）の情報
    - スクラメージラインからのワイドレシーバーの距離（min, max, ave）
    - ワイドレシーバーの周辺5ヤード以内にいる敵/味方のX, Y, S, A（min, max, ave, std, var）

<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/f675b6ac-c262-344f-61bd-b093cff5f1e7.png">

※1：ボール保持者。基本的にはランニングバック(RB) 。
※2：ワイドレシーバーは複数人いる（1〜3人程度）

### 0.5秒後、1.0秒後のデータを用いた補強
- 「速度」「加速度」「体の向き」に基づいて、〇秒後 のX,Y,Sをそれぞれ推定・算出 ※1
-  0.5秒後、1.0秒後のX,Y,Sに置き換えた上で、各種特徴を抽出して結合 (特徴の数：146→379 ※2)

開始時点と1.0秒後のポジション
<img title="開始時点" width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/c41bb1cb-29ae-49f0-0c06-4d9f9ee0d327.png"> <img witdh=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/065c25f4-f028-f89f-90ea-bc13b001863a.png">

※1：等加速度運動と仮定して計算
※2：重複する特徴は除外してカウント

### Neural Networkのアーキテクチャ
- 公開kernelのモデルをForkして使用
    - Optimizer = Adam
    - Loss = categorical cross entropy
- ヤード数は取りうる値が離散的であるため，[-99, 99]の199クラス分類としてモデルを学習

<img width=300 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/151539f0-180b-a180-4d63-539e97b9a15f.png">

### 後処理
- スクラメージラインに基づいて、取り得る値以外の尤度を0とする
- 提出ルールに従って、-99～99ヤードの累積分布の形にする

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/edcb0043-8df2-f672-10a8-d7cf58e59562.png"><img width=250 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/ff08cd37-04e1-3c50-6736-2193b2374068.png">


### 実現しきれなかったアイデア
- プレイヤーの位置情報などをグラフに見立てて、Graph Convolution
- 22人のプレイヤーをある順にソートして、そのままX,Y,S,Aを列に追加
- その他重要なポジションのX,Y,S,Aの情報
- Neural Networkのチューニング

## 感想
- tenyaf
    - 初めてKaggleコンペに参加しましたが、題材がとても面白く楽しめた
    - 処理時間との闘いとなり、速いコードの書き方の必要性を実感した
    - アイデアは浮かぶものの実装まで至らないものが多かったため 実装力を高めていきたいと思った
-  foo_foo
    -  特徴量エンジニアリングは比較的よくできた
    -  テーブルコンペでのNN技術は要習得
    -  タスク管理は何かツール使えば良かった
    -  goldとれるように頑張ります