tensorflow / probability

Probabilistic reasoning and statistical analysis in TensorFlow
https://www.tensorflow.org/probability/
Apache License 2.0
4.25k stars 1.1k forks source link

STS Modeling Case Studies #490

Open donovanfan opened 5 years ago

donovanfan commented 5 years ago

Hi, I am trying to make forecasts similar to examples in Structural_Time_Series_Modeling_Case_Studies_Atmospheric_CO2_and_Electricity_Demand.ipynb. One major differences is that I have multiple lists of data rather than one list. I am curious if it is possible for me to fit all data into the model. For example, say that I have CO2 data from Los Angeles, New York, San Francisco and Chicago, and I would like to predict amount CO2 next month in these four cities. One thing I could do is I use data from Los Angeles only to predict CO2 in Los Angeles next month. Is it possible to use all data from four cities to predict CO2 in Los Angeles? Thanks

davmre commented 5 years ago

The short answer is there's no simple way to use STS for a joint model of multiple time series.

The longer answer is that there are things you can do, but none of them are documented or supported or particularly clean.

The most natural approach probabilistically is to write down a joint generative model of multiple series expressing some assumptions about their relationship, e.g., in which they share some latent component structure, and do (approximate) inference in this model. You can wire up things like this using JointDistributionCoroutine and the STS StateSpaceModel classes, but that's very much advanced-level usage.

A hackier but maybe more intuitive approach is to use tfp.sts.LinearRegression and friends (SparseLinearRegression, DynamicLinearRegression) to model dependence of one series on other series. This works naturally for 'nowcasting', when you just need to predict the value at the current time given access to the current values of the covariate series. Doing forecasting this way requires you to have access to the future values of the covariate series, which of course you don't, but you could hack around this by replacing the future values of the covariate series with STS forecasts. We don't particularly recommend this approach, because the multiple steps of forecasting introduce complexity and because it corresponds to a strange statistical model (you could think of it as imposing an order on your set of series and forecasting each series given the previous ones, which is often unnatural because the order is arbitrary), but it's not necessarily totally crazy.

That said, the short answer is again "don't try any of this stuff unless you're really sure know what you're doing". :-)

amol447 commented 4 years ago

Hi, I have similar use case where we have several timeseries that need to be fit. Right now even a simple loop (pseudocode)

for i in range(some_large_number):
data=get_data_from_service(i)
model=model.fit(data)

Runs out of memory. This ignores the fact that these timeseries have correlations so ideally I want to fit a factor model. Is there some progress or something on the horizon for these type of problems? Thanks!

davmre commented 4 years ago

In TF and TFP it's almost always good to take advantage of batching when you can; most of TFP (including STS) supports passing Tensors with initial batch dimensions. I'd expect that something like

batch_of_data = tf.stack([get_data_from_service(i) for i in range(some_large_number)])
model=model.fit(batch_of_data)

might be significantly more performant than a for loop.

We have no immediate plans to build tooling for joint models of multiple time series, other than what's discussed above, though of course we're always open to contributions.

amol447 commented 4 years ago

Hi, Thanks for suggesting this method. The new problem I run into with this method is following- I am trying to do something similar to https://github.com/tensorflow/probability/issues/940 except every batch has it's own weight_constraining bijector. (The usual examples all seem to broadcast the bijector to all the batches). There seems to be no easy way to specify this or am I missing something. Regards