{
  "id": 610252,
  "title": "2nd Place Solution",
  "url": "/competitions/ariel-data-challenge-2025/discussion/610252",
  "author_name": "BeeMax",
  "post_date": "2025-10-02T19:39:03.053000",
  "votes": 18,
  "comment_count": 1,
  "views": 0,
  "content": "<p><a href=\"https://www.kaggle.com/code/beemax/neurips-adc-25-2nd-place-submission\" target=\"_blank\">Submission notebook link</a></p>\n<h2>Introduction</h2>\n<p>First, I would like to thank the organizers for this great competition!</p>\n<p>My solution uses linear regression with transit depth estimation based on polynomial fitting. I didn't model the full physics of transits, but created features that capture transit shape patterns from light curves.</p>\n<h2>Data Preprocessing</h2>\n<p>I used the standard preprocessing provided by the competition without additional steps.</p>\n<h2>Feature Engineering</h2>\n<p>Most features are based on polynomial fitting. I found transit boundaries by detecting 4 extrema of the second derivative - points where the light curve curvature changes most rapidly. For depth estimation and detrending, I fit a polynomial of chosen degree to out-of-transit points and divide the curve by this interpolation.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2F477e16b77122a69c35507c5c38eea5d6%2Fextrems%20%20.png?generation=1759413459874481&amp;alt=media\" alt=\"\"></p>\n<p>The features fall into three main groups. First: depth estimates from AIRS frequencies averaged with SNR weights, inspired by last year's solutions. Second: depth estimates from intersecting windows across adjacent AIRS frequencies. Third: depth estimates from the FG1 channel separately.</p>\n<p>For the SNR-weighted group, I optimized polynomial degree (1-5) minimizing: err = RMSE × degree^(n_transit / n_total) where RMSE is calculated between the original curve and polynomial interpolation in out-of-transit regions, degree is the polynomial degree used for fitting, n_transit is the number of points inside the transit, and n_total is the total number of observation points. When transits occupy more of the observation, fewer points are available for baseline fitting, making higher degrees less reliable. This optimization gave only small improvement on private leaderboard. For other groups, I used fixed degree 3.</p>\n<p>For each of these three feature groups (AIRS averaged, AIRS windowed, FG1), I calculated multiple depth values: average across transit, mid-transit, and various percentiles. For frequency windows with too much noise, I didn't use polynomial interpolation but instead used a rough estimate based on the ratio of average flux inside and outside the transit.</p>\n<p>I also computed slope features for the SNR-weighted AIRS and FG1 groups only - these measure wall steepness as flux change rate between boundary points. Another small group used remaining physical information but provided little improvement.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2Fdf7a43fcdde1ffc3fe21cb8a8f5f1b7d%2Ffeats%20(2)%20%20.png?generation=1759414981223394&amp;alt=media\" alt=\"\"></p>\n<h2>Outlier Processing</h2>\n<p>I identified transits near observation edges as outliers and trained a separate Ridge model for them. The outlier model was trained on all data, while the main model used only normal cases. For very poor quality transits, I removed them during training and used larger sigma values for inference.</p>\n<h2>Sigma Estimation</h2>\n<p>For uncertainty estimation, I used bootstrapping: created multiple resampled datasets, trained models on each, took standard deviation of all model predictions, and multiplied by an optimized constant. This was combined linearly with cross-validation standard deviations averaged per frequency.</p>\n<h2>Small Ablation Study</h2>\n<p>Due to metric instability, results might improve with small feature and hyperparameter tuning.</p>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Public Score</th>\n<th>Private Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Full solution</td>\n<td>60.9</td>\n<td>61.2</td>\n</tr>\n<tr>\n<td>No SNR-weighted averaging</td>\n<td>60.6</td>\n<td>61.0</td>\n</tr>\n<tr>\n<td>No slope features</td>\n<td>52.6</td>\n<td>54.1</td>\n</tr>\n<tr>\n<td>No bootstrapping</td>\n<td>46.3</td>\n<td>57.6</td>\n</tr>\n<tr>\n<td>No degree optimizing</td>\n<td>60.4</td>\n<td>61.1</td>\n</tr>\n<tr>\n<td>No physical features</td>\n<td>60.2</td>\n<td>61.2</td>\n</tr>\n<tr>\n<td>No percentile features</td>\n<td>57.5</td>\n<td>57.2</td>\n</tr>\n</tbody>\n</table>\n<p><br></p>\n<p>In \"no bootstrapping\", I used RMSE estimates from validation, multiplied by 5 for outliers to prevent zero scores. In \"no percentile features\", I kept only average and mid-transit depth measurements.</p>\n<h2>Conclusion</h2>\n<p>Additional implementation details can be found in the notebook.</p>",
  "messages": [
    {
      "id": 3297294,
      "postDate": "2025-10-02T19:39:03.053Z",
      "content": "<p><a href=\"https://www.kaggle.com/code/beemax/neurips-adc-25-2nd-place-submission\" target=\"_blank\">Submission notebook link</a></p>\n<h2>Introduction</h2>\n<p>First, I would like to thank the organizers for this great competition!</p>\n<p>My solution uses linear regression with transit depth estimation based on polynomial fitting. I didn't model the full physics of transits, but created features that capture transit shape patterns from light curves.</p>\n<h2>Data Preprocessing</h2>\n<p>I used the standard preprocessing provided by the competition without additional steps.</p>\n<h2>Feature Engineering</h2>\n<p>Most features are based on polynomial fitting. I found transit boundaries by detecting 4 extrema of the second derivative - points where the light curve curvature changes most rapidly. For depth estimation and detrending, I fit a polynomial of chosen degree to out-of-transit points and divide the curve by this interpolation.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2F477e16b77122a69c35507c5c38eea5d6%2Fextrems%20%20.png?generation=1759413459874481&amp;alt=media\" alt=\"\"></p>\n<p>The features fall into three main groups. First: depth estimates from AIRS frequencies averaged with SNR weights, inspired by last year's solutions. Second: depth estimates from intersecting windows across adjacent AIRS frequencies. Third: depth estimates from the FG1 channel separately.</p>\n<p>For the SNR-weighted group, I optimized polynomial degree (1-5) minimizing: err = RMSE × degree^(n_transit / n_total) where RMSE is calculated between the original curve and polynomial interpolation in out-of-transit regions, degree is the polynomial degree used for fitting, n_transit is the number of points inside the transit, and n_total is the total number of observation points. When transits occupy more of the observation, fewer points are available for baseline fitting, making higher degrees less reliable. This optimization gave only small improvement on private leaderboard. For other groups, I used fixed degree 3.</p>\n<p>For each of these three feature groups (AIRS averaged, AIRS windowed, FG1), I calculated multiple depth values: average across transit, mid-transit, and various percentiles. For frequency windows with too much noise, I didn't use polynomial interpolation but instead used a rough estimate based on the ratio of average flux inside and outside the transit.</p>\n<p>I also computed slope features for the SNR-weighted AIRS and FG1 groups only - these measure wall steepness as flux change rate between boundary points. Another small group used remaining physical information but provided little improvement.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2Fdf7a43fcdde1ffc3fe21cb8a8f5f1b7d%2Ffeats%20(2)%20%20.png?generation=1759414981223394&amp;alt=media\" alt=\"\"></p>\n<h2>Outlier Processing</h2>\n<p>I identified transits near observation edges as outliers and trained a separate Ridge model for them. The outlier model was trained on all data, while the main model used only normal cases. For very poor quality transits, I removed them during training and used larger sigma values for inference.</p>\n<h2>Sigma Estimation</h2>\n<p>For uncertainty estimation, I used bootstrapping: created multiple resampled datasets, trained models on each, took standard deviation of all model predictions, and multiplied by an optimized constant. This was combined linearly with cross-validation standard deviations averaged per frequency.</p>\n<h2>Small Ablation Study</h2>\n<p>Due to metric instability, results might improve with small feature and hyperparameter tuning.</p>\n<table>\n<thead>\n<tr>\n<th>Method</th>\n<th>Public Score</th>\n<th>Private Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Full solution</td>\n<td>60.9</td>\n<td>61.2</td>\n</tr>\n<tr>\n<td>No SNR-weighted averaging</td>\n<td>60.6</td>\n<td>61.0</td>\n</tr>\n<tr>\n<td>No slope features</td>\n<td>52.6</td>\n<td>54.1</td>\n</tr>\n<tr>\n<td>No bootstrapping</td>\n<td>46.3</td>\n<td>57.6</td>\n</tr>\n<tr>\n<td>No degree optimizing</td>\n<td>60.4</td>\n<td>61.1</td>\n</tr>\n<tr>\n<td>No physical features</td>\n<td>60.2</td>\n<td>61.2</td>\n</tr>\n<tr>\n<td>No percentile features</td>\n<td>57.5</td>\n<td>57.2</td>\n</tr>\n</tbody>\n</table>\n<p><br></p>\n<p>In \"no bootstrapping\", I used RMSE estimates from validation, multiplied by 5 for outliers to prevent zero scores. In \"no percentile features\", I kept only average and mid-transit depth measurements.</p>\n<h2>Conclusion</h2>\n<p>Additional implementation details can be found in the notebook.</p>",
      "rawMarkdown": "[Submission notebook link](https://www.kaggle.com/code/beemax/neurips-adc-25-2nd-place-submission)\n\n## Introduction\n\nFirst, I would like to thank the organizers for this great competition!\n\nMy solution uses linear regression with transit depth estimation based on polynomial fitting. I didn't model the full physics of transits, but created features that capture transit shape patterns from light curves.\n\n## Data Preprocessing\n\nI used the standard preprocessing provided by the competition without additional steps.\n\n## Feature Engineering\n\nMost features are based on polynomial fitting. I found transit boundaries by detecting 4 extrema of the second derivative - points where the light curve curvature changes most rapidly. For depth estimation and detrending, I fit a polynomial of chosen degree to out-of-transit points and divide the curve by this interpolation.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2F477e16b77122a69c35507c5c38eea5d6%2Fextrems%20%20.png?generation=1759413459874481&alt=media)\n\nThe features fall into three main groups. First: depth estimates from AIRS frequencies averaged with SNR weights, inspired by last year's solutions. Second: depth estimates from intersecting windows across adjacent AIRS frequencies. Third: depth estimates from the FG1 channel separately.\n\nFor the SNR-weighted group, I optimized polynomial degree (1-5) minimizing: err = RMSE × degree^(n_transit / n_total) where RMSE is calculated between the original curve and polynomial interpolation in out-of-transit regions, degree is the polynomial degree used for fitting, n_transit is the number of points inside the transit, and n_total is the total number of observation points. When transits occupy more of the observation, fewer points are available for baseline fitting, making higher degrees less reliable. This optimization gave only small improvement on private leaderboard. For other groups, I used fixed degree 3.\n\nFor each of these three feature groups (AIRS averaged, AIRS windowed, FG1), I calculated multiple depth values: average across transit, mid-transit, and various percentiles. For frequency windows with too much noise, I didn't use polynomial interpolation but instead used a rough estimate based on the ratio of average flux inside and outside the transit.\n\nI also computed slope features for the SNR-weighted AIRS and FG1 groups only - these measure wall steepness as flux change rate between boundary points. Another small group used remaining physical information but provided little improvement.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2Fdf7a43fcdde1ffc3fe21cb8a8f5f1b7d%2Ffeats%20(2)%20%20.png?generation=1759414981223394&alt=media)\n\n## Outlier Processing\n\nI identified transits near observation edges as outliers and trained a separate Ridge model for them. The outlier model was trained on all data, while the main model used only normal cases. For very poor quality transits, I removed them during training and used larger sigma values for inference.\n\n## Sigma Estimation\n\nFor uncertainty estimation, I used bootstrapping: created multiple resampled datasets, trained models on each, took standard deviation of all model predictions, and multiplied by an optimized constant. This was combined linearly with cross-validation standard deviations averaged per frequency.\n\n## Small Ablation Study\n\nDue to metric instability, results might improve with small feature and hyperparameter tuning.\n\n| Method | Public Score | Private Score |\n|--------|-------------|---------------|\n| Full solution | 60.9 | 61.2 |\n| No SNR-weighted averaging | 60.6 | 61.0 |\n| No slope features | 52.6 | 54.1 |\n| No bootstrapping | 46.3 | 57.6 |\n| No degree optimizing | 60.4 | 61.1 |\n| No physical features | 60.2 | 61.2 |\n| No percentile features | 57.5 | 57.2 |\n\n<br>\n\nIn \"no bootstrapping\", I used RMSE estimates from validation, multiplied by 5 for outliers to prevent zero scores. In \"no percentile features\", I kept only average and mid-transit depth measurements.\n\n## Conclusion\n\nAdditional implementation details can be found in the notebook.",
      "votes": 18
    },
    {
      "id": 3298142,
      "postDate": "2025-10-04T16:10:50.330Z",
      "content": "<p>Thank you for sharing these insights!</p>",
      "rawMarkdown": "Thank you for sharing these insights!"
    }
  ],
  "comments": [
    {
      "id": 3298142,
      "author_name": "Irakoze Ntawigenga Kelly",
      "author_url": "",
      "post_date": "2025-10-04T16:10:50.330000",
      "content": "<p>Thank you for sharing these insights!</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3297294": "[Submission notebook link](https://www.kaggle.com/code/beemax/neurips-adc-25-2nd-place-submission)\n\n## Introduction\n\nFirst, I would like to thank the organizers for this great competition!\n\nMy solution uses linear regression with transit depth estimation based on polynomial fitting. I didn't model the full physics of transits, but created features that capture transit shape patterns from light curves.\n\n## Data Preprocessing\n\nI used the standard preprocessing provided by the competition without additional steps.\n\n## Feature Engineering\n\nMost features are based on polynomial fitting. I found transit boundaries by detecting 4 extrema of the second derivative - points where the light curve curvature changes most rapidly. For depth estimation and detrending, I fit a polynomial of chosen degree to out-of-transit points and divide the curve by this interpolation.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2F477e16b77122a69c35507c5c38eea5d6%2Fextrems%20%20.png?generation=1759413459874481&alt=media)\n\nThe features fall into three main groups. First: depth estimates from AIRS frequencies averaged with SNR weights, inspired by last year's solutions. Second: depth estimates from intersecting windows across adjacent AIRS frequencies. Third: depth estimates from the FG1 channel separately.\n\nFor the SNR-weighted group, I optimized polynomial degree (1-5) minimizing: err = RMSE × degree^(n_transit / n_total) where RMSE is calculated between the original curve and polynomial interpolation in out-of-transit regions, degree is the polynomial degree used for fitting, n_transit is the number of points inside the transit, and n_total is the total number of observation points. When transits occupy more of the observation, fewer points are available for baseline fitting, making higher degrees less reliable. This optimization gave only small improvement on private leaderboard. For other groups, I used fixed degree 3.\n\nFor each of these three feature groups (AIRS averaged, AIRS windowed, FG1), I calculated multiple depth values: average across transit, mid-transit, and various percentiles. For frequency windows with too much noise, I didn't use polynomial interpolation but instead used a rough estimate based on the ratio of average flux inside and outside the transit.\n\nI also computed slope features for the SNR-weighted AIRS and FG1 groups only - these measure wall steepness as flux change rate between boundary points. Another small group used remaining physical information but provided little improvement.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F10580442%2Fdf7a43fcdde1ffc3fe21cb8a8f5f1b7d%2Ffeats%20(2)%20%20.png?generation=1759414981223394&alt=media)\n\n## Outlier Processing\n\nI identified transits near observation edges as outliers and trained a separate Ridge model for them. The outlier model was trained on all data, while the main model used only normal cases. For very poor quality transits, I removed them during training and used larger sigma values for inference.\n\n## Sigma Estimation\n\nFor uncertainty estimation, I used bootstrapping: created multiple resampled datasets, trained models on each, took standard deviation of all model predictions, and multiplied by an optimized constant. This was combined linearly with cross-validation standard deviations averaged per frequency.\n\n## Small Ablation Study\n\nDue to metric instability, results might improve with small feature and hyperparameter tuning.\n\n| Method | Public Score | Private Score |\n|--------|-------------|---------------|\n| Full solution | 60.9 | 61.2 |\n| No SNR-weighted averaging | 60.6 | 61.0 |\n| No slope features | 52.6 | 54.1 |\n| No bootstrapping | 46.3 | 57.6 |\n| No degree optimizing | 60.4 | 61.1 |\n| No physical features | 60.2 | 61.2 |\n| No percentile features | 57.5 | 57.2 |\n\n<br>\n\nIn \"no bootstrapping\", I used RMSE estimates from validation, multiplied by 5 for outliers to prevent zero scores. In \"no percentile features\", I kept only average and mid-transit depth measurements.\n\n## Conclusion\n\nAdditional implementation details can be found in the notebook.",
    "3298142": "Thank you for sharing these insights!"
  }
}