def logp(value, n, p): return check_parameters( factln(n) - factln(value).sum() + (value * at.log(p)).sum(), at.all(value >= 0), at.all(0 <= p), at.all(p <= 1), at.isclose(p.sum(), 1), )
def logp(value, n, p): return bound( factln(n) - factln(value).sum() + (value * at.log(p)).sum(), at.all(value >= 0), at.all(0 <= p), at.all(p <= 1), at.isclose(p.sum(), 1), broadcast_conditions=False, )
def logp(self, value): n = self.n p = self.p return bound( factln(n) - factln(value).sum() + (value * aet.log(p)).sum(), aet.all(value >= 0), aet.all(0 <= p), aet.all(p <= 1), aet.isclose(p.sum(), 1), broadcast_conditions=False, )
def dlogp(inputs, gradients): (g_logp, ) = gradients cov, delta = inputs g_logp.tag.test_value = floatX(1.0) n, k = delta.shape chol_cov = cholesky(cov) diag = aet.nlinalg.diag(chol_cov) ok = aet.all(diag > 0) chol_cov = aet.switch(ok, chol_cov, aet.fill(chol_cov, 1)) delta_trans = solve_lower(chol_cov, delta.T).T inner = n * aet.eye(k) - aet.dot(delta_trans.T, delta_trans) g_cov = solve_upper(chol_cov.T, inner) g_cov = solve_upper(chol_cov.T, g_cov.T) tau_delta = solve_upper(chol_cov.T, delta_trans.T) g_delta = tau_delta.T g_cov = aet.switch(ok, g_cov, -np.nan) g_delta = aet.switch(ok, g_delta, -np.nan) return [-0.5 * g_cov * g_logp, -g_delta * g_logp]
def check_parameters(logp: Variable, *conditions: Iterable[Variable], msg: str = ""): """ Wrap a log probability graph in a CheckParameterValue that asserts several conditions are True. When conditions are not met a ParameterValueError assertion is raised, with an optional custom message defined by `msg` Note that check_parameter should not be used to enforce the logic of the logp expression under the normal parameter support as it can be disabled by the user via check_bounds = False in pm.Model() """ # at.all does not accept True/False, but accepts np.array(True)/np.array(False) conditions = [ cond if (cond is not True and cond is not False) else np.array(cond) for cond in conditions ] all_true_scalar = at.all([at.all(cond) for cond in conditions]) return CheckParameterValue(msg)(logp, all_true_scalar)
def local_check_parameter_to_ninf_switch(fgraph, node): if isinstance(node.op, CheckParameterValue): logp_expr, *logp_conds = node.inputs if len(logp_conds) > 1: logp_cond = at.all(logp_conds) else: (logp_cond,) = logp_conds out = at.switch(logp_cond, logp_expr, -np.inf) out.name = node.op.msg if out.dtype != node.outputs[0].dtype: out = at.cast(out, node.outputs[0].dtype) return [out]
def alltrue_scalar(vals): return aet.all([aet.all(1 * val) for val in vals])
def MvNormalLogp(): """Compute the log pdf of a multivariate normal distribution. This should be used in MvNormal.logp once Theano#5908 is released. Parameters ---------- cov: aet.matrix The covariance matrix. delta: aet.matrix Array of deviations from the mean. """ cov = aet.matrix("cov") cov.tag.test_value = floatX(np.eye(3)) delta = aet.matrix("delta") delta.tag.test_value = floatX(np.zeros((2, 3))) solve_lower = Solve(A_structure="lower_triangular") solve_upper = Solve(A_structure="upper_triangular") cholesky = Cholesky(lower=True, on_error="nan") n, k = delta.shape n, k = f(n), f(k) chol_cov = cholesky(cov) diag = aet.nlinalg.diag(chol_cov) ok = aet.all(diag > 0) chol_cov = aet.switch(ok, chol_cov, aet.fill(chol_cov, 1)) delta_trans = solve_lower(chol_cov, delta.T).T result = n * k * aet.log(f(2) * np.pi) result += f(2) * n * aet.sum(aet.log(diag)) result += (delta_trans**f(2)).sum() result = f(-0.5) * result logp = aet.switch(ok, result, -np.inf) def dlogp(inputs, gradients): (g_logp, ) = gradients cov, delta = inputs g_logp.tag.test_value = floatX(1.0) n, k = delta.shape chol_cov = cholesky(cov) diag = aet.nlinalg.diag(chol_cov) ok = aet.all(diag > 0) chol_cov = aet.switch(ok, chol_cov, aet.fill(chol_cov, 1)) delta_trans = solve_lower(chol_cov, delta.T).T inner = n * aet.eye(k) - aet.dot(delta_trans.T, delta_trans) g_cov = solve_upper(chol_cov.T, inner) g_cov = solve_upper(chol_cov.T, g_cov.T) tau_delta = solve_upper(chol_cov.T, delta_trans.T) g_delta = tau_delta.T g_cov = aet.switch(ok, g_cov, -np.nan) g_delta = aet.switch(ok, g_delta, -np.nan) return [-0.5 * g_cov * g_logp, -g_delta * g_logp] return OpFromGraph([cov, delta], [logp], grad_overrides=dlogp, inline=True)