I am indeed working through the book. I have not yet wrapped my head around posteriors with Pyro yet, although I do kind of understand the tutorials. Your code does converge. I want to try to create synthetic data and reproduce the version from the book that is not functioning. I am also trying to understand traces.
Here is my Model and Guide (slightly modified from yours):
# I WOULD LIKE MORE EFFICIENT matrix-based routine
start = time.clock()
alpha0 = torch.ones(48) * 2.5 # Why a Beta? Why not uniform? (book, p96, fig. 2.26)
beta0 = torch.ones(48) * 7.5 # set to 0.2 in simplistic model.
skill_p = torch.ones(22) * 0.5 # Each of the seven skills needs 22 prior probs, 1 for each person. Prior.
#if alpha0 and beta0 are constant, won't guess_probs be all over the map?
guess_probs = pyro.sample('guess_prob', dist.Beta(alpha0, beta0))
#print("model, guess_probs= ", guess_probs) # guid and model have the same guess_probs. How is this possible?
prob_mistake = 0.1
skills = 
for x in pyro.irange(0, 7):
# p(skill) [0,1] prior
skill = pyro.sample('skill'+str(x), dist.Bernoulli(skill_p).independent(1)).int()
skills.append(skill) # can change each time
# find a way to make this loop more efficient (q is question number)
for q in range(0, 48):
skill = [skills[i] for i in skills_needed[q]]
prob_guess = guess_probs[q].item()
has_all_req_skills = reduce(lambda x, y: x&y, skill)
prob_correct = has_all_req_skills.float() # convert to float
prob_correct.apply_(lambda x: 1-prob_mistake if x==1. else prob_guess).float()
isCorrect = pyro.sample("isCorrect"+str(q), dist.Bernoulli(prob_correct).independent(1))
print("model: %f sec" % (time.clock()-start))
start = time.clock()
guess_prob_a = pyro.param('guess_prob_a', dist.Uniform(torch.ones(48), torch.ones(48)*20))
guess_prob_b = pyro.param('guess_prob_b', dist.Uniform(torch.ones(48), torch.ones(48)*20))
# why is are the arrays guess_prob_a random variables instead of constant? Shouldn't the guide have simpler structure?
guess_probs = pyro.sample('guess_prob', dist.Beta(guess_prob_a , guess_prob_b))
skill_p = 
for x in range(7):
sp = pyro.param('skill_p'+str(x), torch.abs(torch.rand(22)), constraint=constraints.unit_interval)
# code works
for x in range(0,7):
ss = pyro.sample('skill'+str(x), dist.Bernoulli(skill_p[x]).independent(1))
print("guide: %f sec" % (time.clock()-start))