def model(self, home_team, away_team, gameweek):
        n_gameweeks = max(gameweek) + 1
        sigma_0 = pyro.sample("sigma_0", dist.HalfNormal(5))
        sigma_b = pyro.sample("sigma_b", dist.HalfNormal(5))
        gamma = pyro.sample("gamma", dist.LogNormal(0, 1))

        b = pyro.sample("b", dist.Normal(0, 1))

        loc_mu_b = pyro.sample("loc_mu_b", dist.Normal(0, 1))
        scale_mu_b = pyro.sample("scale_mu_b", dist.HalfNormal(1))

        with pyro.plate("teams", self.n_teams):

            log_a0 = pyro.sample("log_a0", dist.Normal(0, sigma_0))
            mu_b = pyro.sample(
                "mu_b",
                dist.TransformedDistribution(
                    dist.Normal(0, 1),
                    dist.transforms.AffineTransform(loc_mu_b, scale_mu_b),
                ),
            )
            sigma_rw = pyro.sample("sigma_rw", dist.HalfNormal(0.1))

            with pyro.plate("random_walk", n_gameweeks - 1):
                diffs = pyro.sample(
                    "diff",
                    dist.TransformedDistribution(
                        dist.Normal(0, 1),
                        dist.transforms.AffineTransform(0, sigma_rw)),
                )

            diffs = np.vstack((log_a0, diffs))
            log_a = np.cumsum(diffs, axis=-2)

            with pyro.plate("weeks", n_gameweeks):
                log_b = pyro.sample(
                    "log_b",
                    dist.TransformedDistribution(
                        dist.Normal(0, 1),
                        dist.transforms.AffineTransform(
                            mu_b + b * log_a, sigma_b),
                    ),
                )

        pyro.sample("log_a", dist.Delta(log_a), obs=log_a)
        home_inds = np.array([self.team_to_index[team] for team in home_team])
        away_inds = np.array([self.team_to_index[team] for team in away_team])
        home_rate = np.clip(
            log_a[gameweek, home_inds] - log_b[gameweek, away_inds] + gamma,
            -7, 2)
        away_rate = np.clip(
            log_a[gameweek, away_inds] - log_b[gameweek, home_inds], -7, 2)

        pyro.sample("home_goals", dist.Poisson(np.exp(home_rate)))
        pyro.sample("away_goals", dist.Poisson(np.exp(away_rate)))
Exemple #2
0
    def guide(X: DeviceArray):
        n_stores, n_days, n_features = X.shape
        n_features -= 1  # remove one dim for target

        plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
        plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)

        numpyro.sample(
            Site.disp_param_mu,
            dist.Normal(loc=model_params[Param.loc_disp_param_mu],
                        scale=model_params[Param.scale_disp_param_mu]))

        numpyro.sample(
            Site.disp_param_sigma,
            dist.TransformedDistribution(
                dist.Normal(
                    loc=model_params[Param.loc_disp_param_logsigma],
                    scale=model_params[Param.scale_disp_param_logsigma]),
                transforms=dist.transforms.ExpTransform()))

        with plate_stores:
            numpyro.sample(
                Site.disp_param_offsets,
                dist.Normal(loc=numpyro.param(Param.loc_disp_param_offsets,
                                              jnp.zeros((n_stores, 1))),
                            scale=numpyro.param(
                                Param.scale_disp_param_offsets,
                                0.1 * jnp.ones((n_stores, 1)),
                                constraint=dist.constraints.positive)))

        with plate_features:
            numpyro.sample(
                Site.coef_mus,
                dist.Normal(loc=model_params[Param.loc_coef_mus],
                            scale=model_params[Param.scale_coef_mus]))
            numpyro.sample(
                Site.coef_sigmas,
                dist.TransformedDistribution(
                    dist.Normal(
                        loc=model_params[Param.loc_coef_logsigmas],
                        scale=model_params[Param.scale_coef_logsigmas]),
                    transforms=dist.transforms.ExpTransform()))

            with plate_stores:
                numpyro.sample(
                    Site.coef_offsets,
                    dist.Normal(loc=numpyro.param(
                        Param.loc_coef_offsets,
                        jnp.zeros((n_stores, n_features))),
                                scale=numpyro.param(
                                    Param.scale_coef_offsets,
                                    0.5 * jnp.ones((n_stores, n_features)),
                                    constraint=dist.constraints.positive)))
