こんにちは
今回は「NFL 1st and Future - Impact Detection」というコンペに挑戦しました。
NFL 1st and Future - Impact Detection
結果はpublic94位(銅)→private104位(メダルなし)/459でメダル獲得ならずでした。 ワンチャン銀とか取れちゃうんじゃないかと期待して参加してみましたが全くそんな事はありませんでした。調子に乗ってました全力で謝罪します。
Object detectionという分野に関して小麦コンペで触ったときには何もわからなかったので、今回は基本的な部分を学びながらコンペに取り組みました。本記事では簡単な概要、自分の取組内容を書いて、最後に学んだことを自分なりにまとめます。
※なお、Object detectionは今自分が挑戦するべき分野でないと悟ったためかなり浅くなっています。
コンペ概要
アメリカンフットボールの試合のビデオからヘルメットの衝突を特定するタスク
- 動画はプレイ毎にサイドラインから撮影されたものとエンドゾーンから撮影されたものがセットで用意されている
- ヘルメットのBBoxや衝突についてのラベルデータがcsvで与えられている
- trackingデータという各選手が装着しているセンサーに寄るデータが与えられている
- 各選手がフィールド上でどのように移動するかわかる
- 上手く検知できるモデルができれば、選手の安全性工場という研究に貢献できる
- ルールの変更やヘルメットのデザインの改善につながる
様々な情報が与えられていたため、BBoxデータを使ってプレイ動画にBBoxを付与して、衝突時のBoxに色を付けたり1、座標データを使って真上からのtracking animationを作る2notebookが公開されていてそういったものを見るだけでも楽しかったです。
センターデータあるならわざわざビデオから検出するよりもセンサーのほうが精度が高いのでは?という疑問は私も感じていましたが、Discussionで議論がされていました。3
また、日本語の記事でも「使用禁止ヘルメット」10製品 本気度増すNFL脳震盪対策のようなものも有りました。
評価値
F1だが、動画のため前後4フレーム分のずれを考慮してくれるようなことが書いてありました。
アプローチ
偉大な公開ノート4では、ヘルメット・衝突しているヘルメットの2クラス分類を行っていました。ここから派生して偽陽性をフィルタリングするノートも公開されていました。
※片方のフィルターはprivateでかなりスコアを落としていた模様
前述したtracking dataが与えられていることもあり、時間軸を駆使した後処理など(モデルも?)をすることがこのコンペのポイントなのかなーとは思いましたが私は実装できませんでした。今後のsolutionに期待です。
自身のコンペの取り組み
はじめに
今回は公開ノート5をベースに取り組みました。これがなければ何も出来ませんでした本当に感謝しています。
これは注意点ですが、いろいろ試しても公開ノートのスコアの再現が取れず(低いpublicLBが出る)最終的に出来たベストサブに使った手法を書きます。それぞれが効果あったかどうかが自分でもわかっていません。
GroupKFold
フィールドの芝やロゴ、ユニフォームの色が試合ごとに違う(試合が同じだと動画が別でも同じ)ため、gameKey毎のGroupKFoldを行いました。
from sklearn.model_selection import GroupKFold X = video_labels.drop('impact', axis=1) y = video_labels['impact'] groups = video_labels['gameKey'] kf = GroupKFold(n_splits=5) for f, (train_idx, val_idx) in enumerate(kf.split(X, y, groups)): video_labels.loc[val_idx, 'fold'] = f video_labels['fold'] = video_labels['fold'].astype(int) USE_FOLD = 0
ここから5fold分のモデルを作成しました。
nms
object detectionのアンサンブルの仕方を調べて一つピックアップして組み込んでみました。 物体検出で重なったバウンディングボックスを除去・集約するアルゴリズムのまとめ (NMS, Soft-NMS, NMW, WBF)ここのコードをお借りしました。
nmsに投げる処理
# imagenameでループ result_image_ids = [] results_boxes = [] for keys in df_pred.groupby(['image_name']).size().to_dict().keys(): tmp_df = df_pred.query('image_name == @keys') if len(tmp_df) > 2: # 調整の余地有り # ==nms======================================================= bboxes = tmp_df[['left','top','width','height']].values bboxes[:,2], bboxes[:,3] = bboxes[:,2] + bboxes[:,0], bboxes[:,3] + bboxes[:,1] new_bboxes = np.array(nms(bboxes.tolist(), tmp_df.scores.values.tolist(), 0.1)) new_bboxes[:,2], new_bboxes[:,3] = new_bboxes[:,2] - new_bboxes[:,0], new_bboxes[:,3] - new_bboxes[:,1] new_bboxes = new_bboxes.tolist() results_boxes += new_bboxes result_image_ids += [keys.astype(str)]*len(new_bboxes) box_df = pd.DataFrame(results_boxes, columns=['left', 'top', 'width', 'height']) test_df = pd.DataFrame({'image_name':result_image_ids}) test_df = pd.concat([test_df, box_df], axis=1)
post process(filter)
フレーム単位でsidelineとendzoneからの衝突個数が違う場合除去するもの6と、前後のフレームに衝突が検出されていないものの除去するもの7が公開ノートで提案されていましたが、今回は後者が私のベストスコアになりました。
object detection
object detectionについてのメモをまとめていきます。
基本情報
- 画像のどこに何が映っているのかを識別するタスク
- INPUT(inference時)
- 画像
- OUTPUT(inference時)
- Bboxの位置と大きさ情報
- それぞれのBboxが何の物体かを表すラベル情報
- それぞれのBboxの信頼度
- それぞれ上位x個の候補が出てきます efficientdetだと100、SSDだと200?
- 閾値を設定して余分な予測を削除することも必要になる
モデルの種類
大きく分けて二種類ある
- Single Stage
- 高速
- 1つのネットワークで領域抽出とカテゴリ識別を行う
- SSDやYOLO
- Two Stage
- 精度が高い
- 領域抽出とカテゴリ識別を2つのネットワークで行う
- Faster R-CNNやMask R-CNN
- Single Stage
Faster R-CNN(2015)
- SSD(Single Shot Detector)(2015)
- Mask R-CNN(2017)
- Efficientdet(2019)
- Detectron2
- YOLOv5(2020)
Albumentations
- Bboxで拡張パイプラインを使用するには、BboxParamsのインスタンスをComposeに渡す必要がある。
- Bboxの表現(format)の種類
- 参考:Bounding boxes augmentation for object detection
- pascal_voc
- [x_min, y_min, x_max, y_max]
- [98, 345, 420, 462]
- albumentations
- [x_min, y_min, x_max, y_max]
- pascal_vocとの違いは座標を正規化するところ
- [98 / 640, 345 / 480, 420 / 640, 462 / 480]
- coco
- [x_min, y_min, width, height]
- [98, 345, 322, 117]
- yolo
- [x_center, y_center, width, height]
- 中心と、正規化した値で表現
- [((420 + 98) / 2) / 640, ((462 + 345) / 2) / 480, 322 / 640, 117 / 480]
- min_area
- augmentation後のBboxがmin_areaより小さくなったときそのboxを削除する
- min_visibility
- [0-1]
- augmentation後と前のBboxの面積の比率が min_visibility より小さくなるとそのボックスを削除する。
Ensemble
- 物体検出で重なったバウンディングボックスを除去・集約するアルゴリズムのまとめ (NMS, Soft-NMS, NMW, WBF)にわかりやすくまとめてある。
- NMS
- Soft-NMS
- NMW
- WBF
今後に向けて
物体検出タスクは私には早すぎました・・・solutionも理解できるか怪しいですが学べるものは学んで次のコンペ頑張っていきたいです。