Esempio n. 1
0
 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),
     )
Esempio n. 2
0
 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,
     )
Esempio n. 3
0
    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,
        )
Esempio n. 4
0
    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]
Esempio n. 5
0
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)
Esempio n. 6
0
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]
Esempio n. 7
0
def alltrue_scalar(vals):
    return aet.all([aet.all(1 * val) for val in vals])
Esempio n. 8
0
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)