Exemple #3
0
def test_transformed_distributions():
    from tensorflow_probability.substrates.jax import bijectors as tfb
    from numpyro.contrib.tfp import distributions as tfd

    d = dist.TransformedDistribution(dist.Normal(0, 1), dist.transforms.ExpTransform())
    d1 = tfd.TransformedDistribution(tfd.Normal(0, 1), tfb.Exp())
    d2 = dist.TransformedDistribution(dist.Normal(0, 1), tfd.BijectorTransform(tfb.Exp()))
    x = random.normal(random.PRNGKey(0), (1000,))
    d_x = d.log_prob(x).sum()
    d1_x = d1.log_prob(x).sum()
    d2_x = d2.log_prob(x).sum()
    assert_allclose(d_x, d1_x)
    assert_allclose(d_x, d2_x)
def test_transformed_transformed_distribution():
    loc, scale = -2, 3
    dist1 = dist.TransformedDistribution(dist.Normal(2, 3), transforms.PowerTransform(2.))
    dist2 = dist.TransformedDistribution(dist1, transforms.AffineTransform(-2, 3))
    assert isinstance(dist2.base_dist, dist.Normal)
    assert len(dist2.transforms) == 2
    assert isinstance(dist2.transforms[0], transforms.PowerTransform)
    assert isinstance(dist2.transforms[1], transforms.AffineTransform)

    rng_key = random.PRNGKey(0)
    assert_allclose(loc + scale * dist1.sample(rng_key), dist2.sample(rng_key))
    intermediates = dist2.sample_with_intermediates(rng_key)
    assert len(intermediates) == 2
Exemple #5
0
def reparam_model(dim=10):
    y = numpyro.sample('y', dist.Normal(0, 3))
    with numpyro.handlers.reparam(config={'x': TransformReparam()}):
        numpyro.sample(
            'x',
            dist.TransformedDistribution(dist.Normal(jnp.zeros(dim - 1), 1),
                                         AffineTransform(0, jnp.exp(y / 2))))
Exemple #6
0
 def model(data):
     alpha = numpyro.sample('alpha', dist.Uniform(0, 1))
     with handlers.reparam(config={'loc': TransformReparam()}):
         loc = numpyro.sample('loc', dist.TransformedDistribution(
             dist.Uniform(0, 1).mask(False),
             AffineTransform(0, alpha)))
     numpyro.sample('obs', dist.Normal(loc, 0.1), obs=data)
Exemple #7
0
def test_elbo_dynamic_support():
    x_prior = dist.TransformedDistribution(
        dist.Normal(),
        [AffineTransform(0, 2),
         SigmoidTransform(),
         AffineTransform(0, 3)])
    x_guide = dist.Uniform(0, 3)

    def model():
        numpyro.sample('x', x_prior)

    def guide():
        numpyro.sample('x', x_guide)

    adam = optim.Adam(0.01)
    # set base value of x_guide is 0.9
    x_base = 0.9
    guide = substitute(guide, base_param_map={'x': x_base})
    svi = SVI(model, guide, elbo, adam)
    svi_state = svi.init(random.PRNGKey(0), (), ())
    actual_loss = svi.evaluate(svi_state)
    assert np.isfinite(actual_loss)
    x, _ = x_guide.transform_with_intermediates(x_base)
    expected_loss = x_guide.log_prob(x) - x_prior.log_prob(x)
    assert_allclose(actual_loss, expected_loss)
Exemple #8
0
 def _sample_latent(self, base_dist, *args, **kwargs):
     sample_shape = kwargs.pop('sample_shape', ())
     transform = self._get_transform()
     posterior = dist.TransformedDistribution(base_dist, transform)
     return numpyro.sample("_{}_latent".format(self.prefix),
                           posterior,
                           sample_shape=sample_shape)
Exemple #9
0
 def model():
     fn = dist.TransformedDistribution(
         dist.Normal(jnp.zeros_like(loc), jnp.ones_like(scale)),
         [AffineTransform(loc, scale), ExpTransform()]).expand(shape)
     if event_shape:
         fn = fn.to_event(len(event_shape)).expand_by([100000])
     with numpyro.plate_stack("plates", batch_shape):
         with numpyro.plate("particles", 100000):
             return numpyro.sample("x", fn)
