{
  "id": 603611,
  "title": "1st place solution",
  "url": "/competitions/cmi-detect-behavior-with-sensor-data/discussion/603611",
  "author_name": "Ogurtsov",
  "post_date": "2025-09-03T11:14:57.396000",
  "votes": 81,
  "comment_count": 19,
  "views": 0,
  "content": "<p><strong>Links to code:</strong></p>\n<ul>\n<li><a href=\"https://github.com/statist-bhfz/kaggle_cmi_1st_place_solution\" target=\"_blank\">Training code on github</a></li>\n<li><a href=\"https://www.kaggle.com/code/yuanzhezhou/final-sub-cmi3\" target=\"_blank\">Inference notebook</a></li>\n</ul>\n<h2>Solution Writeup</h2>\n<p>Congratulations to all the winners and a big respect to the organizers for putting together such a challenging and rewarding competition. <br>\nSpecial thanks to my teammates <a href=\"https://www.kaggle.com/yuanzhezhou\" target=\"_blank\">yuanzhe zhou</a> and <a href=\"https://www.kaggle.com/devinanzelmo\" target=\"_blank\">Devin Anzelmo</a> for the great collaboration and team spirit.</p>\n<h2>Solution Overview</h2>\n<ul>\n<li><p>Large ensembles for IMU-only and all-features samples, assembled as weighted sum of logits</p></li>\n<li><p>Post-processing to take into account limited number of samples with each class and with each orientation per subject (already described <a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603544\" target=\"_blank\">here</a>)</p></li>\n<li><p>Additional models for orientation prediction</p></li>\n</ul>\n<hr>\n<h2>Devin's part</h2>\n<p><strong>1. Preprocessing/feature engineering:</strong></p>\n<ul>\n<li><p>Removed subjects who wore device incorrectly from both training and validation</p></li>\n<li><p>For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)</p></li>\n<li><p>Some models trained with temporal difference of above TOF features and thermal</p></li>\n<li><p>IMU: raw 7 + temporal diff of <code>acc</code>, rotational diff as posted in notebooks, as well as magnitude of <code>acc</code>/<code>rot</code>; 16 total</p></li>\n<li><p>preprocess left handed to match right handed for IMU and THM/TOF. Flip <code>acc_x</code>, convert <code>rot</code> to xyz euler and flip sign for y and z</p></li>\n<li><p>robust scaler </p></li>\n</ul>\n<p><strong>2. Augmentation:</strong></p>\n<ul>\n<li><p>up scaling/down scaling all features </p></li>\n<li><p>random noise </p></li>\n</ul>\n<p><strong>3. Models:</strong></p>\n<ul>\n<li><p>CNN GRU with different stems for different features. Feature extractor is four branches of CNN with no pooling</p></li>\n<li><p>Pure CNN. Same feature extractor as above but three blocks of residual at end with expanding kernal (5, 9, 13)</p></li>\n<li><p>dense GRU, scores lower but helps a little in ensemble</p></li>\n<li><p>some self excitation models, some not combining helps</p></li>\n<li><p>3D CNN for TOF data scores about 0.83 but blends well</p></li>\n</ul>\n<p><strong>4. Training:</strong></p>\n<ul>\n<li><p>batch size 64</p></li>\n<li><p>train for 60-80 (depending on model) iters with AdamW <code>lr = 0.0005</code></p></li>\n</ul>\n<p><strong>5. Ensemble:</strong></p>\n<ul>\n<li><p>blend IMU models with all-features models </p></li>\n<li><p>blend TOF-only model improves all data score</p></li>\n</ul>\n<hr>\n<h2>Ogurtsov's part</h2>\n<p><strong>1. Filtering data:</strong>    </p>\n<ul>\n<li><p>[all models] remove sequence SEQ_011975 without gesture    </p></li>\n<li><p>[all models] remove sequences with gesture/total ratio &lt; 0.2 (this subset includes almost all shortest sequences)    </p></li>\n<li><p>[models with THM and TOF data] remove sequences with TOF completely missing    (missing values patterns in TOF - 0%, 20% or 100%; 20% missing is ok)   </p></li>\n<li><p>few models were trained without \"problematic\" subjects SUBJ_045235 and SUBJ_019262</p></li>\n</ul>\n<p><strong>2. Preprocessing:</strong></p>\n<ul>\n<li><p>fill quaternion missing values, if possible    </p></li>\n<li><p>mirror data for left-handed subjects </p></li>\n<li><p>replace -1 TOF values with 500 because -1 encodes large distance    </p></li>\n<li><p>ultimate filling NaNs with <code>seq.ffill().bfill().fillna(0)</code></p></li>\n<li><p>pad/crop by 94 percentile in each fold (~120 max seq length)    </p></li>\n<li><p>no scalers - it gave the largest improvement at early stage    </p></li>\n</ul>\n<p><strong>3. Feature engineering:</strong>    </p>\n<ul>\n<li><p>nothing for THM and TOF    </p></li>\n<li><p>35 IMU features:    </p></li>\n</ul>\n<pre><code>[', ', ', ', ', ', ', ', ', ', ', ',    \nrot_w', ', ', ', ', ', ', ', ', ', ',    \nacc_x2', ', ', ', ', ', ', ', ', ', ', ']\n</code></pre>\n<p><code>acc_x2</code> and other <code>***2</code> features are important part of the solution. <br>\nThese features are calculated on values transformed by <code>remove_gravity_from_acc()</code>.    </p>\n<p><strong>4. Models:</strong>    </p>\n<ul>\n<li><p>bunch of models with different architectures for training on IMU-only data and similar models for training with all features    </p></li>\n<li><p>main differences in time dimension processing: LSTM-, attention- or CNN-based    </p></li>\n<li><p>key part - independent processing groups of features at first layers    </p></li>\n</ul>\n<p><strong>5. Augmentations:</strong>    </p>\n<ul>\n<li><p>mixup with <code>MIXUP_ALPHA = 0.4</code></p></li>\n<li><p>augmentation from <a href=\"https://www.kaggle.com/code/alejopaullier/cmi-sequence-data-augmentation\" target=\"_blank\">CMI | Sequence Data Augmentation</a> (thanks <a href=\"https://www.kaggle.com/alejopaullier\" target=\"_blank\">moth</a>):    </p></li>\n</ul>\n<pre><code>transforms = Compose,    \n    TimeStretch,    \n])\n</code></pre>\n<p>with some variations.</p>\n<p>It was hard to pick up right augmetations with right probability &amp; strength and apply it in the correct order.    </p>\n<p><strong>6. Training:</strong>    </p>\n<ul>\n<li><p>CV5 with group by subject K-fold, 5 models are used on inference    </p></li>\n<li><p>200 or 220 epochs, patience 30 or 35    </p></li>\n<li><p><code>torch.optim.Adam</code> with <code>lr = 4e-4</code> or <code>lr = 5e-4</code> and <code>weight_decay = 3e-4</code>    </p></li>\n<li><p><code>CosineAnnealingWarmRestarts</code>; <code>LinearLR</code> + <code>CosineAnnealingWarmRestarts</code> for attention-based models    </p></li>\n<li><p>one model was trained with focal loss and class weights    (class weights obviously mean nothing for mixup samples, maybe it can serve as regularization)  </p></li>\n<li><p>one model contains bug in cross-attention (shared weights for 3 different attentions) but works pretty well</p></li>\n</ul>\n<p><strong>7. Some tricks:</strong>    </p>\n<ul>\n<li><p>pick best result for each fold among 3 runs</p></li>\n<li><p>increase sequence length by 5 on inference (it doesn't improve CV score but effectively decorrelates models)</p></li>\n</ul>\n<hr>\n<h2>zyz's part</h2>\n<p>1.1. Using the pipeline structure from <a href=\"https://www.kaggle.com/code/myso1987/cmi3-pyroch-baseline-model-add-aug-folds?scriptVersionId=248310337\" target=\"_blank\">CMI3 Pyroch Baseline+model_add, Aug, folds</a></p>\n<p>1.2. Fixing many bugs improved my score to 0.85.</p>\n<ol>\n<li><p>Models: simple combinations of RNN and CNN1D.</p></li>\n<li><p>Feature engineering using pytorch, which avoids problem of consistency but makes the training slower.</p></li>\n<li><p>Basic preprocessing mentioned by most teams: fillnan, handedness, etc.</p></li>\n<li><p>Post-processing based on data structure.</p></li>\n<li><p>Augmentation idea from teammates:</p></li>\n</ol>\n<p>6.1. Mask data during training helps.</p>",
  "messages": [
    {
      "id": 3280919,
      "postDate": "2025-09-03T11:14:57.397Z",
      "content": "<p><strong>Links to code:</strong></p>\n<ul>\n<li><a href=\"https://github.com/statist-bhfz/kaggle_cmi_1st_place_solution\" target=\"_blank\">Training code on github</a></li>\n<li><a href=\"https://www.kaggle.com/code/yuanzhezhou/final-sub-cmi3\" target=\"_blank\">Inference notebook</a></li>\n</ul>\n<h2>Solution Writeup</h2>\n<p>Congratulations to all the winners and a big respect to the organizers for putting together such a challenging and rewarding competition. <br>\nSpecial thanks to my teammates <a href=\"https://www.kaggle.com/yuanzhezhou\" target=\"_blank\">yuanzhe zhou</a> and <a href=\"https://www.kaggle.com/devinanzelmo\" target=\"_blank\">Devin Anzelmo</a> for the great collaboration and team spirit.</p>\n<h2>Solution Overview</h2>\n<ul>\n<li><p>Large ensembles for IMU-only and all-features samples, assembled as weighted sum of logits</p></li>\n<li><p>Post-processing to take into account limited number of samples with each class and with each orientation per subject (already described <a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603544\" target=\"_blank\">here</a>)</p></li>\n<li><p>Additional models for orientation prediction</p></li>\n</ul>\n<hr>\n<h2>Devin's part</h2>\n<p><strong>1. Preprocessing/feature engineering:</strong></p>\n<ul>\n<li><p>Removed subjects who wore device incorrectly from both training and validation</p></li>\n<li><p>For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)</p></li>\n<li><p>Some models trained with temporal difference of above TOF features and thermal</p></li>\n<li><p>IMU: raw 7 + temporal diff of <code>acc</code>, rotational diff as posted in notebooks, as well as magnitude of <code>acc</code>/<code>rot</code>; 16 total</p></li>\n<li><p>preprocess left handed to match right handed for IMU and THM/TOF. Flip <code>acc_x</code>, convert <code>rot</code> to xyz euler and flip sign for y and z</p></li>\n<li><p>robust scaler </p></li>\n</ul>\n<p><strong>2. Augmentation:</strong></p>\n<ul>\n<li><p>up scaling/down scaling all features </p></li>\n<li><p>random noise </p></li>\n</ul>\n<p><strong>3. Models:</strong></p>\n<ul>\n<li><p>CNN GRU with different stems for different features. Feature extractor is four branches of CNN with no pooling</p></li>\n<li><p>Pure CNN. Same feature extractor as above but three blocks of residual at end with expanding kernal (5, 9, 13)</p></li>\n<li><p>dense GRU, scores lower but helps a little in ensemble</p></li>\n<li><p>some self excitation models, some not combining helps</p></li>\n<li><p>3D CNN for TOF data scores about 0.83 but blends well</p></li>\n</ul>\n<p><strong>4. Training:</strong></p>\n<ul>\n<li><p>batch size 64</p></li>\n<li><p>train for 60-80 (depending on model) iters with AdamW <code>lr = 0.0005</code></p></li>\n</ul>\n<p><strong>5. Ensemble:</strong></p>\n<ul>\n<li><p>blend IMU models with all-features models </p></li>\n<li><p>blend TOF-only model improves all data score</p></li>\n</ul>\n<hr>\n<h2>Ogurtsov's part</h2>\n<p><strong>1. Filtering data:</strong>    </p>\n<ul>\n<li><p>[all models] remove sequence SEQ_011975 without gesture    </p></li>\n<li><p>[all models] remove sequences with gesture/total ratio &lt; 0.2 (this subset includes almost all shortest sequences)    </p></li>\n<li><p>[models with THM and TOF data] remove sequences with TOF completely missing    (missing values patterns in TOF - 0%, 20% or 100%; 20% missing is ok)   </p></li>\n<li><p>few models were trained without \"problematic\" subjects SUBJ_045235 and SUBJ_019262</p></li>\n</ul>\n<p><strong>2. Preprocessing:</strong></p>\n<ul>\n<li><p>fill quaternion missing values, if possible    </p></li>\n<li><p>mirror data for left-handed subjects </p></li>\n<li><p>replace -1 TOF values with 500 because -1 encodes large distance    </p></li>\n<li><p>ultimate filling NaNs with <code>seq.ffill().bfill().fillna(0)</code></p></li>\n<li><p>pad/crop by 94 percentile in each fold (~120 max seq length)    </p></li>\n<li><p>no scalers - it gave the largest improvement at early stage    </p></li>\n</ul>\n<p><strong>3. Feature engineering:</strong>    </p>\n<ul>\n<li><p>nothing for THM and TOF    </p></li>\n<li><p>35 IMU features:    </p></li>\n</ul>\n<pre><code>[', ', ', ', ', ', ', ', ', ', ', ',    \nrot_w', ', ', ', ', ', ', ', ', ', ',    \nacc_x2', ', ', ', ', ', ', ', ', ', ', ']\n</code></pre>\n<p><code>acc_x2</code> and other <code>***2</code> features are important part of the solution. <br>\nThese features are calculated on values transformed by <code>remove_gravity_from_acc()</code>.    </p>\n<p><strong>4. Models:</strong>    </p>\n<ul>\n<li><p>bunch of models with different architectures for training on IMU-only data and similar models for training with all features    </p></li>\n<li><p>main differences in time dimension processing: LSTM-, attention- or CNN-based    </p></li>\n<li><p>key part - independent processing groups of features at first layers    </p></li>\n</ul>\n<p><strong>5. Augmentations:</strong>    </p>\n<ul>\n<li><p>mixup with <code>MIXUP_ALPHA = 0.4</code></p></li>\n<li><p>augmentation from <a href=\"https://www.kaggle.com/code/alejopaullier/cmi-sequence-data-augmentation\" target=\"_blank\">CMI | Sequence Data Augmentation</a> (thanks <a href=\"https://www.kaggle.com/alejopaullier\" target=\"_blank\">moth</a>):    </p></li>\n</ul>\n<pre><code>transforms = Compose,    \n    TimeStretch,    \n])\n</code></pre>\n<p>with some variations.</p>\n<p>It was hard to pick up right augmetations with right probability &amp; strength and apply it in the correct order.    </p>\n<p><strong>6. Training:</strong>    </p>\n<ul>\n<li><p>CV5 with group by subject K-fold, 5 models are used on inference    </p></li>\n<li><p>200 or 220 epochs, patience 30 or 35    </p></li>\n<li><p><code>torch.optim.Adam</code> with <code>lr = 4e-4</code> or <code>lr = 5e-4</code> and <code>weight_decay = 3e-4</code>    </p></li>\n<li><p><code>CosineAnnealingWarmRestarts</code>; <code>LinearLR</code> + <code>CosineAnnealingWarmRestarts</code> for attention-based models    </p></li>\n<li><p>one model was trained with focal loss and class weights    (class weights obviously mean nothing for mixup samples, maybe it can serve as regularization)  </p></li>\n<li><p>one model contains bug in cross-attention (shared weights for 3 different attentions) but works pretty well</p></li>\n</ul>\n<p><strong>7. Some tricks:</strong>    </p>\n<ul>\n<li><p>pick best result for each fold among 3 runs</p></li>\n<li><p>increase sequence length by 5 on inference (it doesn't improve CV score but effectively decorrelates models)</p></li>\n</ul>\n<hr>\n<h2>zyz's part</h2>\n<p>1.1. Using the pipeline structure from <a href=\"https://www.kaggle.com/code/myso1987/cmi3-pyroch-baseline-model-add-aug-folds?scriptVersionId=248310337\" target=\"_blank\">CMI3 Pyroch Baseline+model_add, Aug, folds</a></p>\n<p>1.2. Fixing many bugs improved my score to 0.85.</p>\n<ol>\n<li><p>Models: simple combinations of RNN and CNN1D.</p></li>\n<li><p>Feature engineering using pytorch, which avoids problem of consistency but makes the training slower.</p></li>\n<li><p>Basic preprocessing mentioned by most teams: fillnan, handedness, etc.</p></li>\n<li><p>Post-processing based on data structure.</p></li>\n<li><p>Augmentation idea from teammates:</p></li>\n</ol>\n<p>6.1. Mask data during training helps.</p>",
      "rawMarkdown": "**Links to code:**\n- [Training code on github](https://github.com/statist-bhfz/kaggle_cmi_1st_place_solution)\n- [Inference notebook](https://www.kaggle.com/code/yuanzhezhou/final-sub-cmi3)\n\n## Solution Writeup\n\nCongratulations to all the winners and a big respect to the organizers for putting together such a challenging and rewarding competition. \nSpecial thanks to my teammates [yuanzhe zhou](https://www.kaggle.com/yuanzhezhou) and [Devin Anzelmo](https://www.kaggle.com/devinanzelmo) for the great collaboration and team spirit.\n\n## Solution Overview\n\n-   Large ensembles for IMU-only and all-features samples, assembled as weighted sum of logits\n\n-   Post-processing to take into account limited number of samples with each class and with each orientation per subject (already described [here](https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603544))\n\n-   Additional models for orientation prediction\n\n------------------------------------------------------------------------\n\n## Devin's part\n\n**1. Preprocessing/feature engineering:**\n\n- Removed subjects who wore device incorrectly from both training and validation\n\n- For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)\n\n- Some models trained with temporal difference of above TOF features and thermal\n\n- IMU: raw 7 + temporal diff of `acc`, rotational diff as posted in notebooks, as well as magnitude of `acc`/`rot`; 16 total\n\n- preprocess left handed to match right handed for IMU and THM/TOF. Flip `acc_x`, convert `rot` to xyz euler and flip sign for y and z\n\n- robust scaler \n\n**2. Augmentation:**\n\n- up scaling/down scaling all features \n\n- random noise \n\n**3. Models:**\n\n- CNN GRU with different stems for different features. Feature extractor is four branches of CNN with no pooling\n\n- Pure CNN. Same feature extractor as above but three blocks of residual at end with expanding kernal (5, 9, 13)\n\n- dense GRU, scores lower but helps a little in ensemble\n\n- some self excitation models, some not combining helps\n\n- 3D CNN for TOF data scores about 0.83 but blends well\n\n**4. Training:**\n\n- batch size 64\n\n- train for 60-80 (depending on model) iters with AdamW `lr = 0.0005`\n\n**5. Ensemble:**\n\n- blend IMU models with all-features models \n\n- blend TOF-only model improves all data score\n\n------------------------------------------------------------------------\n\n## Ogurtsov's part\n\n**1. Filtering data:**\t\n\t\n- [all models] remove sequence SEQ_011975 without gesture\t\n\t\n- [all models] remove sequences with gesture/total ratio < 0.2 (this subset includes almost all shortest sequences)\t\n\t\n- [models with THM and TOF data] remove sequences with TOF completely missing\t(missing values patterns in TOF - 0%, 20% or 100%; 20% missing is ok)\t\n\n- few models were trained without \"problematic\" subjects SUBJ_045235 and SUBJ_019262\n\t\n**2. Preprocessing:**\n\t\n- fill quaternion missing values, if possible\t\n\t\n- mirror data for left-handed subjects \n\n- replace -1 TOF values with 500 because -1 encodes large distance\t\n\t\n- ultimate filling NaNs with `seq.ffill().bfill().fillna(0)`\n\t\n- pad/crop by 94 percentile in each fold (~120 max seq length)\t\n\t\n- no scalers - it gave the largest improvement at early stage\t\n\t\n**3. Feature engineering:**\t\n\t\n- nothing for THM and TOF\t\n\t\n- 35 IMU features:\t\n```\n['acc_x', 'acc_y', 'acc_z', 'acc_mag', 'acc_mag_jerk', 'jerk_x', 'jerk_y', 'jerk_z', 'jerk_magnitude', 'acc_xy_corr', 'acc_xz_corr', 'acc_yz_corr',\t\nrot_w', 'rot_x', 'rot_y', 'rot_z', 'rot_angle', 'rot_angle_vel', 'angular_vel_x', 'angular_vel_y', 'angular_vel_z', 'angular_vel_magnitude', 'angular_distance',\t\nacc_x2', 'acc_y2', 'acc_z2', 'acc_mag2', 'acc_mag_jerk2', 'jerk_x2', 'jerk_y2', 'jerk_z2', 'jerk_magnitude2', 'acc_xy_corr2', 'acc_xz_corr2', 'acc_yz_corr2']\n```\n\n`acc_x2` and other `***2` features are important part of the solution. \nThese features are calculated on values transformed by `remove_gravity_from_acc()`.\t\n\t\n**4. Models:**\t\n\t\n- bunch of models with different architectures for training on IMU-only data and similar models for training with all features\t\n\t\n- main differences in time dimension processing: LSTM-, attention- or CNN-based\t\n\t\n- key part - independent processing groups of features at first layers\t\n\t\n**5. Augmentations:**\t\n\t\n- mixup with `MIXUP_ALPHA = 0.4`\n\t\n- augmentation from [CMI | Sequence Data Augmentation](https://www.kaggle.com/code/alejopaullier/cmi-sequence-data-augmentation) (thanks [moth](https://www.kaggle.com/alejopaullier)):\t\n```\ntransforms = Compose([\t\n    TimeShift(p = 0.35, padding_mode = \"zero\", max_shift_pct = 0.25),\t\n    TimeStretch(p = 0.35, max_rate = 1.5, min_rate = 0.5),\t\n])\n```\nwith some variations.\n\nIt was hard to pick up right augmetations with right probability & strength and apply it in the correct order.\t\n\t\n**6. Training:**\t\n\t\n- CV5 with group by subject K-fold, 5 models are used on inference\t\n\t\n- 200 or 220 epochs, patience 30 or 35\t\n\t\n- `torch.optim.Adam` with `lr = 4e-4` or `lr = 5e-4` and `weight_decay = 3e-4`\t\n\t\n- `CosineAnnealingWarmRestarts`; `LinearLR` + `CosineAnnealingWarmRestarts` for attention-based models\t\n\t\n- one model was trained with focal loss and class weights\t(class weights obviously mean nothing for mixup samples, maybe it can serve as regularization)\t\n\n- one model contains bug in cross-attention (shared weights for 3 different attentions) but works pretty well\n\n**7. Some tricks:**\t\n\t\n- pick best result for each fold among 3 runs\n\n- increase sequence length by 5 on inference (it doesn't improve CV score but effectively decorrelates models)\n\n------------------------------------------------------------------------\n\n## zyz's part\n\n1.1. Using the pipeline structure from [CMI3 Pyroch Baseline+model_add, Aug, folds](https://www.kaggle.com/code/myso1987/cmi3-pyroch-baseline-model-add-aug-folds?scriptVersionId=248310337)\n\n1.2. Fixing many bugs improved my score to 0.85.\n\n2. Models: simple combinations of RNN and CNN1D.\n\n3. Feature engineering using pytorch, which avoids problem of consistency but makes the training slower.\n\n4. Basic preprocessing mentioned by most teams: fillnan, handedness, etc.\n\n5. Post-processing based on data structure.\n\n6. Augmentation idea from teammates:\n\n6.1. Mask data during training helps.\n\n",
      "votes": 81
    },
    {
      "id": 3281797,
      "postDate": "2025-09-05T00:49:45.107Z",
      "content": "<p>Congratulations! I have some question about Devin's part's Preprocessing.</p>\n<blockquote>\n  <p>Removed subjects who wore device incorrectly from both training and validation</p>\n</blockquote>\n<p>How do you know that subjects wore device incorrectly?</p>\n<blockquote>\n  <p>For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)</p>\n</blockquote>\n<p>How do you guy do this? I mean, TOF is a matrix 8x8, using 2x2 square so it must need 16 squares. Or if you do with stride=2?</p>",
      "rawMarkdown": "Congratulations! I have some question about Devin's part's Preprocessing.\n> Removed subjects who wore device incorrectly from both training and validation\n\nHow do you know that subjects wore device incorrectly?\n> For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)\n\nHow do you guy do this? I mean, TOF is a matrix 8x8, using 2x2 square so it must need 16 squares. Or if you do with stride=2?",
      "votes": 3
    },
    {
      "id": 3287738,
      "postDate": "2025-09-12T06:24:00.133Z",
      "content": "<p>Congrats on the 1st place!  Really impressive ensemble design and feature engineering across IMU, TOF, and THM.</p>\n<p>I had a question regarding CV and data imbalance: since some classes/orientations are underrepresented, did you find that group K-fold by subject was sufficient, or did you try any balancing strategies to make sure rare cases were well-covered during validation?</p>",
      "rawMarkdown": "Congrats on the 1st place!  Really impressive ensemble design and feature engineering across IMU, TOF, and THM.\n\nI had a question regarding CV and data imbalance: since some classes/orientations are underrepresented, did you find that group K-fold by subject was sufficient, or did you try any balancing strategies to make sure rare cases were well-covered during validation?",
      "votes": 1,
      "replies": [
        {
          "id": 3287751,
          "postDate": "2025-09-12T07:15:39.703Z",
          "content": "<p>I used K-fold by subject from the very beginning and didn't try anything else.</p>",
          "rawMarkdown": "I used K-fold by subject from the very beginning and didn't try anything else."
        }
      ]
    },
    {
      "id": 3280951,
      "postDate": "2025-09-03T11:33:36.080Z",
      "content": "<p>Congratz !</p>\n<p>I have some questions :)</p>\n<ul>\n<li>How does your ensemble perform without PP ?</li>\n<li>How did you implement PP ? Using optimization heuristics / using a transformer model ?</li>\n</ul>",
      "rawMarkdown": "Congratz !\n\nI have some questions :)\n- How does your ensemble perform without PP ?\n- How did you implement PP ? Using optimization heuristics / using a transformer model ?",
      "votes": 1,
      "replies": [
        {
          "id": 3280962,
          "postDate": "2025-09-03T11:38:21.260Z",
          "rawMarkdown": "",
          "votes": 1,
          "isDeleted": true
        },
        {
          "id": 3280977,
          "postDate": "2025-09-03T11:42:16.810Z",
          "content": "<p>Thanks! Exact pure score without post-processing for best submit is unknown, we literally had no submits left to check. Our sub-ensembles at the team merging moment scored like 0.873-0.874 (public scores) and were significantly improved further. We used optimization heuristics, targets/positions distribution information was explicitly available only for small fraction of base models (72-classes).</p>",
          "rawMarkdown": "Thanks! Exact pure score without post-processing for best submit is unknown, we literally had no submits left to check. Our sub-ensembles at the team merging moment scored like 0.873-0.874 (public scores) and were significantly improved further. We used optimization heuristics, targets/positions distribution information was explicitly available only for small fraction of base models (72-classes).",
          "votes": 1,
          "replies": [
            {
              "id": 3280982,
              "postDate": "2025-09-03T11:45:44.377Z",
              "content": "<p>Thanks for the quick replies.<br>\nLooks like we have comparable ensembles without PP but your PP is stronger !</p>",
              "rawMarkdown": "Thanks for the quick replies.\nLooks like we have comparable ensembles without PP but your PP is stronger !",
              "votes": 1
            }
          ]
        }
      ]
    },
    {
      "id": 3281291,
      "postDate": "2025-09-04T02:29:51.810Z",
      "content": "<p>Congratulations! I have a question about your scales. I also train on no scales data which is better for my model but the scaler data is also better for my inference. I don't know why it will work.</p>",
      "rawMarkdown": "Congratulations! I have a question about your scales. I also train on no scales data which is better for my model but the scaler data is also better for my inference. I don't know why it will work.",
      "votes": 2,
      "replies": [
        {
          "id": 3281315,
          "postDate": "2025-09-04T03:37:20.263Z",
          "content": "<p>It is more about the initialization of the neural network, which is more related to lucky seed. The scale of the provided data is already very good, just divide by 10 is enough.</p>",
          "rawMarkdown": "It is more about the initialization of the neural network, which is more related to lucky seed. The scale of the provided data is already very good, just divide by 10 is enough.",
          "votes": 1,
          "replies": [
            {
              "id": 3281321,
              "postDate": "2025-09-04T03:47:11.770Z",
              "content": "<pre><code>which  more related to lucky seed.\n</code></pre>\n<p><a href=\"https://www.kaggle.com/yuanzhezhou\" target=\"_blank\">@yuanzhezhou</a> may i ask which seed value or values do you use in traning  ?</p>",
              "rawMarkdown": "```python\n\nwhich is more related to lucky seed.\n\n```\n@yuanzhezhou may i ask which seed value or values do you use in traning  ?"
            },
            {
              "id": 3281330,
              "postDate": "2025-09-04T04:23:54.630Z",
              "content": "<p>I did not change the seed use by the public notebook, which is 42. it is important not to tune seed for better score</p>",
              "rawMarkdown": "I did not change the seed use by the public notebook, which is 42. it is important not to tune seed for better score",
              "votes": 2
            }
          ]
        },
        {
          "id": 3281353,
          "postDate": "2025-09-04T05:56:27.460Z",
          "content": "<p>Scaled data on train + not scaled on inference could work only if scaling changes data to a very small extent.</p>",
          "rawMarkdown": "Scaled data on train + not scaled on inference could work only if scaling changes data to a very small extent.",
          "votes": 2
        }
      ]
    },
    {
      "id": 3280988,
      "postDate": "2025-09-03T12:01:00.963Z",
      "content": "<p>Congratulations! I am glad my augmentations worked for you. For me the one that worked the best (besides mixup) was adding random peaks or valleys. This is similar to masking. Another good one is channel dropout :)</p>",
      "rawMarkdown": "Congratulations! I am glad my augmentations worked for you. For me the one that worked the best (besides mixup) was adding random peaks or valleys. This is similar to masking. Another good one is channel dropout :)",
      "votes": 2,
      "replies": [
        {
          "id": 3280994,
          "postDate": "2025-09-03T12:10:29.173Z",
          "content": "<p>Thanks! Your aug notebook helped me make progress when I got stuck at some moment.</p>",
          "rawMarkdown": "Thanks! Your aug notebook helped me make progress when I got stuck at some moment.",
          "votes": 1
        }
      ]
    },
    {
      "id": 3281833,
      "postDate": "2025-09-05T03:47:15.280Z",
      "content": "<p>Congrats! Do you mean bugs in my code? If so, could you share what you fixed?</p>",
      "rawMarkdown": "Congrats! Do you mean bugs in my code? If so, could you share what you fixed?",
      "replies": [
        {
          "id": 3281842,
          "postDate": "2025-09-05T04:21:00.827Z",
          "content": "<p>Hello, it is a good notebook. It was the only pytorch notebook that could train&amp;submit to get good score at that time. The problem is that, many details are limitting further development. For example, ema is never used for validation, Scaler should not use global statistics, etc.</p>",
          "rawMarkdown": "Hello, it is a good notebook. It was the only pytorch notebook that could train&submit to get good score at that time. The problem is that, many details are limitting further development. For example, ema is never used for validation, Scaler should not use global statistics, etc.",
          "votes": 1
        }
      ]
    },
    {
      "id": 3281603,
      "postDate": "2025-09-04T14:53:55.727Z",
      "content": "<p>Wow! Congratulations ! that’s great work. It was clear from the beginning that feature engineering would have a significant impact, the dataset has many faces 😅<br>\n<strong>One question</strong>: What was the level of scores for your GRU model ?</p>",
      "rawMarkdown": "Wow! Congratulations ! that’s great work. It was clear from the beginning that feature engineering would have a significant impact, the dataset has many faces 😅\n**One question**: What was the level of scores for your GRU model ?"
    },
    {
      "id": 3280926,
      "postDate": "2025-09-03T11:18:15.053Z",
      "rawMarkdown": "",
      "isDeleted": true
    },
    {
      "id": 3286789,
      "postDate": "2025-09-10T12:08:00.923Z",
      "content": "<p>Congratulations</p>",
      "rawMarkdown": "Congratulations"
    }
  ],
  "comments": [
    {
      "id": 3281797,
      "author_name": "Sam Bui",
      "author_url": "",
      "post_date": "2025-09-05T00:49:45.107000",
      "content": "<p>Congratulations! I have some question about Devin's part's Preprocessing.</p>\n<blockquote>\n  <p>Removed subjects who wore device incorrectly from both training and validation</p>\n</blockquote>\n<p>How do you know that subjects wore device incorrectly?</p>\n<blockquote>\n  <p>For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)</p>\n</blockquote>\n<p>How do you guy do this? I mean, TOF is a matrix 8x8, using 2x2 square so it must need 16 squares. Or if you do with stride=2?</p>",
      "votes": 3,
      "replies": []
    },
    {
      "id": 3287738,
      "author_name": "Fae Gaze",
      "author_url": "",
      "post_date": "2025-09-12T06:24:00.133000",
      "content": "<p>Congrats on the 1st place!  Really impressive ensemble design and feature engineering across IMU, TOF, and THM.</p>\n<p>I had a question regarding CV and data imbalance: since some classes/orientations are underrepresented, did you find that group K-fold by subject was sufficient, or did you try any balancing strategies to make sure rare cases were well-covered during validation?</p>",
      "votes": 1,
      "replies": [
        {
          "id": 3287751,
          "author_name": "Ogurtsov",
          "author_url": "",
          "post_date": "2025-09-12T07:15:39.703000",
          "content": "<p>I used K-fold by subject from the very beginning and didn't try anything else.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3280951,
      "author_name": "Theo Viel",
      "author_url": "",
      "post_date": "2025-09-03T11:33:36.080000",
      "content": "<p>Congratz !</p>\n<p>I have some questions :)</p>\n<ul>\n<li>How does your ensemble perform without PP ?</li>\n<li>How did you implement PP ? Using optimization heuristics / using a transformer model ?</li>\n</ul>",
      "votes": 1,
      "replies": [
        {
          "id": 3280962,
          "author_name": "",
          "author_url": "",
          "post_date": "2025-09-03T11:38:21.260000",
          "content": "",
          "votes": 1,
          "replies": []
        },
        {
          "id": 3280977,
          "author_name": "Ogurtsov",
          "author_url": "",
          "post_date": "2025-09-03T11:42:16.810000",
          "content": "<p>Thanks! Exact pure score without post-processing for best submit is unknown, we literally had no submits left to check. Our sub-ensembles at the team merging moment scored like 0.873-0.874 (public scores) and were significantly improved further. We used optimization heuristics, targets/positions distribution information was explicitly available only for small fraction of base models (72-classes).</p>",
          "votes": 1,
          "replies": [
            {
              "id": 3280982,
              "author_name": "Theo Viel",
              "author_url": "",
              "post_date": "2025-09-03T11:45:44.377000",
              "content": "<p>Thanks for the quick replies.<br>\nLooks like we have comparable ensembles without PP but your PP is stronger !</p>",
              "votes": 1,
              "replies": []
            }
          ]
        }
      ]
    },
    {
      "id": 3281291,
      "author_name": "Kurise",
      "author_url": "",
      "post_date": "2025-09-04T02:29:51.810000",
      "content": "<p>Congratulations! I have a question about your scales. I also train on no scales data which is better for my model but the scaler data is also better for my inference. I don't know why it will work.</p>",
      "votes": 2,
      "replies": [
        {
          "id": 3281315,
          "author_name": "yuanzhe zhou",
          "author_url": "",
          "post_date": "2025-09-04T03:37:20.263000",
          "content": "<p>It is more about the initialization of the neural network, which is more related to lucky seed. The scale of the provided data is already very good, just divide by 10 is enough.</p>",
          "votes": 1,
          "replies": [
            {
              "id": 3281321,
              "author_name": "Sangram Patil",
              "author_url": "",
              "post_date": "2025-09-04T03:47:11.770000",
              "content": "<pre><code>which  more related to lucky seed.\n</code></pre>\n<p><a href=\"https://www.kaggle.com/yuanzhezhou\" target=\"_blank\">@yuanzhezhou</a> may i ask which seed value or values do you use in traning  ?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 3281330,
              "author_name": "yuanzhe zhou",
              "author_url": "",
              "post_date": "2025-09-04T04:23:54.630000",
              "content": "<p>I did not change the seed use by the public notebook, which is 42. it is important not to tune seed for better score</p>",
              "votes": 2,
              "replies": []
            }
          ]
        },
        {
          "id": 3281353,
          "author_name": "Ogurtsov",
          "author_url": "",
          "post_date": "2025-09-04T05:56:27.460000",
          "content": "<p>Scaled data on train + not scaled on inference could work only if scaling changes data to a very small extent.</p>",
          "votes": 2,
          "replies": []
        }
      ]
    },
    {
      "id": 3280988,
      "author_name": "moth",
      "author_url": "",
      "post_date": "2025-09-03T12:01:00.963000",
      "content": "<p>Congratulations! I am glad my augmentations worked for you. For me the one that worked the best (besides mixup) was adding random peaks or valleys. This is similar to masking. Another good one is channel dropout :)</p>",
      "votes": 2,
      "replies": [
        {
          "id": 3280994,
          "author_name": "Ogurtsov",
          "author_url": "",
          "post_date": "2025-09-03T12:10:29.173000",
          "content": "<p>Thanks! Your aug notebook helped me make progress when I got stuck at some moment.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3281833,
      "author_name": "MYSO",
      "author_url": "",
      "post_date": "2025-09-05T03:47:15.280000",
      "content": "<p>Congrats! Do you mean bugs in my code? If so, could you share what you fixed?</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3281842,
          "author_name": "yuanzhe zhou",
          "author_url": "",
          "post_date": "2025-09-05T04:21:00.827000",
          "content": "<p>Hello, it is a good notebook. It was the only pytorch notebook that could train&amp;submit to get good score at that time. The problem is that, many details are limitting further development. For example, ema is never used for validation, Scaler should not use global statistics, etc.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 3281603,
      "author_name": "Ricardo Pirabed A.A.",
      "author_url": "",
      "post_date": "2025-09-04T14:53:55.727000",
      "content": "<p>Wow! Congratulations ! that’s great work. It was clear from the beginning that feature engineering would have a significant impact, the dataset has many faces 😅<br>\n<strong>One question</strong>: What was the level of scores for your GRU model ?</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3280926,
      "author_name": "",
      "author_url": "",
      "post_date": "2025-09-03T11:18:15.053000",
      "content": "",
      "votes": 0,
      "replies": []
    },
    {
      "id": 3286789,
      "author_name": "Joseph Ekpe",
      "author_url": "",
      "post_date": "2025-09-10T12:08:00.923000",
      "content": "<p>Congratulations</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3280919": "**Links to code:**\n- [Training code on github](https://github.com/statist-bhfz/kaggle_cmi_1st_place_solution)\n- [Inference notebook](https://www.kaggle.com/code/yuanzhezhou/final-sub-cmi3)\n\n## Solution Writeup\n\nCongratulations to all the winners and a big respect to the organizers for putting together such a challenging and rewarding competition. \nSpecial thanks to my teammates [yuanzhe zhou](https://www.kaggle.com/yuanzhezhou) and [Devin Anzelmo](https://www.kaggle.com/devinanzelmo) for the great collaboration and team spirit.\n\n## Solution Overview\n\n-   Large ensembles for IMU-only and all-features samples, assembled as weighted sum of logits\n\n-   Post-processing to take into account limited number of samples with each class and with each orientation per subject (already described [here](https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603544))\n\n-   Additional models for orientation prediction\n\n------------------------------------------------------------------------\n\n## Devin's part\n\n**1. Preprocessing/feature engineering:**\n\n- Removed subjects who wore device incorrectly from both training and validation\n\n- For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)\n\n- Some models trained with temporal difference of above TOF features and thermal\n\n- IMU: raw 7 + temporal diff of `acc`, rotational diff as posted in notebooks, as well as magnitude of `acc`/`rot`; 16 total\n\n- preprocess left handed to match right handed for IMU and THM/TOF. Flip `acc_x`, convert `rot` to xyz euler and flip sign for y and z\n\n- robust scaler \n\n**2. Augmentation:**\n\n- up scaling/down scaling all features \n\n- random noise \n\n**3. Models:**\n\n- CNN GRU with different stems for different features. Feature extractor is four branches of CNN with no pooling\n\n- Pure CNN. Same feature extractor as above but three blocks of residual at end with expanding kernal (5, 9, 13)\n\n- dense GRU, scores lower but helps a little in ensemble\n\n- some self excitation models, some not combining helps\n\n- 3D CNN for TOF data scores about 0.83 but blends well\n\n**4. Training:**\n\n- batch size 64\n\n- train for 60-80 (depending on model) iters with AdamW `lr = 0.0005`\n\n**5. Ensemble:**\n\n- blend IMU models with all-features models \n\n- blend TOF-only model improves all data score\n\n------------------------------------------------------------------------\n\n## Ogurtsov's part\n\n**1. Filtering data:**\t\n\t\n- [all models] remove sequence SEQ_011975 without gesture\t\n\t\n- [all models] remove sequences with gesture/total ratio < 0.2 (this subset includes almost all shortest sequences)\t\n\t\n- [models with THM and TOF data] remove sequences with TOF completely missing\t(missing values patterns in TOF - 0%, 20% or 100%; 20% missing is ok)\t\n\n- few models were trained without \"problematic\" subjects SUBJ_045235 and SUBJ_019262\n\t\n**2. Preprocessing:**\n\t\n- fill quaternion missing values, if possible\t\n\t\n- mirror data for left-handed subjects \n\n- replace -1 TOF values with 500 because -1 encodes large distance\t\n\t\n- ultimate filling NaNs with `seq.ffill().bfill().fillna(0)`\n\t\n- pad/crop by 94 percentile in each fold (~120 max seq length)\t\n\t\n- no scalers - it gave the largest improvement at early stage\t\n\t\n**3. Feature engineering:**\t\n\t\n- nothing for THM and TOF\t\n\t\n- 35 IMU features:\t\n```\n['acc_x', 'acc_y', 'acc_z', 'acc_mag', 'acc_mag_jerk', 'jerk_x', 'jerk_y', 'jerk_z', 'jerk_magnitude', 'acc_xy_corr', 'acc_xz_corr', 'acc_yz_corr',\t\nrot_w', 'rot_x', 'rot_y', 'rot_z', 'rot_angle', 'rot_angle_vel', 'angular_vel_x', 'angular_vel_y', 'angular_vel_z', 'angular_vel_magnitude', 'angular_distance',\t\nacc_x2', 'acc_y2', 'acc_z2', 'acc_mag2', 'acc_mag_jerk2', 'jerk_x2', 'jerk_y2', 'jerk_z2', 'jerk_magnitude2', 'acc_xy_corr2', 'acc_xz_corr2', 'acc_yz_corr2']\n```\n\n`acc_x2` and other `***2` features are important part of the solution. \nThese features are calculated on values transformed by `remove_gravity_from_acc()`.\t\n\t\n**4. Models:**\t\n\t\n- bunch of models with different architectures for training on IMU-only data and similar models for training with all features\t\n\t\n- main differences in time dimension processing: LSTM-, attention- or CNN-based\t\n\t\n- key part - independent processing groups of features at first layers\t\n\t\n**5. Augmentations:**\t\n\t\n- mixup with `MIXUP_ALPHA = 0.4`\n\t\n- augmentation from [CMI | Sequence Data Augmentation](https://www.kaggle.com/code/alejopaullier/cmi-sequence-data-augmentation) (thanks [moth](https://www.kaggle.com/alejopaullier)):\t\n```\ntransforms = Compose([\t\n    TimeShift(p = 0.35, padding_mode = \"zero\", max_shift_pct = 0.25),\t\n    TimeStretch(p = 0.35, max_rate = 1.5, min_rate = 0.5),\t\n])\n```\nwith some variations.\n\nIt was hard to pick up right augmetations with right probability & strength and apply it in the correct order.\t\n\t\n**6. Training:**\t\n\t\n- CV5 with group by subject K-fold, 5 models are used on inference\t\n\t\n- 200 or 220 epochs, patience 30 or 35\t\n\t\n- `torch.optim.Adam` with `lr = 4e-4` or `lr = 5e-4` and `weight_decay = 3e-4`\t\n\t\n- `CosineAnnealingWarmRestarts`; `LinearLR` + `CosineAnnealingWarmRestarts` for attention-based models\t\n\t\n- one model was trained with focal loss and class weights\t(class weights obviously mean nothing for mixup samples, maybe it can serve as regularization)\t\n\n- one model contains bug in cross-attention (shared weights for 3 different attentions) but works pretty well\n\n**7. Some tricks:**\t\n\t\n- pick best result for each fold among 3 runs\n\n- increase sequence length by 5 on inference (it doesn't improve CV score but effectively decorrelates models)\n\n------------------------------------------------------------------------\n\n## zyz's part\n\n1.1. Using the pipeline structure from [CMI3 Pyroch Baseline+model_add, Aug, folds](https://www.kaggle.com/code/myso1987/cmi3-pyroch-baseline-model-add-aug-folds?scriptVersionId=248310337)\n\n1.2. Fixing many bugs improved my score to 0.85.\n\n2. Models: simple combinations of RNN and CNN1D.\n\n3. Feature engineering using pytorch, which avoids problem of consistency but makes the training slower.\n\n4. Basic preprocessing mentioned by most teams: fillnan, handedness, etc.\n\n5. Post-processing based on data structure.\n\n6. Augmentation idea from teammates:\n\n6.1. Mask data during training helps.\n\n",
    "3281797": "Congratulations! I have some question about Devin's part's Preprocessing.\n> Removed subjects who wore device incorrectly from both training and validation\n\nHow do you know that subjects wore device incorrectly?\n> For TOF subsample by taking nine 2x2 squares and calculating mean for each (turn -1 to null first)\n\nHow do you guy do this? I mean, TOF is a matrix 8x8, using 2x2 square so it must need 16 squares. Or if you do with stride=2?",
    "3287738": "Congrats on the 1st place!  Really impressive ensemble design and feature engineering across IMU, TOF, and THM.\n\nI had a question regarding CV and data imbalance: since some classes/orientations are underrepresented, did you find that group K-fold by subject was sufficient, or did you try any balancing strategies to make sure rare cases were well-covered during validation?",
    "3280951": "Congratz !\n\nI have some questions :)\n- How does your ensemble perform without PP ?\n- How did you implement PP ? Using optimization heuristics / using a transformer model ?",
    "3281291": "Congratulations! I have a question about your scales. I also train on no scales data which is better for my model but the scaler data is also better for my inference. I don't know why it will work.",
    "3280988": "Congratulations! I am glad my augmentations worked for you. For me the one that worked the best (besides mixup) was adding random peaks or valleys. This is similar to masking. Another good one is channel dropout :)",
    "3281833": "Congrats! Do you mean bugs in my code? If so, could you share what you fixed?",
    "3281603": "Wow! Congratulations ! that’s great work. It was clear from the beginning that feature engineering would have a significant impact, the dataset has many faces 😅\n**One question**: What was the level of scores for your GRU model ?",
    "3280926": "",
    "3286789": "Congratulations"
  },
  "complete": true,
  "source": "existing_discussion",
  "competition_id": 102335,
  "competition_slug": "cmi-detect-behavior-with-sensor-data",
  "team_id": 13896582,
  "solution_url": "/competitions/cmi-detect-behavior-with-sensor-data/writeups/cmi-1st-place-solution"
}