class_docstr: State space model for a 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 seasonal effect model is a special case of a linear Gaussian SSM. The
  latent states represent an unknown effect from each of several 'seasons';
  these are generally not meteorological seasons, but represent regular
  recurring patterns such as hour-of-day or day-of-week effects. The effect of
  each season drifts from one occurrence to the next, following a Gaussian
  random walk:
  
  ```python
  effects[season, occurrence[i]] = (
    effects[season, occurrence[i-1]] + Normal(loc=0., scale=drift_scale))
  ```
  
  The latent state has dimension `num_seasons`, containing one effect for each
  seasonal component. 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`.
  
  Note: there is no requirement that the effects sum to zero.
  
  #### Mathematical Details
  
  The seasonal effect model implements a
  `tfp.distributions.LinearGaussianStateSpaceModel` with
  `latent_size = num_seasons` and `observation_size = 1`. The latent state
  is organized so that the *current* seasonal effect is always in the first
  (zeroth) dimension. The transition model rotates the latent state to shift
  to a new effect at the end of each season:
  
  ```
  transition_matrix[t] = (permutation_matrix([1, 2, ..., num_seasons-1, 0])
                          if season_is_changing(t)
                          else eye(num_seasons)
  transition_noise[t] ~ Normal(loc=0., scale_diag=(
                               [drift_scale, 0, ..., 0]
                               if season_is_changing(t)
                               else [0, 0, ..., 0]))
  ```
  
  where `season_is_changing(t)` is `True` if ``t `mod`
  sum(num_steps_per_season)`` is in the set of final days for each season,
  given by `cumsum(num_steps_per_season) - 1`. The observation model always
  picks out the effect for the current season, i.e., the first element of
  the latent state:
  
  ```
  observation_matrix = [[1., 0., ..., 0.]]
  observation_noise ~ Normal(loc=0, scale=observation_noise_scale)
  ```
  
  #### Examples
  
  A state-space model with day-of-week seasonality on hourly data:
  
  ```python
  day_of_week = SeasonalStateSpaceModel(
    num_timesteps=30,
    num_seasons=7,
    drift_scale=0.1,
    initial_state_prior=tfd.MultivariateNormalDiag(
      scale_diag=tf.ones([7], dtype=tf.float32),
    num_steps_per_season=24)
  ```
  
  A model with basic month-of-year seasonality on daily data, demonstrating
  seasons of varying length:
  
  ```python
  month_of_year = SeasonalStateSpaceModel(
    num_timesteps=2 * 365,  # 2 years
    num_seasons=12,
    drift_scale=0.1,
    initial_state_prior=tfd.MultivariateNormalDiag(
      scale_diag=tf.ones([12], dtype=tf.float32)),
    num_steps_per_season=[31, 28, 31, 30, 30, 31, 31, 31, 30, 31, 30, 31],
    initial_step=22)
  ```
  
  Note that we've used `initial_step=22` to denote that the model begins
  on January 23 (steps are zero-indexed). This version works over time periods
  not involving a leap year. A general implementation of month-of-year
  seasonality would require additional logic:
  
  ```python
  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 = SeasonalStateSpaceModel(
    num_timesteps=4 * 365 + 2,  # 8 years with leap days
    num_seasons=12,
    drift_scale=0.1,
    initial_state_prior=tfd.MultivariateNormalDiag(
      scale_diag=tf.ones([12], dtype=tf.float32)),
    num_steps_per_season=num_days_per_month,
    initial_step=22)
  ```
class_docstr_tok: ["State","space","model","for","a","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","seasonal","effect","model","is","a","special","case","of","a","linear","Gaussian","SSM",".","The","latent","states","represent","an","unknown","effect","from","each","of","several","'seasons","'",";","these","are","generally","not","meteorological","seasons",",","but","represent","regular","recurring","patterns","such","as","hour-of-day","or","day-of-week","effects",".","The","effect","of","each","season","drifts","from","one","occurrence","to","the","next",",","following","a","Gaussian","random","walk",":","``","`","python","effects","[","season",",","occurrence","[","i","]","]","=","(","effects","[","season",",","occurrence","[","i-1","]","]","+","Normal","(","loc=0.",",","scale=drift_scale",")",")","``","`","The","latent","state","has","dimension","`","num_seasons","`",",","containing","one","effect","for","each","seasonal","component",".","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","`",".","Note",":","there","is","no","requirement","that","the","effects","sum","to","zero",".","#","#","#","#","Mathematical","Details","The","seasonal","effect","model","implements","a","`","tfp.distributions.LinearGaussianStateSpaceModel","`","with","`","latent_size","=","num_seasons","`","and","`","observation_size","=","1","`",".","The","latent","state","is","organized","so","that","the","*","current","*","seasonal","effect","is","always","in","the","first","(","zeroth",")","dimension",".","The","transition","model","rotates","the","latent","state","to","shift","to","a","new","effect","at","the","end","of","each","season",":","``","`","transition_matrix","[","t","]","=","(","permutation_matrix","(","[","1",",","2",",","...",",","num_seasons-1",",","0","]",")","if","season_is_changing","(","t",")","else","eye","(","num_seasons",")","transition_noise","[","t","]","~","Normal","(","loc=0.",",","scale_diag=","(","[","drift_scale",",","0",",","...",",","0","]","if","season_is_changing","(","t",")","else","[","0",",","0",",","...",",","0","]",")",")","``","`","where","`","season_is_changing","(","t",")","`","is","`","True","`","if","``","t","`","mod","`","sum","(","num_steps_per_season",")","``","is","in","the","set","of","final","days","for","each","season",",","given","by","`","cumsum","(","num_steps_per_season",")","-","1","`",".","The","observation","model","always","picks","out","the","effect","for","the","current","season",",","i.e.",",","the","first","element","of","the","latent","state",":","``","`","observation_matrix","=","[","[","1.",",","0.",",","...",",","0",".","]","]","observation_noise","~","Normal","(","loc=0",",","scale=observation_noise_scale",")","``","`","#","#","#","#","Examples","A","state-space","model","with","day-of-week","seasonality","on","hourly","data",":","``","`","python","day_of_week","=","SeasonalStateSpaceModel","(","num_timesteps=30",",","num_seasons=7",",","drift_scale=0.1",",","initial_state_prior=tfd.MultivariateNormalDiag","(","scale_diag=tf.ones","(","[","7","]",",","dtype=tf.float32",")",",","num_steps_per_season=24",")","``","`","A","model","with","basic","month-of-year","seasonality","on","daily","data",",","demonstrating","seasons","of","varying","length",":","``","`","python","month_of_year","=","SeasonalStateSpaceModel","(","num_timesteps=2","*","365",",","#","2","years","num_seasons=12",",","drift_scale=0.1",",","initial_state_prior=tfd.MultivariateNormalDiag","(","scale_diag=tf.ones","(","[","12","]",",","dtype=tf.float32",")",")",",","num_steps_per_season=","[","31",",","28",",","31",",","30",",","30",",","31",",","31",",","31",",","30",",","31",",","30",",","31","]",",","initial_step=22",")","``","`","Note","that","we","'ve","used","`","initial_step=22","`","to","denote","that","the","model","begins","on","January","23","(","steps","are","zero-indexed",")",".","This","version","works","over","time","periods","not","involving","a","leap","year",".","A","general","implementation","of","month-of-year","seasonality","would","require","additional","logic",":","``","`","python","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","=","SeasonalStateSpaceModel","(","num_timesteps=4","*","365","+","2",",","#","8","years","with","leap","days","num_seasons=12",",","drift_scale=0.1",",","initial_state_prior=tfd.MultivariateNormalDiag","(","scale_diag=tf.ones","(","[","12","]",",","dtype=tf.float32",")",")",",","num_steps_per_season=num_days_per_month",",","initial_step=22",")","``","`"]
docstr: Build a seasonal effect state space model.
  
  {seasonal_init_args}
docstr_tok: ["Build","a","seasonal","effect","state","space","model",".","{","seasonal_init_args","}"]
code: def __init__(
      self,
      num_timesteps,
      num_seasons,
      drift_scale,
      initial_state_prior,
      observation_noise_scale=0.0,
      num_steps_per_season=1,
      name=None,
      **linear_gaussian_ssm_kwargs,
  ):  # pylint: disable=g-doc-args
      """Build a seasonal effect state space model.
  
      {seasonal_init_args}
      """
      parameters = dict(locals())
      parameters.update(linear_gaussian_ssm_kwargs)
      del parameters["linear_gaussian_ssm_kwargs"]
      with tf.name_scope(name or "SeasonalStateSpaceModel") as name:
          # The initial state prior determines the dtype of sampled values.
          # Other model parameters must have the same dtype.
          dtype = initial_state_prior.dtype
          drift_scale = tf.convert_to_tensor(
              value=drift_scale, name="drift_scale", dtype=dtype
          )
          observation_noise_scale = tf.convert_to_tensor(
              value=observation_noise_scale,
              name="observation_noise_scale",
              dtype=dtype,
          )
  
          # Coerce `num_steps_per_season` to a canonical form, an array of
          # `num_seasons` integers.
          num_steps_per_season = np.squeeze(
              np.asarray(num_steps_per_season)
          )
          if num_steps_per_season.ndim == 0:  # scalar case
              num_steps_per_season = np.tile(
                  num_steps_per_season, num_seasons
              )
          elif (num_steps_per_season.ndim <= 2) and (  # 1D and 2D case
              num_steps_per_season.shape[-1] != num_seasons
          ):
              raise ValueError(
                  "num_steps_per_season must either be scalar (shape [])"
                  " or have the last dimension equal to [num_seasons] = "
                  "[{}] (saw: shape {})".format(
                      num_seasons, num_steps_per_season.shape
                  )
              )
  
          is_last_day_of_season = build_is_last_day_of_season(
              num_steps_per_season
          )
  
          seasonal_transition_matrix = build_seasonal_transition_matrix(
              num_seasons=num_seasons,
              is_last_day_of_season=is_last_day_of_season,
              dtype=dtype,
          )
  
          seasonal_transition_noise = build_seasonal_transition_noise(
              drift_scale, num_seasons, is_last_day_of_season
          )
  
          observation_matrix = tf.concat(
              [
                  tf.ones([1, 1], dtype=dtype),
                  tf.zeros([1, num_seasons - 1], dtype=dtype),
              ],
              axis=-1,
          )
  
          self._drift_scale = drift_scale
          self._observation_noise_scale = observation_noise_scale
          self._num_seasons = num_seasons
          self._num_steps_per_season = num_steps_per_season
  
          super(SeasonalStateSpaceModel, self).__init__(
              num_timesteps=num_timesteps,
              transition_matrix=seasonal_transition_matrix,
              transition_noise=seasonal_transition_noise,
              observation_matrix=observation_matrix,
              observation_noise=mvn_diag.MultivariateNormalDiag(
                  scale_diag=observation_noise_scale[..., tf.newaxis]
              ),
              initial_state_prior=initial_state_prior,
              name=name,
              **linear_gaussian_ssm_kwargs,
          )
          self._parameters = parameters
  
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import chain
  from tensorflow_probability.python.bijectors import invert
  from tensorflow_probability.python.bijectors import scale
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.bijectors import square
  from tensorflow_probability.python.distributions import inverse_gamma
  from tensorflow_probability.python.distributions import linear_gaussian_ssm
  from tensorflow_probability.python.distributions import lognormal
  from tensorflow_probability.python.distributions import mvn_diag
  from tensorflow_probability.python.distributions import mvn_tril
  from tensorflow_probability.python.distributions import normal
  from tensorflow_probability.python.distributions import transformed_distribution
  from tensorflow_probability.python.experimental.sts_gibbs import sample_parameters
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import docstring_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.sts.internal import util
  from tensorflow_probability.python.sts.structural_time_series import Parameter
  from tensorflow_probability.python.sts.structural_time_series import StructuralTimeSeries
label_desc: Use image node_id 1 to create a new SeasonalStateSpaceModel object from inherited base classes: linear_gaussian_ssm with example: obj = SeasonalStateSpaceModel(num_timesteps, num_seasons, drift_scale, initial_state_prior, observation_noise_scale, num_steps_per_season, name)