Exemple #10
0
 def model(data):
     alpha = numpyro.sample("alpha", dist.Uniform(0, 1))
     with numpyro.handlers.reparam(config={"loc": TransformReparam()}):
         loc = numpyro.sample(
             "loc",
             dist.TransformedDistribution(
                 dist.Uniform(0, 1).mask(False), AffineTransform(0, alpha)),
         )
     numpyro.sample("obs", dist.Normal(loc, 0.1), obs=data)
Exemple #11
0
 def model():
     with numpyro.plate_stack("plates", shape):
         with numpyro.plate("particles", 100000):
             return numpyro.sample(
                 "x",
                 dist.TransformedDistribution(
                     dist.Normal(jnp.zeros_like(loc), jnp.ones_like(scale)),
                     [AffineTransform(loc, scale),
                      ExpTransform()]).expand_by([100000]))
def test_transformed_potential_energy():
    beta_dist = dist.Beta(np.ones(5), np.ones(5))
    transform = transforms.AffineTransform(3, 4)
    inv_transform = transforms.AffineTransform(-0.75, 0.25)

    z = random.normal(random.PRNGKey(0), (5,))
    pe_expected = -dist.TransformedDistribution(beta_dist, transform).log_prob(z)
    potential_fn = lambda x: -beta_dist.log_prob(x)  # noqa: E731
    pe_actual = transformed_potential_energy(potential_fn, inv_transform, z)
    assert_allclose(pe_actual, pe_expected)
Exemple #13
0
 def actual_model(data):
     alpha = numpyro.sample("alpha", dist.Uniform(0, 1))
     with numpyro.handlers.reparam(config={"loc": TransformReparam()}):
         loc = numpyro.sample(
             "loc",
             dist.TransformedDistribution(
                 dist.Uniform(0, 1), transforms.AffineTransform(0, alpha)),
         )
     with numpyro.plate("N", len(data)):
         numpyro.sample("obs", dist.Normal(loc, 0.1), obs=data)
Exemple #14
0
    def get_posterior(self, params):
        """
        Returns the posterior distribution.

        :param dict params: Current parameters of model and autoguide.
            The parameters can be obtained using :meth:`~numpyro.infer.svi.SVI.get_params`
            method from :class:`~numpyro.infer.svi.SVI`.
        """
        base_dist = self.get_base_dist()
        transform = self.get_transform(params)
        return dist.TransformedDistribution(base_dist, transform)
Exemple #15
0
 def _get_posterior(self):
     if self.latent_dim == 1:
         raise ValueError('latent dim = 1. Consider using AutoDiagonalNormal instead')
     flows = []
     for i in range(self.num_flows):
         if i > 0:
             flows.append(PermuteTransform(jnp.arange(self.latent_dim)[::-1]))
         residual = "gated" if i < (self.num_flows - 1) else None
         arn = BlockNeuralAutoregressiveNN(self.latent_dim, self._hidden_factors, residual)
         arnn = numpyro.module('{}_arn__{}'.format(self.prefix, i), arn, (self.latent_dim,))
         flows.append(BlockNeuralAutoregressiveTransform(arnn))
     return dist.TransformedDistribution(self.get_base_dist(), flows)
Exemple #16
0
def BinomialApprox(n, p, conc=None):
    '''
    Return distribution that is a continuous approximation to 
    Binomial(n, p); allows overdispersion by setting conc < n
    '''
    if conc is None:
        conc = n

    a = conc * p
    b = conc * (1 - p)

    # This is the distribution of n * Beta(a, b)
    return dist.TransformedDistribution(
        dist.Beta(a, b), dist.transforms.AffineTransform(loc=0, scale=n))
Exemple #17
0
 def _get_posterior(self):
     if self.latent_dim == 1:
         raise ValueError('latent dim = 1. Consider using AutoDiagonalNormal instead')
     hidden_dims = [self.latent_dim, self.latent_dim] if self._hidden_dims is None else self._hidden_dims
     flows = []
     for i in range(self.num_flows):
         if i > 0:
             flows.append(PermuteTransform(jnp.arange(self.latent_dim)[::-1]))
         arn = AutoregressiveNN(self.latent_dim, hidden_dims,
                                permutation=jnp.arange(self.latent_dim),
                                skip_connections=self._skip_connections,
                                nonlinearity=self._nonlinearity)
         arnn = numpyro.module('{}_arn__{}'.format(self.prefix, i), arn, (self.latent_dim,))
         flows.append(InverseAutoregressiveTransform(arnn))
     return dist.TransformedDistribution(self.get_base_dist(), flows)
