View source on GitHub |
Formal representation of a seasonal effect model.
Inherits From: StructuralTimeSeries
tfp.substrates.jax.sts.Seasonal(
num_seasons,
num_steps_per_season=1,
allow_drift=True,
drift_scale_prior=None,
initial_effect_prior=None,
constrain_mean_effect_to_zero=True,
observed_time_series=None,
name=None
)
Used in the notebooks
Used in the tutorials |
---|
A seasonal effect model posits a fixed set of recurring, discrete 'seasons', each of which is active for a fixed number of timesteps and, while active, contributes a different effect to the time series. These are generally not meteorological seasons, but represent regular recurring patterns such as hour-of-day or day-of-week effects. Each season lasts for a fixed number of timesteps. The effect of each season drifts from one occurrence to the next following a Gaussian random walk:
effects[season, occurrence[i]] = (
effects[season, occurrence[i-1]] + Normal(loc=0., scale=drift_scale))
The drift_scale
parameter governs the standard deviation of the random walk;
for example, in a day-of-week model it governs the change in effect from this
Monday to next Monday.
Examples
A seasonal effect model representing day-of-week seasonality on hourly data:
day_of_week = tfp.sts.Seasonal(num_seasons=7,
num_steps_per_season=24,
observed_time_series=y,
name='day_of_week')
A seasonal effect model representing month-of-year seasonality on daily data, with explicit priors:
month_of_year = tfp.sts.Seasonal(
num_seasons=12,
num_steps_per_season=[31, 28, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31],
drift_scale_prior=tfd.LogNormal(loc=-1., scale=0.1),
initial_effect_prior=tfd.Normal(loc=0., scale=5.),
name='month_of_year')
Note that this version works over time periods not involving a leap year. A general implementation of month-of-year seasonality would require additional logic:
num_days_per_month = np.array(
[[31, 28, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31],
[31, 29, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31], # year with leap day
[31, 28, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31],
[31, 28, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31]])
month_of_year = tfp.sts.Seasonal(
num_seasons=12,
num_steps_per_season=num_days_per_month,
drift_scale_prior=tfd.LogNormal(loc=-1., scale=0.1),
initial_effect_prior=tfd.Normal(loc=0., scale=5.),
name='month_of_year')
A model representing both day-of-week and hour-of-day seasonality, on hourly data:
day_of_week = tfp.sts.Seasonal(num_seasons=7,
num_steps_per_season=24,
observed_time_series=y,
name='day_of_week')
hour_of_day = tfp.sts.Seasonal(num_seasons=24,
num_steps_per_season=1,
observed_time_series=y,
name='hour_of_day')
model = tfp.sts.Sum(components=[day_of_week, hour_of_day],
observed_time_series=y)
Args | |
---|---|
num_seasons
|
Scalar Python int number of seasons.
|
num_steps_per_season
|
Python int number of steps in each
season. This may be either a scalar (shape [] ), in which case all
seasons have the same length, or a NumPy array of shape [num_seasons] ,
in which seasons have different length, but remain constant around
different cycles, or a NumPy array of shape [num_cycles, num_seasons] ,
in which num_steps_per_season for each season also varies in different
cycle (e.g., a 4 years cycle with leap day).
Default value: 1.
|
allow_drift
|
optional Python bool specifying whether the seasonal
effects can drift over time. Setting this to False
removes the drift_scale parameter from the model. This is
mathematically equivalent to
drift_scale_prior = tfd.Deterministic(0.) , but removing drift
directly is preferred because it avoids the use of a degenerate prior.
Default value: True .
|
drift_scale_prior
|
optional tfd.Distribution instance specifying a prior
on the drift_scale parameter. If None , a heuristic default prior is
constructed based on the provided observed_time_series .
Default value: None .
|
initial_effect_prior
|
optional tfd.Distribution instance specifying a
normal prior on the initial effect of each season. This may be either
a scalar tfd.Normal prior, in which case it applies independently to
every season, or it may be multivariate normal (e.g.,
tfd.MultivariateNormalDiag ) with event shape [num_seasons] , in
which case it specifies a joint prior across all seasons. If None , a
heuristic default prior is constructed based on the provided
observed_time_series .
Default value: None .
|
constrain_mean_effect_to_zero
|
if True , use a model parameterization
that constrains the mean effect across all seasons to be zero. This
constraint is generally helpful in identifying the contributions of
different model components and can lead to more interpretable
posterior decompositions. It may be undesirable if you plan to directly
examine the latent space of the underlying state space model.
Default value: True .
|
observed_time_series
|
optional float Tensor of shape
batch_shape + [T, 1] (omitting the trailing unit dimension is also
supported when T > 1 ), specifying an observed time series. Any NaN s
are interpreted as missing observations; missingness may be also be
explicitly specified by passing a tfp.sts.MaskedTimeSeries instance.
Any priors not explicitly set will be given default values according to
the scale of the observed time series (or batch of time series).
Default value: None .
|
name
|
the name of this model component. Default value: 'Seasonal'. |
Methods
batch_shape_tensor
batch_shape_tensor()
Runtime batch shape of models represented by this component.
Returns | |
---|---|
batch_shape
|
int Tensor giving the broadcast batch shape of
all model parameters. This should match the batch shape of
derived state space models, i.e.,
self.make_state_space_model(...).batch_shape_tensor() .
|
copy
copy(
**override_parameters_kwargs
)
Creates a deep copy.
Args | |
---|---|
**override_parameters_kwargs
|
String/value dictionary of initialization arguments to override with new values. |
Returns | |
---|---|
copy
|
A new instance of type(self) initialized from the union
of self.init_parameters and override_parameters_kwargs, i.e.,
dict(self.init_parameters, **override_parameters_kwargs) .
|
experimental_resample_drift_scale
experimental_resample_drift_scale(
latents, sample_shape=(), seed=None
)
Returns a posterior sample of drift scale
given the latents and prior.
This is experimental, and compatibility may be broken in the future.
Args | |
---|---|
latents
|
A value convertible to a tensor of shape [batch shape, timeseries length, latent size]. |
sample_shape
|
Shape of the sample. |
seed
|
The seed to sample with. |
get_parameter
get_parameter(
parameter_name
)
Returns the parameter with the given name, or a KeyError.
joint_distribution
joint_distribution(
observed_time_series=None,
num_timesteps=None,
trajectories_shape=(),
initial_step=0,
mask=None,
experimental_parallelize=False
)
Constructs the joint distribution over parameters and observed values.
Args | |
---|---|
observed_time_series
|
Optional observed time series to model, as a
Tensor or tfp.sts.MaskedTimeSeries instance having shape
concat([batch_shape, trajectories_shape, num_timesteps, 1]) . If
an observed time series is provided, the num_timesteps ,
trajectories_shape , and mask arguments are ignored, and
an unnormalized (pinned) distribution over parameter values is returned.
Default value: None .
|
num_timesteps
|
scalar int Tensor number of timesteps to model. This
must be specified either directly or by passing an
observed_time_series .
Default value: 0 .
|
trajectories_shape
|
int Tensor shape of sampled trajectories
for each set of parameter values. Ignored if an observed_time_series
is passed.
Default value: () .
|
initial_step
|
Optional scalar int Tensor specifying the starting
timestep.
Default value: 0 .
|
mask
|
Optional bool Tensor having shape
concat([batch_shape, trajectories_shape, num_timesteps]) , in which
True entries indicate that the series value at the corresponding step
is missing and should be ignored. This argument should be passed only
if observed_time_series is not specified or does not already contain
a missingness mask; it is an error to pass both this
argument and an observed_time_series value containing a missingness
mask.
Default value: None .
|
experimental_parallelize
|
If True , use parallel message passing
algorithms from tfp.experimental.parallel_filter to perform time
series operations in O(log num_timesteps) sequential steps. The
overall FLOP and memory cost may be larger than for the sequential
implementations by a constant factor.
Default value: False .
|
Returns | |
---|---|
joint_distribution
|
joint distribution of model parameters and
observed trajectories. If no observed_time_series was specified, this
is an instance of tfd.JointDistributionNamedAutoBatched with a
random variable for each model parameter (with names and order matching
self.parameters ), plus a final random variable observed_time_series
representing a trajectory(ies) conditioned on the parameters. If
observed_time_series was specified, the return value is given by
joint_distribution.experimental_pin(
observed_time_series=observed_time_series) where joint_distribution
is as just described, so it defines an unnormalized posterior
distribution over the parameters.
|
Example:
The joint distribution can generate prior samples of parameters and trajectories:
from matplotlib import pylab as plt
import tensorflow_probability as tfp; tfp = tfp.substrates.jax
# Sample and plot 100 trajectories from the prior.
model = tfp.sts.LocalLinearTrend()
prior_samples = model.joint_distribution(num_timesteps=200).sample([100])
plt.plot(
tf.linalg.matrix_transpose(prior_samples['observed_time_series'][..., 0]))
It also integrates with TFP inference APIs, providing a more flexible alternative to the STS-specific fitting utilities.
jd = model.joint_distribution(observed_time_series)
# Variational inference.
surrogate_posterior = (
tfp.experimental.vi.build_factored_surrogate_posterior(
event_shape=jd.event_shape,
bijector=jd.experimental_default_event_space_bijector()))
losses = tfp.vi.fit_surrogate_posterior(
target_log_prob_fn=jd.unnormalized_log_prob,
surrogate_posterior=surrogate_posterior,
optimizer=tf.optimizers.Adam(0.1),
num_steps=200)
parameter_samples = surrogate_posterior.sample(50)
# No U-Turn Sampler.
samples, kernel_results = tfp.experimental.mcmc.windowed_adaptive_nuts(
n_draws=500, joint_dist=dist)
joint_log_prob
joint_log_prob(
observed_time_series
)
Build the joint density log p(params) + log p(y|params)
as a callable.
Args | |
---|---|
observed_time_series
|
Observed Tensor trajectories of shape
sample_shape + batch_shape + [num_timesteps, 1] (the trailing
1 dimension is optional if num_timesteps > 1 ), where
batch_shape should match self.batch_shape (the broadcast batch
shape of all priors on parameters for this structural time series
model). Any NaN s are interpreted as missing observations; missingness
may be also be explicitly specified by passing a
tfp.sts.MaskedTimeSeries instance.
|
Returns | |
---|---|
log_joint_fn
|
A function taking a Tensor argument for each model
parameter, in canonical order, and returning a Tensor log probability
of shape batch_shape . Note that, unlike tfp.Distributions
log_prob methods, the log_joint sums over the sample_shape from y,
so that sample_shape does not appear in the output log_prob. This
corresponds to viewing multiple samples in y as iid observations from a
single model, which is typically the desired behavior for parameter
inference.
|
make_state_space_model
make_state_space_model(
num_timesteps,
param_vals,
initial_state_prior=None,
initial_step=0,
**linear_gaussian_ssm_kwargs
)
Instantiate this model as a Distribution over specified num_timesteps
.
Args | |
---|---|
num_timesteps
|
Python int number of timesteps to model.
|
param_vals
|
a list of Tensor parameter values in order corresponding to
self.parameters , or a dict mapping from parameter names to values.
|
initial_state_prior
|
an optional Distribution instance overriding the
default prior on the model's initial state. This is used in forecasting
("today's prior is yesterday's posterior").
|
initial_step
|
optional int specifying the initial timestep to model.
This is relevant when the model contains time-varying components,
e.g., holidays or seasonality.
|
**linear_gaussian_ssm_kwargs
|
Optional additional keyword arguments to
to the base tfd.LinearGaussianStateSpaceModel constructor.
|
Returns | |
---|---|
dist
|
a LinearGaussianStateSpaceModel Distribution object.
|
prior_sample
prior_sample(
num_timesteps,
initial_step=0,
params_sample_shape=(),
trajectories_sample_shape=(),
seed=None
)
Sample from the joint prior over model parameters and trajectories.
Args | |
---|---|
num_timesteps
|
Scalar int Tensor number of timesteps to model.
|
initial_step
|
Optional scalar int Tensor specifying the starting
timestep.
Default value: 0.
|
params_sample_shape
|
Number of possible worlds to sample iid from the
parameter prior, or more generally, Tensor int shape to fill with
iid samples.
Default value: [] (i.e., draw a single sample and don't expand the
shape).
|
trajectories_sample_shape
|
For each sampled set of parameters, number
of trajectories to sample, or more generally, Tensor int shape to
fill with iid samples.
Default value: [] (i.e., draw a single sample and don't expand the
shape).
|
seed
|
PRNG seed; see tfp.random.sanitize_seed for details.
Default value: None .
|
Returns | |
---|---|
trajectories
|
float Tensor of shape
trajectories_sample_shape + params_sample_shape + [num_timesteps, 1]
containing all sampled trajectories.
|
param_samples
|
list of sampled parameter value Tensor s, in order
corresponding to self.parameters , each of shape
params_sample_shape + prior.batch_shape + prior.event_shape .
|
__add__
__add__(
other
)
Models the sum of the series from the two components.