Attend the Women in ML Symposium on December 7

# tfp.sts.SmoothSeasonalStateSpaceModel

Stay organized with collections Save and categorize content based on your preferences.

State space model for a smooth seasonal effect.

A state space model (SSM) posits a set of latent (unobserved) variables that evolve over time with dynamics specified by a probabilistic transition model `p(z[t+1] | z[t])`. At each timestep, we observe a value sampled from an observation model conditioned on the current state, `p(x[t] | z[t])`. The special case where both the transition and observation models are Gaussians with mean specified as a linear function of the inputs, is known as a linear Gaussian state space model and supports tractable exact probabilistic calculations; see `tfp.distributions.LinearGaussianStateSpaceModel` for details.

A smooth seasonal effect model is a special case of a linear Gaussian SSM. It is the sum of a set of "cyclic" components, with one component for each frequency:

``````frequencies[j] = 2. * pi * frequency_multipliers[j] / period
``````

Each cyclic component contains two latent states which we denote `effect` and `auxiliary`. The two latent states for component `j` drift over time via:

``````effect[t] = (effect[t - 1] * cos(frequencies[j]) +
auxiliary[t - 1] * sin(frequencies[j]) +
Normal(0., drift_scale))

auxiliary[t] = (-effect[t - 1] * sin(frequencies[j]) +
auxiliary[t - 1] * cos(frequencies[j]) +
Normal(0., drift_scale))
``````

The `auxiliary` latent state only appears as a matter of construction and thus its interpretation is not particularly important. The total smooth seasonal effect is the sum of the `effect` values from each of the cyclic components.

The parameters `drift_scale` and `observation_noise_scale` are each (a batch of) scalars. The batch shape of this `Distribution` is the broadcast batch shape of these parameters and of the `initial_state_prior`.

#### Mathematical Details

The smooth seasonal effect model implements a `tfp.distributions.LinearGaussianStateSpaceModel` with ```latent_size = 2 * len(frequency_multipliers)``` and `observation_size = 1`. The latent state is the concatenation of the cyclic latent states which themselves comprise an `effect` and an `auxiliary` state. The transition matrix is a block diagonal matrix where block `j` is:

``````transition_matrix[j] =  [[cos(frequencies[j]), sin(frequencies[j])],
[-sin(frequencies[j]), cos(frequencies[j])]]
``````

The observation model picks out the cyclic `effect` values from the latent state:

``````observation_matrix = [[1., 0., 1., 0., ..., 1., 0.]]
observation_noise ~ Normal(loc=0, scale=observation_noise_scale)
``````

For further mathematical details please see [1].

#### Examples

A state space model with smooth daily seasonality on hourly data. In other words, each day there is a pattern which broadly repeats itself over the course of the day and doesn't change too much from one hour to the next. Four random samples from such a model can be obtained via:

``````from matplotlib import pylab as plt

ssm = SmoothSeasonalStateSpaceModel(
num_timesteps=100,
period=24,
frequency_multipliers=[1, 4],
drift_scale=0.1,
initial_state_prior=tfd.MultivariateNormalDiag(
scale_diag=tf.fill([4], 2.0)),
)

fig, axes = plt.subplots(4)

series = ssm.sample(4)

for series, ax in zip(series[..., 0], axes):
ax.set_xticks(tf.range(ssm.num_timesteps, delta=ssm.period))
ax.grid()
ax.plot(series)

plt.show()
``````

A comparison of the above with a comparable `Seasonal` component gives an example of the difference between these two components:

``````ssm = SeasonalStateSpaceModel(
num_timesteps=100,
num_seasons=24,
num_steps_per_season=1,
drift_scale=0.1,
initial_state_prior=tfd.MultivariateNormalDiag(
scale_diag=tf.fill([24], 2.0)),
)
``````

#### References

[1]: Harvey, A. Forecasting, Structural Time Series Models and the Kalman Filter. Cambridge: Cambridge University Press, 1990.

`num_timesteps` Scalar `int` `Tensor` number of timesteps to model with this distribution.
`period` positive scalar `float` `Tensor` giving the number of timesteps required for the longest cyclic effect to repeat.
`frequency_multipliers` One-dimensional `float` `Tensor` listing the frequencies (cyclic components) included in the model, as multipliers of the base/fundamental frequency `2. * pi / period`. Each component is specified by the number of times it repeats per period, and adds two latent dimensions to the model. A smooth seasonal model that can represent any periodic function is given by ```frequency_multipliers = [1, 2, ..., floor(period / 2)]```. However, it is often desirable to enforce a smoothness assumption (and reduce the computational burden) by dropping some of the higher frequencies.
`drift_scale` Scalar (any additional dimensions are treated as batch dimensions) `float` `Tensor` indicating the standard deviation of the latent state transitions.
`initial_state_prior` instance of `tfd.MultivariateNormal` representing the prior distribution on latent states. Must have event shape `[num_features]`.
`observation_noise_scale` Scalar (any additional dimensions are treated as batch dimensions) `float` `Tensor` indicating the standard deviation of the observation noise. Default value: `0.`.
`name` Python `str` name prefixed to ops created by this class. Default value: 'SmoothSeasonalStateSpaceModel'.
`**linear_gaussian_ssm_kwargs` Optional additional keyword arguments to to the base `tfd.LinearGaussianStateSpaceModel` constructor.