Exemple #18
0
def model_noncentered(num: int,
                      sigma: np.ndarray,
                      y: Optional[np.ndarray] = None) -> None:

    mu = numpyro.sample("mu", dist.Normal(0, 5))
    tau = numpyro.sample("tau", dist.HalfCauchy(5))
    with numpyro.plate("num", num):
        with numpyro.handlers.reparam(config={"theta": TransformReparam()}):
            theta = numpyro.sample(
                "theta",
                dist.TransformedDistribution(
                    dist.Normal(0.0, 1.0),
                    dist.transforms.AffineTransform(mu, tau)),
            )

        numpyro.sample("obs", dist.Normal(theta, sigma), obs=y)
Exemple #19
0
    def __call__(self, *args, **kwargs):
        """
        An automatic guide with the same ``*args, **kwargs`` as the base ``model``.

        :return: A dict mapping sample site name to sampled value.
        :rtype: dict
        """
        if self.prototype_trace is None:
            # run model to inspect the model structure
            self._setup_prototype(*args, **kwargs)

        plates = self._create_plates(*args, **kwargs)
        result = {}
        for name, site in self.prototype_trace.items():
            if site["type"] != "sample" or site["is_observed"]:
                continue

            event_dim = self._event_dims[name]
            init_loc = self._init_locs[name]
            with ExitStack() as stack:
                for frame in site["cond_indep_stack"]:
                    stack.enter_context(plates[frame.name])

                site_loc = numpyro.param("{}_{}_loc".format(name, self.prefix),
                                         init_loc,
                                         event_dim=event_dim)
                site_scale = numpyro.param(
                    "{}_{}_scale".format(name, self.prefix),
                    jnp.full(jnp.shape(init_loc), self._init_scale),
                    constraint=self.scale_constraint,
                    event_dim=event_dim,
                )

                site_fn = dist.Normal(site_loc, site_scale).to_event(event_dim)
                if site["fn"].support is constraints.real or (
                        isinstance(site["fn"].support, constraints.independent)
                        and site["fn"].support is constraints.real):
                    result[name] = numpyro.sample(name, site_fn)
                else:
                    transform = biject_to(site["fn"].support)
                    guide_dist = dist.TransformedDistribution(
                        site_fn, transform)
                    result[name] = numpyro.sample(name, guide_dist)

        return result
Exemple #20
0
    def transition_fn(carry, t):
        x_prev = carry

        gamma_dyn = npyro.deterministic('gamma_dyn', nn.softplus(mu + x_prev))

        logs = logits((beliefs[0][:, t], beliefs[1][:, t]),
                      jnp.expand_dims(gamma_dyn, -1), jnp.expand_dims(U, -2))

        mixing_dist = dist.CategoricalProbs(weights)
        component_dist = dist.CategoricalLogits(logs).mask(mask[t])
        npyro.sample('y', dist.MixtureSameFamily(mixing_dist, component_dist))

        with npyro.handlers.reparam(
                config={"x_next": npyro.infer.reparam.TransformReparam()}):
            affine = dist.transforms.AffineTransform(rho * x_prev, sigma)
            x_next = npyro.sample(
                'x_next',
                dist.TransformedDistribution(dist.Normal(0., 1.), affine))

        return (x_next), None
Exemple #21
0
def test_elbo_dynamic_support():
    x_prior = dist.TransformedDistribution(
        dist.Normal(), [AffineTransform(0, 2), SigmoidTransform(), AffineTransform(0, 3)])
    x_guide = dist.Uniform(0, 3)

    def model():
        numpyro.sample('x', x_prior)

    def guide():
        numpyro.sample('x', x_guide)

    adam = optim.Adam(0.01)
    x = 2.
    guide = substitute(guide, data={'x': x})
    svi = SVI(model, guide, adam, Trace_ELBO())
    svi_state = svi.init(random.PRNGKey(0))
    actual_loss = svi.evaluate(svi_state)
    assert jnp.isfinite(actual_loss)
    expected_loss = x_guide.log_prob(x) - x_prior.log_prob(x)
    assert_allclose(actual_loss, expected_loss)
