User defined positive vector of random variables


#1

Hello,

I need to create a custom random variable positive-definte vector of random variables, and I’d like to know if I’m doing that correctly.

This RV has only one parameter, which I call mu.

As a first thing I tried to inherit from the Countnuous class, but got some problems regarding the boundaries so I moved on the following:

from pymc3.distributions.continuous import PositiveContinuous

def assert_negative_support(var, label, distname, value=-1e-6):
    # Checks for evidence of positive support for a variable
    # FUNCTION IDENTICAL TO THE ONE IN distribution/dist_math.py
    if var is None:
        return
    try:
        # Transformed distribution
        support = np.isfinite(var.transformed.distribution.dist
                            .logp(value).tag.test_value)
    except AttributeError:
        try:
            # Untransformed distribution
            support = np.isfinite(var.distribution.logp(value).tag.test_value)
        except AttributeError:
            # Otherwise no direct evidence of non-positive support
            support = False

    if np.any(support):
        msg = "The variable specified for {0} has negative support for {1}, ".format(label, distname)
        msg += "likely making it unsuitable for this parameter."
        warnings.warn(msg)



class MyPositiveStochastic(PositiveContinuous):
    def __init__(self, mu, *args, **kwargs):
    super(MyPositiveStochastic, self).__init__(*args, **kwargs)
    self.mu = mu = tt.as_tensor_variable(mu)
    assert_negative_support(mu, 'mu', 'MyPositiveStochastic')

    def logp(self, value):
        mu = self.mu
        return tt.switch( tt.all( [1*(mu > 0), 1*(value >= 0)]),
        some_theano_expression(value, mu) ,
        -np.inf)

Which I use with:

X = MyPosiviteStochastic('X', mu=Parent, shape=10, testval=np.repeat(1, 10))

It this the correct way to proceed? I’m asking it because I inferred that from looking the definition of standard positive-defined stochastics, such as HalfNormal and HalfT. I couldn’t find any documentation about that.

Also, it seems necessary to specify both shape and testval . Using only testval gives the following error:

TypeError: For compute_test_value, one input test value does not have the requested type.
The error when converting the test value to that variable type:
Wrong number of dimensions: expected 0, got 1 with shape (10L,).

.
Thanks!


#2

What is the shape of Parent that you pass in?

In general, PyMC3 tries to do shape inference, so if Parent has the right shape it should propagate. Setting of testval should not be necessary anymore.

In general, your approach looks sensible otherwise.


#3

Thanks @twiecki. Parent has the same shape 10 as X so that each element of X has a different (but similar parameter mu). Is that still OK then?
I could update the doc if this approach is fine.


#4

That’s fine. I think your error is expected because you don’t use the same shape for the RV (10, ) than the test-value (1, 10):

In any case, you shouldn’t need to specify either of those.


#5

Great, thanks. I didn’t bother to check that 10 is not (10,).


#6

10 is (10,), but it’s not (1, 10) :).