bambi: ValueError: Non-parent parameter not found in posterior

Hi - I am trying to use a Truncated Normal as my likelihood, see simple example below.

My issue is that the model.predict(trace, kind=“pps”) returns an error:

ValueError: Non-parent parameter not found in posterior.This error shouldn’t have happened!

Is it something to do with the ‘lower’ parameter set as a constant? Thank you for your help. Armelle


likelihood=bmb.Likelihood("TruncatedNormal", params=["mu", "sigma", "lower"], parent="mu")
links={"mu": "identity"}
zip_family = bmb.Family("zip", likelihood, links)
priors = {"sigma": bmb.Prior("HalfStudentT", nu=4, sigma=4.48), "lower": bmb.Prior("ConstantData", value=0.18)}

def glm_mcmc_inference_custom(df,family, priors):
    model = bmb.Model("y ~ x", df, family=family, priors=priors)

    trace = model.fit(
        draws=1000, 
        tune=500,   
        discard_tuned_samples=True,
        chains=4, 
        progressbar=True,
        idata_kwargs={"log_likelihood": True})
    return trace, model

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Comments: 27

Most upvoted comments

@DanielRobertNicoud I think censored is a pretty established term as it refers to the missing data mechanism, while truncation is a bit more ambiguous because it can refer to the missing data mechanism or the fact that you want a certain distribution with a truncated domain.

@zwelitunyiswa thanks for proposing constrained, I think it’s a good alternative. I’ll think a bit more about pros and cons.

@amoulin55 @zwelitunyiswa

I’ve been thinking about this and I’ve discussed it with others too. When we have a truncated distribution in PyMC we can get two kinds of predictions

  1. The predictions of the underlying random variable without the truncation process. This is helpful if we want to draw conclusions about those values that we don’t observe because of the missing data problem. And this is what Bambi is doing now.
  2. The predictions of the truncated random variable. It gives a non-zero probability only to the values within the boundaries that we define. Bambi does not support this for now but I we will support it. I’m now thinking about what the interface should look like. I will post updates here.

What’s happening is that you’re passing data as a prior. It results in Bambi looking for some value in the inference data object, when it shouldn’t be looked there. You can write it as a custom family with a custom likelihood. Feels a little bit hacky but it’s supported.

class CustomTruncatedNormal(pm.TruncatedNormal):
    def __call__(self, *args, **kwargs):
        # Set whatever value you want for `lower=0`
        return pm.TruncatedNormal(*args, **kwargs, lower=0)

    @classmethod
    def dist(self, *args, **kwargs):
        return pm.TruncatedNormal.dist(*args, **kwargs, lower=0)

likelihood = bmb.Likelihood(
    "TruncatedNormal", params=["mu", "sigma"], parent="mu", dist=CustomTruncatedNormal
)
links = {"mu": "identity"}
family = bmb.Family("truncated_normal", likelihood, links)
priors = {"sigma": bmb.Prior("HalfStudentT", nu=4, sigma=4.48)}

model = bmb.Model("y ~ x", df_model, family=family, priors=priors)
trace = model.fit()
model.predict(trace, kind="pps")

Hi @tomicapretto . Still, when fitting a model with a prior set to a constant value as @amoulin55 did in their OP it is unfortunate that the (constant valued) samples do not appear in the posterior, as it makes applying predict very clunky. Having the samples of the fixed hyperparameter appear would make applying the usual pipeline so much easier for very little effort. If we do not want to call it a bug, it’s at least a quite nice feature that is missing. If you direct me to the appropriate scripts in the package managing this, I’ll be happy to try to add it.

Indeed, I did not think it through. Thanks again for the new feature. I will try truncated StudentT next.