Skip to main content

LightGBMCV

Create LightGBM CV object. Parameters:

LightGBMCV.fit

Train boosters simultaneously and assess their performance on the complete forecasting window. Parameters: Returns:

LightGBMCV.predict

Compute predictions with each of the trained boosters. Parameters: Returns:

LightGBMCV.setup

Initialize internal data structures to iteratively train the boosters. Use this before calling partial_fit. Parameters: Returns:

LightGBMCV.partial_fit

Train the boosters for some iterations. Parameters: Returns:

Example

This shows an example with just 4 series of the M4 dataset. If you want to run it yourself on all of them, you can refer to this notebook.
What LightGBMCV does is emulate LightGBM’s cv function where several Boosters are trained simultaneously on different partitions of the data, that is, one boosting iteration is performed on all of them at a time. This allows to have an estimate of the error by iteration, so if we combine this with early stopping we can find the best iteration to train a final model using all the data or even use these individual models’ predictions to compute an ensemble. In order to have a good estimate of the forecasting performance of our model we compute predictions for the whole test period and compute a metric on that. Since this step can slow down training, there’s an eval_every parameter that can be used to control this, that is, if eval_every=10 (the default) every 10 boosting iterations we’re going to compute forecasts for the complete window and report the error. We also have early stopping parameters:
  • early_stopping_evals: how many evaluations of the full window should we go without improving to stop training?
  • early_stopping_pct: what’s the minimum percentage improvement we want in these early_stopping_evals in order to keep training?
This makes the LightGBMCV class a good tool to quickly test different configurations of the model. Consider the following example, where we’re going to try to find out which features can improve the performance of our model. We start just using lags.
By setting compute_cv_preds we get the predictions from each model on their corresponding validation fold.
The individual models we trained are saved, so calling predict returns the predictions from every model trained.
source
We can average these predictions and evaluate them.
Now, since these series are hourly, maybe we can try to remove the daily seasonality by taking the 168th (24 * 7) difference, that is, substract the value at the same hour from one week ago, thus our target will be zt=ytyt168z_t = y_{t} - y_{t-168}. The features will be computed from this target and when we predict they will be automatically re-applied.
Nice! We achieve a better score in less iterations. Let’s see if this improvement translates to the validation set as well.
Great! Maybe we can try some lag transforms now. We’ll try the seasonal rolling mean that averages the values “every season”, that is, if we set season_length=24 and window_size=7 then we’ll average the value at the same hour for every day of the week.
Seems like this is helping as well!
Does this reflect on the validation set?
Nice! mlforecast also supports date features, but in this case our time column is made from integers so there aren’t many possibilites here. As you can see this allows you to iterate faster and get better estimates of the forecasting performance you can expect from your model. If you’re doing hyperparameter tuning it’s useful to be able to run a couple of iterations, assess the performance, and determine if this particular configuration isn’t promising and should be discarded. For example, optuna has pruners that you can call with your current score and it decides if the trial should be discarded. We’ll now show how to do that. Since the CV requires a bit of setup, like the LightGBM datasets and the internal features, we have this setup method.
Once we have this we can call partial_fit to only train for some iterations and return the score of the forecast window.
This is equal to the first evaluation from our first example.
We can now use this score to decide if this configuration is promising. If we want to we can train some more iterations.
This is now equal to our third metric from the first example, since this time we trained for 20 iterations.

Using a custom metric

The built-in metrics are MAPE and RMSE, which are computed by serie and then averaged across all series. If you want to do something different or use a different metric entirely, you can define your own metric like the following: