Beispiel #1
0
    def create_model(self, prior: R.SdPrior, data: pd.Series):
        """
        Args:
          prior: an R.SdPrior object describing the prior distribution on the
            residual variance paramter.
          data:  The time series of observations as a Pandas Series.

        Returns:
          A boom.StateSpaceModel object.
        """
        boom_data = boom.Vector(data.values)
        is_observed = ~data.isna()
        self._model = boom.StateSpaceModel(boom_data, is_observed)

        if prior is None:
            sdy = np.std(data)
            prior = R.SdPrior(sigma_guess=sdy, upper_limit=sdy * 1.2)

        boom_prior = boom.ChisqModel(prior.sample_size, prior.sigma_guess)
        observation_model_sampler = boom.ZeroMeanGaussianConjSampler(
            self._model.observation_model,
            boom_prior)
        observation_model_sampler.set_sigma_upper_limit(
            prior.upper_limit)
        self._model.observation_model.set_method(observation_model_sampler)

        sampler = boom.StateSpacePosteriorSampler(
            self._model, boom.GlobalRng.rng)
        self._model.set_method(sampler)

        self._original_series = data

        return self._model
Beispiel #2
0
 def _set_posterior_sampler(self):
     sampler = boom.ZeroMeanGaussianConjSampler(
         self._state_model.error_distribution,
         self._sigma_prior.boom(),
         boom.GlobalRng.rng)
     if (
             self._sigma_prior.upper_limit > 0
             and np.isfinite(self._sigma_prior.upper_limit)
     ):
         sampler.set_sigma_upper_limit(self._sigma_prior.upper_limit)
     self._state_model.set_method(sampler)
Beispiel #3
0
 def _assign_posterior_sampler(self, innovation_sd_prior: R.SdPrior):
     innovation_precision_prior = boom.ChisqModel(
         innovation_sd_prior.sigma_guess,
         innovation_sd_prior.sample_size)
     state_model_sampler = boom.ZeroMeanGaussianConjSampler(
         self._state_model,
         innovation_precision_prior,
         seeding_rng=boom.GlobalRng.rng)
     state_model_sampler.set_sigma_upper_limit(
         innovation_sd_prior.upper_limit)
     self._state_model.set_method(state_model_sampler)
 def test_mcmc(self):
     true_sigma = 2.3
     data = np.random.randn(100) * true_sigma
     prior = boom.ChisqModel(1.0, 1.0)
     self.model.set_data(boom.Vector(data))
     sampler = boom.ZeroMeanGaussianConjSampler(self.model, prior)
     self.model.set_method(sampler)
     niter = 1000
     draws = np.zeros(niter)
     for i in range(niter):
         self.model.sample_posterior()
         draws[i] = self.model.sigma
     self.assertNotAlmostEqual(draws[0], draws[-1])
    def _create_model(self):
        """
        Creaate self._state_model and assign it a posterior sampler.

        The four priors (level_sigma, slope_sigma, slope_mean, and slope_ar1)
        must have been created and saved to self.
        """
        level_model = boom.ZeroMeanGaussianModel(
            self.level_sigma_prior.initial_value)
        level_sampler = boom.ZeroMeanGaussianConjSampler(
            level_model,
            self.level_sigma_prior.boom(),
            boom.GlobalRng.rng)
        level_sampler.set_sigma_upper_limit(self.level_sigma_prior.upper_limit)
        level_model.set_method(level_sampler)

        slope_model = boom.NonzeroMeanAr1Model(
            self.slope_mean_prior.initial_value,
            self.slope_ar1_prior.initial_value,
            self.slope_sigma_prior.initial_value)

        slope_sampler = boom.NonzeroMeanAr1Sampler(
            slope_model,
            self.slope_mean_prior.boom(),
            self.slope_ar1_prior.boom(),
            self.slope_sigma_prior.boom())

        slope_sampler.set_sigma_upper_limit(self.slope_sigma_prior.upper_limit)
        if self.slope_ar1_prior.force_stationary:
            slope_sampler.force_stationary()
        if self.slope_ar1_prior.force_positive:
            slope_sampler.force_ar1_positive()

        # ----------------------------------------------------------------------
        # Create the state model.
        self._state_model = boom.SemilocalLinearTrendStateModel(
            level_model, slope_model)

        # BOOM models can have more than one posterior sampler if the samplers
        # focus on different parts of the job.
        self._state_model.set_method(level_sampler)
        self._state_model.set_method(slope_sampler)
    def __init__(self,
                 y=None,
                 level_sigma_prior: R.SdPrior = None,
                 slope_mean_prior: R.NormalPrior = None,
                 slope_ar1_prior: R.Ar1CoefficientPrior = None,
                 slope_sigma_prior: R.SdPrior = None,
                 initial_level_prior: R.NormalPrior = None,
                 initial_slope_prior: R.NormalPrior = None,
                 sdy: float = None,
                 initial_y: float = None):
        """
        Args:
          y:  A numeric vector.  The time series to be modeled.
          level_sigma_prior: The prior distribution for the standard deviation
            of the increments in the level component of state.
          slope.mean_prior: The prior distribution for the mean of the AR1
            process for the slope component of state.
          slope_ar1_prior: The prior distribution for the ar1 coefficient in
            the slope component of state.
          slope_sigma_prior: The prior distribution for the standard deviation
            of the increments in the slope component of state.
          initial_level_prior: The prior distribution for the level component
            of state at the time of the first observation.
          initial_slope_prior: The prior distribution for the slope component
            of state at the time of the first observation.
          sdy: The standard deviation of y.  This can be ignored if y is
            provided, or if all the required prior distributions are supplied
            directly.
          initial.y: The initial value of y.  This can be omitted if y is
            provided.
        """

        # ----------------------------------------------------------------------
        # Validate all priors, generating default values as needed.
        if sdy is None:
            sdy = np.nanstd(y)
        if initial_y is None:
            initial_y = y[0]
        level_sigma_prior = self._validate_level_sigma_prior(
            level_sigma_prior, sdy)
        slope_mean_prior = self._validate_slope_mean_prior(
            slope_mean_prior, sdy)
        slope_ar1_prior = self._validate_slope_ar1_prior(slope_ar1_prior, sdy)
        slope_sigma_prior = self._validate_slope_sigma_prior(
            slope_sigma_prior, sdy)
        initial_level_prior = self._validate_initial_level_prior(
            initial_level_prior, initial_y, sdy)
        initial_slope_prior = self._validate_initial_slope_prior(
            initial_slope_prior, sdy)

        # ----------------------------------------------------------------------
        # Create the component models and samplers.
        level_model = boom.ZeroMeanGaussianModel(
            level_sigma_prior.initial_value)
        level_sampler = boom.ZeroMeanGaussianConjSampler(
            level_model, level_sigma_prior.boom(), boom.GlobalRng.rng)
        level_sampler.set_sigma_upper_limit(level_sigma_prior.upper_limit)
        level_model.set_method(level_sampler)

        slope_model = boom.NonzeroMeanAr1Model(slope_mean_prior.initial_value,
                                               slope_ar1_prior.initial_value,
                                               slope_sigma_prior.initial_value)

        slope_sampler = boom.NonzeroMeanAr1Sampler(slope_model,
                                                   slope_mean_prior.boom(),
                                                   slope_ar1_prior.boom(),
                                                   slope_sigma_prior.boom())

        slope_sampler.set_sigma_upper_limit(slope_sigma_prior.upper_limit)
        if slope_ar1_prior.force_stationary:
            slope_sampler.force_stationary()
        if slope_ar1_prior.force_positive:
            slope_sampler.force_ar1_positive()

        # ----------------------------------------------------------------------
        # Create the state model.
        self._state_model = boom.SemilocalLinearTrendStateModel(
            level_model, slope_model)
        self._state_model.set_method(level_sampler)
        self._state_model.set_method(slope_sampler)

        # ----------------------------------------------------------------------
        # Set the initial distribution priors.
        self._state_model.set_initial_level_mean(initial_level_prior.mu)
        self._state_model.set_initial_level_sd(initial_level_prior.sigma)
        self._state_model.set_initial_slope_mean(initial_slope_prior.mu)
        self._state_model.set_initial_slope_sd(initial_slope_prior.sigma)

        self._state_contribution = None
