Hi,
I’ve been following the intro and the first part on SVI, with the purpose of estimating the input parameters of the model, depending on the data.
First, I start by defining the known model to sample data from:
def known_model():
mu = pyro.sample("mu", tdist.Normal(2, 10))
sigma = pyro.sample("sigma", tdist.HalfNormal(10))
return tdist.Normal(mu, sigma)
m = known_model()
data = m.sample([10000])
# m
# Normal(loc: -15.014768600463867, scale: 4.559845924377441)
Then I define the model which I want to estimate the parameters (replaced by 0
and 1
in the mu
sample) and also defining a guide function:
def model(data):
mu = pyro.sample("mu", tdist.Normal(
torch.zeros(1), # I know it's 2
torch.ones(1) # I know it's 10
))
sigma = pyro.sample("sigma", tdist.HalfNormal(10))
with pyro.plate("observe_data"):
pyro.sample("obs", tdist.Normal(mu, sigma), obs=data)
def guide(data):
a = pyro.param("a", torch.rand(1))
b = pyro.param("b", torch.rand(1), constraint=constraints.positive)
return pyro.sample("mu", tdist.Normal(a, b))
Finally, I run the process:
pyro.clear_param_store()
num_steps = 5000
initial_lr = .75
gamma = 0.25 # final learning rate will be gamma * initial_lr
lrd = gamma ** (1 / num_steps)
svi = pyro.infer.SVI(model=model,
guide=guide,
optim=pyro.optim.ClippedAdam({'lr': initial_lr, 'lrd': lrd}),
loss=pyro.infer.Trace_ELBO())
losses, a, b = [], [], []
for t in range(num_steps):
losses.append(svi.step(data))
a.append(pyro.param("a").item())
b.append(pyro.param("b").item())
if t % 100 == 0:
print('.', end='')
print()
print('a = ',pyro.param("a").item())
print('b = ', pyro.param("b").item())
obtaining the results:
a = -15.18841552734375
b = 0.03032298944890499
Shouldn’t I get something close to 2 and 10, respectively? If not, how can I estimate the initial parameters of such a model? In a similar question, he suggested to use pyro.param
to mark them as free model parameters. I may have misunderstood something.
Thanks