`allow_nan_stats` Python `bool` describing behavior when a stat is undefined.

Stats return +/- infinity when it makes sense. E.g., the variance of a Cauchy distribution is infinity. However, sometimes the statistic is undefined, e.g., if a distribution's pdf does not achieve a maximum within the support of the distribution, the mode is undefined. If the mean is undefined, then by definition the variance is undefined. E.g. the mean for Student's T for df = 1 is undefined (no clear way to say it is either + or - infinity), so the variance = E[(X - mean)**2] is also undefined.

`batch_shape` Shape of a single sample from a single event index as a `TensorShape`.

May be partially defined or unknown.

The batch dimensions are indexes into independent, non-identical parameterizations of this distribution.

`drift_scale` Standard deviation of the drift in the cyclic effects.
`dtype` The `DType` of `Tensor`s handled by this `Distribution`.
`event_shape` Shape of a single sample from a single batch as a `TensorShape`.

May be partially defined or unknown.

`experimental_parallelize`

`experimental_shard_axis_names` The list or structure of lists of active shard axis names.
`frequency_multipliers` Multipliers of the fundamental frequency.
`initial_state_prior`

`initial_step`

`mask`

`name` Name prepended to all ops created by this `Distribution`.
`name_scope` Returns a `tf.name_scope` instance for this class.
`non_trainable_variables` Sequence of non-trainable variables owned by this module and its submodules.

`num_timesteps`

`observation_matrix`

`observation_noise`

`observation_noise_scale` Standard deviation of the observation noise.
`parameters` Dictionary of parameters used to instantiate this `Distribution`.
`period` The seasonal period.
`reparameterization_type` Describes how samples from the distribution are reparameterized.

Currently this is one of the static instances `tfd.FULLY_REPARAMETERIZED` or `tfd.NOT_REPARAMETERIZED`.

`submodules` Sequence of all sub-modules.

Submodules are modules which are properties of this module, or found as properties of modules which are properties of this module (and so on).

````a = tf.Module()`
`b = tf.Module()`
`c = tf.Module()`
`a.b = b`
`b.c = c`
`list(a.submodules) == [b, c]`
`True`
`list(b.submodules) == [c]`
`True`
`list(c.submodules) == []`
`True`
```

`trainable_variables` Sequence of trainable variables owned by this module and its submodules.

`transition_matrix`

`transition_noise`

`validate_args` Python `bool` indicating possibly expensive checks are enabled.
`variables` Sequence of variables owned by this module and its submodules.

## Methods

### `backward_smoothing_pass`

View source

Run the backward pass in Kalman smoother.

The backward smoothing is using Rauch, Tung and Striebel smoother as as discussed in section 18.3.2 of Kevin P. Murphy, 2012, Machine Learning: A Probabilistic Perspective, The MIT Press. The inputs are returned by `forward_filter` function.

Args
`filtered_means` Means of the per-timestep filtered marginal distributions p(z[t] | x[:t]), as a Tensor of shape `sample_shape(x) + batch_shape + [num_timesteps, latent_size]`.
`filtered_covs` Covariances of the per-timestep filtered marginal distributions p(z[t] | x[:t]), as a Tensor of shape ```sample_shape(x) + batch_shape + [num_timesteps, latent_size, latent_size]```.
`predicted_means` Means of the per-timestep predictive distributions over latent states, p(z[t+1] | x[:t]), as a Tensor of shape ```sample_shape(x) + batch_shape + [num_timesteps, latent_size]```.
`predicted_covs` Covariances of the per-timestep predictive distributions over latent states, p(z[t+1] | x[:t]), as a Tensor of shape ```sample_shape(x) + batch_shape + [num_timesteps, latent_size, latent_size]```.

Returns
`posterior_means` Means of the smoothed marginal distributions p(z[t] | x[1:T]), as a Tensor of shape `sample_shape(x) + batch_shape + [num_timesteps, latent_size]`, which is of the same shape as filtered_means.
`posterior_covs`