def _build_test_model(self,
                          num_timesteps=5,
                          num_features=2,
                          batch_shape=(),
                          missing_prob=0,
                          true_noise_scale=0.1,
                          true_level_scale=0.04,
                          true_slope_scale=0.02,
                          prior_class=tfd.InverseGamma,
                          dtype=tf.float32):
        seed = test_util.test_seed(sampler_type='stateless')
        (design_seed, weights_seed, noise_seed, level_seed, slope_seed,
         is_missing_seed) = samplers.split_seed(seed,
                                                6,
                                                salt='_build_test_model')

        design_matrix = samplers.normal([num_timesteps, num_features],
                                        dtype=dtype,
                                        seed=design_seed)
        weights = samplers.normal(list(batch_shape) + [num_features],
                                  dtype=dtype,
                                  seed=weights_seed)
        regression = tf.linalg.matvec(design_matrix, weights)
        noise = samplers.normal(list(batch_shape) + [num_timesteps],
                                dtype=dtype,
                                seed=noise_seed) * true_noise_scale

        level_residuals = samplers.normal(list(batch_shape) + [num_timesteps],
                                          dtype=dtype,
                                          seed=level_seed) * true_level_scale
        if true_slope_scale is not None:
            slope = tf.cumsum(
                samplers.normal(list(batch_shape) + [num_timesteps],
                                dtype=dtype,
                                seed=slope_seed) * true_slope_scale,
                axis=-1)
            level_residuals += slope
        level = tf.cumsum(level_residuals, axis=-1)
        time_series = (regression + noise + level)
        is_missing = samplers.uniform(list(batch_shape) + [num_timesteps],
                                      dtype=dtype,
                                      seed=is_missing_seed) < missing_prob

        model = gibbs_sampler.build_model_for_gibbs_fitting(
            observed_time_series=tfp.sts.MaskedTimeSeries(
                time_series[..., tf.newaxis], is_missing),
            design_matrix=design_matrix,
            weights_prior=tfd.Normal(loc=tf.cast(0., dtype),
                                     scale=tf.cast(10.0, dtype)),
            level_variance_prior=prior_class(concentration=tf.cast(
                0.01, dtype),
                                             scale=tf.cast(0.01 * 0.01,
                                                           dtype)),
            slope_variance_prior=None if true_slope_scale is None else
            prior_class(concentration=tf.cast(0.01, dtype),
                        scale=tf.cast(0.01 * 0.01, dtype)),
            observation_noise_variance_prior=prior_class(
                concentration=tf.cast(0.01, dtype),
                scale=tf.cast(0.01 * 0.01, dtype)))
        return model, time_series, is_missing
Пример #2
0
 def test_model_with_linop_precision_works(self):
   observed_time_series = tf.ones([2])
   design_matrix = tf.eye(2)
   sampler = gibbs_sampler.build_model_for_gibbs_fitting(
       observed_time_series,
       design_matrix=design_matrix,
       weights_prior=tfde.MultivariateNormalPrecisionFactorLinearOperator(
           precision_factor=tf.linalg.LinearOperatorDiag(tf.ones(2))),
       level_variance_prior=tfd.InverseGamma(0.01, 0.01),
       observation_noise_variance_prior=tfd.InverseGamma(0.01, 0.01))
   self.assertIsNotNone(sampler)
Пример #3
0
  def test_invalid_model_spec_raises_error(self):
    observed_time_series = tf.ones([2])
    design_matrix = tf.eye(2)
    with self.assertRaisesRegexp(
        ValueError, 'Weights prior must be a normal distribution'):
      gibbs_sampler.build_model_for_gibbs_fitting(
          observed_time_series, design_matrix=design_matrix,
          weights_prior=tfd.StudentT(df=10, loc=0., scale=1.),
          level_variance_prior=tfd.InverseGamma(0.01, 0.01),
          observation_noise_variance_prior=tfd.InverseGamma(0.01, 0.01))

    with self.assertRaisesRegexp(
        ValueError, 'Level variance prior must be an inverse gamma'):
      gibbs_sampler.build_model_for_gibbs_fitting(
          observed_time_series, design_matrix=design_matrix,
          weights_prior=tfd.Normal(loc=0., scale=1.),
          level_variance_prior=tfd.LogNormal(0., 3.),
          observation_noise_variance_prior=tfd.InverseGamma(0.01, 0.01))

    with self.assertRaisesRegexp(
        ValueError, 'noise variance prior must be an inverse gamma'):
      gibbs_sampler.build_model_for_gibbs_fitting(
          observed_time_series, design_matrix=design_matrix,
          weights_prior=tfd.Normal(loc=0., scale=1.),
          level_variance_prior=tfd.InverseGamma(0.01, 0.01),
          observation_noise_variance_prior=tfd.LogNormal(0., 3.))
