awslabs / gluonts

Probabilistic time series modeling in Python
https://ts.gluon.ai
Apache License 2.0
4.46k stars 742 forks source link

What is the proper format for generating a cold start forecast? #667

Open SkanderHn opened 4 years ago

SkanderHn commented 4 years ago

I'm trying to test cold start forecasting using the DeepAREstimator. My test setup is the following:

Try to generate a forecast by feeding the predictor data sets that have categorical features and start dates in the future (relative to the training set) but empty target arrays, something along this pattern:

{'target': array([], dtype=float32), 'feat_static_cat': array([3], dtype=int32), 'start': Timestamp('2017-12-31 00:00:00', freq='W-SUN'), 'source': SourceContext(source='list_data', row=1)},

The results are always zero or near zero. Using the estimator's default settings, the median forecast is close to zero, but the quantiles fluctuate a little.

The forecast look flat when compared to the actuals, so I assumed a bug in my forecast plotting code: Screen Shot 2020-02-24 at 11 52 00 PM

But if we zoom in, we notice very small prediction intervals (meaning that there isn't some bug in my plotting code, just a very flat forecast):

Screen Shot 2020-02-24 at 11 51 30 PM

The forecast intervals get smaller and smaller if I increase some of the Hyperparameters (number of epochs, number of neurons, etc...).

I don't know if I am doing something wrong when trying to generate a cold start forecast, or if it is just a bad model / bad forecast outcome?

I know cold starts are going to be noise, but in this case (sine waves + slight gaussian noise) it seems like DeepAR should be able to figure it out easily, with minimal tweaking. Am I missing something?

I also get similar results using TransformerEstimator.

vafl commented 4 years ago

Can you attach an example notebook for this? Thanks

SkanderHn commented 4 years ago

@vafl Here is an example notebook with csv's of the synthetic data I used. DeepARExample.zip

vafl commented 4 years ago

The below settings seem to work.

The important changes are scaling=False and context_length=1. Using negative binomial is not necessary, but perhaps a better choice if you are dealing with integer values.

from gluonts.distribution import NegativeBinomialOutput

estimator = DeepAREstimator(
    freq="W",
    prediction_length=13,
    context_length=1,
    num_layers=2,
    num_cells=40,
    distr_output=NegativeBinomialOutput(),
    scaling=False,
    trainer=Trainer(epochs=20, learning_rate=0.01),
    use_feat_static_cat=True,
    cardinality=[4]
)
predictor = estimator.train(training_data=train_data)
SkanderHn commented 4 years ago

@vafl Thanks - this does work a lot better, and solves my immediate problem.

However, it seems I am misunderstanding how the context_length works then - I assumed the larger the better (but at the risk of overfitting),but you're saying reduce it to 1 to get better results.

Should it be treated as a lead time or forecast horizon of sorts?

vafl commented 4 years ago

Maybe larger context_length also work, I didn't try that.

jaschau commented 4 years ago

@SkanderHn I had a similar issue described in #684. There I describe a way how to get proper results, but I think it's only in workaround and there's in fact a bug.