{
  "id": 704743,
  "title": "3rd Place Solution for the WiDS Global Datathon 2026 Competition",
  "content": "<p><strong>Team Name:</strong> BTT_Heatwave<br>\n<strong>Team Members:</strong> Rishik Yesgari and Ayooluwa Wojuade<br>\n<strong>Private Leaderboard Score:</strong> 0.97250<br>\n<strong>Private Leaderboard Place:</strong> 3rd Place  </p>\n<h2>Overview</h2>\n<p>This competition focused on predicting when a wildfire may threaten an evacuation zone. For each fire, we estimated the probability of a threat within 12, 24, 48, and 72 hours using only the first five hours of fire perimeter information.</p>\n<p>This was a right-censored survival prediction problem. Some fires reached an evacuation zone, while others did not during the observation window. For censored fires, we only know that a hit was not observed during the available time. Because of this, the model had to handle event timing and censoring while still producing calibrated probabilities for fixed horizons.</p>\n<p>Our approach was to build a horizon-specific ensemble. We engineered features for distance, movement, fire growth, alignment, and estimated time to reach an evacuation zone. Then we trained multiple model families, combined their outputs, and applied post-processing so the final probabilities stayed valid and followed the required cumulative order over time.</p>\n<h2>Main Idea</h2>\n<p>The main idea was to avoid treating the task as one single classification problem. Since the competition required probabilities at four horizons, we built the solution around those horizons directly. A fire that may threaten an evacuation zone within 12 hours can behave differently from one that becomes risky closer to 48 or 72 hours.</p>\n<p>We also handled censoring carefully. For each horizon, fires censored before that horizon were not treated as clear negatives because their true outcome was unknown. We built horizon-specific labels only from examples where the outcome was known and used censor-aware weighting to reduce bias.</p>\n<p>The final solution combined two views of the problem. Horizon-specific models helped produce calibrated probabilities for fixed time windows, while survival-risk models helped capture the overall urgency ranking of fires. This matched the competition metric, which rewarded both ranking and probability calibration.</p>\n<h2>Feature Engineering</h2>\n<p>Feature engineering was important because the original columns did not fully capture the relationship between the fire, its movement, and the nearest evacuation zone. We created features that described closeness, movement, growth, direction, and estimated arrival time.</p>\n<p>The engineered features included distance transformations such as distance in kilometers, log distance, square-root distance, inverse distance, and distance-zone indicators. We also added distance trend features such as normalized distance change, normalized distance slope, normalized distance variation, distance acceleration, and a distance-trend reliability flag.</p>\n<p>We created movement and ETA-based features using closing speed, radial growth rate, effective closing speed, and along-track speed. From these, we estimated time-to-arrival values and horizon-specific ETA indicators for 12, 24, 48, and 72 hours. We also added fire size and growth features such as estimated fire radius, radius-to-distance ratio, area-to-distance ratio, growth-to-distance ratio, and radial-growth-to-distance ratio.</p>\n<p>Finally, we added directional and temporal features, including alignment with the evacuation zone, alignment and closing-speed interactions, threat pressure, cross-track movement, bearing strength, movement flags, perimeter density, short-window indicators, low temporal resolution indicators, and cyclical encodings for hour, day of week, and month.</p>\n<h2>Modeling Approach</h2>\n<p>Our final approach was a seed-bagged, horizon-specific ensemble with survival-risk blending and monotonic post-processing. Since the required outputs were cumulative probabilities at 12, 24, 48, and 72 hours, we trained the model around those time horizons instead of using one general prediction.</p>\n<p>We used LightGBM, XGBoost, and CatBoost as horizon-specific tree-based models. For 12 and 24 hours, these models predicted whether a fire would threaten an evacuation zone by that time. For 48 hours, we used a tail-modeling approach to estimate the additional probability of a threat between 24 and 48 hours. The 72-hour probability was extended from the 48-hour probability using the late-event rate from the training data.</p>\n<p>Because the dataset included censored examples, we used censor-aware training and inverse probability of censoring weighting. This helped avoid treating unknown outcomes as negatives and made the usable examples better represent the full training distribution.</p>\n<p>We also trained XGBoost Cox and XGBoost AFT models to capture the time-to-event structure. Their outputs were converted into horizon probabilities using isotonic calibration and combined into one survival-risk component. The final prediction blended four components: LightGBM, XGBoost, CatBoost, and the Cox/AFT survival-risk component. Multiple random seeds were averaged for the tree-based models to improve stability.</p>\n<p>After blending, we applied post-processing. The 12-hour probability received an extra calibration adjustment because the earliest horizon was the most sensitive. We then applied a final consistency check so the cumulative probabilities followed the expected time ordering across the four horizons.</p>\n<h2>Validation and Metric</h2>\n<p>We used a local version of the competition metric to compare modeling ideas. The metric combined C-index and weighted Brier score. C-index measured how well the model ranked fires by urgency, while the weighted Brier score measured probability accuracy at the 24-hour, 48-hour, and 72-hour horizons.</p>\n<p>For the Brier score, censoring was handled by horizon. Fires that hit before the horizon were labeled as 1, fires still observed past the horizon without hitting were labeled as 0, and fires censored before the horizon were excluded because their true outcome was unknown.</p>\n<p>Since the final score placed more weight on probability calibration than ranking, we focused on stable and well-calibrated probabilities. This is why horizon-specific models, censor-aware labels, calibration, and post-processing were important.</p>\n<h2>Reproducibility</h2>\n<p>The final submission can be reproduced using the terminal-executable script <code>src/Submission/submit.py</code>. This script loads the data, applies the same feature engineering used in the final solution, trains the model components, loads the saved blending settings from <code>src/models/stack_bundle.joblib</code>, blends the model outputs, and creates the final submission file.</p>\n<p>The generated submission is saved to:</p>\n<p><code>src/Submission/submission.csv</code></p>\n<p>The original notebook workflow is also included as <code>src/Submission/submit.ipynb</code> for review. The notebook shows the same final modeling workflow in notebook form, while the Python script provides a cleaner command-line version for reproducibility.</p>\n<p>To verify reproducibility, we included <code>check_reproducibility.py</code> in the <code>src/ReproducibilityCheck</code> folder. This script regenerates the submission and saves it as:</p>\n<p><code>src/ReproducibilityCheck/generated_submission.csv</code></p>\n<p>It then compares the regenerated file with the Kaggle-downloaded submission file:</p>\n<p><code>src/ReproducibilityCheck/kaggle_submission.csv</code></p>\n<p>The reproducibility check verifies that the event IDs match and that the prediction values match within a small floating-point tolerance. The check saves and reloads the generated predictions before comparison to avoid confusion from tiny in-memory floating-point formatting differences.</p>\n<p>The full final pipeline took <strong>99.40 seconds</strong>, or about <strong>1 minute and 39 seconds</strong>, in our tested environment.</p>\n<h2>Code</h2>\n<p>The code for our final solution is available here: <a href=\"https://github.com/Rishik15/WiDs\" target=\"_blank\">GitHub Repository</a>. </p>\n<p>The repository includes the terminal-executable final submission script, the original final submission notebook, the reproducibility check script, the reproducibility check notebook, and the saved blending settings needed to reproduce the submitted file.</p>\n<p>The main files are:</p>\n<ul>\n<li><code>src/Submission/submit.py</code>: terminal-executable script that reproduces the final submission.</li>\n<li><code>src/Submission/submit.ipynb</code>: original notebook version of the final workflow.</li>\n<li><code>src/ReproducibilityCheck/check_reproducibility.py</code>: script that regenerates the submission and compares it with the Kaggle-downloaded submission.</li>\n<li><code>src/ReproducibilityCheck/reproducibilityCheck.ipynb</code>: notebook version of the reproducibility check.</li>\n<li><code>src/models/stack_bundle.joblib</code>: saved blending and post-processing settings used by the final workflow.</li>\n</ul>\n<p>The final solution can be run from the project root using:</p>\n<p><code>python -m src.Submission.submit</code></p>\n<p>or, using uv:</p>\n<p><code>uv run python -m src.Submission.submit</code></p>\n<p>The reproducibility check can be run using:</p>\n<p><code>python -m src.ReproducibilityCheck.check_reproducibility</code></p>\n<p>or, using uv:</p>\n<p><code>uv run python -m src.ReproducibilityCheck.check_reproducibility</code></p>\n<h2>What Worked Well</h2>\n<p>The most important part of our solution was building around the four prediction horizons instead of using one general risk prediction. This made the model outputs more directly connected to the required submission probabilities.</p>\n<p>Feature engineering also made a big difference. Distance, movement, fire growth, alignment, and estimated time-to-arrival features gave the models clearer signals about whether a fire was likely to threaten an evacuation zone soon.</p>\n<p>The ensemble approach helped make predictions more stable. Averaging multiple seeds reduced variance, and combining tree-based models with Cox and AFT survival-risk models helped balance probability calibration with urgency ranking.</p>\n<h2>Team</h2>\n<p>BTT_Heatwave consisted of Rishik Yesgari and Ayooluwa Wojuade. We met through the Break Through Tech AI program.</p>\n<h2>Sources</h2>\n<p>The final solution used the competition-provided data and the following software libraries and documentation:</p>\n<ul>\n<li>Kaggle competition overview: <a href=\"https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/overview\" target=\"_blank\">https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/overview</a></li>\n<li>Kaggle competition data page: <a href=\"https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/data\" target=\"_blank\">https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/data</a></li>\n<li>LightGBM documentation: <a href=\"https://lightgbm.readthedocs.io\" target=\"_blank\">https://lightgbm.readthedocs.io</a></li>\n<li>XGBoost documentation: <a href=\"https://xgboost.readthedocs.io\" target=\"_blank\">https://xgboost.readthedocs.io</a></li>\n<li>CatBoost documentation: <a href=\"https://catboost.ai\" target=\"_blank\">https://catboost.ai</a></li>\n<li>scikit-learn documentation: <a href=\"https://scikit-learn.org\" target=\"_blank\">https://scikit-learn.org</a></li>\n<li>pandas documentation: <a href=\"https://pandas.pydata.org\" target=\"_blank\">https://pandas.pydata.org</a></li>\n<li>NumPy documentation: <a href=\"https://numpy.org\" target=\"_blank\">https://numpy.org</a></li>\n<li>joblib documentation: <a href=\"https://joblib.readthedocs.io\" target=\"_blank\">https://joblib.readthedocs.io</a></li>\n<li>lifelines documentation: <a href=\"https://lifelines.readthedocs.io\" target=\"_blank\">https://lifelines.readthedocs.io</a></li>\n<li>scikit-survival documentation: <a href=\"https://scikit-survival.readthedocs.io\" target=\"_blank\">https://scikit-survival.readthedocs.io</a></li>\n</ul>",
  "comments": [],
  "comment_count": 0,
  "messages": [
    {
      "id": 3467318,
      "postDate": "2026-06-05T22:23:19.400Z",
      "content": "<p><strong>Team Name:</strong> BTT_Heatwave<br>\n<strong>Team Members:</strong> Rishik Yesgari and Ayooluwa Wojuade<br>\n<strong>Private Leaderboard Score:</strong> 0.97250<br>\n<strong>Private Leaderboard Place:</strong> 3rd Place  </p>\n<h2>Overview</h2>\n<p>This competition focused on predicting when a wildfire may threaten an evacuation zone. For each fire, we estimated the probability of a threat within 12, 24, 48, and 72 hours using only the first five hours of fire perimeter information.</p>\n<p>This was a right-censored survival prediction problem. Some fires reached an evacuation zone, while others did not during the observation window. For censored fires, we only know that a hit was not observed during the available time. Because of this, the model had to handle event timing and censoring while still producing calibrated probabilities for fixed horizons.</p>\n<p>Our approach was to build a horizon-specific ensemble. We engineered features for distance, movement, fire growth, alignment, and estimated time to reach an evacuation zone. Then we trained multiple model families, combined their outputs, and applied post-processing so the final probabilities stayed valid and followed the required cumulative order over time.</p>\n<h2>Main Idea</h2>\n<p>The main idea was to avoid treating the task as one single classification problem. Since the competition required probabilities at four horizons, we built the solution around those horizons directly. A fire that may threaten an evacuation zone within 12 hours can behave differently from one that becomes risky closer to 48 or 72 hours.</p>\n<p>We also handled censoring carefully. For each horizon, fires censored before that horizon were not treated as clear negatives because their true outcome was unknown. We built horizon-specific labels only from examples where the outcome was known and used censor-aware weighting to reduce bias.</p>\n<p>The final solution combined two views of the problem. Horizon-specific models helped produce calibrated probabilities for fixed time windows, while survival-risk models helped capture the overall urgency ranking of fires. This matched the competition metric, which rewarded both ranking and probability calibration.</p>\n<h2>Feature Engineering</h2>\n<p>Feature engineering was important because the original columns did not fully capture the relationship between the fire, its movement, and the nearest evacuation zone. We created features that described closeness, movement, growth, direction, and estimated arrival time.</p>\n<p>The engineered features included distance transformations such as distance in kilometers, log distance, square-root distance, inverse distance, and distance-zone indicators. We also added distance trend features such as normalized distance change, normalized distance slope, normalized distance variation, distance acceleration, and a distance-trend reliability flag.</p>\n<p>We created movement and ETA-based features using closing speed, radial growth rate, effective closing speed, and along-track speed. From these, we estimated time-to-arrival values and horizon-specific ETA indicators for 12, 24, 48, and 72 hours. We also added fire size and growth features such as estimated fire radius, radius-to-distance ratio, area-to-distance ratio, growth-to-distance ratio, and radial-growth-to-distance ratio.</p>\n<p>Finally, we added directional and temporal features, including alignment with the evacuation zone, alignment and closing-speed interactions, threat pressure, cross-track movement, bearing strength, movement flags, perimeter density, short-window indicators, low temporal resolution indicators, and cyclical encodings for hour, day of week, and month.</p>\n<h2>Modeling Approach</h2>\n<p>Our final approach was a seed-bagged, horizon-specific ensemble with survival-risk blending and monotonic post-processing. Since the required outputs were cumulative probabilities at 12, 24, 48, and 72 hours, we trained the model around those time horizons instead of using one general prediction.</p>\n<p>We used LightGBM, XGBoost, and CatBoost as horizon-specific tree-based models. For 12 and 24 hours, these models predicted whether a fire would threaten an evacuation zone by that time. For 48 hours, we used a tail-modeling approach to estimate the additional probability of a threat between 24 and 48 hours. The 72-hour probability was extended from the 48-hour probability using the late-event rate from the training data.</p>\n<p>Because the dataset included censored examples, we used censor-aware training and inverse probability of censoring weighting. This helped avoid treating unknown outcomes as negatives and made the usable examples better represent the full training distribution.</p>\n<p>We also trained XGBoost Cox and XGBoost AFT models to capture the time-to-event structure. Their outputs were converted into horizon probabilities using isotonic calibration and combined into one survival-risk component. The final prediction blended four components: LightGBM, XGBoost, CatBoost, and the Cox/AFT survival-risk component. Multiple random seeds were averaged for the tree-based models to improve stability.</p>\n<p>After blending, we applied post-processing. The 12-hour probability received an extra calibration adjustment because the earliest horizon was the most sensitive. We then applied a final consistency check so the cumulative probabilities followed the expected time ordering across the four horizons.</p>\n<h2>Validation and Metric</h2>\n<p>We used a local version of the competition metric to compare modeling ideas. The metric combined C-index and weighted Brier score. C-index measured how well the model ranked fires by urgency, while the weighted Brier score measured probability accuracy at the 24-hour, 48-hour, and 72-hour horizons.</p>\n<p>For the Brier score, censoring was handled by horizon. Fires that hit before the horizon were labeled as 1, fires still observed past the horizon without hitting were labeled as 0, and fires censored before the horizon were excluded because their true outcome was unknown.</p>\n<p>Since the final score placed more weight on probability calibration than ranking, we focused on stable and well-calibrated probabilities. This is why horizon-specific models, censor-aware labels, calibration, and post-processing were important.</p>\n<h2>Reproducibility</h2>\n<p>The final submission can be reproduced using the terminal-executable script <code>src/Submission/submit.py</code>. This script loads the data, applies the same feature engineering used in the final solution, trains the model components, loads the saved blending settings from <code>src/models/stack_bundle.joblib</code>, blends the model outputs, and creates the final submission file.</p>\n<p>The generated submission is saved to:</p>\n<p><code>src/Submission/submission.csv</code></p>\n<p>The original notebook workflow is also included as <code>src/Submission/submit.ipynb</code> for review. The notebook shows the same final modeling workflow in notebook form, while the Python script provides a cleaner command-line version for reproducibility.</p>\n<p>To verify reproducibility, we included <code>check_reproducibility.py</code> in the <code>src/ReproducibilityCheck</code> folder. This script regenerates the submission and saves it as:</p>\n<p><code>src/ReproducibilityCheck/generated_submission.csv</code></p>\n<p>It then compares the regenerated file with the Kaggle-downloaded submission file:</p>\n<p><code>src/ReproducibilityCheck/kaggle_submission.csv</code></p>\n<p>The reproducibility check verifies that the event IDs match and that the prediction values match within a small floating-point tolerance. The check saves and reloads the generated predictions before comparison to avoid confusion from tiny in-memory floating-point formatting differences.</p>\n<p>The full final pipeline took <strong>99.40 seconds</strong>, or about <strong>1 minute and 39 seconds</strong>, in our tested environment.</p>\n<h2>Code</h2>\n<p>The code for our final solution is available here: <a href=\"https://github.com/Rishik15/WiDs\" target=\"_blank\">GitHub Repository</a>. </p>\n<p>The repository includes the terminal-executable final submission script, the original final submission notebook, the reproducibility check script, the reproducibility check notebook, and the saved blending settings needed to reproduce the submitted file.</p>\n<p>The main files are:</p>\n<ul>\n<li><code>src/Submission/submit.py</code>: terminal-executable script that reproduces the final submission.</li>\n<li><code>src/Submission/submit.ipynb</code>: original notebook version of the final workflow.</li>\n<li><code>src/ReproducibilityCheck/check_reproducibility.py</code>: script that regenerates the submission and compares it with the Kaggle-downloaded submission.</li>\n<li><code>src/ReproducibilityCheck/reproducibilityCheck.ipynb</code>: notebook version of the reproducibility check.</li>\n<li><code>src/models/stack_bundle.joblib</code>: saved blending and post-processing settings used by the final workflow.</li>\n</ul>\n<p>The final solution can be run from the project root using:</p>\n<p><code>python -m src.Submission.submit</code></p>\n<p>or, using uv:</p>\n<p><code>uv run python -m src.Submission.submit</code></p>\n<p>The reproducibility check can be run using:</p>\n<p><code>python -m src.ReproducibilityCheck.check_reproducibility</code></p>\n<p>or, using uv:</p>\n<p><code>uv run python -m src.ReproducibilityCheck.check_reproducibility</code></p>\n<h2>What Worked Well</h2>\n<p>The most important part of our solution was building around the four prediction horizons instead of using one general risk prediction. This made the model outputs more directly connected to the required submission probabilities.</p>\n<p>Feature engineering also made a big difference. Distance, movement, fire growth, alignment, and estimated time-to-arrival features gave the models clearer signals about whether a fire was likely to threaten an evacuation zone soon.</p>\n<p>The ensemble approach helped make predictions more stable. Averaging multiple seeds reduced variance, and combining tree-based models with Cox and AFT survival-risk models helped balance probability calibration with urgency ranking.</p>\n<h2>Team</h2>\n<p>BTT_Heatwave consisted of Rishik Yesgari and Ayooluwa Wojuade. We met through the Break Through Tech AI program.</p>\n<h2>Sources</h2>\n<p>The final solution used the competition-provided data and the following software libraries and documentation:</p>\n<ul>\n<li>Kaggle competition overview: <a href=\"https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/overview\" target=\"_blank\">https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/overview</a></li>\n<li>Kaggle competition data page: <a href=\"https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/data\" target=\"_blank\">https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/data</a></li>\n<li>LightGBM documentation: <a href=\"https://lightgbm.readthedocs.io\" target=\"_blank\">https://lightgbm.readthedocs.io</a></li>\n<li>XGBoost documentation: <a href=\"https://xgboost.readthedocs.io\" target=\"_blank\">https://xgboost.readthedocs.io</a></li>\n<li>CatBoost documentation: <a href=\"https://catboost.ai\" target=\"_blank\">https://catboost.ai</a></li>\n<li>scikit-learn documentation: <a href=\"https://scikit-learn.org\" target=\"_blank\">https://scikit-learn.org</a></li>\n<li>pandas documentation: <a href=\"https://pandas.pydata.org\" target=\"_blank\">https://pandas.pydata.org</a></li>\n<li>NumPy documentation: <a href=\"https://numpy.org\" target=\"_blank\">https://numpy.org</a></li>\n<li>joblib documentation: <a href=\"https://joblib.readthedocs.io\" target=\"_blank\">https://joblib.readthedocs.io</a></li>\n<li>lifelines documentation: <a href=\"https://lifelines.readthedocs.io\" target=\"_blank\">https://lifelines.readthedocs.io</a></li>\n<li>scikit-survival documentation: <a href=\"https://scikit-survival.readthedocs.io\" target=\"_blank\">https://scikit-survival.readthedocs.io</a></li>\n</ul>",
      "rawMarkdown": "**Team Name:** BTT_Heatwave  \n**Team Members:** Rishik Yesgari and Ayooluwa Wojuade  \n**Private Leaderboard Score:** 0.97250  \n**Private Leaderboard Place:** 3rd Place  \n\n## Overview\n\nThis competition focused on predicting when a wildfire may threaten an evacuation zone. For each fire, we estimated the probability of a threat within 12, 24, 48, and 72 hours using only the first five hours of fire perimeter information.\n\nThis was a right-censored survival prediction problem. Some fires reached an evacuation zone, while others did not during the observation window. For censored fires, we only know that a hit was not observed during the available time. Because of this, the model had to handle event timing and censoring while still producing calibrated probabilities for fixed horizons.\n\nOur approach was to build a horizon-specific ensemble. We engineered features for distance, movement, fire growth, alignment, and estimated time to reach an evacuation zone. Then we trained multiple model families, combined their outputs, and applied post-processing so the final probabilities stayed valid and followed the required cumulative order over time.\n\n## Main Idea\n\nThe main idea was to avoid treating the task as one single classification problem. Since the competition required probabilities at four horizons, we built the solution around those horizons directly. A fire that may threaten an evacuation zone within 12 hours can behave differently from one that becomes risky closer to 48 or 72 hours.\n\nWe also handled censoring carefully. For each horizon, fires censored before that horizon were not treated as clear negatives because their true outcome was unknown. We built horizon-specific labels only from examples where the outcome was known and used censor-aware weighting to reduce bias.\n\nThe final solution combined two views of the problem. Horizon-specific models helped produce calibrated probabilities for fixed time windows, while survival-risk models helped capture the overall urgency ranking of fires. This matched the competition metric, which rewarded both ranking and probability calibration.\n\n## Feature Engineering\n\nFeature engineering was important because the original columns did not fully capture the relationship between the fire, its movement, and the nearest evacuation zone. We created features that described closeness, movement, growth, direction, and estimated arrival time.\n\nThe engineered features included distance transformations such as distance in kilometers, log distance, square-root distance, inverse distance, and distance-zone indicators. We also added distance trend features such as normalized distance change, normalized distance slope, normalized distance variation, distance acceleration, and a distance-trend reliability flag.\n\nWe created movement and ETA-based features using closing speed, radial growth rate, effective closing speed, and along-track speed. From these, we estimated time-to-arrival values and horizon-specific ETA indicators for 12, 24, 48, and 72 hours. We also added fire size and growth features such as estimated fire radius, radius-to-distance ratio, area-to-distance ratio, growth-to-distance ratio, and radial-growth-to-distance ratio.\n\nFinally, we added directional and temporal features, including alignment with the evacuation zone, alignment and closing-speed interactions, threat pressure, cross-track movement, bearing strength, movement flags, perimeter density, short-window indicators, low temporal resolution indicators, and cyclical encodings for hour, day of week, and month.\n\n## Modeling Approach\n\nOur final approach was a seed-bagged, horizon-specific ensemble with survival-risk blending and monotonic post-processing. Since the required outputs were cumulative probabilities at 12, 24, 48, and 72 hours, we trained the model around those time horizons instead of using one general prediction.\n\nWe used LightGBM, XGBoost, and CatBoost as horizon-specific tree-based models. For 12 and 24 hours, these models predicted whether a fire would threaten an evacuation zone by that time. For 48 hours, we used a tail-modeling approach to estimate the additional probability of a threat between 24 and 48 hours. The 72-hour probability was extended from the 48-hour probability using the late-event rate from the training data.\n\nBecause the dataset included censored examples, we used censor-aware training and inverse probability of censoring weighting. This helped avoid treating unknown outcomes as negatives and made the usable examples better represent the full training distribution.\n\nWe also trained XGBoost Cox and XGBoost AFT models to capture the time-to-event structure. Their outputs were converted into horizon probabilities using isotonic calibration and combined into one survival-risk component. The final prediction blended four components: LightGBM, XGBoost, CatBoost, and the Cox/AFT survival-risk component. Multiple random seeds were averaged for the tree-based models to improve stability.\n\nAfter blending, we applied post-processing. The 12-hour probability received an extra calibration adjustment because the earliest horizon was the most sensitive. We then applied a final consistency check so the cumulative probabilities followed the expected time ordering across the four horizons.\n\n## Validation and Metric\n\nWe used a local version of the competition metric to compare modeling ideas. The metric combined C-index and weighted Brier score. C-index measured how well the model ranked fires by urgency, while the weighted Brier score measured probability accuracy at the 24-hour, 48-hour, and 72-hour horizons.\n\nFor the Brier score, censoring was handled by horizon. Fires that hit before the horizon were labeled as 1, fires still observed past the horizon without hitting were labeled as 0, and fires censored before the horizon were excluded because their true outcome was unknown.\n\nSince the final score placed more weight on probability calibration than ranking, we focused on stable and well-calibrated probabilities. This is why horizon-specific models, censor-aware labels, calibration, and post-processing were important.\n\n## Reproducibility\n\nThe final submission can be reproduced using the terminal-executable script `src/Submission/submit.py`. This script loads the data, applies the same feature engineering used in the final solution, trains the model components, loads the saved blending settings from `src/models/stack_bundle.joblib`, blends the model outputs, and creates the final submission file.\n\nThe generated submission is saved to:\n\n`src/Submission/submission.csv`\n\nThe original notebook workflow is also included as `src/Submission/submit.ipynb` for review. The notebook shows the same final modeling workflow in notebook form, while the Python script provides a cleaner command-line version for reproducibility.\n\nTo verify reproducibility, we included `check_reproducibility.py` in the `src/ReproducibilityCheck` folder. This script regenerates the submission and saves it as:\n\n`src/ReproducibilityCheck/generated_submission.csv`\n\nIt then compares the regenerated file with the Kaggle-downloaded submission file:\n\n`src/ReproducibilityCheck/kaggle_submission.csv`\n\nThe reproducibility check verifies that the event IDs match and that the prediction values match within a small floating-point tolerance. The check saves and reloads the generated predictions before comparison to avoid confusion from tiny in-memory floating-point formatting differences.\n\nThe full final pipeline took **99.40 seconds**, or about **1 minute and 39 seconds**, in our tested environment.\n\n## Code\n\nThe code for our final solution is available here: [GitHub Repository](https://github.com/Rishik15/WiDs). \n\nThe repository includes the terminal-executable final submission script, the original final submission notebook, the reproducibility check script, the reproducibility check notebook, and the saved blending settings needed to reproduce the submitted file.\n\nThe main files are:\n\n* `src/Submission/submit.py`: terminal-executable script that reproduces the final submission.\n* `src/Submission/submit.ipynb`: original notebook version of the final workflow.\n* `src/ReproducibilityCheck/check_reproducibility.py`: script that regenerates the submission and compares it with the Kaggle-downloaded submission.\n* `src/ReproducibilityCheck/reproducibilityCheck.ipynb`: notebook version of the reproducibility check.\n* `src/models/stack_bundle.joblib`: saved blending and post-processing settings used by the final workflow.\n\nThe final solution can be run from the project root using:\n\n`python -m src.Submission.submit`\n\nor, using uv:\n\n`uv run python -m src.Submission.submit`\n\nThe reproducibility check can be run using:\n\n`python -m src.ReproducibilityCheck.check_reproducibility`\n\nor, using uv:\n\n`uv run python -m src.ReproducibilityCheck.check_reproducibility`\n\n## What Worked Well\n\nThe most important part of our solution was building around the four prediction horizons instead of using one general risk prediction. This made the model outputs more directly connected to the required submission probabilities.\n\nFeature engineering also made a big difference. Distance, movement, fire growth, alignment, and estimated time-to-arrival features gave the models clearer signals about whether a fire was likely to threaten an evacuation zone soon.\n\nThe ensemble approach helped make predictions more stable. Averaging multiple seeds reduced variance, and combining tree-based models with Cox and AFT survival-risk models helped balance probability calibration with urgency ranking.\n\n## Team\n\nBTT_Heatwave consisted of Rishik Yesgari and Ayooluwa Wojuade. We met through the Break Through Tech AI program.\n\n## Sources\n\nThe final solution used the competition-provided data and the following software libraries and documentation:\n\n* Kaggle competition overview: https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/overview\n* Kaggle competition data page: https://www.kaggle.com/competitions/WiDSWorldWide_GlobalDathon26/data\n* LightGBM documentation: https://lightgbm.readthedocs.io\n* XGBoost documentation: https://xgboost.readthedocs.io\n* CatBoost documentation: https://catboost.ai\n* scikit-learn documentation: https://scikit-learn.org\n* pandas documentation: https://pandas.pydata.org\n* NumPy documentation: https://numpy.org\n* joblib documentation: https://joblib.readthedocs.io\n* lifelines documentation: https://lifelines.readthedocs.io\n* scikit-survival documentation: https://scikit-survival.readthedocs.io",
      "votes": 2
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T08:49:39Z",
  "competition_id": 125681,
  "competition_slug": "WiDSWorldWide_GlobalDathon26",
  "team_id": 15179133,
  "solution_url": "/competitions/WiDSWorldWide_GlobalDathon26/writeups/wids-global-datathon-2026-solution-btt-heatwave"
}