Exemple #22
0
def ExponentialRandomWalk(loc=1., scale=1e-2, drift=0., num_steps=100):
    '''
    Return distrubtion of exponentiated Gaussian random walk
    
    Variables are x_0, ..., x_{T-1}
    
    Dynamics in log-space are random walk with drift:
       log(x_0) := log(loc) 
       log(x_t) := log(x_{t-1}) + drift + eps_t,    eps_t ~ N(0, scale)
        
    ==> Dynamics in non-log space are:
        x_0 := loc
        x_t := x_{t-1} * exp(drift + eps_t),    eps_t ~ N(0, scale)        
    '''

    log_loc = np.log(loc) + drift * (np.arange(num_steps) + 0.)

    return dist.TransformedDistribution(
        dist.GaussianRandomWalk(scale=scale, num_steps=num_steps), [
            dist.transforms.AffineTransform(loc=log_loc, scale=1.),
            dist.transforms.ExpTransform()
        ])
Exemple #23
0
def ar_k(n_coefs, obs=None, X=None):

    beta = numpyro.sample(name="beta",
                          sample_shape=(n_coefs, ),
                          fn=dist.TransformedDistribution(
                              dist.Normal(loc=0., scale=1),
                              transforms=dist.transforms.AffineTransform(
                                  loc=0,
                                  scale=1,
                                  domain=dist.constraints.interval(-1, 1))))
    tau = numpyro.sample(name="tau", fn=dist.HalfCauchy(scale=1))

    z_init = numpyro.sample(name='z_init',
                            fn=dist.Normal(0, 1),
                            sample_shape=(n_coefs, ))

    obs_init = z_init[:n_coefs - 1]

    (beta, obs_last), zs_exp = scan_fn(n_coefs, beta, obs_init, obs)
    Z_exp = np.concatenate((z_init, zs_exp), axis=0)

    Z = numpyro.sample(name="Z", fn=dist.Normal(loc=Z_exp, scale=tau), obs=obs)

    return Z_exp, obs_last
Exemple #24
0
def guide(X: DeviceArray):
    """Guide with parameters of the posterior

    Args:
        X: input data
    """
    n_stores, n_days, n_features = X.shape
    n_features -= 1  # remove one dim for target

    plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
    plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)

    numpyro.sample(
        Site.disp_param_mu,
        dist.Normal(loc=numpyro.param(Param.loc_disp_param_mu,
                                      4. * jnp.ones(1)),
                    scale=numpyro.param(Param.scale_disp_param_mu,
                                        1. * jnp.ones(1),
                                        constraint=dist.constraints.positive)))
    numpyro.sample(
        Site.disp_param_sigma,
        dist.TransformedDistribution(
            dist.Normal(loc=numpyro.param(Param.loc_disp_param_logsigma,
                                          1.0 * jnp.ones(1)),
                        scale=numpyro.param(
                            Param.scale_disp_param_logsigma,
                            0.1 * jnp.ones(1),
                            constraint=dist.constraints.positive)),
            transforms=dist.transforms.ExpTransform()))

    with plate_stores:
        numpyro.sample(
            Site.disp_param_offsets,
            dist.Normal(loc=numpyro.param(Param.loc_disp_param_offsets,
                                          jnp.zeros((n_stores, 1))),
                        scale=numpyro.param(
                            Param.scale_disp_param_offsets,
                            0.1 * jnp.ones((n_stores, 1)),
                            constraint=dist.constraints.positive)))

    with plate_features:
        numpyro.sample(
            Site.coef_mus,
            dist.Normal(loc=numpyro.param(Param.loc_coef_mus,
                                          jnp.ones(n_features)),
                        scale=numpyro.param(
                            Param.scale_coef_mus,
                            0.5 * jnp.ones(n_features),
                            constraint=dist.constraints.positive)))
        numpyro.sample(
            Site.coef_sigmas,
            dist.TransformedDistribution(
                dist.Normal(loc=numpyro.param(Param.loc_coef_logsigmas,
                                              jnp.zeros(n_features)),
                            scale=numpyro.param(
                                Param.scale_coef_logsigmas,
                                0.5 * jnp.ones(n_features),
                                constraint=dist.constraints.positive)),
                transforms=dist.transforms.ExpTransform()))

        with plate_stores:
            numpyro.sample(
                Site.coef_offsets,
                dist.Normal(
                    loc=numpyro.param(Param.loc_coef_offsets,
                                      jnp.zeros((n_stores, n_features))),
                    scale=numpyro.param(Param.scale_coef_offsets,
                                        0.5 * jnp.ones((n_stores, n_features)),
                                        constraint=dist.constraints.positive)))
