In discussion located here, @chartl mentiones a way to transform any distribution using the Transform API in order to add a location parameter to the Weibull distribution.
His code states the following:
class Translate(pm.Transform):
def __init__(self, v):
self.v_ = v
def forward(self, x):
return x + self.v_
def forward_val(self, x):
return x + self.v_
def backward(self, z):
return x - self.v_
def jacobian_det(self, x):
return 0. * x # log(1) = 0
def apply(self, dist):
return TransformedDistribution.dist(dist, self)
with pm.Model() as model:
l = pm.Gamma('l_pr', 3.)
a = pm.Gamma('a_pr', 3.)
b = pm.Gamma('b_pr', 3.)
shift = Translate(l)
weib = shift.apply(pm.Weibull('base', a, b))
This code does not work out-of the box, but I got it working by changing the Translate class into:
import pymc3 as pm
class Translate(pm.distributions.transforms.Transform):
def __init__(self, v):
self.v_ = v
def forward(self, x):
return x.T + self.v_
def forward_val(self, x):
return x.T + self.v_
def backward(self, x):
return x.T - self.v_
def jacobian_det(self, x):
return 0. * x.T # log(1) = 0
def apply(self, rv):
return pm.distributions.transforms.TransformedDistribution.dist(rv.distribution, self)
The code above works perfectly, when the shape of the distributions is not given. However, my own code is:
X = theano.shared(x)
if NEW_POSTERIOR:
with pm.Model() as model:
# Priors for unknown model parameters
alpha = pm.TruncatedNormal('alpha', mu=0.5, sd=10, lower=0.01, shape=9)
beta = pm.TruncatedNormal('beta', mu=40, sd=100, lower=0.01, shape=9)
loc = pm.Gamma('loc', alpha=3., beta=3.)
# Likelihood (sampling distribution) of observations
shift = Translate(loc)
Y_obs = shift.apply(pm.Weibull('Y_obs', alpha=alpha[X], beta=beta[X], observed=Y))
ppc = pm.sample_posterior_predictive(trace, samples=500, model=model)
However, this code does not run at all. Perhaps due to the shape parameter, but I can not get this working without getting more into Theano.
Traceback (most recent call last):
File "C:/Users/xxx/source/xx/run_scripts/xxx/xxxx.py", line 48, in <module>
Y_obs = shift.apply(pm.Weibull('Y_obs', alpha=alpha[X], beta=beta[X], observed=Y))
File "C:\Users\xxx\source\xxx\stats\Transform.py", line 20, in apply
return pm.distributions.transforms.TransformedDistribution.dist(rv.distribution, self)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxxx\lib\site-packages\pymc3\distributions\distribution.py", line 52, in dist
dist.__init__(*args, **kwargs)
File "C:\Users\xxxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\pymc3\distributions\transforms.py", line 125, in __init__
v = forward(FreeRV(name='v', distribution=dist))
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\pymc3\model.py", line 1209, in __init__
self.logp_elemwiset = distribution.logp(self)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\pymc3\distributions\continuous.py", line 2666, in logp
- (value / beta)**alpha,
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\tensor\var.py", line 197, in __truediv__
return theano.tensor.basic.true_div(self, other)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\gof\op.py", line 615, in __call__
node = self.make_node(*inputs, **kwargs)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\tensor\elemwise.py", line 482, in make_node
DimShuffle, *inputs)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\tensor\elemwise.py", line 438, in get_output_info
['x'] * difference + list(range(length)))(input))
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\gof\op.py", line 625, in __call__
storage_map[ins] = [self._get_test_value(ins)]
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\gof\op.py", line 562, in _get_test_value
ret = v.type.filter(v.tag.test_value)
File "C:\Users\xxx\AppData\Local\Continuum\anaconda3\envs\xxx\lib\site-packages\theano\tensor\type.py", line 178, in filter
data.shape))
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 (10000,).