Пример #1
0
    def test_constant_offset(self):
        offset_ = 1.23456
        offset = self._build_placeholder(offset_)
        ssm = self._dummy_model()

        additive_ssm = AdditiveStateSpaceModel([ssm])
        additive_ssm_with_offset = AdditiveStateSpaceModel(
            [ssm], constant_offset=offset)
        additive_ssm_with_offset_and_explicit_scale = AdditiveStateSpaceModel(
            [ssm],
            constant_offset=offset,
            observation_noise_scale=(
                ssm.get_observation_noise_for_timestep(0).stddev()[..., 0]))

        mean_, offset_mean_, offset_with_scale_mean_ = self.evaluate(
            (additive_ssm.mean(), additive_ssm_with_offset.mean(),
             additive_ssm_with_offset_and_explicit_scale.mean()))
        print(mean_.shape, offset_mean_.shape, offset_with_scale_mean_.shape)
        self.assertAllClose(mean_, offset_mean_ - offset_)
        self.assertAllClose(mean_, offset_with_scale_mean_ - offset_)

        # Offset should not affect the stddev.
        stddev_, offset_stddev_, offset_with_scale_stddev_ = self.evaluate(
            (additive_ssm.stddev(), additive_ssm_with_offset.stddev(),
             additive_ssm_with_offset_and_explicit_scale.stddev()))
        self.assertAllClose(stddev_, offset_stddev_)
        self.assertAllClose(stddev_, offset_with_scale_stddev_)
Пример #2
0
    def test_nesting_additive_ssms(self):

        ssm1 = self._dummy_model(batch_shape=[1, 2])
        ssm2 = self._dummy_model(batch_shape=[3, 2])
        observation_noise_scale = 0.1

        additive_ssm = AdditiveStateSpaceModel(
            [ssm1, ssm2], observation_noise_scale=observation_noise_scale)

        nested_additive_ssm = AdditiveStateSpaceModel(
            [AdditiveStateSpaceModel([ssm1]),
             AdditiveStateSpaceModel([ssm2])],
            observation_noise_scale=observation_noise_scale)

        # Test that both models behave equivalently.
        y = self.evaluate(nested_additive_ssm.sample())

        additive_lp = additive_ssm.log_prob(y)
        nested_additive_lp = nested_additive_ssm.log_prob(y)
        self.assertAllClose(self.evaluate(additive_lp),
                            self.evaluate(nested_additive_lp))

        additive_mean = additive_ssm.mean()
        nested_additive_mean = nested_additive_ssm.mean()
        self.assertAllClose(self.evaluate(additive_mean),
                            self.evaluate(nested_additive_mean))

        additive_variance = additive_ssm.variance()
        nested_additive_variance = nested_additive_ssm.variance()
        self.assertAllClose(self.evaluate(additive_variance),
                            self.evaluate(nested_additive_variance))
Пример #3
0
    def test_constant_offset(self, is_scalar=True):
        offset_ = np.array(3.1415) if is_scalar else np.array(
            [3., 1., 4., 1., 5.])
        offset = self._build_placeholder(offset_)
        ssm = self._dummy_model()

        additive_ssm = AdditiveStateSpaceModel([ssm])
        additive_ssm_with_offset = AdditiveStateSpaceModel(
            [ssm], constant_offset=offset)
        additive_ssm_with_offset_and_explicit_scale = AdditiveStateSpaceModel(
            [ssm],
            constant_offset=offset,
            observation_noise_scale=(
                ssm.get_observation_noise_for_timestep(0).stddev()[..., 0]))

        mean_, offset_mean_, offset_with_scale_mean_ = self.evaluate(
            (additive_ssm.mean(), additive_ssm_with_offset.mean(),
             additive_ssm_with_offset_and_explicit_scale.mean()))
        self.assertAllClose(mean_, offset_mean_ - offset_[..., tf.newaxis])
        self.assertAllClose(mean_,
                            offset_with_scale_mean_ - offset_[..., tf.newaxis])

        # Offset should not affect the stddev.
        stddev_, offset_stddev_, offset_with_scale_stddev_ = self.evaluate(
            (additive_ssm.stddev(), additive_ssm_with_offset.stddev(),
             additive_ssm_with_offset_and_explicit_scale.stddev()))
        self.assertAllClose(stddev_, offset_stddev_)
        self.assertAllClose(stddev_, offset_with_scale_stddev_)
Пример #4
0
    def test_sum_of_local_linear_trends(self):

        # We know analytically that the sum of two local linear trends is
        # another local linear trend, with means and variances scaled
        # accordingly, so the additive model should match this behavior.

        level_scale = 0.5
        slope_scale = 1.1
        initial_level = 3.
        initial_slope = -2.
        observation_noise_scale = 0.
        num_timesteps = 5
        y = self._build_placeholder([1.0, 2.5, 4.3, 6.1, 7.8])

        # Combine two local linear trend models, one a full model, the other
        # with just a moving mean (zero slope).
        local_ssm = LocalLinearTrendStateSpaceModel(
            num_timesteps=num_timesteps,
            level_scale=level_scale,
            slope_scale=slope_scale,
            initial_state_prior=tfd.MultivariateNormalDiag(
                loc=self._build_placeholder([initial_level, initial_slope]),
                scale_diag=self._build_placeholder([1., 1.])))

        second_level_scale = 0.3
        second_initial_level = 1.1
        moving_level_ssm = LocalLinearTrendStateSpaceModel(
            num_timesteps=num_timesteps,
            level_scale=second_level_scale,
            slope_scale=0.,
            initial_state_prior=tfd.MultivariateNormalDiag(
                loc=self._build_placeholder([second_initial_level, 0.]),
                scale_diag=self._build_placeholder([1., 0.])))

        additive_ssm = AdditiveStateSpaceModel(
            [local_ssm, moving_level_ssm],
            observation_noise_scale=observation_noise_scale)

        # Build the analytical sum of the two processes.
        target_ssm = LocalLinearTrendStateSpaceModel(
            num_timesteps=num_timesteps,
            level_scale=np.float32(
                np.sqrt(level_scale**2 + second_level_scale**2)),
            slope_scale=np.float32(slope_scale),
            observation_noise_scale=observation_noise_scale,
            initial_state_prior=tfd.MultivariateNormalDiag(
                loc=self._build_placeholder(
                    [initial_level + second_initial_level,
                     initial_slope + 0.]),
                scale_diag=self._build_placeholder(np.sqrt([2., 1.]))))

        # Test that both models behave equivalently.
        additive_mean = additive_ssm.mean()
        target_mean = target_ssm.mean()
        self.assertAllClose(self.evaluate(additive_mean),
                            self.evaluate(target_mean))

        additive_variance = additive_ssm.variance()
        target_variance = target_ssm.variance()
        self.assertAllClose(self.evaluate(additive_variance),
                            self.evaluate(target_variance))

        additive_lp = additive_ssm.log_prob(y[:, np.newaxis])
        target_lp = target_ssm.log_prob(y[:, np.newaxis])
        self.assertAllClose(self.evaluate(additive_lp),
                            self.evaluate(target_lp))