Exemple #25
0
def reparam_model(dim=10):
    y = numpyro.sample('y', dist.Normal(0, 3))
    numpyro.sample(
        'x',
        dist.TransformedDistribution(dist.Normal(np.zeros(dim - 1), 1),
                                     AffineTransform(0, np.exp(y / 2))))
Exemple #26
0
    def model(X: DeviceArray):
        n_stores, n_days, n_features = X.shape
        n_features -= 1  # remove one dim for target

        plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
        plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)
        plate_days = numpyro.plate(Plate.days, n_days, dim=-1)

        disp_param_mu = numpyro.sample(
            Site.disp_param_mu,
            dist.Normal(
                loc=model_params[Param.loc_disp_param_mu],
                scale=model_params[Param.scale_disp_param_mu],
            ),
        )
        disp_param_sigma = numpyro.sample(
            Site.disp_param_sigma,
            dist.TransformedDistribution(
                dist.Normal(
                    loc=model_params[Param.loc_disp_param_logsigma],
                    scale=model_params[Param.scale_disp_param_logsigma],
                ),
                transforms=dist.transforms.ExpTransform(),
            ),
        )

        with plate_stores:
            with numpyro.handlers.reparam(
                    config={Site.disp_params: TransformReparam()}):
                disp_params = numpyro.sample(
                    Site.disp_params,
                    dist.TransformedDistribution(
                        dist.Normal(
                            loc=model_params[Param.loc_disp_params],
                            scale=model_params[Param.scale_disp_params],
                        ),
                        dist.transforms.AffineTransform(
                            disp_param_mu, disp_param_sigma),
                    ),
                )

        with plate_features:
            coef_mus = numpyro.sample(
                Site.coef_mus,
                dist.Normal(
                    loc=model_params[Param.loc_coef_mus],
                    scale=model_params[Param.scale_coef_mus],
                ),
            )
            coef_sigmas = numpyro.sample(
                Site.coef_sigmas,
                dist.TransformedDistribution(
                    dist.Normal(
                        loc=model_params[Param.loc_coef_logsigmas],
                        scale=model_params[Param.scale_coef_logsigmas],
                    ),
                    transforms=dist.transforms.ExpTransform(),
                ),
            )

            with plate_stores:
                with numpyro.handlers.reparam(
                        config={Site.coefs: TransformReparam()}):
                    coefs = numpyro.sample(
                        Site.coefs,
                        dist.TransformedDistribution(
                            dist.Normal(
                                loc=model_params[Param.loc_coefs],
                                scale=model_params[Param.scale_coefs],
                            ),
                            dist.transforms.AffineTransform(
                                coef_mus, coef_sigmas),
                        ),
                    )

        with plate_days, plate_stores:
            features = jnp.nan_to_num(X[..., :-1])
            means = jnp.exp(
                jnp.sum(jnp.expand_dims(coefs, axis=1) * features, axis=2))
            betas = jnp.exp(-disp_params)
            alphas = means * betas
            return numpyro.sample(Site.days, dist.GammaPoisson(alphas, betas))
Exemple #27
0
    assert np.shape(actual) == batch_shape
    if len(shape) == transform.event_dim:
        if isinstance(transform, PermuteTransform):
            expected = onp.linalg.slogdet(jax.jacobian(transform)(x))[1]
            inv_expected = onp.linalg.slogdet(jax.jacobian(
                transform.inv)(y))[1]
        else:
            expected = np.log(np.abs(grad(transform)(x)))
            inv_expected = np.log(np.abs(grad(transform.inv)(y)))

        assert_allclose(actual, expected, atol=1e-6)
        assert_allclose(actual, -inv_expected, atol=1e-6)


