def logpow(x, m): """ Calculates log(x**m) since m*log(x) will fail when m, x = 0. """ # return m * log(x) return aet.switch(aet.eq(x, 0), aet.switch(aet.eq(m, 0), 0.0, -np.inf), m * aet.log(x))
def test_nested(): notimpl = NotImplementedOp() ifelseifelseif = IfElseIfElseIf() x1 = tt.scalar("x1") x2 = tt.scalar("x2") c1 = tt.scalar("c1") c2 = tt.scalar("c2") t1 = ifelse(c1, x1, notimpl(x2)) t1.name = "t1" t2 = t1 * 10 t2.name = "t2" t3 = ifelse(c2, t2, x1 + t1) t3.name = "t3" t4 = ifelseifelseif(tt.eq(x1, x2), x1, tt.eq(x1, 5), x2, c2, t3, t3 + 0.5) t4.name = "t4" linker = aesara.gof.vm.VM_Linker(lazy=False) f = function([c1, c2, x1, x2], t4, mode=Mode(linker=linker, optimizer="fast_run")) with pytest.raises(NotImplementedOpException): f(1, 0, np.array(10, dtype=x1.dtype), 0) linker = aesara.gof.vm.VM_Linker(lazy=True) f = function([c1, c2, x1, x2], t4, mode=Mode(linker=linker, optimizer="fast_run")) assert f(1, 0, np.array(10, dtype=x1.dtype), 0) == 20.5
def __call__(self, X): XY = X.dot(X.T) x2 = at.sum(X**2, axis=1).dimshuffle(0, "x") X2e = at.repeat(x2, X.shape[0], axis=1) H = X2e + X2e.T - 2.0 * XY V = at.sort(H.flatten()) length = V.shape[0] # median distance m = at.switch( at.eq((length % 2), 0), # if even vector at.mean(V[((length // 2) - 1):((length // 2) + 1)]), # if odd vector V[length // 2], ) h = 0.5 * m / at.log(floatX(H.shape[0]) + floatX(1)) # RBF Kxy = at.exp(-H / h / 2.0) # Derivative dxkxy = -at.dot(Kxy, X) sumkxy = at.sum(Kxy, axis=-1, keepdims=True) dxkxy = at.add(dxkxy, at.mul(X, sumkxy)) / h return Kxy, dxkxy
def get_steps( steps: Optional[Union[int, np.ndarray, TensorVariable]], *, shape: Optional[Shape] = None, dims: Optional[Dims] = None, observed: Optional[Any] = None, step_shape_offset: int = 0, ): """Extract number of steps from shape / dims / observed information Parameters ---------- steps: User specified steps for timeseries distribution shape: User specified shape for timeseries distribution dims: User specified dims for timeseries distribution observed: User specified observed data from timeseries distribution step_shape_offset: Difference between last shape dimension and number of steps in timeseries distribution, defaults to 0 Returns ------- steps Steps, if specified directly by user, or inferred from the last dimension of shape / dims / observed. When two sources of step information are provided, a symbolic Assert is added to ensure they are consistent. """ inferred_steps = None if shape is not None: shape = to_tuple(shape) if shape[-1] is not ...: inferred_steps = shape[-1] - step_shape_offset if inferred_steps is None and dims is not None: dims = convert_dims(dims) if dims[-1] is not ...: model = modelcontext(None) inferred_steps = model.dim_lengths[dims[-1]] - step_shape_offset if inferred_steps is None and observed is not None: observed = convert_observed_data(observed) inferred_steps = observed.shape[-1] - step_shape_offset if inferred_steps is None: inferred_steps = steps # If there are two sources of information for the steps, assert they are consistent elif steps is not None: inferred_steps = Assert(msg="Steps do not match last shape dimension")( inferred_steps, at.eq(inferred_steps, steps) ) return inferred_steps
def moment_censored(op, rv, dist, lower, upper): moment = at.switch( at.eq(lower, -np.inf), at.switch( at.isinf(upper), # lower = -inf, upper = inf 0, # lower = -inf, upper = x upper - 1, ), at.switch( at.eq(upper, np.inf), # lower = x, upper = inf lower + 1, # lower = x, upper = x (lower + upper) / 2, ), ) moment = at.full_like(dist, moment) return moment
def logp(self, obs): """Return the scalar Theano log-likelihood at a point.""" obs_tt = at.as_tensor_variable(obs) logp_val = at.alloc(-np.inf, *obs.shape) for i, dist in enumerate(self.comp_dists): i_mask = at.eq(self.states, i) obs_i = obs_tt[i_mask] subset_dist = dist.dist(*distribution_subset_args(dist, obs.shape, i_mask)) logp_val = at.set_subtensor(logp_val[i_mask], subset_dist.logp(obs_i)) return logp_val
def _step(i, pkm1, pkm2, qkm1, qkm2, k1, k2, k3, k4, k5, k6, k7, k8, r): xk = -(x * k1 * k2) / (k3 * k4) pk = pkm1 + pkm2 * xk qk = qkm1 + qkm2 * xk pkm2 = pkm1 pkm1 = pk qkm2 = qkm1 qkm1 = qk xk = (x * k5 * k6) / (k7 * k8) pk = pkm1 + pkm2 * xk qk = qkm1 + qkm2 * xk pkm2 = pkm1 pkm1 = pk qkm2 = qkm1 qkm1 = qk old_r = r r = aet.switch(aet.eq(qk, zero), r, pk / qk) k1 += one k2 += k26update k3 += two k4 += two k5 += one k6 -= k26update k7 += two k8 += two big_cond = aet.gt(aet.abs_(qk) + aet.abs_(pk), BIG) biginv_cond = aet.or_(aet.lt(aet.abs_(qk), BIGINV), aet.lt(aet.abs_(pk), BIGINV)) pkm2 = aet.switch(big_cond, pkm2 * BIGINV, pkm2) pkm1 = aet.switch(big_cond, pkm1 * BIGINV, pkm1) qkm2 = aet.switch(big_cond, qkm2 * BIGINV, qkm2) qkm1 = aet.switch(big_cond, qkm1 * BIGINV, qkm1) pkm2 = aet.switch(biginv_cond, pkm2 * BIG, pkm2) pkm1 = aet.switch(biginv_cond, pkm1 * BIG, pkm1) qkm2 = aet.switch(biginv_cond, qkm2 * BIG, qkm2) qkm1 = aet.switch(biginv_cond, qkm1 * BIG, qkm1) return ( (pkm1, pkm2, qkm1, qkm2, k1, k2, k3, k4, k5, k6, k7, k8, r), until(aet.abs_(old_r - r) < (THRESH * aet.abs_(r))), )
def logp(self, value): return at.switch(at.eq(value, self.c), 0.0, -np.inf)
def logp(self, states): r"""Create a Theano graph that computes the log-likelihood for a discrete Markov chain. This is the log-likelihood for the joint distribution of states, :math:`S_t`, conditional on state samples, :math:`s_t`, given by the following: .. math:: \int_{S_0} P(S_1 = s_1 \mid S_0) dP(S_0) \prod^{T}_{t=2} P(S_t = s_t \mid S_{t-1} = s_{t-1}) The first term (i.e. the integral) simply computes the marginal :math:`P(S_1 = s_1)`, so another way to express this result is as follows: .. math:: P(S_1 = s_1) \prod^{T}_{t=2} P(S_t = s_t \mid S_{t-1} = s_{t-1}) """ # noqa: E501 Gammas = at.shape_padleft(self.Gammas, states.ndim - (self.Gammas.ndim - 2)) # Multiply the initial state probabilities by the first transition # matrix by to get the marginal probability for state `S_1`. # The integral that produces the marginal is essentially # `gamma_0.dot(Gammas[0])` Gamma_1 = Gammas[..., 0:1, :, :] gamma_0 = tt_expand_dims(self.gamma_0, (-3, -1)) P_S_1 = at.sum(gamma_0 * Gamma_1, axis=-2) # The `tt.switch`s allow us to broadcast the indexing operation when # the replication dimensions of `states` and `Gammas` don't match # (e.g. `states.shape[0] > Gammas.shape[0]`) S_1_slices = tuple( slice( at.switch(at.eq(P_S_1.shape[i], 1), 0, 0), at.switch(at.eq(P_S_1.shape[i], 1), 1, d), ) for i, d in enumerate(states.shape) ) S_1_slices = (tuple(at.ogrid[S_1_slices]) if S_1_slices else tuple()) + ( states[..., 0:1], ) logp_S_1 = at.log(P_S_1[S_1_slices]).sum(axis=-1) # These are slices for the extra dimensions--including the state # sequence dimension (e.g. "time")--along which which we need to index # the transition matrix rows using the "observed" `states`. trans_slices = tuple( slice( at.switch( at.eq(Gammas.shape[i], 1), 0, 1 if i == states.ndim - 1 else 0 ), at.switch(at.eq(Gammas.shape[i], 1), 1, d), ) for i, d in enumerate(states.shape) ) trans_slices = (tuple(at.ogrid[trans_slices]) if trans_slices else tuple()) + ( states[..., :-1], ) # Select the transition matrix row of each observed state; this yields # `P(S_t | S_{t-1} = s_{t-1})` P_S_2T = Gammas[trans_slices] obs_slices = tuple(slice(None, d) for d in P_S_2T.shape[:-1]) obs_slices = (tuple(at.ogrid[obs_slices]) if obs_slices else tuple()) + ( states[..., 1:], ) logp_S_1T = at.log(P_S_2T[obs_slices]) res = logp_S_1 + at.sum(logp_S_1T, axis=-1) res.name = "DiscreteMarkovChain_logp" return res