Best way to programatically set model parameters to contant values?

Hello!

I am currently experimenting with different variants of a model and I would like to be able to set parameters to constant values for some variants of the model.

For example, if my model looks like:

with pm.Model():
    mu = pm.Normal("mu", mu=0, sigma=1)
    sigma = pm.LogNormal("sigma",mu=0, sigma=1)
    x = pm.Normal("x",  mu=mu, sigma=sigma)

I might want to set mu to 10 and sample from that model. Then in a different run set sigma to 7 (and use the prior defined above for mu). I would like to do this programatically, without manually editing the model code for each version.

My current solution has been something like:

def my_model(priors: dict):
    with pm.Model() as m:
        mu = priors["mu"]
        sigma = priors["sigma"]
        x = pm.Normal("x",  mu=mu, sigma=sigma)
    return m

with my_model({
    "mu": pm.ConstantData("mu", 10)
    "sigma": pm.LogNormal("sigma",mu=0, sigma=1)
}):
...

But as the model gets more complex this style is hurting the readability of the model (e.g. difficult to know the dims of mu from mu = priors["mu"]).

Is there a better way to do this, or is my current solution already about as good as I can get?

Thank you!

Right now that’s the best solution I can think of. You can pass dims to ConstantData as well as standard variables.

Ah, I see. Thanks!

With this implementation, do you have a problem with defining the variables in the arguments to the model constructor? In other words, is there a problem with creating the model variables “mu” and “sigma” outside of the model context (with block)?

Yes that’s problematic. You can use a callable that initializes the variables inside the model such as lambda: pm.Normal("x") or you can create the variables with .dist and then register them in the model with model.register_rv(rv, name, ...)

x = pm.Normal.dist()
m = pm.Model()
m.register_rv(x, name="x")