@pytest.mark.parametrize('transformed_dist', [
    dist.TransformedDistribution(dist.Normal(np.array([2., 3.]), 1.),
                                 constraints.ExpTransform()),
    dist.TransformedDistribution(dist.Exponential(np.ones(2)), [
        constraints.PowerTransform(0.7),
        constraints.AffineTransform(0.,
                                    np.ones(2) * 3)
    ]),
])
def test_transformed_distribution_intermediates(transformed_dist):
    sample, intermediates = transformed_dist.sample_with_intermediates(
        random.PRNGKey(1))
    assert_allclose(transformed_dist.log_prob(sample, intermediates),
                    transformed_dist.log_prob(sample))


def test_transformed_transformed_distribution():
    loc, scale = -2, 3
Exemple #28
0
    def guide(X: DeviceArray):
        n_stores, n_days, n_features = X.shape
        n_features -= 1  # remove one dim for target

        plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
        plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)

        disp_param_mu = numpyro.sample(
            Site.disp_param_mu,
            dist.Normal(
                loc=model_params[Param.loc_disp_param_mu],
                scale=model_params[Param.scale_disp_param_mu],
            ),
        )

        disp_param_sigma = numpyro.sample(
            Site.disp_param_sigma,
            dist.TransformedDistribution(
                dist.Normal(
                    loc=model_params[Param.loc_disp_param_logsigma],
                    scale=model_params[Param.scale_disp_param_logsigma],
                ),
                transforms=dist.transforms.ExpTransform(),
            ),
        )

        with plate_stores:
            with numpyro.handlers.reparam(
                    config={Site.disp_params: TransformReparam()}):
                numpyro.sample(
                    Site.disp_params,
                    dist.TransformedDistribution(
                        dist.Normal(
                            loc=numpyro.param(Param.loc_disp_params,
                                              jnp.zeros((n_stores, 1))),
                            scale=numpyro.param(
                                Param.scale_disp_params,
                                0.1 * jnp.ones((n_stores, 1)),
                                constraint=dist.constraints.positive,
                            ),
                        ),
                        dist.transforms.AffineTransform(
                            disp_param_mu, disp_param_sigma),
                    ),
                )

        with plate_features:
            coef_mus = numpyro.sample(
                Site.coef_mus,
                dist.Normal(
                    loc=model_params[Param.loc_coef_mus],
                    scale=model_params[Param.scale_coef_mus],
                ),
            )
            coef_sigmas = numpyro.sample(
                Site.coef_sigmas,
                dist.TransformedDistribution(
                    dist.Normal(
                        loc=model_params[Param.loc_coef_logsigmas],
                        scale=model_params[Param.scale_coef_logsigmas],
                    ),
                    transforms=dist.transforms.ExpTransform(),
                ),
            )

            with plate_stores:
                with numpyro.handlers.reparam(
                        config={Site.coefs: TransformReparam()}):
                    numpyro.sample(
                        Site.coefs,
                        dist.TransformedDistribution(
                            dist.Normal(
                                loc=numpyro.param(
                                    Param.loc_coefs,
                                    jnp.zeros((n_stores, n_features))),
                                scale=numpyro.param(
                                    Param.scale_coefs,
                                    0.5 * jnp.ones((n_stores, n_features)),
                                    constraint=dist.constraints.positive,
                                ),
                            ),
                            dist.transforms.AffineTransform(
                                coef_mus, coef_sigmas),
                        ),
                    )
