Consider this minimal example:
y = np.array([1, 2, 3])
with pm.Model() as model:
sigma = pm.Uniform('sigma', 0, 10)
yl = pm.Normal('likelihood', mu=y.mean(), sd=sigma, observed=y)
trace = smc.sample_smc(n_steps=20, n_chains=1000, homepath='/tmp')
This works fine with NUTS but fails with SMC. The error:
~/miniconda3/envs/base/lib/python3.6/site-packages/pymc3/step_methods/smc.py in <dictcomp>(.0)
185 self.array_population = np.zeros(n_chains)
186 for _ in range(self.n_chains):
--> 187 self.population.append(pm.Point({v.name: v.random() for v in vars}, model=model))
188
189 self.chain_previous_lpoint = copy.deepcopy(self.population)
TypeError: 'NoneType' object is not callable
It works fine if the Uniform prior is replaced with a Normal--or for that matter, with any other non-bounded distribution. The problem seems to be that the loop over vars includes the transformed variables (in this case, sigma_interval__), so the random() call fails.
Hi @tyarkoni thanks for the report your diagnostic is right, this is a know limitation of the current implementation of SMC (and something that needs to be fixed!)
In the mean time you can do:
sigma = pm.Uniform('sigma', 0, 10, transform=None)
Hi @aloctavodia, is this the same reason why I am seeing errors running smc.sample_smc with a HalfStudentT prior on my standard deviation for a Normal distribution? I'm new to pymc3 but it looks like HalfStudentT is using a log transformation.
Hi @markberger, I guess you could have the same problem, if that's the case using transform=None should make your model run. Every distribution with a boundary it is automatically transformed by PyMC3. Tomorrow I will send a PR to allow SMC to work with transfomed variables.
It still fails for some model:
import numpy as np
import pymc3 as pm
import theano.tensor as tt
from tempfile import mkdtemp
from pymc3.step_methods import smc
M = 6
N = 10
X = np.random.randn(100, M)
L = np.random.randn(100, N)
w0 = np.random.randn(M, 1)
z0 = np.random.randn(N, 1)
y = np.dot(X, w0) + np.dot(L, z0) + np.random.rand(100,)
test_folder = mkdtemp(prefix='ATMIP_TEST')
n_chains = 500
n_steps = 100
tune_interval = 25
n_jobs = 1
with pm.Model() as mixedEffect2:
### hyperpriors
# transform need to be None for SMC to work (transformed doesnt have random method)
h2 = pm.Uniform('h2')
sigma2 = pm.HalfCauchy('sigma2', 5)
# beta_0 = pm.Uniform('beta_0', lower=-1000, upper=1000) # a replacement for improper prior
w = pm.Normal('w', mu=0, sd=100, shape=M)
z = pm.Normal('z', mu=0, sd=(h2 * sigma2) ** 0.5, shape=N)
g = tt.dot(L, z)
y = pm.Normal('y', mu=g + tt.dot(X, w),
sd=((1 - h2) * sigma2) ** 0.5, observed=y)
mtrace = smc.sample_smc(
n_steps=n_steps,
n_chains=n_chains,
tune_interval=tune_interval,
n_jobs=n_jobs,
progressbar=False,
stage=0,
homepath=test_folder
)
OK, I will check this!
It seems that sampling from the prior is not as straightforward as I previously thought, I will try an alternative and send a PR tomorrow :-)