{
  "id": 391607,
  "title": "19th place writeup",
  "url": "/competitions/nfl-player-contact-detection/discussion/391607",
  "author_name": "",
  "post_date": "2023-03-02T00:03:51.873115800Z",
  "votes": 16,
  "comment_count": 3,
  "views": 0,
  "content": "<p>At the first place, thanks for hosting this wonderful competiton.<br>\nSince most of metadatas are already created for us, it was way more easier to join this competition than the last one.</p>\n<p>Below is my solution writeup.</p>\n<h2>General description</h2>\n<p>At first, I devided this competition task as these two:</p>\n<ul>\n<li>Player-Player contact detection (P2P)</li>\n<li>Player-Ground contact detection (P2G)</li>\n</ul>\n<p>Since I considered these two tasks are completely different ones, I built two pipelines separrately depending on these tasks.<br>\nFor short, let's call them P2P and P2G.</p>\n<p>In each tasks, I constructed the following 3-stage pipeline:</p>\n<ul>\n<li>1st stage: Candidate Extractor - XGBoost</li>\n<li>2nd stage: Image Feature Extractor - small CNN (<code>tf_efficientnet_b0</code>)</li>\n<li>3rd stage: Binary Classifier - XGBoost</li>\n</ul>\n<h2>1st stage: Candidate Extractor - Public LB: 0.748; Private LB: 0.736</h2>\n<p>In this competition, I aimed to take a lot of experiments quickly, so I first started this competition with tabular data.<br>\nSince I started to use Polars from Otto competitioin, I also use this tool for this competition.<br>\nIt was really quick: it tooks only 17-18 sec to extract 1031 features from helmet &amp; tracking data using Polars.<br>\nThen I train xgboost model. Utilizing GPU, it took for minitutes to train 5-fold models.</p>\n<p>Notably, using only tabular data, I got <strong>public LB 0.748 (Private LB: 0.736)</strong>.</p>\n<h3>Preprocessing</h3>\n<ul>\n<li>restoring all player-player matching pairs by swapping <code>nfl_player_id_1</code> and <code>nfl_player_id_2</code></li>\n<li>for p2p pipeline, pruning player pairs within 2 yard</li>\n</ul>\n<h3>Feature extraction</h3>\n<p>extracting <strong>1031</strong> features (mostly shift &amp; diff features) from helmet &amp; tracking data</p>\n<p><a href=\"https://docs.google.com/spreadsheets/d/1u96aSvD1r7jhCsPhlxtfVcK5pbNx5mrNZkvFox_kW5E/edit\" target=\"_blank\">feature design list</a></p>\n<h3>Postprocess</h3>\n<ul>\n<li>for p2p, TTA by swapping <code>nfl_player_id_1</code> and <code>nfl_player_id_2</code></li>\n<li>taking moving average of prediction score through time series</li>\n</ul>\n<h2>2nd stage: Image Feature Extractor</h2>\n<h3>Pruning samples using 1st stage model</h3>\n<p>Since image classification takes much more time than tabular tasks, I pruned samples using 1st stage model's prediction score.<br>\nThe performance of pruning is as below:</p>\n<ul>\n<li>p2p: keeping recall 0.992, reduced ~50% of samples</li>\n<li>p2g: keeping recall 0.992, reduced ~75% of samples</li>\n</ul>\n<p>Thanks to pruning, I can reduced both training &amp; inference time.<br>\nIt took only 1 hour to training all 5-fold, 3-channel 2.5D-CNNs for 5 epoch for each (NVIDIA RTX-3090 Ti).</p>\n<p>One thing to note is, thanks to 1st stage model pruning, I got much boost in TNR &amp; NPV.</p>\n<h3>Image Augmentation</h3>\n<p>Because of few samples, I observed the model easy to overfit. Avoiding this, I adopted domain-specific augmentation as well as the common image augmentations.</p>\n<p>Commomn image augmentations:</p>\n<ul>\n<li>horizontal flip, median blur, cutout, affine transform etc. Note that I don't use rotations and translations in case it might cause domain-shift.</li>\n</ul>\n<p>Domain-specific image augmentations:</p>\n<ul>\n<li>Cropping interested 240x240 pixels of regions around helmet. Since the size of the player in the frame differs frame to frame, I adopted cropping based on the helmet size. I found 6x helmet size is the best to identify region of interest. Note that I set center of cropped region a bit below the center of helmet bounding box to capture entire body of the players.</li>\n<li>Adding helmet marker by uniform noize for each helmet bounding boxes to highlight player pairs of interesk.</li>\n<li>Adding +-3 frame of shift which expect to simulate actual sensor delay etc.</li>\n</ul>\n<p>I also note that helmet marker should be added after the common augmentation processings because altering marker pattern deteriorates the merit of markers (I obserbed drop of AUC when adding helmet marker before adopting augumentations).</p>\n<h2>3rd stage: Binary Classifier - Public LB: 0.771 (+0.023); Private LB 0.767 (+0.031)</h2>\n<p>The final stage is very similar to 1st stage, except it uses 2nd-stage's prediction scores of both <code>Endzone</code> and <code>Sideline</code> frames.</p>\n<p>I also reused 1st stage feature because it boost both CV &amp; LB scores.</p>\n<p>The total features are <strong>1033</strong> for both p2g and p2p models.</p>\n<h2>Future Works…</h2>\n<p>The last thing I left for future is finding out the reason of discrepancy between CV &amp; LB scores.</p>\n<p>In the 3rd stage, I also tried to extract more features using 2nd-stage prediction scores (e.g. shift features, aggregation features of players, player-player pairs etc.).<br>\nHowever, although the CV scores increased constantly with using more features, the LB scores decrease as adding more features. So I couldn't increase LB score any more.<br>\nMy best CV score is <strong>0.833</strong> but I got LB score <strong>0.754</strong> for this submission.</p>\n<p>My current hypotheses of this issue are as below:</p>\n<ul>\n<li>Train &amp; Test samples are sampled by different data source (e.g. samples of non-overlapping teams or players). Beause of this, I only observed CVs that was overfitted to the specific players or teams.</li>\n<li>My pipeline has some bug.</li>\n</ul>\n<hr>\n<p><strong>Updates:</strong></p>\n<p>I solved this issue using less-player-duplicated fold sprit.<br>\nMy updated solution is available <a href=\"https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/394302\" target=\"_blank\">here</a>.</p>\n<h2>Other attempts that didn't worked</h2>\n<ul>\n<li>increasing channels of 2.5D CNN: although the AUC in 2nd stage is best for 5-channeled CNN, the final result of 3rd stage is same as 3-channeled models.</li>\n<li>pseudo labels using previous contest (NFL-2)</li>\n<li>I don't even remember…</li>\n</ul>\n<h2>Aknowledgement</h2>\n<p>Throughout the competition, I refered to the following notebooks. I appriciate the authors.</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/code/columbia2131/nfl-player-contact-detection-simple-xgb-baseline\" target=\"_blank\">COLUM2131's XGBoost starter notebook</a> - as a XGBoost's baseline notebook</li>\n<li><a href=\"https://www.kaggle.com/code/kyoshioka47/train-dfl-effnet-1dcnn-cv0-77/notebook\" target=\"_blank\">ARUTEMA47's 1D-CNN notebook</a> - as a baseline of 2D/2.5D-CNN pipeline</li>\n<li><a href=\"https://www.kaggle.com/code/kyoshioka47/team-tara-submission-2-stage-3d/notebook\" target=\"_blank\">ARUTEMA47's notebook in NFL-1</a> - how to generate video frame images from movie files</li>\n<li><a href=\"https://www.kaggle.com/code/zzy990106/nfl-2-5d-cnn-baseline-inference\" target=\"_blank\">ZZY's 2.5D-CNN notebook</a> - idea of cropping &amp; stacking local picture</li>\n</ul>\n<p>I don't remenber who share it first, but I adopted an idea of pruning samples within 2 yard from some notebook or discussion topic.</p>",
  "messages": [
    {
      "id": "2165024",
      "postDate": "03/02/2023 00:03:51",
      "content": "<p>At the first place, thanks for hosting this wonderful competiton.<br>\nSince most of metadatas are already created for us, it was way more easier to join this competition than the last one.</p>\n<p>Below is my solution writeup.</p>\n<h2>General description</h2>\n<p>At first, I devided this competition task as these two:</p>\n<ul>\n<li>Player-Player contact detection (P2P)</li>\n<li>Player-Ground contact detection (P2G)</li>\n</ul>\n<p>Since I considered these two tasks are completely different ones, I built two pipelines separrately depending on these tasks.<br>\nFor short, let's call them P2P and P2G.</p>\n<p>In each tasks, I constructed the following 3-stage pipeline:</p>\n<ul>\n<li>1st stage: Candidate Extractor - XGBoost</li>\n<li>2nd stage: Image Feature Extractor - small CNN (<code>tf_efficientnet_b0</code>)</li>\n<li>3rd stage: Binary Classifier - XGBoost</li>\n</ul>\n<h2>1st stage: Candidate Extractor - Public LB: 0.748; Private LB: 0.736</h2>\n<p>In this competition, I aimed to take a lot of experiments quickly, so I first started this competition with tabular data.<br>\nSince I started to use Polars from Otto competitioin, I also use this tool for this competition.<br>\nIt was really quick: it tooks only 17-18 sec to extract 1031 features from helmet &amp; tracking data using Polars.<br>\nThen I train xgboost model. Utilizing GPU, it took for minitutes to train 5-fold models.</p>\n<p>Notably, using only tabular data, I got <strong>public LB 0.748 (Private LB: 0.736)</strong>.</p>\n<h3>Preprocessing</h3>\n<ul>\n<li>restoring all player-player matching pairs by swapping <code>nfl_player_id_1</code> and <code>nfl_player_id_2</code></li>\n<li>for p2p pipeline, pruning player pairs within 2 yard</li>\n</ul>\n<h3>Feature extraction</h3>\n<p>extracting <strong>1031</strong> features (mostly shift &amp; diff features) from helmet &amp; tracking data</p>\n<p><a href=\"https://docs.google.com/spreadsheets/d/1u96aSvD1r7jhCsPhlxtfVcK5pbNx5mrNZkvFox_kW5E/edit\" target=\"_blank\">feature design list</a></p>\n<h3>Postprocess</h3>\n<ul>\n<li>for p2p, TTA by swapping <code>nfl_player_id_1</code> and <code>nfl_player_id_2</code></li>\n<li>taking moving average of prediction score through time series</li>\n</ul>\n<h2>2nd stage: Image Feature Extractor</h2>\n<h3>Pruning samples using 1st stage model</h3>\n<p>Since image classification takes much more time than tabular tasks, I pruned samples using 1st stage model's prediction score.<br>\nThe performance of pruning is as below:</p>\n<ul>\n<li>p2p: keeping recall 0.992, reduced ~50% of samples</li>\n<li>p2g: keeping recall 0.992, reduced ~75% of samples</li>\n</ul>\n<p>Thanks to pruning, I can reduced both training &amp; inference time.<br>\nIt took only 1 hour to training all 5-fold, 3-channel 2.5D-CNNs for 5 epoch for each (NVIDIA RTX-3090 Ti).</p>\n<p>One thing to note is, thanks to 1st stage model pruning, I got much boost in TNR &amp; NPV.</p>\n<h3>Image Augmentation</h3>\n<p>Because of few samples, I observed the model easy to overfit. Avoiding this, I adopted domain-specific augmentation as well as the common image augmentations.</p>\n<p>Commomn image augmentations:</p>\n<ul>\n<li>horizontal flip, median blur, cutout, affine transform etc. Note that I don't use rotations and translations in case it might cause domain-shift.</li>\n</ul>\n<p>Domain-specific image augmentations:</p>\n<ul>\n<li>Cropping interested 240x240 pixels of regions around helmet. Since the size of the player in the frame differs frame to frame, I adopted cropping based on the helmet size. I found 6x helmet size is the best to identify region of interest. Note that I set center of cropped region a bit below the center of helmet bounding box to capture entire body of the players.</li>\n<li>Adding helmet marker by uniform noize for each helmet bounding boxes to highlight player pairs of interesk.</li>\n<li>Adding +-3 frame of shift which expect to simulate actual sensor delay etc.</li>\n</ul>\n<p>I also note that helmet marker should be added after the common augmentation processings because altering marker pattern deteriorates the merit of markers (I obserbed drop of AUC when adding helmet marker before adopting augumentations).</p>\n<h2>3rd stage: Binary Classifier - Public LB: 0.771 (+0.023); Private LB 0.767 (+0.031)</h2>\n<p>The final stage is very similar to 1st stage, except it uses 2nd-stage's prediction scores of both <code>Endzone</code> and <code>Sideline</code> frames.</p>\n<p>I also reused 1st stage feature because it boost both CV &amp; LB scores.</p>\n<p>The total features are <strong>1033</strong> for both p2g and p2p models.</p>\n<h2>Future Works…</h2>\n<p>The last thing I left for future is finding out the reason of discrepancy between CV &amp; LB scores.</p>\n<p>In the 3rd stage, I also tried to extract more features using 2nd-stage prediction scores (e.g. shift features, aggregation features of players, player-player pairs etc.).<br>\nHowever, although the CV scores increased constantly with using more features, the LB scores decrease as adding more features. So I couldn't increase LB score any more.<br>\nMy best CV score is <strong>0.833</strong> but I got LB score <strong>0.754</strong> for this submission.</p>\n<p>My current hypotheses of this issue are as below:</p>\n<ul>\n<li>Train &amp; Test samples are sampled by different data source (e.g. samples of non-overlapping teams or players). Beause of this, I only observed CVs that was overfitted to the specific players or teams.</li>\n<li>My pipeline has some bug.</li>\n</ul>\n<hr>\n<p><strong>Updates:</strong></p>\n<p>I solved this issue using less-player-duplicated fold sprit.<br>\nMy updated solution is available <a href=\"https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/394302\" target=\"_blank\">here</a>.</p>\n<h2>Other attempts that didn't worked</h2>\n<ul>\n<li>increasing channels of 2.5D CNN: although the AUC in 2nd stage is best for 5-channeled CNN, the final result of 3rd stage is same as 3-channeled models.</li>\n<li>pseudo labels using previous contest (NFL-2)</li>\n<li>I don't even remember…</li>\n</ul>\n<h2>Aknowledgement</h2>\n<p>Throughout the competition, I refered to the following notebooks. I appriciate the authors.</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/code/columbia2131/nfl-player-contact-detection-simple-xgb-baseline\" target=\"_blank\">COLUM2131's XGBoost starter notebook</a> - as a XGBoost's baseline notebook</li>\n<li><a href=\"https://www.kaggle.com/code/kyoshioka47/train-dfl-effnet-1dcnn-cv0-77/notebook\" target=\"_blank\">ARUTEMA47's 1D-CNN notebook</a> - as a baseline of 2D/2.5D-CNN pipeline</li>\n<li><a href=\"https://www.kaggle.com/code/kyoshioka47/team-tara-submission-2-stage-3d/notebook\" target=\"_blank\">ARUTEMA47's notebook in NFL-1</a> - how to generate video frame images from movie files</li>\n<li><a href=\"https://www.kaggle.com/code/zzy990106/nfl-2-5d-cnn-baseline-inference\" target=\"_blank\">ZZY's 2.5D-CNN notebook</a> - idea of cropping &amp; stacking local picture</li>\n</ul>\n<p>I don't remenber who share it first, but I adopted an idea of pruning samples within 2 yard from some notebook or discussion topic.</p>",
      "rawMarkdown": "At the first place, thanks for hosting this wonderful competiton.\nSince most of metadatas are already created for us, it was way more easier to join this competition than the last one.\n\nBelow is my solution writeup.\n\n## General description\n\nAt first, I devided this competition task as these two:\n\n- Player-Player contact detection (P2P)\n- Player-Ground contact detection (P2G)\n\nSince I considered these two tasks are completely different ones, I built two pipelines separrately depending on these tasks.\nFor short, let's call them P2P and P2G.\n\nIn each tasks, I constructed the following 3-stage pipeline:\n\n- 1st stage: Candidate Extractor - XGBoost\n- 2nd stage: Image Feature Extractor - small CNN (`tf_efficientnet_b0`)\n- 3rd stage: Binary Classifier - XGBoost\n\n## 1st stage: Candidate Extractor - Public LB: 0.748; Private LB: 0.736\n\nIn this competition, I aimed to take a lot of experiments quickly, so I first started this competition with tabular data.\nSince I started to use Polars from Otto competitioin, I also use this tool for this competition.\nIt was really quick: it tooks only 17-18 sec to extract 1031 features from helmet & tracking data using Polars.\nThen I train xgboost model. Utilizing GPU, it took for minitutes to train 5-fold models.\n\nNotably, using only tabular data, I got **public LB 0.748 (Private LB: 0.736)**.\n\n### Preprocessing\n\n- restoring all player-player matching pairs by swapping `nfl_player_id_1` and `nfl_player_id_2`\n- for p2p pipeline, pruning player pairs within 2 yard\n\n### Feature extraction\n\nextracting **1031** features (mostly shift & diff features) from helmet & tracking data\n\n[feature design list](https://docs.google.com/spreadsheets/d/1u96aSvD1r7jhCsPhlxtfVcK5pbNx5mrNZkvFox_kW5E/edit)\n\n### Postprocess\n\n- for p2p, TTA by swapping `nfl_player_id_1` and `nfl_player_id_2`\n- taking moving average of prediction score through time series\n\n## 2nd stage: Image Feature Extractor\n\n### Pruning samples using 1st stage model\n\nSince image classification takes much more time than tabular tasks, I pruned samples using 1st stage model's prediction score.\nThe performance of pruning is as below:\n\n- p2p: keeping recall 0.992, reduced ~50% of samples\n- p2g: keeping recall 0.992, reduced ~75% of samples\n\nThanks to pruning, I can reduced both training & inference time.\nIt took only 1 hour to training all 5-fold, 3-channel 2.5D-CNNs for 5 epoch for each (NVIDIA RTX-3090 Ti).\n\nOne thing to note is, thanks to 1st stage model pruning, I got much boost in TNR & NPV.\n\n### Image Augmentation\n\nBecause of few samples, I observed the model easy to overfit. Avoiding this, I adopted domain-specific augmentation as well as the common image augmentations.\n\nCommomn image augmentations:\n- horizontal flip, median blur, cutout, affine transform etc. Note that I don't use rotations and translations in case it might cause domain-shift.\n\nDomain-specific image augmentations:\n- Cropping interested 240x240 pixels of regions around helmet. Since the size of the player in the frame differs frame to frame, I adopted cropping based on the helmet size. I found 6x helmet size is the best to identify region of interest. Note that I set center of cropped region a bit below the center of helmet bounding box to capture entire body of the players.\n- Adding helmet marker by uniform noize for each helmet bounding boxes to highlight player pairs of interesk.\n- Adding +-3 frame of shift which expect to simulate actual sensor delay etc.\n\nI also note that helmet marker should be added after the common augmentation processings because altering marker pattern deteriorates the merit of markers (I obserbed drop of AUC when adding helmet marker before adopting augumentations).\n\n## 3rd stage: Binary Classifier - Public LB: 0.771 (+0.023); Private LB 0.767 (+0.031)\n\nThe final stage is very similar to 1st stage, except it uses 2nd-stage's prediction scores of both `Endzone` and `Sideline` frames.\n\nI also reused 1st stage feature because it boost both CV & LB scores.\n\nThe total features are **1033** for both p2g and p2p models.\n\n## Future Works...\n\nThe last thing I left for future is finding out the reason of discrepancy between CV & LB scores.\n\nIn the 3rd stage, I also tried to extract more features using 2nd-stage prediction scores (e.g. shift features, aggregation features of players, player-player pairs etc.).\nHowever, although the CV scores increased constantly with using more features, the LB scores decrease as adding more features. So I couldn't increase LB score any more.\nMy best CV score is **0.833** but I got LB score **0.754** for this submission.\n\nMy current hypotheses of this issue are as below:\n\n- Train & Test samples are sampled by different data source (e.g. samples of non-overlapping teams or players). Beause of this, I only observed CVs that was overfitted to the specific players or teams.\n- My pipeline has some bug.\n\n---\n\n**Updates:**\n\nI solved this issue using less-player-duplicated fold sprit.\nMy updated solution is available [here](https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/394302).\n\n## Other attempts that didn't worked\n\n- increasing channels of 2.5D CNN: although the AUC in 2nd stage is best for 5-channeled CNN, the final result of 3rd stage is same as 3-channeled models.\n- pseudo labels using previous contest (NFL-2)\n- I don't even remember...\n\n## Aknowledgement\n\nThroughout the competition, I refered to the following notebooks. I appriciate the authors.\n\n- [COLUM2131's XGBoost starter notebook](https://www.kaggle.com/code/columbia2131/nfl-player-contact-detection-simple-xgb-baseline) - as a XGBoost's baseline notebook\n- [ARUTEMA47's 1D-CNN notebook](https://www.kaggle.com/code/kyoshioka47/train-dfl-effnet-1dcnn-cv0-77/notebook) - as a baseline of 2D/2.5D-CNN pipeline\n- [ARUTEMA47's notebook in NFL-1](https://www.kaggle.com/code/kyoshioka47/team-tara-submission-2-stage-3d/notebook) - how to generate video frame images from movie files\n- [ZZY's 2.5D-CNN notebook](https://www.kaggle.com/code/zzy990106/nfl-2-5d-cnn-baseline-inference) - idea of cropping & stacking local picture\n\nI don't remenber who share it first, but I adopted an idea of pruning samples within 2 yard from some notebook or discussion topic.",
      "votes": null
    },
    {
      "id": "2165025",
      "postDate": "03/02/2023 00:07:01",
      "content": "<p>Here is the features of Top50 importances in the 1st stage.</p>\n<p>P2P:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fe95e98e9c5e78ffb22708775d0602e32%2Fimportance_p2p.png?generation=1677715572374749&amp;alt=media\" alt=\"\"></p>\n<p>P2G:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fce7fd44ef6e681abeaff463a80957e4f%2Fimportance_p2g.png?generation=1677715579910986&amp;alt=media\" alt=\"\"></p>",
      "rawMarkdown": "Here is the features of Top50 importances in the 1st stage.\n\nP2P:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fe95e98e9c5e78ffb22708775d0602e32%2Fimportance_p2p.png?generation=1677715572374749&alt=media)\n\nP2G:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fce7fd44ef6e681abeaff463a80957e4f%2Fimportance_p2g.png?generation=1677715579910986&alt=media)",
      "votes": null
    },
    {
      "id": "2165029",
      "postDate": "03/02/2023 00:17:01",
      "content": "<p>I know my writeup is imperfect. Please ask question if you have ones.</p>",
      "rawMarkdown": "I know my writeup is imperfect. Please ask question if you have ones.",
      "votes": null
    },
    {
      "id": "2165065",
      "postDate": "03/02/2023 00:55:51",
      "content": "<p>Picture of augmented image samples:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2F2220b2f5dd870527bd6a22d4c185ef9a%2FScreen%20Shot%202023-03-02%20at%209.54.52.png?generation=1677718505656313&amp;alt=media\" alt=\"\"></p>",
      "rawMarkdown": "Picture of augmented image samples:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2F2220b2f5dd870527bd6a22d4c185ef9a%2FScreen%20Shot%202023-03-02%20at%209.54.52.png?generation=1677718505656313&alt=media)",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 2165025,
      "author_name": "tatamikenn",
      "author_url": "",
      "post_date": "03/02/2023 00:07:01",
      "content": "<p>Here is the features of Top50 importances in the 1st stage.</p>\n<p>P2P:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fe95e98e9c5e78ffb22708775d0602e32%2Fimportance_p2p.png?generation=1677715572374749&amp;alt=media\" alt=\"\"></p>\n<p>P2G:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fce7fd44ef6e681abeaff463a80957e4f%2Fimportance_p2g.png?generation=1677715579910986&amp;alt=media\" alt=\"\"></p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2165029,
      "author_name": "tatamikenn",
      "author_url": "",
      "post_date": "03/02/2023 00:17:01",
      "content": "<p>I know my writeup is imperfect. Please ask question if you have ones.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 2165065,
      "author_name": "tatamikenn",
      "author_url": "",
      "post_date": "03/02/2023 00:55:51",
      "content": "<p>Picture of augmented image samples:<br>\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2F2220b2f5dd870527bd6a22d4c185ef9a%2FScreen%20Shot%202023-03-02%20at%209.54.52.png?generation=1677718505656313&amp;alt=media\" alt=\"\"></p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "2165024": "At the first place, thanks for hosting this wonderful competiton.\nSince most of metadatas are already created for us, it was way more easier to join this competition than the last one.\n\nBelow is my solution writeup.\n\n## General description\n\nAt first, I devided this competition task as these two:\n\n- Player-Player contact detection (P2P)\n- Player-Ground contact detection (P2G)\n\nSince I considered these two tasks are completely different ones, I built two pipelines separrately depending on these tasks.\nFor short, let's call them P2P and P2G.\n\nIn each tasks, I constructed the following 3-stage pipeline:\n\n- 1st stage: Candidate Extractor - XGBoost\n- 2nd stage: Image Feature Extractor - small CNN (`tf_efficientnet_b0`)\n- 3rd stage: Binary Classifier - XGBoost\n\n## 1st stage: Candidate Extractor - Public LB: 0.748; Private LB: 0.736\n\nIn this competition, I aimed to take a lot of experiments quickly, so I first started this competition with tabular data.\nSince I started to use Polars from Otto competitioin, I also use this tool for this competition.\nIt was really quick: it tooks only 17-18 sec to extract 1031 features from helmet & tracking data using Polars.\nThen I train xgboost model. Utilizing GPU, it took for minitutes to train 5-fold models.\n\nNotably, using only tabular data, I got **public LB 0.748 (Private LB: 0.736)**.\n\n### Preprocessing\n\n- restoring all player-player matching pairs by swapping `nfl_player_id_1` and `nfl_player_id_2`\n- for p2p pipeline, pruning player pairs within 2 yard\n\n### Feature extraction\n\nextracting **1031** features (mostly shift & diff features) from helmet & tracking data\n\n[feature design list](https://docs.google.com/spreadsheets/d/1u96aSvD1r7jhCsPhlxtfVcK5pbNx5mrNZkvFox_kW5E/edit)\n\n### Postprocess\n\n- for p2p, TTA by swapping `nfl_player_id_1` and `nfl_player_id_2`\n- taking moving average of prediction score through time series\n\n## 2nd stage: Image Feature Extractor\n\n### Pruning samples using 1st stage model\n\nSince image classification takes much more time than tabular tasks, I pruned samples using 1st stage model's prediction score.\nThe performance of pruning is as below:\n\n- p2p: keeping recall 0.992, reduced ~50% of samples\n- p2g: keeping recall 0.992, reduced ~75% of samples\n\nThanks to pruning, I can reduced both training & inference time.\nIt took only 1 hour to training all 5-fold, 3-channel 2.5D-CNNs for 5 epoch for each (NVIDIA RTX-3090 Ti).\n\nOne thing to note is, thanks to 1st stage model pruning, I got much boost in TNR & NPV.\n\n### Image Augmentation\n\nBecause of few samples, I observed the model easy to overfit. Avoiding this, I adopted domain-specific augmentation as well as the common image augmentations.\n\nCommomn image augmentations:\n- horizontal flip, median blur, cutout, affine transform etc. Note that I don't use rotations and translations in case it might cause domain-shift.\n\nDomain-specific image augmentations:\n- Cropping interested 240x240 pixels of regions around helmet. Since the size of the player in the frame differs frame to frame, I adopted cropping based on the helmet size. I found 6x helmet size is the best to identify region of interest. Note that I set center of cropped region a bit below the center of helmet bounding box to capture entire body of the players.\n- Adding helmet marker by uniform noize for each helmet bounding boxes to highlight player pairs of interesk.\n- Adding +-3 frame of shift which expect to simulate actual sensor delay etc.\n\nI also note that helmet marker should be added after the common augmentation processings because altering marker pattern deteriorates the merit of markers (I obserbed drop of AUC when adding helmet marker before adopting augumentations).\n\n## 3rd stage: Binary Classifier - Public LB: 0.771 (+0.023); Private LB 0.767 (+0.031)\n\nThe final stage is very similar to 1st stage, except it uses 2nd-stage's prediction scores of both `Endzone` and `Sideline` frames.\n\nI also reused 1st stage feature because it boost both CV & LB scores.\n\nThe total features are **1033** for both p2g and p2p models.\n\n## Future Works...\n\nThe last thing I left for future is finding out the reason of discrepancy between CV & LB scores.\n\nIn the 3rd stage, I also tried to extract more features using 2nd-stage prediction scores (e.g. shift features, aggregation features of players, player-player pairs etc.).\nHowever, although the CV scores increased constantly with using more features, the LB scores decrease as adding more features. So I couldn't increase LB score any more.\nMy best CV score is **0.833** but I got LB score **0.754** for this submission.\n\nMy current hypotheses of this issue are as below:\n\n- Train & Test samples are sampled by different data source (e.g. samples of non-overlapping teams or players). Beause of this, I only observed CVs that was overfitted to the specific players or teams.\n- My pipeline has some bug.\n\n---\n\n**Updates:**\n\nI solved this issue using less-player-duplicated fold sprit.\nMy updated solution is available [here](https://www.kaggle.com/competitions/nfl-player-contact-detection/discussion/394302).\n\n## Other attempts that didn't worked\n\n- increasing channels of 2.5D CNN: although the AUC in 2nd stage is best for 5-channeled CNN, the final result of 3rd stage is same as 3-channeled models.\n- pseudo labels using previous contest (NFL-2)\n- I don't even remember...\n\n## Aknowledgement\n\nThroughout the competition, I refered to the following notebooks. I appriciate the authors.\n\n- [COLUM2131's XGBoost starter notebook](https://www.kaggle.com/code/columbia2131/nfl-player-contact-detection-simple-xgb-baseline) - as a XGBoost's baseline notebook\n- [ARUTEMA47's 1D-CNN notebook](https://www.kaggle.com/code/kyoshioka47/train-dfl-effnet-1dcnn-cv0-77/notebook) - as a baseline of 2D/2.5D-CNN pipeline\n- [ARUTEMA47's notebook in NFL-1](https://www.kaggle.com/code/kyoshioka47/team-tara-submission-2-stage-3d/notebook) - how to generate video frame images from movie files\n- [ZZY's 2.5D-CNN notebook](https://www.kaggle.com/code/zzy990106/nfl-2-5d-cnn-baseline-inference) - idea of cropping & stacking local picture\n\nI don't remenber who share it first, but I adopted an idea of pruning samples within 2 yard from some notebook or discussion topic.",
    "2165025": "Here is the features of Top50 importances in the 1st stage.\n\nP2P:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fe95e98e9c5e78ffb22708775d0602e32%2Fimportance_p2p.png?generation=1677715572374749&alt=media)\n\nP2G:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2Fce7fd44ef6e681abeaff463a80957e4f%2Fimportance_p2g.png?generation=1677715579910986&alt=media)",
    "2165029": "I know my writeup is imperfect. Please ask question if you have ones.",
    "2165065": "Picture of augmented image samples:\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4910466%2F2220b2f5dd870527bd6a22d4c185ef9a%2FScreen%20Shot%202023-03-02%20at%209.54.52.png?generation=1677718505656313&alt=media)"
  },
  "source": "meta"
}