I’m pretty new to PyMC3 and is planning on using for one of my thesis analysis.
I am trying to find out a hierarchical switch point model for body length measurement of my target animal.
There are a total of 100 individuals that I’ve measured across Age (1-20 years).
The idea behind was that there exist some individual heterogeneity but however governed by the with species distribution.
There is no problem at all with the pooled model, just as the pooled model in the radon example (https://docs.pymc.io/notebooks/multilevel_modeling.html)
There are several problems arising when I built the hierarchical model.
The model couldn’t converge as I can see the traces remain horizontal.
Should I be modelling intercept1 and slope1 in one line since they should be “switching” at the same age?
and if so how do I link the 2 variables together?
[intercept,slope] = pm.math.switch(switchpoint[idx] <= df.Age, [intercept1,slope1][idx], [intercept2, slope2][idx])
I tried using the advi method, but as I read more about it, it seems I shouldn’t have use the advi method since I’m not running any differential calculation?
However the advi method did converge faster, although I fully understand that it is only an approximation.
with hierarchical_model_advi: mean_field = pm.variational.inference.fit(n=10000, method='advi')
Sorry it’s my 1st post and first trial with PyMC3. Much appreciated! Please excuse me if this post should be posted anywhere else.
### Hierarchical Switch Point with pm.Model() as hierarchical_model: # Model Error sigma = pm.HalfCauchy('sigma', beta=10, testval=1.) # SwitchPoint Distribution mean_sp = pm.TruncatedNormal('mean_sp', 5., sd=5., lower=0.) sigma_sp = pm.HalfCauchy('sigma_sp', beta=5) # Intercept Distribution intercept_i1 = pm.Uniform('intercept_i1',lower=10., upper=20.) intercept_i2 = pm.Uniform('intercept_i2',lower=10., upper=20.) sigma_i = pm.HalfCauchy('sigma_i', 5) # Slope Distribution slope_s1 = pm.Normal('slope_s1', mu=0., sd=1.) slope_s2 = pm.Normal('slope_s2', mu=0., sd=1.) sigma_s = pm.HalfCauchy('sigma_s', 5) # Priors for pre- and post-switch intercepts and slopes intercept1 = pm.Normal('intercept1', mu = intercept_i1, sd=sigma_i, shape=len(idx)) intercept2 = pm.Normal('intercept2', mu = intercept_i2, sd=sigma_i, shape=len(idx)) slope1 = pm.Normal('slope1', mu=slope_s1, sd=sigma_s, shape=len(idx)) slope2 = pm.Normal('slope2', mu=slope_s2, sd=sigma_s, shape=len(idx)) switchpoint = pm.TruncatedNormal('switchpoint', mean_sp, sd=sigma_sp, lower=0, upper=10, shape=len(idx)) intercept = pm.math.switch(switchpoint[idx] <= df.Age, intercept1[idx], intercept2[idx]) slope = pm.math.switch(switchpoint[idx] <= df.Age, slope1[idx], slope2[idx]) # Data likelihood likelihood = pm.Normal('likelihood', mu = intercept + slope * df.Age, sd=sigma, observed=df.Body_length)
step1 = pm.NUTS([intercept, slope])
step2 = pm.NUTS([switchpoint])
hierarchical_trace = pm.sample(5000, step=[step1, step2], progressbar=True, njobs=4, tune = 1000, burn = 1000, thin = 10, nuts_kwargs=dict(target_accept=.95))