Attend the Women in ML Symposium on December 7 Register now

tfp.sts.SmoothSeasonalStateSpaceModel

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

State space model for a smooth seasonal effect.

Inherits From: LinearGaussianStateSpaceModel, Distribution, AutoCompositeTensor

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 Tensors 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