{
  "id": 418134,
  "title": "ETS, Linear Models, and MARS",
  "content": "<p>Below is a brief description + thoughts on my forecasting solution.<br>\n<strong>Private LB Place</strong>: 122/3,546<br>\n<strong>Private LB Score</strong>: 3.9884<br>\n<strong>Code</strong>: <a href=\"https://www.kaggle.com/code/abandura/mbd-forecasting-w-mars-lms-r\" target=\"_blank\">https://www.kaggle.com/code/abandura/mbd-forecasting-w-mars-lms-r</a></p>\n<p>Thanks to everyone who shared their insights and code!</p>\n<h2>Pre-Processing</h2>\n<p>Many counties exhibit level shifts in their historical microbusiness density, which reduces overall accuracy if simply included in the modeling process. I separated these from the rest of the counties by identifying any counties with a month-to-month change greater than 25%, and simply used last value predictions for them. Many other contestants took a similar approach. Looking at the size distribution of these counties (visualized in the histogram below) we can see that it excludes most of the smallest counties as well as a group of larger volume counties.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F12985b7771d35940abaa8a6db8e72484%2Fexcl_cfips.png?generation=1687123492757230&amp;alt=media\" alt=\"\"></p>\n<p>Small counties are unpredictable, as a single domain registration can dramatically change the density. However, looking at the larger counties with high variance it's clear that there is still a strong signal in many of them that could be leveraged for better predictions than a simple last value. For example, county ID 24013 has only one level shift up early on in the data set, and data before that shift could be removed and then interpolated so that it could be included in the forecast model training/prediction process. County IDs 10003 and 32510  have two level shifts that creates a \"hump\", which could be corrected in a similar manner using interpolation. I had planned to implement an algorithm to correct shifts for these larger counties, but unfortunately ran out of time. </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6b3c0541a03e4f405b1aa745b943d5b6%2Flarge_excl_cfips.png?generation=1687123510916081&amp;alt=media\" alt=\"\"></p>\n<p>Like many others, I also made the \"percent change\" adjustment to microbusiness density before training so that loss metrics like RMSE would weight small counties higher in the same way that SMAPE does. I used that adjusted target for all training other than the linear models, because they can be flexibly trained to directly minimize SMAPE (as described below).</p>\n<h2>Traditional Time-Series Forecasting, and other features</h2>\n<p>Of the traditional autoregressive time-series forecasting methods (ARIMA, Holt-Winters, Exponential Smoothing, etc.) that I tried, Exponential Smoothing (ETS) was the best. I ended up using ETS forecasts as features for the linear modeling by rolling through the data and generating ets forecasts for 1-6 month time horizons.</p>\n<p>Other features I toyed with included moving-average terms, difference terms, month and year, and the average of all previous MB density values. </p>\n<h2>CV Strategy</h2>\n<p>For CV I used the last 6 months of data, as shown below, and trained separate models for each forecast horizon. I wanted to use as much data as possible for training, since we only had a few years of historical data spanning the pandemic.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6ae7279f1d78b31a125355f0c2d34cd8%2Fcv_strategy.png?generation=1687123527511586&amp;alt=media\" alt=\"\"></p>\n<h2>Linear Modeling via Optimization</h2>\n<p>I tried other ML approaches like XGBoost, but found the most success with the simpler linear models.</p>\n<p>Another nice feature of linear models is you can directly fit them to minimize SMAPE by solving the optimization problem with the following objective:</p>\n<pre><code>\nfn  par df r_cols y norm_col l2 l1 \n  preds  par df.N\n  l2p  \n  l1p  \n   ind  par \n    i_col  r_colsind\n    preds  preds  parinddf geti_colmeangeti_colsdgeti_col\n    l2p  l2p  l2parind\n    l1p  l1p  l1parind\n  \n  err  smapeadfgety fcpreds  l1p  l2p\n  err\n\n</code></pre>\n<p>I tested L1 and L2 regularization, but found the lowest CV accuracy with no regularization. Looking at the fitted weight magnitudes, it seems that MA terms are most important in the forecasts. This was my best-scoring final submission.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F8b4a56ee77fff6fe87562ab6916726f5%2Flm_weights.png?generation=1687130521279924&amp;alt=media\" alt=\"\"></p>\n<h2>Multivariate adaptive regression spline (MARS)</h2>\n<p><a href=\"https://en.wikipedia.org/wiki/Multivariate_adaptive_regression_spline\" target=\"_blank\">https://en.wikipedia.org/wiki/Multivariate_adaptive_regression_spline</a></p>\n<p>Because I had success with the LMs, I though that MARS would be a natural improvement since it is an algorithm for fitting piecewise linear models to automatically deal with non-linearities and incorporate variable interactions.</p>\n<p>I did some hyperparameter tuning, but had the most success with the default parameters, and based on the CV accuracy I hoped it would outperform the LMs. However that wasn't the case with the private LB (I'm still not sure why, perhaps MARS was more sensitive to erroneous Dec data…)</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2Fb41c10f7948ea74940de90bd4e8f357a%2Fsmape_comp.png?generation=1687127830752749&amp;alt=media\" alt=\"\"></p>",
  "comments": [],
  "comment_count": 0,
  "messages": [
    {
      "id": 2308446,
      "postDate": "2023-06-19T00:22:50.377Z",
      "content": "<p>Below is a brief description + thoughts on my forecasting solution.<br>\n<strong>Private LB Place</strong>: 122/3,546<br>\n<strong>Private LB Score</strong>: 3.9884<br>\n<strong>Code</strong>: <a href=\"https://www.kaggle.com/code/abandura/mbd-forecasting-w-mars-lms-r\" target=\"_blank\">https://www.kaggle.com/code/abandura/mbd-forecasting-w-mars-lms-r</a></p>\n<p>Thanks to everyone who shared their insights and code!</p>\n<h2>Pre-Processing</h2>\n<p>Many counties exhibit level shifts in their historical microbusiness density, which reduces overall accuracy if simply included in the modeling process. I separated these from the rest of the counties by identifying any counties with a month-to-month change greater than 25%, and simply used last value predictions for them. Many other contestants took a similar approach. Looking at the size distribution of these counties (visualized in the histogram below) we can see that it excludes most of the smallest counties as well as a group of larger volume counties.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F12985b7771d35940abaa8a6db8e72484%2Fexcl_cfips.png?generation=1687123492757230&amp;alt=media\" alt=\"\"></p>\n<p>Small counties are unpredictable, as a single domain registration can dramatically change the density. However, looking at the larger counties with high variance it's clear that there is still a strong signal in many of them that could be leveraged for better predictions than a simple last value. For example, county ID 24013 has only one level shift up early on in the data set, and data before that shift could be removed and then interpolated so that it could be included in the forecast model training/prediction process. County IDs 10003 and 32510  have two level shifts that creates a \"hump\", which could be corrected in a similar manner using interpolation. I had planned to implement an algorithm to correct shifts for these larger counties, but unfortunately ran out of time. </p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6b3c0541a03e4f405b1aa745b943d5b6%2Flarge_excl_cfips.png?generation=1687123510916081&amp;alt=media\" alt=\"\"></p>\n<p>Like many others, I also made the \"percent change\" adjustment to microbusiness density before training so that loss metrics like RMSE would weight small counties higher in the same way that SMAPE does. I used that adjusted target for all training other than the linear models, because they can be flexibly trained to directly minimize SMAPE (as described below).</p>\n<h2>Traditional Time-Series Forecasting, and other features</h2>\n<p>Of the traditional autoregressive time-series forecasting methods (ARIMA, Holt-Winters, Exponential Smoothing, etc.) that I tried, Exponential Smoothing (ETS) was the best. I ended up using ETS forecasts as features for the linear modeling by rolling through the data and generating ets forecasts for 1-6 month time horizons.</p>\n<p>Other features I toyed with included moving-average terms, difference terms, month and year, and the average of all previous MB density values. </p>\n<h2>CV Strategy</h2>\n<p>For CV I used the last 6 months of data, as shown below, and trained separate models for each forecast horizon. I wanted to use as much data as possible for training, since we only had a few years of historical data spanning the pandemic.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6ae7279f1d78b31a125355f0c2d34cd8%2Fcv_strategy.png?generation=1687123527511586&amp;alt=media\" alt=\"\"></p>\n<h2>Linear Modeling via Optimization</h2>\n<p>I tried other ML approaches like XGBoost, but found the most success with the simpler linear models.</p>\n<p>Another nice feature of linear models is you can directly fit them to minimize SMAPE by solving the optimization problem with the following objective:</p>\n<pre><code>\nfn  par df r_cols y norm_col l2 l1 \n  preds  par df.N\n  l2p  \n  l1p  \n   ind  par \n    i_col  r_colsind\n    preds  preds  parinddf geti_colmeangeti_colsdgeti_col\n    l2p  l2p  l2parind\n    l1p  l1p  l1parind\n  \n  err  smapeadfgety fcpreds  l1p  l2p\n  err\n\n</code></pre>\n<p>I tested L1 and L2 regularization, but found the lowest CV accuracy with no regularization. Looking at the fitted weight magnitudes, it seems that MA terms are most important in the forecasts. This was my best-scoring final submission.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F8b4a56ee77fff6fe87562ab6916726f5%2Flm_weights.png?generation=1687130521279924&amp;alt=media\" alt=\"\"></p>\n<h2>Multivariate adaptive regression spline (MARS)</h2>\n<p><a href=\"https://en.wikipedia.org/wiki/Multivariate_adaptive_regression_spline\" target=\"_blank\">https://en.wikipedia.org/wiki/Multivariate_adaptive_regression_spline</a></p>\n<p>Because I had success with the LMs, I though that MARS would be a natural improvement since it is an algorithm for fitting piecewise linear models to automatically deal with non-linearities and incorporate variable interactions.</p>\n<p>I did some hyperparameter tuning, but had the most success with the default parameters, and based on the CV accuracy I hoped it would outperform the LMs. However that wasn't the case with the private LB (I'm still not sure why, perhaps MARS was more sensitive to erroneous Dec data…)</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2Fb41c10f7948ea74940de90bd4e8f357a%2Fsmape_comp.png?generation=1687127830752749&amp;alt=media\" alt=\"\"></p>",
      "rawMarkdown": "Below is a brief description + thoughts on my forecasting solution.\n**Private LB Place**: 122/3,546\n**Private LB Score**: 3.9884\n**Code**: https://www.kaggle.com/code/abandura/mbd-forecasting-w-mars-lms-r\n\nThanks to everyone who shared their insights and code!\n\n## Pre-Processing\n\nMany counties exhibit level shifts in their historical microbusiness density, which reduces overall accuracy if simply included in the modeling process. I separated these from the rest of the counties by identifying any counties with a month-to-month change greater than 25%, and simply used last value predictions for them. Many other contestants took a similar approach. Looking at the size distribution of these counties (visualized in the histogram below) we can see that it excludes most of the smallest counties as well as a group of larger volume counties.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F12985b7771d35940abaa8a6db8e72484%2Fexcl_cfips.png?generation=1687123492757230&alt=media)\n\nSmall counties are unpredictable, as a single domain registration can dramatically change the density. However, looking at the larger counties with high variance it's clear that there is still a strong signal in many of them that could be leveraged for better predictions than a simple last value. For example, county ID 24013 has only one level shift up early on in the data set, and data before that shift could be removed and then interpolated so that it could be included in the forecast model training/prediction process. County IDs 10003 and 32510  have two level shifts that creates a \"hump\", which could be corrected in a similar manner using interpolation. I had planned to implement an algorithm to correct shifts for these larger counties, but unfortunately ran out of time. \n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6b3c0541a03e4f405b1aa745b943d5b6%2Flarge_excl_cfips.png?generation=1687123510916081&alt=media)\n\nLike many others, I also made the \"percent change\" adjustment to microbusiness density before training so that loss metrics like RMSE would weight small counties higher in the same way that SMAPE does. I used that adjusted target for all training other than the linear models, because they can be flexibly trained to directly minimize SMAPE (as described below).\n\n## Traditional Time-Series Forecasting, and other features\n\nOf the traditional autoregressive time-series forecasting methods (ARIMA, Holt-Winters, Exponential Smoothing, etc.) that I tried, Exponential Smoothing (ETS) was the best. I ended up using ETS forecasts as features for the linear modeling by rolling through the data and generating ets forecasts for 1-6 month time horizons.\n\nOther features I toyed with included moving-average terms, difference terms, month and year, and the average of all previous MB density values. \n\n## CV Strategy\n\nFor CV I used the last 6 months of data, as shown below, and trained separate models for each forecast horizon. I wanted to use as much data as possible for training, since we only had a few years of historical data spanning the pandemic.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F6ae7279f1d78b31a125355f0c2d34cd8%2Fcv_strategy.png?generation=1687123527511586&alt=media)\n\n## Linear Modeling via Optimization\n\nI tried other ML approaches like XGBoost, but found the most success with the simpler linear models.\n\nAnother nice feature of linear models is you can directly fit them to minimize SMAPE by solving the optimization problem with the following objective:\n\n```r\n# objective function for linear model optimization\nfn = function(par, df, r_cols, y, norm_col=F, l2=0, l1=0) {\n  preds = rep(par[1], df[,.N])\n  l2p = 0\n  l1p = 0\n  for (ind in 2:length(par)) {\n    i_col = r_cols[ind-1]\n    preds = preds + par[ind]*df[, (get(i_col)-mean(get(i_col)))/sd(get(i_col))]\n    l2p = l2p + l2*(par[ind])^2\n    l1p = l1p + l1*abs(par[ind])\n  }\n  err = smape(a=df[,get(y)], fc=preds) + l1p + l2p\n  return(err)\n}\n```\n\nI tested L1 and L2 regularization, but found the lowest CV accuracy with no regularization. Looking at the fitted weight magnitudes, it seems that MA terms are most important in the forecasts. This was my best-scoring final submission.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2F8b4a56ee77fff6fe87562ab6916726f5%2Flm_weights.png?generation=1687130521279924&alt=media)\n\n## Multivariate adaptive regression spline (MARS)\n\nhttps://en.wikipedia.org/wiki/Multivariate_adaptive_regression_spline\n\nBecause I had success with the LMs, I though that MARS would be a natural improvement since it is an algorithm for fitting piecewise linear models to automatically deal with non-linearities and incorporate variable interactions.\n\nI did some hyperparameter tuning, but had the most success with the default parameters, and based on the CV accuracy I hoped it would outperform the LMs. However that wasn't the case with the private LB (I'm still not sure why, perhaps MARS was more sensitive to erroneous Dec data...)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F13474157%2Fb41c10f7948ea74940de90bd4e8f357a%2Fsmape_comp.png?generation=1687127830752749&alt=media)",
      "votes": 3
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-19T19:29:03Z",
  "competition_id": 41881,
  "competition_slug": "godaddy-microbusiness-density-forecasting",
  "team_id": 9888987,
  "solution_url": "/competitions/godaddy-microbusiness-density-forecasting/writeups/abandura-ets-linear-models-and-mars"
}