unit8co / darts

A python library for user-friendly forecasting and anomaly detection on time series.
https://unit8co.github.io/darts/
Apache License 2.0
8.11k stars 884 forks source link

[Question] How to perform rolling predictions? #2483

Closed KunzstBGR closed 3 months ago

KunzstBGR commented 3 months ago

Hi there, I wanted to ask if what I'm trying to achieve is overly complicated or if this is the intended way to get rolling predictions.

I have multiple time series for which I want to calculate rolling predictions for 16 weeks using a TFT model with a Lookback window/Input chunk length of 52 weeks. I specified the test period to overlap wih the last year of the validation set, so the test period is from 2015 - 2020. My goal is to obtain 16 predictions starting from the first week of 2016, then 16 predictions starting from the second week of 2016 and so on.

Here's how I specified the model:

INPUT_CHUNK_LENGTH = 52
OUTPUT_CHUNK_LENGTH = 16

model_tft = TFTModel(
    input_chunk_length=INPUT_CHUNK_LENGTH ,
    output_chunk_length=OUTPUT_CHUNK_LENGTH ,
    hidden_size=32,
    lstm_layers=1,
    batch_size=4096,
    n_epochs=5,
    dropout=0.2,
    likelihood=QuantileRegression(quantiles=quantiles),
    categorical_embedding_sizes=categorical_embedding_sizes,
    random_state=42,
    add_relative_index=False, 
    save_checkpoints=True,
    model_name='TFT_test',
    log_tensorboard=True,
    pl_trainer_kwargs={'callbacks': [early_stopper, lr_sched, lr_logger]}
)

model_tft.fit(
    series=train_gws, 
    past_covariates=train_cov,
    future_covariates=train_cov,
    val_series=val_gws, 
    val_past_covariates=val_cov,
    val_future_covariates=val_cov,
    verbose=True
)

To obtain the predictions I created 52 week slices of my test data for each week across the test period:

rolling_pred_len = len(test_gws[:1][0]) - OUTPUT_CHUNK_LENGTH - INPUT_CHUNK_LENGTH +1 # don't want to predict past the test period
rolling_prediction = []

for i in range(0, rolling_pred_len):

    current_target_series = []

    for idx, data in enumerate(test_gws[1:3]):
         start = i 
         end = i + INPUT_CHUNK_LENGTH
         current_target = data[start:end]
         current_target_series.append(current_target)

    # Make Prediction
    pred = model_tft.predict(n=OUTPUT_CHUNK_LENGTH,
                             series=current_target_series,
                             past_covariates=cov_series[1:3],
                             future_covariates=cov_series[1:3],
                             num_samples=100)

    rolling_prediction.append(pred)

Is this the right way of doing this? Also, if I understood correctly, I don't need to worry about the correct slicing of the past and future covariates, because Darts takes care of this?

dennisbader commented 3 months ago

Hi @KunzstBGR , I assume what you're trying to do is historical forecasting. You can let the model generate the forecasts for you using, model.historical_forecasts() (check out the docs here).

In general you can train/predict with any global forecasting model (including TFTModel) using a list of TimeSeries as input.

You can also check out the examples in our Quickstart here. The same works for multiple series, just pass a list of TimeSeries as series to historical forecasts.

KunzstBGR commented 3 months ago

Hi @dennisbader, thanks a lot for the clarification! I indeed overcomplicated things. I somehow thought that histrocial_forecast() would only relate to back/hindcasting and didn't look into it.

dennisbader commented 3 months ago

No worries, closing in that case.