Exemple #29
0
def model(X: DeviceArray) -> DeviceArray:
    """Gamma-Poisson hierarchical model for daily sales forecasting

    Args:
        X: input data

    Returns:
        output data
    """
    n_stores, n_days, n_features = X.shape
    n_features -= 1  # remove one dim for target
    eps = 1e-12  # epsilon

    plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
    plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)
    plate_days = numpyro.plate(Plate.days, n_days, dim=-1)

    disp_param_mu = numpyro.sample(Site.disp_param_mu,
                                   dist.Normal(loc=4.0, scale=1.0))
    disp_param_sigma = numpyro.sample(Site.disp_param_sigma,
                                      dist.HalfNormal(scale=1.0))

    with plate_stores:
        with numpyro.handlers.reparam(
                config={Site.disp_params: TransformReparam()}):
            disp_params = numpyro.sample(
                Site.disp_params,
                dist.TransformedDistribution(
                    dist.Normal(loc=jnp.zeros((n_stores, 1)), scale=0.1),
                    dist.transforms.AffineTransform(disp_param_mu,
                                                    disp_param_sigma),
                ),
            )

    with plate_features:
        coef_mus = numpyro.sample(
            Site.coef_mus,
            dist.Normal(loc=jnp.zeros(n_features), scale=jnp.ones(n_features)),
        )
        coef_sigmas = numpyro.sample(
            Site.coef_sigmas,
            dist.HalfNormal(scale=2.0 * jnp.ones(n_features)))

        with plate_stores:
            with numpyro.handlers.reparam(
                    config={Site.coefs: TransformReparam()}):
                coefs = numpyro.sample(
                    Site.coefs,
                    dist.TransformedDistribution(
                        dist.Normal(loc=jnp.zeros((n_stores, n_features)),
                                    scale=1.0),
                        dist.transforms.AffineTransform(coef_mus, coef_sigmas),
                    ),
                )

    with plate_days, plate_stores:
        targets = X[..., -1]
        features = jnp.nan_to_num(X[..., :-1])  # padded features to 0
        is_observed = jnp.where(jnp.isnan(targets), jnp.zeros_like(targets),
                                jnp.ones_like(targets))
        not_observed = 1 - is_observed
        means = (is_observed * jnp.exp(
            jnp.sum(jnp.expand_dims(coefs, axis=1) * features, axis=2)) +
                 not_observed * eps)

        betas = is_observed * jnp.exp(-disp_params) + not_observed
        alphas = means * betas
        return numpyro.sample(Site.days,
                              dist.GammaPoisson(alphas, betas),
                              obs=jnp.nan_to_num(targets))
Exemple #30
0
    def model(X: DeviceArray):
        n_stores, n_days, n_features = X.shape
        n_features -= 1  # remove one dim for target

        plate_features = numpyro.plate(Plate.features, n_features, dim=-1)
        plate_stores = numpyro.plate(Plate.stores, n_stores, dim=-2)
        plate_days = numpyro.plate(Plate.days, n_days, dim=-1)

        disp_param_mu = numpyro.sample(
            Site.disp_param_mu,
            dist.Normal(loc=model_params[Param.loc_disp_param_mu],
                        scale=model_params[Param.scale_disp_param_mu]))
        disp_param_sigma = numpyro.sample(
            Site.disp_param_sigma,
            dist.TransformedDistribution(
                dist.Normal(
                    loc=model_params[Param.loc_disp_param_logsigma],
                    scale=model_params[Param.scale_disp_param_logsigma]),
                transforms=dist.transforms.ExpTransform()))

        with plate_stores:
            disp_param_offsets = numpyro.sample(
                Site.disp_param_offsets,
                dist.Normal(
                    loc=model_params[Param.loc_disp_param_offsets],
                    scale=model_params[Param.scale_disp_param_offsets]),
            )
            disp_params = disp_param_mu + disp_param_offsets * disp_param_sigma
            disp_params = numpyro.sample(Site.disp_params,
                                         dist.Delta(disp_params),
                                         obs=disp_params)

        with plate_features:
            coef_mus = numpyro.sample(
                Site.coef_mus,
                dist.Normal(loc=model_params[Param.loc_coef_mus],
                            scale=model_params[Param.scale_coef_mus]))
            coef_sigmas = numpyro.sample(
                Site.coef_sigmas,
                dist.TransformedDistribution(
                    dist.Normal(
                        loc=model_params[Param.loc_coef_logsigmas],
                        scale=model_params[Param.scale_coef_logsigmas]),
                    transforms=dist.transforms.ExpTransform()))

            with plate_stores:
                coef_offsets = numpyro.sample(
                    Site.coef_offsets,
                    dist.Normal(loc=model_params[Param.loc_coef_offsets],
                                scale=model_params[Param.scale_coef_offsets]))
                coefs = coef_mus + coef_offsets * coef_sigmas
                coefs = numpyro.sample(Site.coefs,
                                       dist.Delta(coefs),
                                       obs=coefs)

        with plate_days, plate_stores:
            features = jnp.nan_to_num(X[..., :-1])
            means = jnp.exp(
                jnp.sum(jnp.expand_dims(coefs, axis=1) * features, axis=2))
            betas = jnp.exp(-disp_params)
            alphas = means * betas
            return numpyro.sample(Site.days, dist.GammaPoisson(alphas, betas))