Truncated lognormal observations

I’m trying to create a model for truncated lognormal observations, but unsure of how to approach this with PyMC3

with pm.Model() as trunc_model:

theta = pm.Normal('theta', 6.8, 0.3)
sigma = pm.Exponential('sigma', 1.25)
logp = pm.Lognormal.dist(theta, sigma).logp(y_post_pred)
y = pm.Potential('y', logp - pm.Lognormal.dist(theta, sigma).logcdf(2000))
trace = pm.sample(tune=4000, return_inferencedata=True)
prior_p = pm.sample_prior_predictive()
pp = pm.sample_posterior_predictive(trace)

The model fits the parameters, but the posterior predictive samples are empty and the prior predictive samples are just the log likelihoods.

Here’s the data gen process:
lognorm_data = np.random.lognormal(6.6, 0.82, 10000)
y_post_pred= lognorm_data[lognorm_data <= 2000][:100]

Three questions:

  1. Any idea on how to improve this?
  2. Any ideas on how to get this model setup to the point that it can also generate samples?
  3. How would I implement a lower truncation as well?

Hi @john_c, unfortunately pymc3 cannot sample from potentials as in your model. I suggest you generate random samples with the theta and sigma traces using np.random.lognormal and truncating the observations yourself. This should give you the correct ppc samples.

For lower truncation you subtract the difference between the upper and lower logcdf (on the natural scale). This thread has an example with a truncated exponential: Help with pm.Potential - #12 by sspickle

Something along the lines of:

lognorm = pm.Lognormal.dist(theta, sigma)
y = pm.Potential('y', lognorm.logp(data) - pm.math.logdiffexp(lognorm.logcdf(2000), lognorm.logcdf(5)))
1 Like