def _verify_initial_state_prior(self, initial_state_prior, xtx, xty, sdy):
        if initial_state_prior is None:
            try:
                beta_hat = np.linalg.solve(xtx, xty)
                if not np.all(np.finite(beta_hat)):
                    raise Exception("Least squares initializer failed.")

                self._initial_state_prior = R.MvnPrior(
                    beta_hat, sdy * sdy * np.linalg.inv(xtx))
            except Exception:
                self._initial_state_prior = R.MvnPrior(
                    np.zeros(self.xdim),
                    sdy * sdy * np.diag(1.0 / np.diagonal(xtx)))

        elif isinstance(initial_state_prior, R.NormalPrior):
            mean = np.full(initial_state_prior.mean, self.xdim)
            var = np.full(initial_state_prior.sd**2, self.xdim)
            self._initial_state_prior = R.MvnPrior(mean, np.diag(var))

        elif isinstance(initial_state_prior, list) and all(
            [isinstance(x, R.NormalPrior) for x in initial_state_prior]):
            mean = np.array([x.mean for x in initial_state_prior])
            var = np.array([x.sd**2 for x in initial_state_prior])
            self._initial_state_prior = R.MvnPrior(mean, np.diag(var))

        else:
            if not isinstance(initial_state_prior, R.MvnPrior):
                raise Exception("Unrecognized type for initial_state_prior.")
            self._initial_state_prior = initial_state_prior

        return self._initial_state_prior
Esempio n. 2
0
 def _default_initial_state_prior(self, sdy):
     """
     The default prior to use for the initial state vector.
     """
     dim = self.nseasons - 1
     return R.MvnPrior(np.zeros(dim),
                       np.diag(np.full(dim, float(sdy))))
Esempio n. 3
0
 def _validate_initial_distribution(self, initial_state_prior, sdy):
     if initial_state_prior is None:
         dim = self.state_dimension
         initial_state_prior = R.MvnPrior(np.zeros(dim), np.eye(dim) * sdy)
     if not isinstance(initial_state_prior, R.MvnPrior):
         raise Exception("Wrong type for initial_state_prior.")
     if initial_state_prior.dim != self.state_dimension:
         raise Exception(
             f"Initial_state_prior dimension was {initial_state_prior.dim}."
             f"  State dimension is {self.state_dimension}.")
     self._initial_state_prior = initial_state_prior
Esempio n. 4
0
 def _default_initial_state_prior(self, sdy):
     dim = 2 * self._nseasons
     mean = np.zeros(dim)
     variance = np.diag(np.ones(dim) * sdy)
     return R.MvnPrior(mean, variance)
Esempio n. 5
0
    def __init__(self,
                 y,
                 nseasons: int,
                 initial_state_prior=None,
                 level_precision_priors=None,
                 slope_precision_priors=None,
                 sdy: float = None):
        """
        Args:
          y: The time series to be modeled.  This can be "None" if 'sdy' is
            supplied.
          nseasons: The number of seasons in a cycle.
          initial_state_prior: An R.NormalPrior object describing the initial
            distribution of the state at time 0.  If None then a default prior
            will be assumed.
          level_precision_priors: A list of R.SdPrior objects describing the
            prior distribution on the innovation standard deviations for the
            level portion of the model.  There is one such prior for each
            season in the cycle.
          slope_precision_priors: A list of R.SdPrior objects describing the
            prior distribution on the innovation standard deviations for the
            slope portion of the model.  There is one such prior for each
            season in the cycle.
          sdy: The standard deviation of the time series to be modeled.  This
            is not needed if 'y' is supplied, or if all the prior distributions
            are explicity supplied.
        """

        self._nseasons = int(nseasons)
        if nseasons <= 1:
            raise Exception("Seasonal models require at least 2 seasons.")

        if initial_state_prior is None:
            if sdy is None:
                sdy = self._compute_sdy(y, "initial_state_prior")
            initial_state_prior = self._default_initial_state_prior(sdy)

        if isinstance(initial_state_prior, R.NormalPrior):
            dim = 2 * self._nseasons
            mu = np.zeros(dim)
            sigma = initial_state_prior.sd
            Sigma = np.diag(np.ones(dim) * sigma**2)
            self._initial_state_prior = R.MvnPrior(mu, Sigma)
        else:
            self._initial_state_prior = initial_state_prior

        assert isinstance(self._initial_state_prior, R.MvnPrior)

        if level_precision_priors is None:
            if sdy is None:
                sdy = self._compute_sdy(y, "level_precision_priors")
            self._level_precision_priors = [
                R.SdPrior(sdy / 100, .1, upper_limit=sdy)
                for i in range(self.nseasons)
            ]
        else:
            self._level_precision_priors = level_precision_priors
        msg = "level_precision_priors must be a list of R.SdPrior objects"
        if not isinstance(self._level_precision_priors, list):
            raise Exception(msg)
        for x in self._level_precision_priors:
            if not isinstance(x, R.SdPrior):
                raise Exception(msg)

        if slope_precision_priors is None:
            if sdy is None:
                sdy = self._compute_sdy(y, "slope_precision_priors")
            self._slope_precision_priors = [
                R.SdPrior(sdy / 100, .1, upper_limit=sdy)
                for i in range(self.nseasons)
            ]
        else:
            self._slope_precision_priors = slope_precision_priors
        msg = "slope_precision_priors must be a list of R.SdPrior objects"
        if not isinstance(self._slope_precision_priors, list):
            raise Exception(msg)
        for x in self._slope_precision_priors:
            if not isinstance(x, R.SdPrior):
                raise Exception(msg)

        self._build_model()
        self._state_contribution = None
Esempio n. 6
0
    def __init__(self,
                 y,
                 nseasons: int,
                 season_duration: int = 1,
                 initial_state_prior=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._nseasons = nseasons
        self._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, ddof=1)
            initial_state_prior = self._default_initial_state_prior(sdy)

        if isinstance(initial_state_prior, R.NormalPrior):
            dim = nseasons - 1
            mu = initial_state_prior.mean
            sigma = initial_state_prior.sd
            initial_state_prior = R.MvnPrior(
                mu=np.fill(dim, mu),
                Sigma=np.diag(np.fill(dim, sigma * sigma)))

        if not isinstance(initial_state_prior, R.MvnPrior):
            raise Exception("Unexpected type for 'initial_state_prior'.  "
                            "Acceptable types include R.NormalPrior or "
                            "R.MvnPrior.")
        self._initial_state_prior = initial_state_prior

        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, ddof=1)
            innovation_sd_prior = self._default_sigma_prior(sdy)
        if not isinstance(innovation_sd_prior, R.SdPrior):
            raise Exception("Expected an R.SdPrior for innovation_sd_prior.")
        self._innovation_sd_prior = innovation_sd_prior

        self._build_model()
        self._state_contribution = None