WillianFuks / tfcausalimpact

Python Causal Impact Implementation Based on Google's R Package. Built using TensorFlow Probability.
Apache License 2.0
593 stars 70 forks source link

Using tfcausalimpact for forecasting #58

Open samirchoksy opened 1 year ago

samirchoksy commented 1 year ago

As this relies on the BSTS methodology, is there a way to use tfcausalimpact for forecasting alone, i.e. setting the post-period to values beyond the final timestamp of the available data? R BSTS of course implements forecasting functionality, and while tfcausalimpact essentially fits the same model under the hood, I can't figure out how to use this appropriately to forecast forward in time.

Any ideas or hack-y approaches are welcome. At some point I can probably contribute to the project to do this if it's not yet available.

Thanks!

WillianFuks commented 1 year ago

Hi @samirchoksy ,

Unfortunately this is (probably) not possible. As you can see in the code the complete input data has to be used beforehand, even before fitting the model.

This is because that's how TFP works so we are restrained to their API, which also means it's not possible to observe new data after post event and run new forecasts on the fly (I would also enjoy having this feature).

If you are not using a linear regression component then it may even be possible. First you could reference both one_step_dist and posterior_dist and use them for forecasting, which would be as simple as doing something like posterior_dist.mean() for instance.

Whilst possible, by sacrificing the linear component it's expected you'll be left with less performative models for the forecasting which may defeat the purpose altogether either way.

Let me know if this solves your issue.

Best,

Will

samirchoksy commented 1 year ago

Hi Will,

Thanks for the reply. Using the links above I spent a little while digging into the Structural Time Series API, in particular, looking at TF's "Electricity Demand Forecasting" example. It appears that in the final "Forecasting and Criticism" section, they fit the model using (electricity) demand training data and then proceed to forecast ahead a variable number of steps in the "num_steps_forecast" parameter.

Additionally, this example appears to incorporate a linear regression component for which the model is trained using the entire temperature history. Later, forecasting simply requires the posterior parameter estimates and a value for "num_steps_forecast".

I essentially have an online learning problem for which I need to forecast ahead N steps each day, and I'd prefer to do everything in Python rather than off-load to R/C++. I think this might get me there, but I'm not too familiar with TFP so reviewing the documents has been somewhat difficult.

Any thoughts would be appreciated, but thanks again for the help, I appreciate it!

WillianFuks commented 1 year ago

Hi @samirchoksy ,

This electricity example is actually quite good. I just ran it on colab and changed the code to:

demand_forecast_dist = tfp.sts.forecast(
    model=demand_model,
    observed_time_series=demand_training_data,
    parameter_samples=q_samples_demand_,
    num_steps_forecast=num_forecast_steps + 1)

That is, I added +1 to num_forecast_steps. The next cell when set to run raises the exception:

InvalidArgumentError: Graph execution error

The model will be able to run forecasts only for the data it was trained upon. New unseen data (as the ones you want to add after the post-intervention data) will raise exceptions.

For your problem it seems you can solve it still just using Python (which is essentially a wrapping of C++ code). You'll only have to offer the model values for the linear regression so it can run the forecasts. If you don't have those then maybe having a linear regression component might not the best approach for you. This should hold true even in R code as well.

Hope that helps,

Best,

Will

samirchoksy commented 1 year ago

Hi @WillianFuks,

Yeah, this makes sense.

I can't quite tell if parameters are estimated using the complete history of the regression component (if included) rather than simply a training subset of it. The original BSTS theoretical papers by Scott & Brodersen et. al. suggest the latter, but the TFP API, as you've noted, requires the entire history. In any case, thanks for your help! If I can find regressors with such availability, I'll use them otherwise time series modeling only, I guess.