def test_AR(): # AR1 data = np.array([0.3, 1, 2, 3, 4]) phi = np.array([0.99]) with Model() as t: y = AR("y", phi, sigma=1, shape=len(data)) z = Normal("z", mu=phi * data[:-1], sigma=1, shape=len(data) - 1) ar_like = t["y"].logp({"z": data[1:], "y": data}) reg_like = t["z"].logp({"z": data[1:], "y": data}) np.testing.assert_allclose(ar_like, reg_like) # AR1 and AR(1) with Model() as t: rho = Normal("rho", 0.0, 1.0) y1 = AR1("y1", rho, 1.0, observed=data) y2 = AR("y2", rho, 1.0, init=Normal.dist(0, 1), observed=data) np.testing.assert_allclose(y1.logp(t.initial_point), y2.logp(t.initial_point)) # AR1 + constant with Model() as t: y = AR("y", np.hstack((0.3, phi)), sigma=1, shape=len(data), constant=True) z = Normal("z", mu=0.3 + phi * data[:-1], sigma=1, shape=len(data) - 1) ar_like = t["y"].logp({"z": data[1:], "y": data}) reg_like = t["z"].logp({"z": data[1:], "y": data}) np.testing.assert_allclose(ar_like, reg_like) # AR2 phi = np.array([0.84, 0.10]) with Model() as t: y = AR("y", phi, sigma=1, shape=len(data)) z = Normal("z", mu=phi[0] * data[1:-1] + phi[1] * data[:-2], sigma=1, shape=len(data) - 2) ar_like = t["y"].logp({"z": data[2:], "y": data}) reg_like = t["z"].logp({"z": data[2:], "y": data}) np.testing.assert_allclose(ar_like, reg_like)
def logp(self, value): """ Calculate log-probability of AR distribution at specified value. Parameters ---------- value: numeric Value for which log-probability is calculated. Returns ------- TensorVariable """ if self.constant: x = at.add(*[ self.rho[i + 1] * value[self.p - (i + 1):-(i + 1)] for i in range(self.p) ]) eps = value[self.p:] - self.rho[0] - x else: if self.p == 1: x = self.rho * value[:-1] else: x = at.add(*[ self.rho[i] * value[self.p - (i + 1):-(i + 1)] for i in range(self.p) ]) eps = value[self.p:] - x innov_like = Normal.dist(mu=0.0, tau=self.tau).logp(eps) init_like = self.init.logp(value[:self.p]) return at.sum(innov_like) + at.sum(init_like)
def __init__(self, w, mu, sigma=None, tau=None, sd=None, comp_shape=(), *args, **kwargs): if sd is not None: sigma = sd _, sigma = get_tau_sigma(tau=tau, sigma=sigma) self.mu = mu = at.as_tensor_variable(mu) self.sigma = self.sd = sigma = at.as_tensor_variable(sigma) super().__init__(w, Normal.dist(mu, sigma=sigma, shape=comp_shape), *args, **kwargs)
def __init__(self, w, mu, sigma=None, tau=None, sd=None, comp_shape=(), *args, **kwargs): if sd is not None: sigma = sd warnings.warn("sd is deprecated, use sigma instead", DeprecationWarning) _, sigma = get_tau_sigma(tau=tau, sigma=sigma) self.mu = mu = tt.as_tensor_variable(mu) self.sigma = self.sd = sigma = tt.as_tensor_variable(sigma) super().__init__(w, Normal.dist(mu, sigma=sigma, shape=comp_shape), *args, **kwargs)
def test_logpt_subtensor(): """Make sure we can compute a log-likelihood for ``Y[I]`` where ``Y`` and ``I`` are random variables.""" size = 5 mu_base = floatX(np.power(10, np.arange(np.prod(size)))).reshape(size) mu = np.stack([mu_base, -mu_base]) sigma = 0.001 rng = aesara.shared(np.random.RandomState(232), borrow=True) A_rv = Normal.dist(mu, sigma, rng=rng) A_rv.name = "A" p = 0.5 I_rv = Bernoulli.dist(p, size=size, rng=rng) I_rv.name = "I" A_idx = A_rv[I_rv, at.ogrid[A_rv.shape[-1]:]] assert isinstance(A_idx.owner.op, (Subtensor, AdvancedSubtensor, AdvancedSubtensor1)) A_idx_value_var = A_idx.type() A_idx_value_var.name = "A_idx_value" I_value_var = I_rv.type() I_value_var.name = "I_value" A_idx_logp = logpt(A_idx, {A_idx: A_idx_value_var, I_rv: I_value_var}) logp_vals_fn = aesara.function([A_idx_value_var, I_value_var], A_idx_logp) # The compiled graph should not contain any `RandomVariables` assert_no_rvs(logp_vals_fn.maker.fgraph.outputs[0]) decimals = select_by_precision(float64=6, float32=4) for i in range(10): bern_sp = sp.bernoulli(p) I_value = bern_sp.rvs(size=size).astype(I_rv.dtype) norm_sp = sp.norm(mu[I_value, np.ogrid[mu.shape[1]:]], sigma) A_idx_value = norm_sp.rvs().astype(A_idx.dtype) exp_obs_logps = norm_sp.logpdf(A_idx_value) exp_obs_logps += bern_sp.logpmf(I_value) logp_vals = logp_vals_fn(A_idx_value, I_value) np.testing.assert_almost_equal(logp_vals, exp_obs_logps, decimal=decimals)
def logp(self, x): """ Calculate log-probability of AR1 distribution at specified value. Parameters ---------- x: numeric Value for which log-probability is calculated. Returns ------- TensorVariable """ k = self.k tau_e = self.tau_e # innovation precision tau = tau_e * (1 - k**2) # ar1 precision x_im1 = x[:-1] x_i = x[1:] boundary = Normal.dist(0.0, tau=tau).logp innov_like = Normal.dist(k * x_im1, tau=tau_e).logp(x_i) return boundary(x[0]) + at.sum(innov_like)
def logp(self, x): """ Calculate log-probability of GARCH(1, 1) distribution at specified value. Parameters ---------- x: numeric Value for which log-probability is calculated. Returns ------- TensorVariable """ vol = self.get_volatility(x) return at.sum(Normal.dist(0.0, sigma=vol).logp(x))
def logp(self, x): """ Calculate log-probability of EulerMaruyama distribution at specified value. Parameters ---------- x: numeric Value for which log-probability is calculated. Returns ------- TensorVariable """ xt = x[:-1] f, g = self.sde_fn(x[:-1], *self.sde_pars) mu = xt + self.dt * f sd = at.sqrt(self.dt) * g return at.sum(Normal.dist(mu=mu, sigma=sd).logp(x[1:]))
def logp(self, x): """ Calculate log-probability of Gaussian Random Walk distribution at specified value. Parameters ---------- x: numeric Value for which log-probability is calculated. Returns ------- TensorVariable """ if x.ndim > 0: x_im1 = x[:-1] x_i = x[1:] mu, sigma = self._mu_and_sigma(self.mu, self.sigma) innov_like = Normal.dist(mu=x_im1 + mu, sigma=sigma).logp(x_i) return self.init.logp(x[0]) + at.sum(innov_like) return self.init.logp(x)
def test_logpt_incsubtensor(indices, size): """Make sure we can compute a log-likelihood for ``Y[idx] = data`` where ``Y`` is univariate.""" mu = floatX(np.power(10, np.arange(np.prod(size)))).reshape(size) data = mu[indices] sigma = 0.001 rng = aesara.shared(np.random.RandomState(232), borrow=True) a = Normal.dist(mu, sigma, size=size, rng=rng) a.name = "a" a_idx = at.set_subtensor(a[indices], data) assert isinstance( a_idx.owner.op, (IncSubtensor, AdvancedIncSubtensor, AdvancedIncSubtensor1)) a_idx_value_var = a_idx.type() a_idx_value_var.name = "a_idx_value" a_idx_logp = logpt(a_idx, a_idx_value_var) logp_vals = a_idx_logp.eval() # The indices that were set should all have the same log-likelihood values, # because the values they were set to correspond to the unique means along # that dimension. This helps us confirm that the log-likelihood is # associating the assigned values with their correct parameters. exp_obs_logps = sp.norm.logpdf(mu, mu, sigma)[indices] np.testing.assert_almost_equal(logp_vals[indices], exp_obs_logps) # Next, we need to confirm that the unset indices are being sampled # from the original random variable in the correct locations. # rng.get_value(borrow=True).seed(232) res_ancestors = list(walk_model((a_idx_logp, ), walk_past_rvs=True)) res_rv_ancestors = tuple( v for v in res_ancestors if v.owner and isinstance(v.owner.op, RandomVariable)) # The imputed missing values are drawn from the original distribution (a_new, ) = res_rv_ancestors assert a_new is not a assert a_new.owner.op == a.owner.op fg = FunctionGraph( [ v for v in graph_inputs((a_idx_logp, )) if not isinstance(v, Constant) ], [a_idx_logp], clone=False, ) ((a_client, _), ) = fg.clients[a_new] # The imputed values should be treated as constants when gradients are # taken assert isinstance(a_client.op, DisconnectedGrad) ((a_client, _), ) = fg.clients[a_client.outputs[0]] assert isinstance( a_client.op, (IncSubtensor, AdvancedIncSubtensor, AdvancedIncSubtensor1)) indices = tuple(i.eval() for i in a_client.inputs[2:]) np.testing.assert_almost_equal(indices, indices)