Пример #4
0
  def test_invalid_options_with_none_design_matrix_raises_error(self):
    observed_time_series = tf.ones([2])
    with self.assertRaisesRegex(
        ValueError,
        'Design matrix is None thus sparse_weights_nonzero_prob should '
        'not be defined'):
      gibbs_sampler.build_model_for_gibbs_fitting(
          observed_time_series,
          design_matrix=None,
          weights_prior=None,
          sparse_weights_nonzero_prob=0.4,
          level_variance_prior=tfd.InverseGamma(0.01, 0.01),
          observation_noise_variance_prior=tfd.InverseGamma(0.01, 0.01))

    with self.assertRaisesRegex(
        ValueError,
        'Design matrix is None thus weights_prior should not be defined'):
      gibbs_sampler.build_model_for_gibbs_fitting(
          observed_time_series,
          design_matrix=None,
          weights_prior=tfd.Normal(loc=0., scale=1.),
          level_variance_prior=tfd.InverseGamma(0.01, 0.01),
          observation_noise_variance_prior=tfd.InverseGamma(0.01, 0.01))
def _fit_seasonal_model_with_gibbs_sampling(observed_time_series,
                                            seasonal_structure,
                                            num_warmup_steps=50,
                                            num_results=100,
                                            seed=None):
    """Builds a seasonality-as-regression model and fits it by Gibbs sampling."""
    with tf.name_scope('fit_seasonal_model_with_gibbs_sampling'):
        observed_time_series = sts_util.canonicalize_observed_time_series_with_mask(
            observed_time_series)
        dtype = observed_time_series.time_series.dtype
        design_matrix = seasonality_util.build_fixed_effects(
            num_steps=ps.shape(observed_time_series.time_series)[-2],
            seasonal_structure=seasonal_structure,
            dtype=dtype)

        # Default priors.
        # pylint: disable=protected-access
        one = tf.ones([], dtype=dtype)
        level_variance_prior = tfd.InverseGamma(concentration=16,
                                                scale=16. * 0.001**2 * one)
        level_variance_prior._upper_bound = one
        slope_variance_prior = tfd.InverseGamma(concentration=16,
                                                scale=16. * 0.05**2 * one)
        slope_variance_prior._upper_bound = 0.01 * one
        observation_noise_variance_prior = tfd.InverseGamma(concentration=0.05,
                                                            scale=0.05 * one)
        observation_noise_variance_prior._upper_bound = 1.2 * one
        # pylint: enable=protected-access

    model = gibbs_sampler.build_model_for_gibbs_fitting(
        observed_time_series=observed_time_series,
        design_matrix=design_matrix,
        weights_prior=tfd.Normal(loc=0., scale=one),
        level_variance_prior=level_variance_prior,
        slope_variance_prior=slope_variance_prior,
        observation_noise_variance_prior=observation_noise_variance_prior)
    return [
        model,
        gibbs_sampler.fit_with_gibbs_sampling(
            model,
            observed_time_series,
            num_results=num_results,
            num_warmup_steps=num_warmup_steps,
            seed=seed)
    ]
    def _build_test_model(self,
                          num_timesteps=5,
                          num_features=2,
                          batch_shape=(),
                          missing_prob=0,
                          true_noise_scale=0.1,
                          true_level_scale=0.04,
                          dtype=tf.float32):
        strm = tfp_test_util.test_seed_stream()
        design_matrix = tf.random.normal([num_timesteps, num_features],
                                         dtype=dtype,
                                         seed=strm())
        weights = tf.random.normal(list(batch_shape) + [num_features],
                                   dtype=dtype,
                                   seed=strm())
        regression = tf.linalg.matvec(design_matrix, weights)
        noise = tf.random.normal(list(batch_shape) + [num_timesteps],
                                 dtype=dtype,
                                 seed=strm()) * true_noise_scale
        level = tf.cumsum(tf.random.normal(
            list(batch_shape) + [num_timesteps], dtype=dtype, seed=strm()) *
                          true_level_scale,
                          axis=-1)
        time_series = (regression + noise + level)
        is_missing = tf.random.uniform(list(batch_shape) + [num_timesteps],
                                       dtype=dtype,
                                       seed=strm()) < missing_prob

        model = gibbs_sampler.build_model_for_gibbs_fitting(
            observed_time_series=tfp.sts.MaskedTimeSeries(
                time_series[..., tf.newaxis], is_missing),
            design_matrix=design_matrix,
            weights_prior=tfd.Normal(loc=tf.cast(0., dtype),
                                     scale=tf.cast(10.0, dtype)),
            level_variance_prior=tfd.InverseGamma(
                concentration=tf.cast(0.01, dtype),
                scale=tf.cast(0.01 * 0.01, dtype)),
            observation_noise_variance_prior=tfd.InverseGamma(
                concentration=tf.cast(0.01, dtype),
                scale=tf.cast(0.01 * 0.01, dtype)))
        return model, time_series, is_missing
