Search code examples
pythonpymc3

How to add constraints to parameters in pymc3 model?


I followed the first tutorial in pymc3 concerning a linear regression. I tried to adapt it to a different function that is :

Y_obs = log (x+a)^2 / (x-c)^2

As you can see it could be preferable that c was negative. Thus I wonder how to define the prior for c with negative values. For example, an HalfNormal distribution but with only the negative values instead of the positive ones.

More generally I wonder if it is possible to set bounds to parameters ?

For example, using Stan (or pyStan) in the model set up you can write :

parameters {
    real<lower=0, upper=1> p;
}

to set p \in [0, 1].


Solution

  • To get a variable that is constrained to the negative values you can define a positive one and take the negative of that:

    a = pm.HalfNormal('a', sd=1)
    b = -a
    

    If you want to access the value in the trace you can tell pymc3 to store it by wrapping it in a pm.Deterministic (probably not that useful in a simple case like this...)

    a = pm.HalfNormal('a', sd=1)
    b = pm.Deterministic('b', -a)
    

    Use pm.Bound to add arbitrary constraints:

    NegNormal = pm.Bound(pm.Normal, lower=-np.inf, upper=0)
    a = NegNormal('a', mu=0, sd=1)
    

    But keep in mind that this does not change the density of the normal distribution, so it won't integrate to 1 anymore. Usually this doesn't matter, as the difference in the logp will be a constant, and we don't care about constants for most things. If it does matter (this could be if the lower or upper bound is a variable) you can fix this by defining your own distribution with pm.DensityDist (same problem in stan by the way, although it has support for truncated distributions with the T[a,b] syntax).