Hi, I am new to Pyro and trying to create this model after going through a few tutorials. This example by @gbernstein helped me get started, thank you!
I have a discrete latent variable, Z ~ Ber(t)
.
I have a set of variables Xj ( j = (1,2,3))
dependent on Z, P(Xj | Z) ~ Dir(a)
and Xj
can take one of 3 values.
X is observed and let’s say, data_x
has a shape of [3,100]
, 100 observations for X1,X2,X3
Code below is working,
@pyro.infer.config_enumerate
def model():
p_Z = pyro.sample('p_Z', dist.Beta(1, 1))
# repeat 3 times for 3 Xj
p_X = pyro.sample('p_X', dist.Dirichlet(torch.ones(2,3).repeat(3,1,1)).to_event(2))
with pyro.plate('data_plate', 100, 10) as i:
obs = data_x[:,i]
Z = pyro.sample('Z', dist.Bernoulli(p_Z), infer={"enumerate": "parallel"})
for s_ind in pyro.plate('source_plate', 3):
X = pyro.sample('X_{}'.format(s_ind), dist.Categorical(Vindex(p_X)[s_ind,Z.type(torch.long)]), obs=obs[s_ind])
def guide():
t = pyro.param('t', 5*torch.ones(2), constraint=constraints.positive)
pyro.sample('p_Z', dist.Beta(t[0], t[1]))
x = pyro.param('x', torch.ones(2,3).repeat(3,1,1))
pyro.sample('p_X', dist.Dirichlet(x).to_event(2))
loss_func = pyro.infer.TraceEnum_ELBO(max_plate_nesting=2)
svi = pyro.infer.SVI(model,
guide,
pyro.optim.Adam({'lr': .01}),
loss=loss_func
)
losses = []
for _ in tqdm(range(num_steps)):
loss = svi.step()
losses.append(loss)
- Is this implementation right? Is there a more pyronic way of doing this?
- I have sequential plate now, How to vectorize it? I was not able to get X tensor shape agree with what was expected.
- I didn’t quite understand why p_X had to be
to_event(2)
for this to work and notto_event(1)
- How do I calculate
p(Z|X)
for new observation?