{
  "id": 583220,
  "title": "CMI | WaveNet PyTorch IMU-only",
  "url": "/competitions/cmi-detect-behavior-with-sensor-data/discussion/583220",
  "author_name": "",
  "post_date": "2025-06-05T13:30:58.911202200Z",
  "votes": 26,
  "comment_count": 10,
  "views": 0,
  "content": "<p>I am sharing my WaveNet approach using IMU-only data using PyTorch:</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-train\" target=\"_blank\">CMI | WaveNet PyTorch IMU-Only [Train]</a></li>\n<li><a href=\"https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-inference\" target=\"_blank\">CMI | WaveNet PyTorch IMU-Only [Inference]</a></li>\n</ul>\n<p>This approach's model is a 2-stream WaveNet model with Temporal attention and 2 classification heads, 1 for the multiclass classification task and another one for the binary classification task. For the multiclass problem, <code>Non-Target</code> gestures were collapsed into a single class, thus the last last linear layer contains 9 classes instead of 18. The acceleration data and the rotation data are handled independently and are later concatenated.</p>\n<p>Here is an overview diagram of the architecture:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3197853%2F5561d2b2c2638ed84ccf08fa1059b08a%2FScreenshot%202025-06-05%20at%2010.09.35.png?generation=1749130065965897&amp;alt=media\" alt=\"\"></p>\n<p>This approach achieves CV: ~0.66 LB: 0.65 with a <code>StratifiedGroupKFold</code> validation taking <code>subject</code> as groups.</p>\n<p>Please, leave your thoughts, comments and improvements! Thanks!</p>\n<p>Happy Kaggling</p>\n<p>Edit: enlarging the WaveNet improved scrore CV and LB: 0.65 -&gt; 0.68</p>",
  "messages": [
    {
      "id": "3217881",
      "postDate": "06/05/2025 13:30:58",
      "content": "<p>I am sharing my WaveNet approach using IMU-only data using PyTorch:</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-train\" target=\"_blank\">CMI | WaveNet PyTorch IMU-Only [Train]</a></li>\n<li><a href=\"https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-inference\" target=\"_blank\">CMI | WaveNet PyTorch IMU-Only [Inference]</a></li>\n</ul>\n<p>This approach's model is a 2-stream WaveNet model with Temporal attention and 2 classification heads, 1 for the multiclass classification task and another one for the binary classification task. For the multiclass problem, <code>Non-Target</code> gestures were collapsed into a single class, thus the last last linear layer contains 9 classes instead of 18. The acceleration data and the rotation data are handled independently and are later concatenated.</p>\n<p>Here is an overview diagram of the architecture:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3197853%2F5561d2b2c2638ed84ccf08fa1059b08a%2FScreenshot%202025-06-05%20at%2010.09.35.png?generation=1749130065965897&amp;alt=media\" alt=\"\"></p>\n<p>This approach achieves CV: ~0.66 LB: 0.65 with a <code>StratifiedGroupKFold</code> validation taking <code>subject</code> as groups.</p>\n<p>Please, leave your thoughts, comments and improvements! Thanks!</p>\n<p>Happy Kaggling</p>\n<p>Edit: enlarging the WaveNet improved scrore CV and LB: 0.65 -&gt; 0.68</p>",
      "rawMarkdown": "I am sharing my WaveNet approach using IMU-only data using PyTorch:\n- [CMI | WaveNet PyTorch IMU-Only [Train]][1]\n- [CMI | WaveNet PyTorch IMU-Only [Inference]][2]\n\nThis approach's model is a 2-stream WaveNet model with Temporal attention and 2 classification heads, 1 for the multiclass classification task and another one for the binary classification task. For the multiclass problem, `Non-Target` gestures were collapsed into a single class, thus the last last linear layer contains 9 classes instead of 18. The acceleration data and the rotation data are handled independently and are later concatenated.\n\nHere is an overview diagram of the architecture:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3197853%2F5561d2b2c2638ed84ccf08fa1059b08a%2FScreenshot%202025-06-05%20at%2010.09.35.png?generation=1749130065965897&alt=media)\n\nThis approach achieves CV: ~0.66 LB: 0.65 with a `StratifiedGroupKFold` validation taking `subject` as groups.\n\nPlease, leave your thoughts, comments and improvements! Thanks!\n\nHappy Kaggling\n\nEdit: enlarging the WaveNet improved scrore CV and LB: 0.65 -> 0.68\n\n[1]: https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-train\n[2]: https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-inference",
      "votes": null
    },
    {
      "id": "3217883",
      "postDate": "06/05/2025 13:33:48",
      "content": "<p>Thank you for sharing! I noticed that you designed two parallel classification heads. In your experiments, did this design lead to better performance?</p>",
      "rawMarkdown": "Thank you for sharing! I noticed that you designed two parallel classification heads. In your experiments, did this design lead to better performance?",
      "votes": null
    },
    {
      "id": "3217913",
      "postDate": "06/05/2025 14:09:27",
      "content": "<p>Not much tbh. Most perfomance boosts came from trying different configurations of batch size, LR, epochs. </p>",
      "rawMarkdown": "Not much tbh. Most perfomance boosts came from trying different configurations of batch size, LR, epochs.",
      "votes": null
    },
    {
      "id": "3217917",
      "postDate": "06/05/2025 14:16:31",
      "content": "<p>Have you tried adding demographic data (numerical and categorical features)? I've tried doing that by adding another input stream that would create a dense representation out of those features, and concatenating with IMU activations. Like this:</p>\n<pre><code> = Input(shape=(pad_len_to_use, len(sensor_feature_cols)), name=)\n = Conv1D(filters=, kernel_size=, activation=)(sensor_input)\n = MaxPooling1D(pool_size=)(x)\n = Dropout()(x)\n = Conv1D(filters=, kernel_size=, activation=)(x)\n = MaxPooling1D(pool_size=)(x)\n = Dropout()(x)\n = Flatten()(x)\n\n\n = Input(shape=(len(demo_feature_cols),), name=)\n = Dense(, activation=)(participant_input)\n = Dropout()(y)\n\n\n = concatenate([x, y])\n = Dense(, activation=)(combined)\n = Dropout()(z)\n = Dense(, activation=)(z)\n = Dropout()(z)\n = Dense(num_classes, activation=)(z)\n</code></pre>\n<p>I found it improves my CV by a little, have some difficulties with actual inference though</p>",
      "rawMarkdown": "Have you tried adding demographic data (numerical and categorical features)? I've tried doing that by adding another input stream that would create a dense representation out of those features, and concatenating with IMU activations. Like this:\n```\nsensor_input = Input(shape=(pad_len_to_use, len(sensor_feature_cols)), name='sensor_input')\nx = Conv1D(filters=128, kernel_size=5, activation='relu')(sensor_input)\nx = MaxPooling1D(pool_size=2)(x)\nx = Dropout(0.4)(x)\nx = Conv1D(filters=256, kernel_size=2, activation='relu')(x)\nx = MaxPooling1D(pool_size=2)(x)\nx = Dropout(0.4)(x)\nx = Flatten()(x)\n\n# Demo\nparticipant_input = Input(shape=(len(demo_feature_cols),), name='demographic_data')\ny = Dense(64, activation='relu')(participant_input)\ny = Dropout(0.3)(y)\n\n# Combine, then dense\ncombined = concatenate([x, y])\nz = Dense(256, activation='relu')(combined)\nz = Dropout(0.5)(z)\nz = Dense(128, activation='relu')(z)\nz = Dropout(0.3)(z)\noutput = Dense(num_classes, activation='softmax')(z)\n```\nI found it improves my CV by a little, have some difficulties with actual inference though",
      "votes": null
    },
    {
      "id": "3217944",
      "postDate": "06/05/2025 15:05:49",
      "content": "<p>I wanted to try an IMU-only approach. What you can do is train and infer with your model and create OOF predictions. Then use these leak-less predictions as new columns together with demographic data and train a GBM model instead of directly inputting the demographics data in the neural network.</p>",
      "rawMarkdown": "I wanted to try an IMU-only approach. What you can do is train and infer with your model and create OOF predictions. Then use these leak-less predictions as new columns together with demographic data and train a GBM model instead of directly inputting the demographics data in the neural network.",
      "votes": null
    },
    {
      "id": "3218055",
      "postDate": "06/05/2025 18:05:26",
      "content": "<p>Hey Alejo! Cool write up, I have mixed feelings about that model though ;).</p>",
      "rawMarkdown": "Hey Alejo! Cool write up, I have mixed feelings about that model though ;).",
      "votes": null
    },
    {
      "id": "3218057",
      "postDate": "06/05/2025 18:10:08",
      "content": "<p>Hi Jan! Long time no see! :)</p>",
      "rawMarkdown": "Hi Jan! Long time no see! :)",
      "votes": null
    },
    {
      "id": "3219920",
      "postDate": "06/08/2025 14:05:10",
      "content": "<p>Curious if you tried a one wavenet version where you concat acc and rot and pass everything in together. My initiation tells me that since there's not a ton of data here, creating separate models for each sensor type makes more sense than a pass it all in at once approach.</p>",
      "rawMarkdown": "Curious if you tried a one wavenet version where you concat acc and rot and pass everything in together. My initiation tells me that since there's not a ton of data here, creating separate models for each sensor type makes more sense than a pass it all in at once approach.",
      "votes": null
    },
    {
      "id": "3220036",
      "postDate": "06/08/2025 17:26:20",
      "content": "<p>Haha <a href=\"https://www.kaggle.com/janbrederecke\" target=\"_blank\">@janbrederecke</a>  type of comp.. be nice model reminds of your old models :) </p>",
      "rawMarkdown": "Haha @janbrederecke  type of comp.. be nice model reminds of your old models :)",
      "votes": null
    },
    {
      "id": "3220038",
      "postDate": "06/08/2025 17:28:12",
      "content": "<p>Yeah, there is definitely some stuff that could be recycled - hit me up if you want to team up again! 😊</p>",
      "rawMarkdown": "Yeah, there is definitely some stuff that could be recycled - hit me up if you want to team up again! 😊",
      "votes": null
    },
    {
      "id": "3220043",
      "postDate": "06/08/2025 17:37:31",
      "content": "<p>Ya this reminded me of h$# :) came back from a hiatus (finally some break from office work).. just trying few ideas then surely gang up 😄</p>",
      "rawMarkdown": "Ya this reminded me of h$# :) came back from a hiatus (finally some break from office work).. just trying few ideas then surely gang up 😄",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 3217883,
      "author_name": "ryenhails",
      "author_url": "",
      "post_date": "06/05/2025 13:33:48",
      "content": "<p>Thank you for sharing! I noticed that you designed two parallel classification heads. In your experiments, did this design lead to better performance?</p>",
      "votes": null,
      "replies": [
        {
          "id": 3217913,
          "author_name": "alejopaullier",
          "author_url": "",
          "post_date": "06/05/2025 14:09:27",
          "content": "<p>Not much tbh. Most perfomance boosts came from trying different configurations of batch size, LR, epochs. </p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3217917,
      "author_name": "defdet",
      "author_url": "",
      "post_date": "06/05/2025 14:16:31",
      "content": "<p>Have you tried adding demographic data (numerical and categorical features)? I've tried doing that by adding another input stream that would create a dense representation out of those features, and concatenating with IMU activations. Like this:</p>\n<pre><code> = Input(shape=(pad_len_to_use, len(sensor_feature_cols)), name=)\n = Conv1D(filters=, kernel_size=, activation=)(sensor_input)\n = MaxPooling1D(pool_size=)(x)\n = Dropout()(x)\n = Conv1D(filters=, kernel_size=, activation=)(x)\n = MaxPooling1D(pool_size=)(x)\n = Dropout()(x)\n = Flatten()(x)\n\n\n = Input(shape=(len(demo_feature_cols),), name=)\n = Dense(, activation=)(participant_input)\n = Dropout()(y)\n\n\n = concatenate([x, y])\n = Dense(, activation=)(combined)\n = Dropout()(z)\n = Dense(, activation=)(z)\n = Dropout()(z)\n = Dense(num_classes, activation=)(z)\n</code></pre>\n<p>I found it improves my CV by a little, have some difficulties with actual inference though</p>",
      "votes": null,
      "replies": [
        {
          "id": 3217944,
          "author_name": "alejopaullier",
          "author_url": "",
          "post_date": "06/05/2025 15:05:49",
          "content": "<p>I wanted to try an IMU-only approach. What you can do is train and infer with your model and create OOF predictions. Then use these leak-less predictions as new columns together with demographic data and train a GBM model instead of directly inputting the demographics data in the neural network.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3218055,
      "author_name": "janbrederecke",
      "author_url": "",
      "post_date": "06/05/2025 18:05:26",
      "content": "<p>Hey Alejo! Cool write up, I have mixed feelings about that model though ;).</p>",
      "votes": null,
      "replies": [
        {
          "id": 3218057,
          "author_name": "alejopaullier",
          "author_url": "",
          "post_date": "06/05/2025 18:10:08",
          "content": "<p>Hi Jan! Long time no see! :)</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 3220036,
          "author_name": "gauravbrills",
          "author_url": "",
          "post_date": "06/08/2025 17:26:20",
          "content": "<p>Haha <a href=\"https://www.kaggle.com/janbrederecke\" target=\"_blank\">@janbrederecke</a>  type of comp.. be nice model reminds of your old models :) </p>",
          "votes": null,
          "replies": [
            {
              "id": 3220038,
              "author_name": "janbrederecke",
              "author_url": "",
              "post_date": "06/08/2025 17:28:12",
              "content": "<p>Yeah, there is definitely some stuff that could be recycled - hit me up if you want to team up again! 😊</p>",
              "votes": null,
              "replies": [
                {
                  "id": 3220043,
                  "author_name": "gauravbrills",
                  "author_url": "",
                  "post_date": "06/08/2025 17:37:31",
                  "content": "<p>Ya this reminded me of h$# :) came back from a hiatus (finally some break from office work).. just trying few ideas then surely gang up 😄</p>",
                  "votes": null,
                  "replies": []
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "id": 3219920,
      "author_name": "msthil",
      "author_url": "",
      "post_date": "06/08/2025 14:05:10",
      "content": "<p>Curious if you tried a one wavenet version where you concat acc and rot and pass everything in together. My initiation tells me that since there's not a ton of data here, creating separate models for each sensor type makes more sense than a pass it all in at once approach.</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3217881": "I am sharing my WaveNet approach using IMU-only data using PyTorch:\n- [CMI | WaveNet PyTorch IMU-Only [Train]][1]\n- [CMI | WaveNet PyTorch IMU-Only [Inference]][2]\n\nThis approach's model is a 2-stream WaveNet model with Temporal attention and 2 classification heads, 1 for the multiclass classification task and another one for the binary classification task. For the multiclass problem, `Non-Target` gestures were collapsed into a single class, thus the last last linear layer contains 9 classes instead of 18. The acceleration data and the rotation data are handled independently and are later concatenated.\n\nHere is an overview diagram of the architecture:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F3197853%2F5561d2b2c2638ed84ccf08fa1059b08a%2FScreenshot%202025-06-05%20at%2010.09.35.png?generation=1749130065965897&alt=media)\n\nThis approach achieves CV: ~0.66 LB: 0.65 with a `StratifiedGroupKFold` validation taking `subject` as groups.\n\nPlease, leave your thoughts, comments and improvements! Thanks!\n\nHappy Kaggling\n\nEdit: enlarging the WaveNet improved scrore CV and LB: 0.65 -> 0.68\n\n[1]: https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-train\n[2]: https://www.kaggle.com/code/alejopaullier/cmi-wavenet-pytorch-imu-only-inference",
    "3217883": "Thank you for sharing! I noticed that you designed two parallel classification heads. In your experiments, did this design lead to better performance?",
    "3217913": "Not much tbh. Most perfomance boosts came from trying different configurations of batch size, LR, epochs.",
    "3217917": "Have you tried adding demographic data (numerical and categorical features)? I've tried doing that by adding another input stream that would create a dense representation out of those features, and concatenating with IMU activations. Like this:\n```\nsensor_input = Input(shape=(pad_len_to_use, len(sensor_feature_cols)), name='sensor_input')\nx = Conv1D(filters=128, kernel_size=5, activation='relu')(sensor_input)\nx = MaxPooling1D(pool_size=2)(x)\nx = Dropout(0.4)(x)\nx = Conv1D(filters=256, kernel_size=2, activation='relu')(x)\nx = MaxPooling1D(pool_size=2)(x)\nx = Dropout(0.4)(x)\nx = Flatten()(x)\n\n# Demo\nparticipant_input = Input(shape=(len(demo_feature_cols),), name='demographic_data')\ny = Dense(64, activation='relu')(participant_input)\ny = Dropout(0.3)(y)\n\n# Combine, then dense\ncombined = concatenate([x, y])\nz = Dense(256, activation='relu')(combined)\nz = Dropout(0.5)(z)\nz = Dense(128, activation='relu')(z)\nz = Dropout(0.3)(z)\noutput = Dense(num_classes, activation='softmax')(z)\n```\nI found it improves my CV by a little, have some difficulties with actual inference though",
    "3217944": "I wanted to try an IMU-only approach. What you can do is train and infer with your model and create OOF predictions. Then use these leak-less predictions as new columns together with demographic data and train a GBM model instead of directly inputting the demographics data in the neural network.",
    "3218055": "Hey Alejo! Cool write up, I have mixed feelings about that model though ;).",
    "3218057": "Hi Jan! Long time no see! :)",
    "3219920": "Curious if you tried a one wavenet version where you concat acc and rot and pass everything in together. My initiation tells me that since there's not a ton of data here, creating separate models for each sensor type makes more sense than a pass it all in at once approach.",
    "3220036": "Haha @janbrederecke  type of comp.. be nice model reminds of your old models :)",
    "3220038": "Yeah, there is definitely some stuff that could be recycled - hit me up if you want to team up again! 😊",
    "3220043": "Ya this reminded me of h$# :) came back from a hiatus (finally some break from office work).. just trying few ideas then surely gang up 😄"
  },
  "source": "meta"
}