Custom Distribution with pm.CustomDist

Thanks for response @ricardoV94 and you’re exactly right about passing the arguments from pm.CustomDist into the custom logp and random functions. I’ve learned now that all variables after the name in pm.CustomDist are passed into the logp and random functions so I needed all of them to be available as inputs in the custom functions, even if those variables aren’t all used.

I updated the code with:

def _lognormal_logp(value, mu, sigma, Ni_summary, lnsd2_summary):
    # First input is observed value
    term1 = (Ni_summary*value)
    term2 = (Ni_summary/2.)*pm.math.log(sigma**2)
    term3 = ((Ni_summary - 1)*lnsd2_summary)/(2*sigma**2)
    term4 = (Ni_summary*(value - mu)**2)/(2*sigma**2)
    logp = (Ni_summary/2)*pm.math.log(2*np.pi) - (term1 + term2 + term3 + term4)
    return logp

def _lognormal_random(mu, sigma, Ni_summary, lnsd2_summary, rng=None, size=None):
    # Need Ni_summary and lnsd2_summary even though they aren't used
    return rng.normal(loc=mu, scale=sigma, size=size)

pm.CustomDist("conc_summary", lnconc_summary, sigma_summary, Ni_summary, lnsd2_summary, logp=_lognormal_logp, random=_lognormal_random, observed=lny_summary

And now everything runs nicely with pm.CustomDist and I’m able to rum pm.sample_posterior_predictive as well.

Thanks!