Reputation: 137
I have a large number of priors that can be put into a dictionary. For the sake of simplicity, let's use the following example containing only 3 priors:
d = {'a1':{'name':'a1','lower':0,'upper':10},\
'a2':{'name':'a2','lower':0,'upper':10},\
'a3':{'name':'a3','lower':0,'upper':10}}
I can create these variables manually with:
import pymc3
model = pymc3.Model()
with model:
a1 = pymc3.Uniform('a1',lower=0,upper=10)
a2 = pymc3.Uniform('a2',lower=0,upper=10)
a3 = pymc3.Uniform('a3',lower=0,upper=10)
But the number of priors that I have makes this approach painful. Is there a proper way to define the priors from a dictionary in pymc3? So far, the only automatic solution that I've found is:
list_prior_names = ['a1','a2','a3']
for prior_name in list_prior_names:
exec(prior_name+"=pymc3.Uniform(prior_name,lower=d[prior_name]['lower'],upper=d[prior_name]['upper'])")
Is there a better way to proceed?
Similarly, I have a dictionary that gives the relations between these priors and other variables. For the sake of simplicity, let's use the following example defining linear relations between the priors and these new variables:
relations = {'a1':{'b1':2,'b2:4},'a2':{'b1':1},'a3':{'b3':5}}
Once again, I could create b1, b2 and b3 manually with the following code:
b1 = 2*a1 + a2
b2 = 4*a1
b3 = 5*a3
I could use a solution similar to the other one, but I think that there is here too a better way to create b1, b2, b3.
The code I'm currently using is:
import pymc3
model = pymc3.Model()
obs1,obs2,obs3 = 2,4,5
d = {'a1':{'name':'a1','lower':0,'upper':10},\
'a2':{'name':'a2','lower':0,'upper':10},\
'a3':{'name':'a3','lower':0,'upper':10}}
with model:
list_prior_names = ['a1','a2','a3']
for prior_name in list_prior_names:
exec(prior_name+"=pymc3.Uniform(prior_name,lower=d[prior_name]['lower'],upper=d[prior_name]['upper'])")
b1 = 2*a1 + a2
b2 = 4*a1
b3 = 5*a3
m1 = pymc3.Normal('M1',mu=b1,sd=0.1,observed=obs1)
m2 = pymc3.Normal('M2',mu=b2,sd=0.1,observed=obs2)
m3 = pymc3.Normal('M3',mu=b3,sd=0.1,observed=obs3)
trace = pymc3.sample(1000)
If anyone had a clue on a proper way to create a1, a2, a3, b1, b2 and b3, I'd be grateful.
Upvotes: 1
Views: 180
Reputation: 137
In fact, pymc3 can make its calculations with variables that are defined in dictionaries. I've therefore written the following code to solve my problem. I give it here, in case someone has some day to deal with the same question.
import pymc3
model = pymc3.Model()
obs1,obs2,obs3 = 2,4,5
d = {'a1':{'name':'a1','lower':0,'upper':10},
'a2':{'name':'a2','lower':0,'upper':10},
'a3':{'name':'a3','lower':0,'upper':10}}
relations = {'b1':{'a1':2,'a2':1},'b2':{'a1':4},'b3':{'a3':5}}
correspondances_dict = {'b1':{'random_var_name':'m1','observation':obs1},
'b2':{'random_var_name':'m2','observation':obs2},
'b3':{'random_var_name':'m3','observation':obs3}}
with model:
priors={prior_name:pymc3.Uniform(prior_name,lower=d[prior_name]['lower'],
upper=d[prior_name]['upper']) for prior_name in list(d.keys())}
intermediate_vars = {intermediate_var:sum([relations[intermediate_var][prior_name]*priors[prior_name]
for prior_name in list(relations[intermediate_var].keys())])
for intermediate_var in list(relations.keys())}
observed_vars = {correspondances_dict[intermediate_var]['random_var_name']:
pymc3.Normal(correspondances_dict[intermediate_var]['random_var_name'],
mu=intermediate_vars[intermediate_var],
sd=0.1,
observed=correspondances_dict[intermediate_var]['observation'])
for intermediate_var in list(intermediate_vars.keys())}
trace = pymc3.sample(1000)
Upvotes: 1