{
  "id": 555236,
  "title": "1st Place Solution - Single LGBM model",
  "url": "/competitions/brist1d/discussion/555236",
  "author_name": "Sebastian Cuya",
  "post_date": "2025-01-06T06:41:24.092000",
  "votes": 11,
  "comment_count": 0,
  "views": 0,
  "content": "<p>This is the 1st place solution that I submitted for the BrisT1D Blood Glucose Prediction Competition</p>\n<p>First of all I would we would like to thank the organizers for hosting this competition. I was looking forward to applying what I had recently learned about data science (specially on time series) and the dataset provided was really helpful for trying out different data manipualtion strategies and different models.</p>\n<p><strong>Final result:</strong> 1st place. Public LB score: <code>2.3386</code>, Private LB score: <code>2.3615</code>. You can find the link to my repository with the complete solution <a href=\"https://github.com/scuya2050/brist1d_blood_glucose_prediction_competition.git\" target=\"_blank\">here</a>.</p>\n<h2>Model</h2>\n<p>After testing many options, a single LightGBM turned out to be the fastest and also the most accurate alternative. XGBoost and Catboost provided similar results but with less accuracy and both were considerably slower. Other algorithms resulted in a greater RMSE. I didn't try ensembles much since I focused more on the feature engineering side.</p>\n<h2>Features</h2>\n<p>I included all features, but just up to the latest hour. In the case of blood glucose, I just included the last 30 minutes as they provided good predictive power without introducing too much noise. In addition, given that all other features where interval measures rather than point-in-time measures, the blood glucose difference between 5-minute gaps turned out to be a very useful feature.</p>\n<h2>Data Expansion</h2>\n<p>A key part to improving the score was the obtention of more data from the test data. As I just was using the last hour of data per observation to make the predictions, I noticed that the test data could be expanded, and taht I could extract more data for training. Since there were 6 hours of data of 5-minute gaps,  and since it was stated that the observation didn't overlap, I could create 48 + 1 windows of 1 hour of data with their respective target 1 hour in the future, per row. The expansion schema would look something like this:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8796031%2Fedcbeac27898c003f285115f0a537eae%2FTest%20data%20expansion%20-%20no%20EXIF.png?generation=1736143232275401&amp;alt=media\" alt=\"\"></p>\n<p>I applied the same in the original train data, but I didn't get too many new rows since the dataset was already pretty much complete. I still decided to expand the train data just in case.</p>\n<h2>Cross Validation</h2>\n<p>The other key component was the cross validation. Now that I had the expanded test data, I could use it for cross validation as well, as it was the most similar in distribution to what was asked to predict. Initially I used 4 folds + 1 holdout fold to test the procedure, and finally applied cross validation with the 5 folds. The folds I used were as follows:</p>\n<table>\n<thead>\n<tr>\n<th>Fold</th>\n<th>Train</th>\n<th>Valid</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-4:00 through bg-3:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-2:00</td>\n</tr>\n<tr>\n<td>2</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-3:30 through bg-2:30</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-1:30</td>\n</tr>\n<tr>\n<td>3</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-3:00 through bg-2:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-1:00</td>\n</tr>\n<tr>\n<td>4</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-2:30 through bg-1:30</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-0:30</td>\n</tr>\n<tr>\n<td>5</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-2:00 through bg-1:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-0:00</td>\n</tr>\n</tbody>\n</table>\n<h2>Key insights</h2>\n<p>I had participated in a couple of competitions in the past and I noticed that actually simple models were the ones that were getting the highest scores, as long as the feature engineering and cross validation were robust. In this case, I based my feature engineering on statistical analysis (ACF, PACF, CCF, etc), and even though I tried creating and modifying features, using the ones already given and worrying more about the relationships between them and the missing data handling resulted in the best score (and also made the model more interpretable). As for the cross validation, I used other methods like a some sort of TimeSeriesSplit and GroupKFold, but using an expanding window approach with the expanded test data to generate the folds resulted in a more robust CV process. So I would say that, as long as the features are well-handled and the cross validation is reasonable, a single model can perform very well on its own (but I'll keep an eye on ensembles as I see they can adjust to other datasets and situations)</p>",
  "messages": [
    {
      "id": 3089512,
      "postDate": "2025-01-06T06:41:24.093Z",
      "content": "<p>This is the 1st place solution that I submitted for the BrisT1D Blood Glucose Prediction Competition</p>\n<p>First of all I would we would like to thank the organizers for hosting this competition. I was looking forward to applying what I had recently learned about data science (specially on time series) and the dataset provided was really helpful for trying out different data manipualtion strategies and different models.</p>\n<p><strong>Final result:</strong> 1st place. Public LB score: <code>2.3386</code>, Private LB score: <code>2.3615</code>. You can find the link to my repository with the complete solution <a href=\"https://github.com/scuya2050/brist1d_blood_glucose_prediction_competition.git\" target=\"_blank\">here</a>.</p>\n<h2>Model</h2>\n<p>After testing many options, a single LightGBM turned out to be the fastest and also the most accurate alternative. XGBoost and Catboost provided similar results but with less accuracy and both were considerably slower. Other algorithms resulted in a greater RMSE. I didn't try ensembles much since I focused more on the feature engineering side.</p>\n<h2>Features</h2>\n<p>I included all features, but just up to the latest hour. In the case of blood glucose, I just included the last 30 minutes as they provided good predictive power without introducing too much noise. In addition, given that all other features where interval measures rather than point-in-time measures, the blood glucose difference between 5-minute gaps turned out to be a very useful feature.</p>\n<h2>Data Expansion</h2>\n<p>A key part to improving the score was the obtention of more data from the test data. As I just was using the last hour of data per observation to make the predictions, I noticed that the test data could be expanded, and taht I could extract more data for training. Since there were 6 hours of data of 5-minute gaps,  and since it was stated that the observation didn't overlap, I could create 48 + 1 windows of 1 hour of data with their respective target 1 hour in the future, per row. The expansion schema would look something like this:</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8796031%2Fedcbeac27898c003f285115f0a537eae%2FTest%20data%20expansion%20-%20no%20EXIF.png?generation=1736143232275401&amp;alt=media\" alt=\"\"></p>\n<p>I applied the same in the original train data, but I didn't get too many new rows since the dataset was already pretty much complete. I still decided to expand the train data just in case.</p>\n<h2>Cross Validation</h2>\n<p>The other key component was the cross validation. Now that I had the expanded test data, I could use it for cross validation as well, as it was the most similar in distribution to what was asked to predict. Initially I used 4 folds + 1 holdout fold to test the procedure, and finally applied cross validation with the 5 folds. The folds I used were as follows:</p>\n<table>\n<thead>\n<tr>\n<th>Fold</th>\n<th>Train</th>\n<th>Valid</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-4:00 through bg-3:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-2:00</td>\n</tr>\n<tr>\n<td>2</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-3:30 through bg-2:30</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-1:30</td>\n</tr>\n<tr>\n<td>3</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-3:00 through bg-2:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-1:00</td>\n</tr>\n<tr>\n<td>4</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-2:30 through bg-1:30</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-0:30</td>\n</tr>\n<tr>\n<td>5</td>\n<td><strong>Expanded train data</strong>: All. <br> <strong>Expanded test data</strong>: Observations with target bg-2:00 through bg-1:00</td>\n<td><strong>Expanded test data</strong>: Observations with target bg-0:00</td>\n</tr>\n</tbody>\n</table>\n<h2>Key insights</h2>\n<p>I had participated in a couple of competitions in the past and I noticed that actually simple models were the ones that were getting the highest scores, as long as the feature engineering and cross validation were robust. In this case, I based my feature engineering on statistical analysis (ACF, PACF, CCF, etc), and even though I tried creating and modifying features, using the ones already given and worrying more about the relationships between them and the missing data handling resulted in the best score (and also made the model more interpretable). As for the cross validation, I used other methods like a some sort of TimeSeriesSplit and GroupKFold, but using an expanding window approach with the expanded test data to generate the folds resulted in a more robust CV process. So I would say that, as long as the features are well-handled and the cross validation is reasonable, a single model can perform very well on its own (but I'll keep an eye on ensembles as I see they can adjust to other datasets and situations)</p>",
      "rawMarkdown": "This is the 1st place solution that I submitted for the BrisT1D Blood Glucose Prediction Competition\n\nFirst of all I would we would like to thank the organizers for hosting this competition. I was looking forward to applying what I had recently learned about data science (specially on time series) and the dataset provided was really helpful for trying out different data manipualtion strategies and different models.\n\n**Final result:** 1st place. Public LB score: `2.3386`, Private LB score: `2.3615`. You can find the link to my repository with the complete solution [here](https://github.com/scuya2050/brist1d_blood_glucose_prediction_competition.git).\n\n## Model\n\nAfter testing many options, a single LightGBM turned out to be the fastest and also the most accurate alternative. XGBoost and Catboost provided similar results but with less accuracy and both were considerably slower. Other algorithms resulted in a greater RMSE. I didn't try ensembles much since I focused more on the feature engineering side.\n\n## Features\n\nI included all features, but just up to the latest hour. In the case of blood glucose, I just included the last 30 minutes as they provided good predictive power without introducing too much noise. In addition, given that all other features where interval measures rather than point-in-time measures, the blood glucose difference between 5-minute gaps turned out to be a very useful feature.\n\n## Data Expansion\n\nA key part to improving the score was the obtention of more data from the test data. As I just was using the last hour of data per observation to make the predictions, I noticed that the test data could be expanded, and taht I could extract more data for training. Since there were 6 hours of data of 5-minute gaps,  and since it was stated that the observation didn't overlap, I could create 48 + 1 windows of 1 hour of data with their respective target 1 hour in the future, per row. The expansion schema would look something like this:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8796031%2Fedcbeac27898c003f285115f0a537eae%2FTest%20data%20expansion%20-%20no%20EXIF.png?generation=1736143232275401&alt=media)\n\nI applied the same in the original train data, but I didn't get too many new rows since the dataset was already pretty much complete. I still decided to expand the train data just in case.\n\n## Cross Validation\n\nThe other key component was the cross validation. Now that I had the expanded test data, I could use it for cross validation as well, as it was the most similar in distribution to what was asked to predict. Initially I used 4 folds + 1 holdout fold to test the procedure, and finally applied cross validation with the 5 folds. The folds I used were as follows:\n\n| Fold | Train | Valid |\n| --- | --- | --- |\n| 1 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-4:00 through bg-3:00  | **Expanded test data**: Observations with target bg-2:00 |\n| 2 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-3:30 through bg-2:30  | **Expanded test data**: Observations with target bg-1:30 |\n| 3 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-3:00 through bg-2:00  | **Expanded test data**: Observations with target bg-1:00 |\n| 4 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-2:30 through bg-1:30  | **Expanded test data**: Observations with target bg-0:30 |\n| 5 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-2:00 through bg-1:00  | **Expanded test data**: Observations with target bg-0:00 |\n\n## Key insights\n\nI had participated in a couple of competitions in the past and I noticed that actually simple models were the ones that were getting the highest scores, as long as the feature engineering and cross validation were robust. In this case, I based my feature engineering on statistical analysis (ACF, PACF, CCF, etc), and even though I tried creating and modifying features, using the ones already given and worrying more about the relationships between them and the missing data handling resulted in the best score (and also made the model more interpretable). As for the cross validation, I used other methods like a some sort of TimeSeriesSplit and GroupKFold, but using an expanding window approach with the expanded test data to generate the folds resulted in a more robust CV process. So I would say that, as long as the features are well-handled and the cross validation is reasonable, a single model can perform very well on its own (but I'll keep an eye on ensembles as I see they can adjust to other datasets and situations)\n\n\n",
      "votes": 11
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "3089512": "This is the 1st place solution that I submitted for the BrisT1D Blood Glucose Prediction Competition\n\nFirst of all I would we would like to thank the organizers for hosting this competition. I was looking forward to applying what I had recently learned about data science (specially on time series) and the dataset provided was really helpful for trying out different data manipualtion strategies and different models.\n\n**Final result:** 1st place. Public LB score: `2.3386`, Private LB score: `2.3615`. You can find the link to my repository with the complete solution [here](https://github.com/scuya2050/brist1d_blood_glucose_prediction_competition.git).\n\n## Model\n\nAfter testing many options, a single LightGBM turned out to be the fastest and also the most accurate alternative. XGBoost and Catboost provided similar results but with less accuracy and both were considerably slower. Other algorithms resulted in a greater RMSE. I didn't try ensembles much since I focused more on the feature engineering side.\n\n## Features\n\nI included all features, but just up to the latest hour. In the case of blood glucose, I just included the last 30 minutes as they provided good predictive power without introducing too much noise. In addition, given that all other features where interval measures rather than point-in-time measures, the blood glucose difference between 5-minute gaps turned out to be a very useful feature.\n\n## Data Expansion\n\nA key part to improving the score was the obtention of more data from the test data. As I just was using the last hour of data per observation to make the predictions, I noticed that the test data could be expanded, and taht I could extract more data for training. Since there were 6 hours of data of 5-minute gaps,  and since it was stated that the observation didn't overlap, I could create 48 + 1 windows of 1 hour of data with their respective target 1 hour in the future, per row. The expansion schema would look something like this:\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F8796031%2Fedcbeac27898c003f285115f0a537eae%2FTest%20data%20expansion%20-%20no%20EXIF.png?generation=1736143232275401&alt=media)\n\nI applied the same in the original train data, but I didn't get too many new rows since the dataset was already pretty much complete. I still decided to expand the train data just in case.\n\n## Cross Validation\n\nThe other key component was the cross validation. Now that I had the expanded test data, I could use it for cross validation as well, as it was the most similar in distribution to what was asked to predict. Initially I used 4 folds + 1 holdout fold to test the procedure, and finally applied cross validation with the 5 folds. The folds I used were as follows:\n\n| Fold | Train | Valid |\n| --- | --- | --- |\n| 1 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-4:00 through bg-3:00  | **Expanded test data**: Observations with target bg-2:00 |\n| 2 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-3:30 through bg-2:30  | **Expanded test data**: Observations with target bg-1:30 |\n| 3 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-3:00 through bg-2:00  | **Expanded test data**: Observations with target bg-1:00 |\n| 4 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-2:30 through bg-1:30  | **Expanded test data**: Observations with target bg-0:30 |\n| 5 | **Expanded train data**: All. <br> **Expanded test data**: Observations with target bg-2:00 through bg-1:00  | **Expanded test data**: Observations with target bg-0:00 |\n\n## Key insights\n\nI had participated in a couple of competitions in the past and I noticed that actually simple models were the ones that were getting the highest scores, as long as the feature engineering and cross validation were robust. In this case, I based my feature engineering on statistical analysis (ACF, PACF, CCF, etc), and even though I tried creating and modifying features, using the ones already given and worrying more about the relationships between them and the missing data handling resulted in the best score (and also made the model more interpretable). As for the cross validation, I used other methods like a some sort of TimeSeriesSplit and GroupKFold, but using an expanding window approach with the expanded test data to generate the folds resulted in a more robust CV process. So I would say that, as long as the features are well-handled and the cross validation is reasonable, a single model can perform very well on its own (but I'll keep an eye on ensembles as I see they can adjust to other datasets and situations)\n\n\n"
  }
}