{
  "id": 611432,
  "title": "2nd place solution",
  "url": "/competitions/2nd-wear-dataset-challenge/discussion/611432",
  "author_name": "Anh Tuan Ha",
  "post_date": "2025-10-11T13:17:20.193000",
  "votes": 4,
  "comment_count": 0,
  "views": 0,
  "content": "<p>First of all, congratulations to all the winners and big respect to the organizers for creating such a challenging competition.<br>\nI planned to publish my solution as a paper, but my student's income didn't allow it. Also, this is my first write-up, if something isn’t clear, feel free to ask.<br>\nLet me give a quick summary of my solution and share the code.</p>\n<h3>Overview</h3>\n<p>This year's WEAR challenge emphasizes <strong><em><em>robustness</em></em></strong> and <strong><em><em>generalization</em></em></strong> on data from new and augmented participants. To address this, my solution is built on <strong>specialization</strong>.</p>\n<p>Each sub-model uses a hybrid of Patch Embedding, a Bidirectional LSTM to capture temporal dependencies, and Attention Pooling to extract salient information from the time series.</p>\n<h3>Preprocessing and Data Preparation</h3>\n<p><strong>1. Sliding Window and Normalization</strong><br>\nThe data is segmented into 1-second windows for processing.</p>\n<ul>\n<li><code>window_size = 50</code>: Each data window is 50 timesteps long</li>\n<li><code>stride = 25</code>: Windows have a 50% overlap to increase the number of training samples and ensure activity continuity is captured.<br>\nNormalization uses the mean and standard deviation computed per sensor location over the entire training set.</li>\n</ul>\n<p><strong>2. Data Augmentation</strong><br>\nThe following augmentations are <strong>Randomly</strong> applied during training; on each <code>__getitem__</code> call, an independent draw determines whether each augmentation is applied, teaching the model to handle uncertainty:</p>\n<ul>\n<li><strong>Jittering</strong>: Adds small Gaussian noise.</li>\n<li><strong>Scaling</strong>: Randomly scales the signal's amplitude.</li>\n<li><strong>Rotation</strong>: Applies a random 3D rotation.</li>\n<li><strong>Time warping</strong>: Stretches or compresses the signal along the time axis.</li>\n</ul>\n<h3>Model Architecture</h3>\n<p>This is the central architecture used for all four sub-models.<br>\n<code>LocationSpecificModel (</code><br>\n <code>(patch): PatchEmbed1D (...)</code><br>\n  <code>(lstm): LSTM(..., bidirectional=True)</code><br>\n  <code>(attn_pool): Sequential (...)</code><br>\n  <code>(head): Sequential (...)</code><br>\n<code>)</code></p>\n<ol>\n<li>Input: 1-second window, shape (3, 50).</li>\n<li>PatchEmbed1D: split into 10 patches (0.1 s each). A Conv1d encodes each patch to a 256-dimensional vector; add positional information.</li>\n<li>Bidirectional LSTM: 4-layer Bi-LSTM processes the 10-patch sequence to learn temporal relationships in both directions.</li>\n<li>Attention Pooling: learn weights over patches and aggregate to focus on the most informative parts within the window.</li>\n<li>Classification Head: feed the pooled representation into a classification block to predict one of 19 activity classes.</li>\n</ol>\n<h3>Training</h3>\n<ul>\n<li>Split for Generalization: split by sbj_id. Validation uses participants unseen during training to better simulate the final test scenario with new users.</li>\n<li>Optimization: Adam optimizer (lr = 1e-3) with Cross-Entropy Loss and early stopping.</li>\n<li>To improve the model, just change the random score in the data arguments and hope for better luck with the RNG.</li>\n</ul>\n<p><strong>Observed per-location validation</strong></p>\n<ul>\n<li>Right Arm: macro F1 ~ 0.60</li>\n<li>Left Arm: macro F1 ~ 0.59</li>\n<li>Right Leg: macro F1 ~ 0.61</li>\n<li>Left Leg: macro F1 ~ 0.58</li>\n</ul>\n<h3>Link to code: <a href=\"https://www.kaggle.com/code/schw1eg0/testing-v0-535\" target=\"_blank\">Kaggle Notebook</a></h3>\n<p>No worries about the name. I call every Kaggle notebook “Testing”. ;)</p>",
  "messages": [
    {
      "id": 3300776,
      "postDate": "2025-10-11T13:17:20.193Z",
      "content": "<p>First of all, congratulations to all the winners and big respect to the organizers for creating such a challenging competition.<br>\nI planned to publish my solution as a paper, but my student's income didn't allow it. Also, this is my first write-up, if something isn’t clear, feel free to ask.<br>\nLet me give a quick summary of my solution and share the code.</p>\n<h3>Overview</h3>\n<p>This year's WEAR challenge emphasizes <strong><em><em>robustness</em></em></strong> and <strong><em><em>generalization</em></em></strong> on data from new and augmented participants. To address this, my solution is built on <strong>specialization</strong>.</p>\n<p>Each sub-model uses a hybrid of Patch Embedding, a Bidirectional LSTM to capture temporal dependencies, and Attention Pooling to extract salient information from the time series.</p>\n<h3>Preprocessing and Data Preparation</h3>\n<p><strong>1. Sliding Window and Normalization</strong><br>\nThe data is segmented into 1-second windows for processing.</p>\n<ul>\n<li><code>window_size = 50</code>: Each data window is 50 timesteps long</li>\n<li><code>stride = 25</code>: Windows have a 50% overlap to increase the number of training samples and ensure activity continuity is captured.<br>\nNormalization uses the mean and standard deviation computed per sensor location over the entire training set.</li>\n</ul>\n<p><strong>2. Data Augmentation</strong><br>\nThe following augmentations are <strong>Randomly</strong> applied during training; on each <code>__getitem__</code> call, an independent draw determines whether each augmentation is applied, teaching the model to handle uncertainty:</p>\n<ul>\n<li><strong>Jittering</strong>: Adds small Gaussian noise.</li>\n<li><strong>Scaling</strong>: Randomly scales the signal's amplitude.</li>\n<li><strong>Rotation</strong>: Applies a random 3D rotation.</li>\n<li><strong>Time warping</strong>: Stretches or compresses the signal along the time axis.</li>\n</ul>\n<h3>Model Architecture</h3>\n<p>This is the central architecture used for all four sub-models.<br>\n<code>LocationSpecificModel (</code><br>\n <code>(patch): PatchEmbed1D (...)</code><br>\n  <code>(lstm): LSTM(..., bidirectional=True)</code><br>\n  <code>(attn_pool): Sequential (...)</code><br>\n  <code>(head): Sequential (...)</code><br>\n<code>)</code></p>\n<ol>\n<li>Input: 1-second window, shape (3, 50).</li>\n<li>PatchEmbed1D: split into 10 patches (0.1 s each). A Conv1d encodes each patch to a 256-dimensional vector; add positional information.</li>\n<li>Bidirectional LSTM: 4-layer Bi-LSTM processes the 10-patch sequence to learn temporal relationships in both directions.</li>\n<li>Attention Pooling: learn weights over patches and aggregate to focus on the most informative parts within the window.</li>\n<li>Classification Head: feed the pooled representation into a classification block to predict one of 19 activity classes.</li>\n</ol>\n<h3>Training</h3>\n<ul>\n<li>Split for Generalization: split by sbj_id. Validation uses participants unseen during training to better simulate the final test scenario with new users.</li>\n<li>Optimization: Adam optimizer (lr = 1e-3) with Cross-Entropy Loss and early stopping.</li>\n<li>To improve the model, just change the random score in the data arguments and hope for better luck with the RNG.</li>\n</ul>\n<p><strong>Observed per-location validation</strong></p>\n<ul>\n<li>Right Arm: macro F1 ~ 0.60</li>\n<li>Left Arm: macro F1 ~ 0.59</li>\n<li>Right Leg: macro F1 ~ 0.61</li>\n<li>Left Leg: macro F1 ~ 0.58</li>\n</ul>\n<h3>Link to code: <a href=\"https://www.kaggle.com/code/schw1eg0/testing-v0-535\" target=\"_blank\">Kaggle Notebook</a></h3>\n<p>No worries about the name. I call every Kaggle notebook “Testing”. ;)</p>",
      "rawMarkdown": "First of all, congratulations to all the winners and big respect to the organizers for creating such a challenging competition.\nI planned to publish my solution as a paper, but my student's income didn't allow it. Also, this is my first write-up, if something isn’t clear, feel free to ask.\nLet me give a quick summary of my solution and share the code.\n\n###Overview\nThis year's WEAR challenge emphasizes ****robustness**** and ****generalization**** on data from new and augmented participants. To address this, my solution is built on **specialization**.\n\nEach sub-model uses a hybrid of Patch Embedding, a Bidirectional LSTM to capture temporal dependencies, and Attention Pooling to extract salient information from the time series.\n\n###Preprocessing and Data Preparation\n\n**1. Sliding Window and Normalization**\nThe data is segmented into 1-second windows for processing.\n- `window_size = 50`: Each data window is 50 timesteps long\n- `stride = 25`: Windows have a 50% overlap to increase the number of training samples and ensure activity continuity is captured.\nNormalization uses the mean and standard deviation computed per sensor location over the entire training set.\n\n**2. Data Augmentation**\nThe following augmentations are **Randomly** applied during training; on each `__getitem__` call, an independent draw determines whether each augmentation is applied, teaching the model to handle uncertainty:\n  - **Jittering**: Adds small Gaussian noise.\n  - **Scaling**: Randomly scales the signal's amplitude.\n  - **Rotation**: Applies a random 3D rotation.\n  - **Time warping**: Stretches or compresses the signal along the time axis.\n\n###Model Architecture\nThis is the central architecture used for all four sub-models.\n`LocationSpecificModel (`\n `(patch): PatchEmbed1D (...)`\n  `(lstm): LSTM(..., bidirectional=True)`\n  `(attn_pool): Sequential (...)`\n  `(head): Sequential (...)`\n`)`\n1. Input: 1-second window, shape (3, 50).\n2. PatchEmbed1D: split into 10 patches (0.1 s each). A Conv1d encodes each patch to a 256-dimensional vector; add positional information.\n3. Bidirectional LSTM: 4-layer Bi-LSTM processes the 10-patch sequence to learn temporal relationships in both directions.\n4. Attention Pooling: learn weights over patches and aggregate to focus on the most informative parts within the window.\n5. Classification Head: feed the pooled representation into a classification block to predict one of 19 activity classes.\n\n###Training\n- Split for Generalization: split by sbj_id. Validation uses participants unseen during training to better simulate the final test scenario with new users.\n- Optimization: Adam optimizer (lr = 1e-3) with Cross-Entropy Loss and early stopping.\n- To improve the model, just change the random score in the data arguments and hope for better luck with the RNG.\n\n**Observed per-location validation**\n- Right Arm: macro F1 ~ 0.60\n- Left Arm: macro F1 ~ 0.59\n- Right Leg: macro F1 ~ 0.61\n- Left Leg: macro F1 ~ 0.58\n\n###Link to code: [Kaggle Notebook](https://www.kaggle.com/code/schw1eg0/testing-v0-535)\nNo worries about the name. I call every Kaggle notebook “Testing”. ;)",
      "votes": 4
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "3300776": "First of all, congratulations to all the winners and big respect to the organizers for creating such a challenging competition.\nI planned to publish my solution as a paper, but my student's income didn't allow it. Also, this is my first write-up, if something isn’t clear, feel free to ask.\nLet me give a quick summary of my solution and share the code.\n\n###Overview\nThis year's WEAR challenge emphasizes ****robustness**** and ****generalization**** on data from new and augmented participants. To address this, my solution is built on **specialization**.\n\nEach sub-model uses a hybrid of Patch Embedding, a Bidirectional LSTM to capture temporal dependencies, and Attention Pooling to extract salient information from the time series.\n\n###Preprocessing and Data Preparation\n\n**1. Sliding Window and Normalization**\nThe data is segmented into 1-second windows for processing.\n- `window_size = 50`: Each data window is 50 timesteps long\n- `stride = 25`: Windows have a 50% overlap to increase the number of training samples and ensure activity continuity is captured.\nNormalization uses the mean and standard deviation computed per sensor location over the entire training set.\n\n**2. Data Augmentation**\nThe following augmentations are **Randomly** applied during training; on each `__getitem__` call, an independent draw determines whether each augmentation is applied, teaching the model to handle uncertainty:\n  - **Jittering**: Adds small Gaussian noise.\n  - **Scaling**: Randomly scales the signal's amplitude.\n  - **Rotation**: Applies a random 3D rotation.\n  - **Time warping**: Stretches or compresses the signal along the time axis.\n\n###Model Architecture\nThis is the central architecture used for all four sub-models.\n`LocationSpecificModel (`\n `(patch): PatchEmbed1D (...)`\n  `(lstm): LSTM(..., bidirectional=True)`\n  `(attn_pool): Sequential (...)`\n  `(head): Sequential (...)`\n`)`\n1. Input: 1-second window, shape (3, 50).\n2. PatchEmbed1D: split into 10 patches (0.1 s each). A Conv1d encodes each patch to a 256-dimensional vector; add positional information.\n3. Bidirectional LSTM: 4-layer Bi-LSTM processes the 10-patch sequence to learn temporal relationships in both directions.\n4. Attention Pooling: learn weights over patches and aggregate to focus on the most informative parts within the window.\n5. Classification Head: feed the pooled representation into a classification block to predict one of 19 activity classes.\n\n###Training\n- Split for Generalization: split by sbj_id. Validation uses participants unseen during training to better simulate the final test scenario with new users.\n- Optimization: Adam optimizer (lr = 1e-3) with Cross-Entropy Loss and early stopping.\n- To improve the model, just change the random score in the data arguments and hope for better luck with the RNG.\n\n**Observed per-location validation**\n- Right Arm: macro F1 ~ 0.60\n- Left Arm: macro F1 ~ 0.59\n- Right Leg: macro F1 ~ 0.61\n- Left Leg: macro F1 ~ 0.58\n\n###Link to code: [Kaggle Notebook](https://www.kaggle.com/code/schw1eg0/testing-v0-535)\nNo worries about the name. I call every Kaggle notebook “Testing”. ;)"
  }
}