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
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)
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.))
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
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