It looks like find_MAP has a problem with a start value when a variable has a Uniform distribution, as shown in the example below (version 3.1). It seems related to #2042.
import numpy as np
import pymc3 as pm
from theano import as_op
import theano.tensor as tt
# Initialize random number generator
np.random.seed(123)
# True parameter values
alpha, sigma = 1, 1
beta = [1, 2.5]
# Size of dataset
size = 100
# Predictor variable
X1 = np.random.randn(size)
X2 = np.random.randn(size) * 0.2
# Simulate outcome variable
Y = alpha + beta[0]*X1 + beta[1]*X2 + np.random.randn(size)*sigma
basic_model = pm.Model()
with basic_model:
# Priors for unknown model parameters
# this works fine:
#alpha = pm.Normal('alpha', mu=0, sd=10)
#beta0 = pm.Normal('beta0', mu=0, sd=10)
#beta1 = pm.Normal('beta1', mu=0, sd=10)
# this doesn't work:
alpha = pm.Uniform('alpha', -10, 10)
beta0 = pm.Uniform('beta0', -10, 10)
beta1 = pm.Uniform('beta1', -10, 10)
# Expected value of outcome
mu = alpha + beta0 * X1 + beta1 * X2
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=mu, sd=1, observed=Y)
start = {'alpha': 0.7, 'beta0': 1.2, 'beta1': 2.1}
map_estimate = pm.find_MAP(model=basic_model, start=start)
map_estimate
Traceback (most recent call last):
File "bug_find_map.py", line 45, in
map_estimate = pm.find_MAP(model=basic_model, start=start)
File "/home/david/soft/anaconda3/lib/python3.6/site-packages/pymc3/tuning/starting.py", line 101, in find_MAP
r = fmin(logp_o, bij.map(start), fprime=grad_logp_o, callback=callback, args, *kwargs)
File "/home/david/soft/anaconda3/lib/python3.6/site-packages/pymc3/blocking.py", line 63, in map
apt[slc] = dpt[var].ravel()
KeyError: 'beta1_interval__'
The start argument of find_MAP requires starting positions for the variables in the transformed space (annoying!), i.e. {'alpha_interval__': 0.0, 'beta0_interval__': 0.0, 'beta1_interval__': 0.0}. You don't get this error for Normal because it doesn't undergo a transformation.
To avoid this, you could alternatively specify start positions using the testval argument:
pm.Uniform('beta1', -10, 10, testval=2.1)
Is the testval as start an officially supported way to specify start, or is it something that is subject to change? Because IMHO it's much more convenient than the dictionary based approach, which requires quite a bit of munging.
I'm not sure... IMO it would be nice if both were supported.
Is the testval as start an officially supported way to specify start,
yes, is officially supported and I agree with you that is a very convenient way to specify and initial position.
Thanks for reporting @davidbrochart , should be fixed in #2397
perhaps we could add a with pm.Model(random_testval=True) which samples from the prior.
Most helpful comment
Thanks for reporting @davidbrochart , should be fixed in #2397