pymc-devs / pymc

Bayesian Modeling and Probabilistic Programming in Python
https://docs.pymc.io/
Other
8.66k stars 2k forks source link

Automatic transformation does not support heterogeneous bounds #1273

Closed fonnesbeck closed 5 years ago

fonnesbeck commented 8 years ago

The automatic transformation of bounded variables to an unconstrained support needs to be generalized to support vector-valued variables with different bounds among the elements of the variable. This comes up in situations like this:

BoundedWeibull = Bound(Weibull, lower=dataset.day1)
day_masked = masked_values(dataset.day0b.values, 500)
day = BoundedWeibull('day', alpha=alpha, beta=theta, observed=day_masked)

This is a survival model, so each element of the data array is constrained below by the censoring time, which varies for each element of day_masked. However, when this is run:

/Users/fonnescj/Repositories/pymc3/pymc3/distributions/continuous.py in __init__(self, distribution, lower, upper, transform, *args, **kwargs)
   1018                     self.testval = lower + 1
   1019 
-> 1020             if np.isinf(lower) and not np.isinf(upper):
   1021                 self.transform = transforms.upperbound(upper)
   1022                 if default >= upper:

/Users/fonnescj/anaconda3/lib/python3.5/site-packages/pandas/core/generic.py in __nonzero__(self)
    890         raise ValueError("The truth value of a {0} is ambiguous. "
    891                          "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
--> 892                          .format(self.__class__.__name__))
    893 
    894     __bool__ = __nonzero__

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Clearly, the transformation was not engineered to handle this. This should hopefully be easy to accommodate.

vykintasmak commented 7 years ago

I have similar problem here:

bounded = pm.Bound(pm.Normal, lower=0., upper=1.)
out = bounded('out', mu=prediction, sd=sigma, observed=ann_output)

Is there a way to overcome this?

fonnesbeck commented 7 years ago

That example seems only to have a scalar bound. Shouldn't be a problem.

vykintasmak commented 7 years ago

Here's a full error:

     74 
     75     # Binary classification -> Bernoulli likelihood
---> 76     out = bounded('out', mu=prediction, sd=sigma, observed=ann_output)
     77 
     78     return out

/usr/local/lib/python2.7/dist-packages/pymc3/distributions/distribution.pyc in __call__(self, *args, **kwargs)
    476 
    477         return Bounded(first, self.distribution, self.lower, self.upper,
--> 478                        *args, **kwargs)
    479 
    480     def dist(self, *args, **kwargs):

/usr/local/lib/python2.7/dist-packages/pymc3/distributions/distribution.pyc in __new__(cls, name, *args, **kwargs)
     32             data = kwargs.pop('observed', None)
     33             total_size = kwargs.pop('total_size', None)
---> 34             dist = cls.dist(*args, **kwargs)
     35             return model.Var(name, dist, data, total_size)
     36         else:

/usr/local/lib/python2.7/dist-packages/pymc3/distributions/distribution.pyc in dist(cls, *args, **kwargs)
     43     def dist(cls, *args, **kwargs):
     44         dist = object.__new__(cls)
---> 45         dist.__init__(*args, **kwargs)
     46         return dist
     47 

/usr/local/lib/python2.7/dist-packages/pymc3/distributions/distribution.pyc in __init__(self, distribution, lower, upper, transform, *args, **kwargs)
    408             if not np.isinf(lower) and not np.isinf(upper):
    409                 self.transform = transforms.interval(lower, upper)
--> 410                 if default <= lower or default >= upper:
    411                     self.testval = 0.5 * (upper + lower)
    412 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()