Beispiel #7
0
    def __init__(self,
                 y,
                 nseasons: int,
                 season_duration: int = 1,
                 initial_state_prior: boom.MvnModel = None,
                 innovation_sd_prior: R.SdPrior = None,
                 sdy: float = None):
        """
        Args:
          y: The time series being modeled.  This can be omitted if either (a)
            initial_state_prior and sdy and initial_y are passed, or (b) sdy
            and initial_y are passed.
          nseasons: The number of seasons in a cycle.
          season_duration:  The number of time periods each season.  See below.
          initial_state_prior: A multivariate normal distribution of dimension
            nseasons - 1.  This is a distribution on the seasonal value at time
            0 and on the nseasons-2 previous values.  If None is passed then a
            default prior will be assumed.
          innovation_sd_prior: Prior distribution on the standard deviation of
            the innovation terms.  If None, then a default prior will be
            assumed.
          sdy: The standard deviation of the time series being modeled.

        Details:

        """
        self._state_model = boom.SeasonalStateModel(
            nseasons=nseasons, season_duration=season_duration)

        if initial_state_prior is None:
            if sdy is None:
                if y is None:
                    raise Exception("One of 'y', 'sdy', or "
                                    "'initial_state_prior' must be supplied.")
                sdy = np.nanstd(y)
            initial_state_prior = self._default_initial_state_prior(sdy)
        if innovation_sd_prior is None:
            if sdy is None:
                if y is None:
                    raise Exception("One of 'y', 'sdy', or "
                                    "'innovation_sd_prior' must be supplied.")
                sdy = np.nanstd(y)
            innovation_sd_prior = self._default_sigma_prior(sdy)

        self._state_model.set_initial_state_mean(
            initial_state_prior.mu)
        self._state_model.set_initial_state_variance(
            initial_state_prior.Sigma)

        innovation_precision_prior = boom.ChisqModel(
            innovation_sd_prior.sigma_guess,
            innovation_sd_prior.sample_size)
        state_model_sampler = boom.ZeroMeanGaussianConjSampler(
            self._state_model,
            innovation_precision_prior,
            seeding_rng=boom.GlobalRng.rng)

        state_model_sampler.set_sigma_upper_limit(
            innovation_sd_prior.upper_limit)
        self._state_model.set_method(state_model_sampler)

        self._state_contribution = None