Пример #7
0
  def _build_test_model(self,
                        num_timesteps=5,
                        num_features=2,
                        batch_shape=(),
                        missing_prob=0,
                        true_noise_scale=0.1,
                        true_level_scale=0.04,
                        true_slope_scale=0.02,
                        prior_class=tfd.InverseGamma,
                        weights=None,
                        weights_prior_scale=10.,
                        sparse_weights_nonzero_prob=None,
                        time_series_shift=0.,
                        dtype=tf.float32,
                        design_matrix=False,
                        seed=None):
    if seed is None:
      seed = test_util.test_seed(sampler_type='stateless')
    (design_seed,
     weights_seed,
     noise_seed,
     level_seed,
     slope_seed,
     is_missing_seed) = samplers.split_seed(seed, 6, salt='_build_test_model')

    if weights is None:
      weights = samplers.normal(
          list(batch_shape) + [num_features], dtype=dtype, seed=weights_seed)
    if design_matrix is None:
      regression = tf.zeros(num_timesteps, dtype)
    else:
      if isinstance(design_matrix, bool) and not design_matrix:
        design_matrix = samplers.normal([num_timesteps, num_features],
                                        dtype=dtype,
                                        seed=design_seed)
      regression = tf.linalg.matvec(design_matrix, weights)
    noise = samplers.normal(
        list(batch_shape) + [num_timesteps],
        dtype=dtype, seed=noise_seed) * true_noise_scale

    level_residuals = samplers.normal(
        list(batch_shape) + [num_timesteps],
        dtype=dtype, seed=level_seed) * true_level_scale
    if true_slope_scale is not None:
      slope = tf.cumsum(samplers.normal(
          list(batch_shape) + [num_timesteps],
          dtype=dtype, seed=slope_seed) * true_slope_scale, axis=-1)
      level_residuals += slope
    level = tf.cumsum(level_residuals, axis=-1)
    time_series = (regression + noise + level + time_series_shift)
    is_missing = samplers.uniform(
        list(batch_shape) + [num_timesteps],
        dtype=dtype, seed=is_missing_seed) < missing_prob

    observation_noise_variance_prior = prior_class(
        concentration=tf.cast(0.01, dtype),
        scale=tf.cast(0.01 * 0.01, dtype))
    observation_noise_variance_prior.upper_bound = 100.0

    observed_time_series = tfp.sts.MaskedTimeSeries(
        time_series[..., tf.newaxis], is_missing)
    if time_series_shift != 0.:
      observed_mean, observed_stddev, observed_initial = (
          sts_util.empirical_statistics(observed_time_series))
      initial_level_prior = tfd.Normal(
          loc=observed_mean + observed_initial,
          scale=tf.abs(observed_initial) + observed_stddev)
    else:
      initial_level_prior = None

    model = gibbs_sampler.build_model_for_gibbs_fitting(
        observed_time_series=observed_time_series,
        design_matrix=design_matrix,
        weights_prior=(
            None if weights_prior_scale is None
            else tfd.Normal(loc=tf.cast(0., dtype),
                            scale=tf.cast(weights_prior_scale, dtype))),
        level_variance_prior=prior_class(
            concentration=tf.cast(0.01, dtype),
            scale=tf.cast(0.01 * 0.01, dtype)),
        slope_variance_prior=None if true_slope_scale is None else prior_class(
            concentration=tf.cast(0.01, dtype),
            scale=tf.cast(0.01 * 0.01, dtype)),
        initial_level_prior=initial_level_prior,
        observation_noise_variance_prior=observation_noise_variance_prior,
        sparse_weights_nonzero_prob=sparse_weights_nonzero_prob)
    return model, time_series, is_missing