Zero-Inflated Poisson Example

Hi All,

I was going through Bill Engels zero-inflated Poisson Likelihood GP example here:

I see the following code:

with pm.Model() as model:
    ℓ = pm.Gamma("ℓ", alpha=2, beta=2)
    cov =, ℓ)

    c = pm.Gamma("c", alpha=2, beta=1)
    mu =

    f ="f", X=x[:,None], mean_func=mu, cov_func=cov)

    p = pm.Beta("p", alpha=1, beta=1)
    likelihood = pm.ZeroInflatedPoisson("likelihood", psi=p, theta=tt.exp(f), observed=y)

    tr = pm.sample(2000)

Forgive me if this is obvious, but doesn’t seem to be anything that exists in the PyMC3 version I just installed. What is the correct format expected here?

I presume you specify a gp with gp =, cov_func=cov) and then use f = gp.prior("f", X=x[:,None]). Is this correct? Thanks in advance!

I think you should use gp.Latent for that, see for more information.

Specifically, you replace f ="f", X=x[:,None], mean_func=mu, cov_func=cov) with:

    gp =, cov_func=cov)
    f = gp.prior("f", X=x[:,None])

cc @bwengals

1 Like

This indeed solved it.

On a related note, is it possible to design your own likelihood? I’d like to add Zero-Inflated Negative Binomial (ZINB)… models the same kind of thing as ZIP but the mean is not constrained to be the same as the variance as in Poisson likelihoods.

Yes, custom log likelihood could be implemented using pm.DensityDist

For the Zero-inflated Poisson model itself, you can see a good example of someone having coded it manually himself in this thread here, amg119.

I should probably take those posts down, or edit them. They used an older and very different syntax for PyMC3 GPs.

I will throw in my absolutely pithy two cents here, and confirm that I have had to learn to look at the age of a PyMC3 notebook - relative to how complex the modelling example is - and know when to ignore their syntax if they’re too old.

Which is not to say I’m complaining here, since you guys take the time to write amazing notebooks with very intuitive statistical explanations that help so many people, I’m just confirming what bwengals mentioned above ^^; .

We love breaking user’s code without giving warnings :sweat_smile:

It’s better for things to change in the first place, rather than otherwise like in many complex projects that span years, and people are afraid of breaking backward compatibility :wink: .

We do promised that the changes are meaningful and reflect the current best practice. In a way this is to push downstream user to change their code accordingly. :smile:

1 Like

To be fair to PyMC3 devs though, that code was from my personal blog which has absolutely zero guarantees of being correct. So I’m solely the one to blame there… I don’t think the syntax ever made it into a release.