{
  "id": 604095,
  "title": "42th Solution (Late sub private=0.854)",
  "url": "/competitions/cmi-detect-behavior-with-sensor-data/discussion/604095",
  "author_name": "Bilzard",
  "post_date": "2025-09-06T06:33:08.911000",
  "votes": 14,
  "comment_count": 0,
  "views": 0,
  "content": "<h2>TL; DR</h2>\n<ul>\n<li>Converted left-handed sensor data into pseudo right-handed data, which (I believe) result in not shaken much in Private LB</li>\n<li>Triple tower model which consists of IMU/ToF/IMU+ToF branch</li>\n<li>Multi modal training is slightly stable: gesture, orientation, target-type, behavior</li>\n<li>Key factor: splitting temporal attention module per each target is key (I hypothesize that different time frames are important for each targets)</li>\n</ul>\n<h2>Architecture</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F65699b02b3a1b53465eb6d073a72ee0c%2Farchitecture.png?generation=1757138427893997&amp;alt=media\" alt=\"\"></p>\n<ul>\n<li>earlier model has squeezeformer blocks before temporal attention modules, but later these blocks are discard because only using several layers of temporal attention module performs equivalently.</li>\n<li>developed architecture which replaced temporal attention module with CrossAttention, BERT, LSTM. Among these, BERT is the best, but LSTM model seems to play better orthogonality in ensemble</li>\n</ul>\n<h2>Result</h2>\n<h3>Single Architecture (5-fold)</h3>\n<table>\n<thead>\n<tr>\n<th>model_id</th>\n<th>model</th>\n<th>#models</th>\n<th>augmentation</th>\n<th>ensemble_method</th>\n<th>flip correction</th>\n<th>CV (IMU-only, Full)</th>\n<th>Public LB</th>\n<th>Private LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256</td>\n<td>5</td>\n<td>heavy12</td>\n<td>prob</td>\n<td>-</td>\n<td>0.825 (0.787, 0.863)</td>\n<td>-</td>\n<td>-</td>\n</tr>\n<tr>\n<td>2</td>\n<td>d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256</td>\n<td>5</td>\n<td>heavy13</td>\n<td>prob</td>\n<td>-</td>\n<td>0.839 (0.811, 0.867)</td>\n<td>0.842</td>\n<td>0.832</td>\n</tr>\n<tr>\n<td>3</td>\n<td>d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128</td>\n<td>5</td>\n<td>heavy14</td>\n<td>prob</td>\n<td>-</td>\n<td>0.843 (0.809, 0.878)</td>\n<td>0.845</td>\n<td>0.840</td>\n</tr>\n<tr>\n<td>3</td>\n<td>d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128</td>\n<td>5</td>\n<td>heavy14</td>\n<td>prob</td>\n<td>✅</td>\n<td>0.843 (0.809, 0.878)</td>\n<td>0.845</td>\n<td>0.846</td>\n</tr>\n<tr>\n<td>4</td>\n<td>d09_bilstm_isolated_ncl_full_b1</td>\n<td>5</td>\n<td>heavy15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.845 (0.814, 0.875)</td>\n<td>0.841</td>\n<td>0.832</td>\n</tr>\n<tr>\n<td>5</td>\n<td>d09_3b_bert_null_emb_isolated_ncl_full_b12</td>\n<td>5</td>\n<td>heavy15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.849 (0.812, 0.885)</td>\n<td>0.838</td>\n<td>0.833</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li><code>l{n}_b{m}</code> means, n-layer of squeezeformer and m-layer of temporal attention module</li>\n</ul>\n<h3>Ensemble</h3>\n<table>\n<thead>\n<tr>\n<th>ensemble_id</th>\n<th>model</th>\n<th>#models</th>\n<th>ensemble method</th>\n<th>flip-correction</th>\n<th>CV (IMU-only, Full)</th>\n<th>Public LB</th>\n<th>Private LB</th>\n<th>Note</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>top3</td>\n<td>ensemble {3,4,5}</td>\n<td>15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.858 (0.826, 0.890)</td>\n<td>0.853</td>\n<td>0.841</td>\n<td>Final Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>prob</td>\n<td>-</td>\n<td>0.861 (0.83, 0.892)</td>\n<td>0.853</td>\n<td>0.843</td>\n<td>Final Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>rank</td>\n<td>-</td>\n<td>0.859 (0.828, 0.89)</td>\n<td>0.852</td>\n<td>0.844</td>\n<td>Late Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>prob</td>\n<td>✅</td>\n<td>0.861 (0.83, 0.892)</td>\n<td>0.853</td>\n<td><strong>0.854</strong></td>\n<td>Late Sub</td>\n</tr>\n</tbody>\n</table>\n<h2>Convert left-handed sensor data into pseudo right-handed sensor data</h2>\n<ul>\n<li>converted left-handed data into \"mimic\" right-handed data.</li>\n<li>I didn't tested on LB, but always perform better than raw data in CV</li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2Fc3ea9e4dcfb9c083bcf027e13ff761b6%2Finbox_4910466_3382172f16fce862379f2c186497702e_invariant_transform_ToF.png?generation=1757139431917144&amp;alt=media\" alt=\"\"></p>\n<p>Concept and hand-written note is already shared with:<br>\n<a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566\" target=\"_blank\">https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566</a></p>\n<p>Almost the same approach that Jack's does, so details are omitted here.<br>\n<a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution\" target=\"_blank\">https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution</a></p>\n<h2>Data Correction of Flipped Subject in Train set</h2>\n<p>Same as above.</p>\n<h2>Data Correction of Flipped Subject in Private Test set [Late Submission]</h2>\n<ul>\n<li>automatically generate flipped data by applying inverse transform of Flipped subject with p=0.066</li>\n<li>train classifier 100 epochs with the similar architecture of gesture classification model</li>\n</ul>\n<p><strong>Result</strong></p>\n<ul>\n<li>precision: 0.996</li>\n<li>recall:  0.980</li>\n</ul>\n<p>Data correction if prob &gt; 0.5 -&gt; Private LB is improved by +0.01 (0.844 -&gt; 0.854), which is significant impact.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F80f7ac3a2e2d0b7f0baf1ab82b63600b%2FScreenshot%202025-09-06%20at%2015.21.42.png?generation=1757139722173647&amp;alt=media\" alt=\"\"></p>\n<h2>Other Training Details</h2>\n<ul>\n<li>cosine schedule which restarts <strong>every epoch</strong> -&gt; slightly stable compared to one-cycle cosine schedule <ul>\n<li>Note that this schedule is considered as kind of \"schedule-less\" training where we can restart training at any epochs if checkpoints are available</li></ul></li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F672df8deec00b965ee38cbf7ab822c4d%2FScreenshot%202025-09-06%20at%2015.22.43.png?generation=1757139784959096&amp;alt=media\" alt=\"\"></p>\n<ul>\n<li>Data Augmentation<ul>\n<li>replace non-gesture frames sampled with different sequence with the same orientation/gesture -&gt; CV is slightly improved</li>\n<li>resampling only on gesture frame</li>\n<li>Rotate around Z axis (-90, 90)</li>\n<li>other augmentations stabilize training, but minor improve on CV</li></ul></li>\n</ul>\n<pre><code>    : Compose(\n        \n        RandomCropOnlyGesture(max_crop_ratio=, min_gesture_length=, p=),\n        Choice(\n            RandomResampleOnlyGestureV2(resample_rate_range=(, ), p=),\n            RandomResampleOnlyGestureV2(resample_rate_range=(, ), p=),\n            ResampleOnlyGesture(sample_rate=(, ), p=),\n            p=,\n        ),\n        \n        Compose(\n            RandomRotateZ(angle_range=, p=),\n            RandomEulerRotation(\n                angle_range=,\n                transform_features=(,),\n                p=,\n            ),\n            Choice(\n                RandomEye([]),\n                RandomZeroOut([]),\n                p=,\n            ),\n        ),\n        \n        Compose(\n            RandomAffine(\n                keys=(,),\n                translate_range=(-, ),\n                rotation_range=(-, ),\n                scale_range=(, ),\n                p=,\n            ),\n            RandomAdditiveNoise(key=, shift=, scale=, p=),\n            RandomAdditiveNoise(key=, shift=, scale=, p=),\n            SensorChannelDropout(key=, drop_prob=, p=),\n            SensorChannelDropout(key=, drop_prob=, p=),\n            Choice(\n                RandomZeroOut([]),\n                RandomZeroOut([]),\n                p=,\n            ),\n        ),\n        Choice(\n            \n            RandomZeroOut([, ], p=),\n            Compose(RandomEye([]), RandomZeroOut([]), p=),\n            Identity(p=),\n        ),\n    ),\n</code></pre>\n<h2>Rererence</h2>\n<ul>\n<li>[Ensemble Top4 - Private=0.854] <a href=\"https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735\" target=\"_blank\">https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735</a></li>\n</ul>",
  "messages": [
    {
      "id": 3282342,
      "postDate": "2025-09-06T06:33:08.913Z",
      "content": "<h2>TL; DR</h2>\n<ul>\n<li>Converted left-handed sensor data into pseudo right-handed data, which (I believe) result in not shaken much in Private LB</li>\n<li>Triple tower model which consists of IMU/ToF/IMU+ToF branch</li>\n<li>Multi modal training is slightly stable: gesture, orientation, target-type, behavior</li>\n<li>Key factor: splitting temporal attention module per each target is key (I hypothesize that different time frames are important for each targets)</li>\n</ul>\n<h2>Architecture</h2>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F65699b02b3a1b53465eb6d073a72ee0c%2Farchitecture.png?generation=1757138427893997&amp;alt=media\" alt=\"\"></p>\n<ul>\n<li>earlier model has squeezeformer blocks before temporal attention modules, but later these blocks are discard because only using several layers of temporal attention module performs equivalently.</li>\n<li>developed architecture which replaced temporal attention module with CrossAttention, BERT, LSTM. Among these, BERT is the best, but LSTM model seems to play better orthogonality in ensemble</li>\n</ul>\n<h2>Result</h2>\n<h3>Single Architecture (5-fold)</h3>\n<table>\n<thead>\n<tr>\n<th>model_id</th>\n<th>model</th>\n<th>#models</th>\n<th>augmentation</th>\n<th>ensemble_method</th>\n<th>flip correction</th>\n<th>CV (IMU-only, Full)</th>\n<th>Public LB</th>\n<th>Private LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256</td>\n<td>5</td>\n<td>heavy12</td>\n<td>prob</td>\n<td>-</td>\n<td>0.825 (0.787, 0.863)</td>\n<td>-</td>\n<td>-</td>\n</tr>\n<tr>\n<td>2</td>\n<td>d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256</td>\n<td>5</td>\n<td>heavy13</td>\n<td>prob</td>\n<td>-</td>\n<td>0.839 (0.811, 0.867)</td>\n<td>0.842</td>\n<td>0.832</td>\n</tr>\n<tr>\n<td>3</td>\n<td>d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128</td>\n<td>5</td>\n<td>heavy14</td>\n<td>prob</td>\n<td>-</td>\n<td>0.843 (0.809, 0.878)</td>\n<td>0.845</td>\n<td>0.840</td>\n</tr>\n<tr>\n<td>3</td>\n<td>d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128</td>\n<td>5</td>\n<td>heavy14</td>\n<td>prob</td>\n<td>✅</td>\n<td>0.843 (0.809, 0.878)</td>\n<td>0.845</td>\n<td>0.846</td>\n</tr>\n<tr>\n<td>4</td>\n<td>d09_bilstm_isolated_ncl_full_b1</td>\n<td>5</td>\n<td>heavy15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.845 (0.814, 0.875)</td>\n<td>0.841</td>\n<td>0.832</td>\n</tr>\n<tr>\n<td>5</td>\n<td>d09_3b_bert_null_emb_isolated_ncl_full_b12</td>\n<td>5</td>\n<td>heavy15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.849 (0.812, 0.885)</td>\n<td>0.838</td>\n<td>0.833</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li><code>l{n}_b{m}</code> means, n-layer of squeezeformer and m-layer of temporal attention module</li>\n</ul>\n<h3>Ensemble</h3>\n<table>\n<thead>\n<tr>\n<th>ensemble_id</th>\n<th>model</th>\n<th>#models</th>\n<th>ensemble method</th>\n<th>flip-correction</th>\n<th>CV (IMU-only, Full)</th>\n<th>Public LB</th>\n<th>Private LB</th>\n<th>Note</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>top3</td>\n<td>ensemble {3,4,5}</td>\n<td>15</td>\n<td>prob</td>\n<td>-</td>\n<td>0.858 (0.826, 0.890)</td>\n<td>0.853</td>\n<td>0.841</td>\n<td>Final Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>prob</td>\n<td>-</td>\n<td>0.861 (0.83, 0.892)</td>\n<td>0.853</td>\n<td>0.843</td>\n<td>Final Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>rank</td>\n<td>-</td>\n<td>0.859 (0.828, 0.89)</td>\n<td>0.852</td>\n<td>0.844</td>\n<td>Late Sub</td>\n</tr>\n<tr>\n<td>top4</td>\n<td>ensemble {2,3,4,5}</td>\n<td>20</td>\n<td>prob</td>\n<td>✅</td>\n<td>0.861 (0.83, 0.892)</td>\n<td>0.853</td>\n<td><strong>0.854</strong></td>\n<td>Late Sub</td>\n</tr>\n</tbody>\n</table>\n<h2>Convert left-handed sensor data into pseudo right-handed sensor data</h2>\n<ul>\n<li>converted left-handed data into \"mimic\" right-handed data.</li>\n<li>I didn't tested on LB, but always perform better than raw data in CV</li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2Fc3ea9e4dcfb9c083bcf027e13ff761b6%2Finbox_4910466_3382172f16fce862379f2c186497702e_invariant_transform_ToF.png?generation=1757139431917144&amp;alt=media\" alt=\"\"></p>\n<p>Concept and hand-written note is already shared with:<br>\n<a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566\" target=\"_blank\">https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566</a></p>\n<p>Almost the same approach that Jack's does, so details are omitted here.<br>\n<a href=\"https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution\" target=\"_blank\">https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution</a></p>\n<h2>Data Correction of Flipped Subject in Train set</h2>\n<p>Same as above.</p>\n<h2>Data Correction of Flipped Subject in Private Test set [Late Submission]</h2>\n<ul>\n<li>automatically generate flipped data by applying inverse transform of Flipped subject with p=0.066</li>\n<li>train classifier 100 epochs with the similar architecture of gesture classification model</li>\n</ul>\n<p><strong>Result</strong></p>\n<ul>\n<li>precision: 0.996</li>\n<li>recall:  0.980</li>\n</ul>\n<p>Data correction if prob &gt; 0.5 -&gt; Private LB is improved by +0.01 (0.844 -&gt; 0.854), which is significant impact.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F80f7ac3a2e2d0b7f0baf1ab82b63600b%2FScreenshot%202025-09-06%20at%2015.21.42.png?generation=1757139722173647&amp;alt=media\" alt=\"\"></p>\n<h2>Other Training Details</h2>\n<ul>\n<li>cosine schedule which restarts <strong>every epoch</strong> -&gt; slightly stable compared to one-cycle cosine schedule <ul>\n<li>Note that this schedule is considered as kind of \"schedule-less\" training where we can restart training at any epochs if checkpoints are available</li></ul></li>\n</ul>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F672df8deec00b965ee38cbf7ab822c4d%2FScreenshot%202025-09-06%20at%2015.22.43.png?generation=1757139784959096&amp;alt=media\" alt=\"\"></p>\n<ul>\n<li>Data Augmentation<ul>\n<li>replace non-gesture frames sampled with different sequence with the same orientation/gesture -&gt; CV is slightly improved</li>\n<li>resampling only on gesture frame</li>\n<li>Rotate around Z axis (-90, 90)</li>\n<li>other augmentations stabilize training, but minor improve on CV</li></ul></li>\n</ul>\n<pre><code>    : Compose(\n        \n        RandomCropOnlyGesture(max_crop_ratio=, min_gesture_length=, p=),\n        Choice(\n            RandomResampleOnlyGestureV2(resample_rate_range=(, ), p=),\n            RandomResampleOnlyGestureV2(resample_rate_range=(, ), p=),\n            ResampleOnlyGesture(sample_rate=(, ), p=),\n            p=,\n        ),\n        \n        Compose(\n            RandomRotateZ(angle_range=, p=),\n            RandomEulerRotation(\n                angle_range=,\n                transform_features=(,),\n                p=,\n            ),\n            Choice(\n                RandomEye([]),\n                RandomZeroOut([]),\n                p=,\n            ),\n        ),\n        \n        Compose(\n            RandomAffine(\n                keys=(,),\n                translate_range=(-, ),\n                rotation_range=(-, ),\n                scale_range=(, ),\n                p=,\n            ),\n            RandomAdditiveNoise(key=, shift=, scale=, p=),\n            RandomAdditiveNoise(key=, shift=, scale=, p=),\n            SensorChannelDropout(key=, drop_prob=, p=),\n            SensorChannelDropout(key=, drop_prob=, p=),\n            Choice(\n                RandomZeroOut([]),\n                RandomZeroOut([]),\n                p=,\n            ),\n        ),\n        Choice(\n            \n            RandomZeroOut([, ], p=),\n            Compose(RandomEye([]), RandomZeroOut([]), p=),\n            Identity(p=),\n        ),\n    ),\n</code></pre>\n<h2>Rererence</h2>\n<ul>\n<li>[Ensemble Top4 - Private=0.854] <a href=\"https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735\" target=\"_blank\">https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735</a></li>\n</ul>",
      "rawMarkdown": "## TL; DR\n\n- Converted left-handed sensor data into pseudo right-handed data, which (I believe) result in not shaken much in Private LB\n- Triple tower model which consists of IMU/ToF/IMU+ToF branch\n- Multi modal training is slightly stable: gesture, orientation, target-type, behavior\n- Key factor: splitting temporal attention module per each target is key (I hypothesize that different time frames are important for each targets)\n\n## Architecture\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F65699b02b3a1b53465eb6d073a72ee0c%2Farchitecture.png?generation=1757138427893997&alt=media)\n\n- earlier model has squeezeformer blocks before temporal attention modules, but later these blocks are discard because only using several layers of temporal attention module performs equivalently.\n- developed architecture which replaced temporal attention module with CrossAttention, BERT, LSTM. Among these, BERT is the best, but LSTM model seems to play better orthogonality in ensemble\n\n## Result\n\n### Single Architecture (5-fold)\n\n|model_id|model|#models|augmentation|ensemble_method|flip correction|CV (IMU-only, Full)|Public LB|Private LB|\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n|1|d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256|5|heavy12|prob|-|0.825 (0.787, 0.863)|-|-|\n|2|d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256|5|heavy13|prob|-|0.839 (0.811, 0.867)|0.842|0.832|\n|3|d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128|5|heavy14|prob|-|0.843 (0.809, 0.878)|0.845|0.840|\n|3|d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128|5|heavy14|prob|✅|0.843 (0.809, 0.878)|0.845|0.846|\n|4|d09_bilstm_isolated_ncl_full_b1|5|heavy15|prob|-|0.845 (0.814, 0.875)|0.841|0.832|\n|5|d09_3b_bert_null_emb_isolated_ncl_full_b12|5|heavy15|prob|-|0.849 (0.812, 0.885)|0.838|0.833|\n\n- `l{n}_b{m}` means, n-layer of squeezeformer and m-layer of temporal attention module\n\n### Ensemble\n\nensemble_id|model|#models|ensemble method|flip-correction|CV (IMU-only, Full)|Public LB|Private LB|Note\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\ntop3|ensemble {3,4,5}|15|prob|-|0.858 (0.826, 0.890)|0.853|0.841|Final Sub\ntop4|ensemble {2,3,4,5}|20|prob|-|0.861 (0.83, 0.892)|0.853|0.843|Final Sub\ntop4|ensemble {2,3,4,5}|20|rank|-|0.859 (0.828, 0.89)|0.852|0.844|Late Sub\ntop4|ensemble {2,3,4,5}|20|prob|✅|0.861 (0.83, 0.892)|0.853|**0.854**|Late Sub\n\n## Convert left-handed sensor data into pseudo right-handed sensor data\n\n- converted left-handed data into \"mimic\" right-handed data.\n- I didn't tested on LB, but always perform better than raw data in CV\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2Fc3ea9e4dcfb9c083bcf027e13ff761b6%2Finbox_4910466_3382172f16fce862379f2c186497702e_invariant_transform_ToF.png?generation=1757139431917144&alt=media)\n\nConcept and hand-written note is already shared with:\nhttps://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566\n\nAlmost the same approach that Jack's does, so details are omitted here.\nhttps://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution\n\n## Data Correction of Flipped Subject in Train set\n\nSame as above.\n\n## Data Correction of Flipped Subject in Private Test set [Late Submission]\n\n- automatically generate flipped data by applying inverse transform of Flipped subject with p=0.066\n- train classifier 100 epochs with the similar architecture of gesture classification model\n\n**Result**\n\n- precision: 0.996\n- recall:  0.980\n\nData correction if prob > 0.5 -> Private LB is improved by +0.01 (0.844 -> 0.854), which is significant impact.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F80f7ac3a2e2d0b7f0baf1ab82b63600b%2FScreenshot%202025-09-06%20at%2015.21.42.png?generation=1757139722173647&alt=media)\n\n## Other Training Details\n\n- cosine schedule which restarts **every epoch** -> slightly stable compared to one-cycle cosine schedule \n    - Note that this schedule is considered as kind of \"schedule-less\" training where we can restart training at any epochs if checkpoints are available\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F672df8deec00b965ee38cbf7ab822c4d%2FScreenshot%202025-09-06%20at%2015.22.43.png?generation=1757139784959096&alt=media)\n\n- Data Augmentation\n   - replace non-gesture frames sampled with different sequence with the same orientation/gesture -> CV is slightly improved\n   - resampling only on gesture frame\n   - Rotate around Z axis (-90, 90)\n   - other augmentations stabilize training, but minor improve on CV\n\n```python\n    \"heavy15\": Compose(\n        # Resample All Series\n        RandomCropOnlyGesture(max_crop_ratio=0.5, min_gesture_length=10, p=1.0),\n        Choice(\n            RandomResampleOnlyGestureV2(resample_rate_range=(1.0, 2.0), p=0.4),\n            RandomResampleOnlyGestureV2(resample_rate_range=(0.5, 1.0), p=0.2),\n            ResampleOnlyGesture(sample_rate=(1.0, 1.2), p=0.2),\n            p=0.8,\n        ),\n        # IMU Transformations\n        Compose(\n            RandomRotateZ(angle_range=90, p=1.0),\n            RandomEulerRotation(\n                angle_range=20,\n                transform_features=(\"acc\",),\n                p=1.0,\n            ),\n            Choice(\n                RandomEye([\"sensor_basis_world\"]),\n                RandomZeroOut([\"acc\"]),\n                p=0.15,\n            ),\n        ),\n        # ToF/Thermo Transformations\n        Compose(\n            RandomAffine(\n                keys=(\"tof\",),\n                translate_range=(-1, 1),\n                rotation_range=(-15, 15),\n                scale_range=(0.9, 1.1),\n                p=0.3,\n            ),\n            RandomAdditiveNoise(key=\"thermo\", shift=1.0, scale=0.3, p=0.3),\n            RandomAdditiveNoise(key=\"tof\", shift=5.0, scale=10.0, p=0.3),\n            SensorChannelDropout(key=\"tof\", drop_prob=0.5, p=0.5),\n            SensorChannelDropout(key=\"thermo\", drop_prob=0.5, p=0.5),\n            Choice(\n                RandomZeroOut([\"thermo\"]),\n                RandomZeroOut([\"tof\"]),\n                p=0.25,\n            ),\n        ),\n        Choice(\n            # Completely Drop ToF/Thermo or IMU data\n            RandomZeroOut([\"tof\", \"thermo\"], p=0.7),\n            Compose(RandomEye([\"sensor_basis_world\"]), RandomZeroOut([\"acc\"]), p=0.05),\n            Identity(p=0.25),\n        ),\n    ),\n```\n\n## Rererence\n\n- [Ensemble Top4 - Private=0.854] https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735",
      "votes": 14
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "3282342": "## TL; DR\n\n- Converted left-handed sensor data into pseudo right-handed data, which (I believe) result in not shaken much in Private LB\n- Triple tower model which consists of IMU/ToF/IMU+ToF branch\n- Multi modal training is slightly stable: gesture, orientation, target-type, behavior\n- Key factor: splitting temporal attention module per each target is key (I hypothesize that different time frames are important for each targets)\n\n## Architecture\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F65699b02b3a1b53465eb6d073a72ee0c%2Farchitecture.png?generation=1757138427893997&alt=media)\n\n- earlier model has squeezeformer blocks before temporal attention modules, but later these blocks are discard because only using several layers of temporal attention module performs equivalently.\n- developed architecture which replaced temporal attention module with CrossAttention, BERT, LSTM. Among these, BERT is the best, but LSTM model seems to play better orthogonality in ensemble\n\n## Result\n\n### Single Architecture (5-fold)\n\n|model_id|model|#models|augmentation|ensemble_method|flip correction|CV (IMU-only, Full)|Public LB|Private LB|\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n|1|d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256|5|heavy12|prob|-|0.825 (0.787, 0.863)|-|-|\n|2|d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256|5|heavy13|prob|-|0.839 (0.811, 0.867)|0.842|0.832|\n|3|d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128|5|heavy14|prob|-|0.843 (0.809, 0.878)|0.845|0.840|\n|3|d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128|5|heavy14|prob|✅|0.843 (0.809, 0.878)|0.845|0.846|\n|4|d09_bilstm_isolated_ncl_full_b1|5|heavy15|prob|-|0.845 (0.814, 0.875)|0.841|0.832|\n|5|d09_3b_bert_null_emb_isolated_ncl_full_b12|5|heavy15|prob|-|0.849 (0.812, 0.885)|0.838|0.833|\n\n- `l{n}_b{m}` means, n-layer of squeezeformer and m-layer of temporal attention module\n\n### Ensemble\n\nensemble_id|model|#models|ensemble method|flip-correction|CV (IMU-only, Full)|Public LB|Private LB|Note\n| --- | --- | --- | --- | --- | --- | --- | --- | --- |\ntop3|ensemble {3,4,5}|15|prob|-|0.858 (0.826, 0.890)|0.853|0.841|Final Sub\ntop4|ensemble {2,3,4,5}|20|prob|-|0.861 (0.83, 0.892)|0.853|0.843|Final Sub\ntop4|ensemble {2,3,4,5}|20|rank|-|0.859 (0.828, 0.89)|0.852|0.844|Late Sub\ntop4|ensemble {2,3,4,5}|20|prob|✅|0.861 (0.83, 0.892)|0.853|**0.854**|Late Sub\n\n## Convert left-handed sensor data into pseudo right-handed sensor data\n\n- converted left-handed data into \"mimic\" right-handed data.\n- I didn't tested on LB, but always perform better than raw data in CV\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2Fc3ea9e4dcfb9c083bcf027e13ff761b6%2Finbox_4910466_3382172f16fce862379f2c186497702e_invariant_transform_ToF.png?generation=1757139431917144&alt=media)\n\nConcept and hand-written note is already shared with:\nhttps://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566\n\nAlmost the same approach that Jack's does, so details are omitted here.\nhttps://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution\n\n## Data Correction of Flipped Subject in Train set\n\nSame as above.\n\n## Data Correction of Flipped Subject in Private Test set [Late Submission]\n\n- automatically generate flipped data by applying inverse transform of Flipped subject with p=0.066\n- train classifier 100 epochs with the similar architecture of gesture classification model\n\n**Result**\n\n- precision: 0.996\n- recall:  0.980\n\nData correction if prob > 0.5 -> Private LB is improved by +0.01 (0.844 -> 0.854), which is significant impact.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F80f7ac3a2e2d0b7f0baf1ab82b63600b%2FScreenshot%202025-09-06%20at%2015.21.42.png?generation=1757139722173647&alt=media)\n\n## Other Training Details\n\n- cosine schedule which restarts **every epoch** -> slightly stable compared to one-cycle cosine schedule \n    - Note that this schedule is considered as kind of \"schedule-less\" training where we can restart training at any epochs if checkpoints are available\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F4910466%2F672df8deec00b965ee38cbf7ab822c4d%2FScreenshot%202025-09-06%20at%2015.22.43.png?generation=1757139784959096&alt=media)\n\n- Data Augmentation\n   - replace non-gesture frames sampled with different sequence with the same orientation/gesture -> CV is slightly improved\n   - resampling only on gesture frame\n   - Rotate around Z axis (-90, 90)\n   - other augmentations stabilize training, but minor improve on CV\n\n```python\n    \"heavy15\": Compose(\n        # Resample All Series\n        RandomCropOnlyGesture(max_crop_ratio=0.5, min_gesture_length=10, p=1.0),\n        Choice(\n            RandomResampleOnlyGestureV2(resample_rate_range=(1.0, 2.0), p=0.4),\n            RandomResampleOnlyGestureV2(resample_rate_range=(0.5, 1.0), p=0.2),\n            ResampleOnlyGesture(sample_rate=(1.0, 1.2), p=0.2),\n            p=0.8,\n        ),\n        # IMU Transformations\n        Compose(\n            RandomRotateZ(angle_range=90, p=1.0),\n            RandomEulerRotation(\n                angle_range=20,\n                transform_features=(\"acc\",),\n                p=1.0,\n            ),\n            Choice(\n                RandomEye([\"sensor_basis_world\"]),\n                RandomZeroOut([\"acc\"]),\n                p=0.15,\n            ),\n        ),\n        # ToF/Thermo Transformations\n        Compose(\n            RandomAffine(\n                keys=(\"tof\",),\n                translate_range=(-1, 1),\n                rotation_range=(-15, 15),\n                scale_range=(0.9, 1.1),\n                p=0.3,\n            ),\n            RandomAdditiveNoise(key=\"thermo\", shift=1.0, scale=0.3, p=0.3),\n            RandomAdditiveNoise(key=\"tof\", shift=5.0, scale=10.0, p=0.3),\n            SensorChannelDropout(key=\"tof\", drop_prob=0.5, p=0.5),\n            SensorChannelDropout(key=\"thermo\", drop_prob=0.5, p=0.5),\n            Choice(\n                RandomZeroOut([\"thermo\"]),\n                RandomZeroOut([\"tof\"]),\n                p=0.25,\n            ),\n        ),\n        Choice(\n            # Completely Drop ToF/Thermo or IMU data\n            RandomZeroOut([\"tof\", \"thermo\"], p=0.7),\n            Compose(RandomEye([\"sensor_basis_world\"]), RandomZeroOut([\"acc\"]), p=0.05),\n            Identity(p=0.25),\n        ),\n    ),\n```\n\n## Rererence\n\n- [Ensemble Top4 - Private=0.854] https://www.kaggle.com/code/tatamikenn/top4-flip-detection/notebook?scriptVersionId=260191735"
  },
  "complete": true,
  "source": "existing_discussion",
  "competition_id": 102335,
  "competition_slug": "cmi-detect-behavior-with-sensor-data",
  "team_id": 13923861,
  "solution_url": "/competitions/cmi-detect-behavior-with-sensor-data/writeups/42th-solution-late-sub-private0-854"
}