Hi there, I’m trying the generalize the example of the coin fairness in the tutorial to the case of many coins from a single mint, each coin being flipped 100 times. However, I’m unable to recover the parameters (alpha, beta) of the Beta distribution of the mint (coin fairness generation distribution).
It seems that alpha / beta ratio is correct, but the alpha and beta parameters themselves seem to grow without bound.
Three extra questions: is my way handling subsample OK? What about the 2 iaranges inside model function? Is latent_fairness necessary inside the guide or do I even a local parameter for each coin in guide?
import math
import os
import torch
import torch.distributions.constraints as constraints
import pyro
from pyro.optim import Adam, Adamax
from pyro.infer import SVI, Trace_ELBO
import pyro.distributions as dist
from scipy import stats
import numpy as np
from torch.utils import data
# this is for running the notebook in our testing framework
smoke_test = ('CI' in os.environ)
n_steps = 2 if smoke_test else 2000
# enable validation (e.g. validate parameters of distributions)
pyro.enable_validation(True)
# clear the param store in case we're in a REPL
pyro.clear_param_store()
# create some data with 6 observed heads and 4 observed tails
np.random.seed(10)
dataset = stats.beta.rvs(20, 5, size=1_000_000)
dataset = [stats.bernoulli.rvs(dataset, size=1_000_000)
for x in range(100)]
dataset = np.array(dataset).T
dataset = torch.FloatTensor(dataset)
def model(data, total_data_len):
loc_prior_1 = torch.tensor(12.0).cuda()
loc_prior_2 = torch.tensor(7.0).cuda()
scale_prior_1 = torch.tensor(5.0).cuda()
scale_prior_2 = torch.tensor(5.0).cuda()
alpha = torch.functional.F.softplus(pyro.sample("alpha", dist.Normal(loc_prior_1, scale_prior_1)))
beta = torch.functional.F.softplus(pyro.sample("beta", dist.Normal(loc_prior_2, scale_prior_2)))
with pyro.iarange('observed_data_inter_coins', total_data_len, len(data)):
f = pyro.sample("latent_fairness",
dist.Beta(alpha, beta).expand_by([len(data)]))
with pyro.iarange('observed_data_intra_coin'):
pyro.sample('obs', dist.Bernoulli(f),
obs=data.transpose(0, 1))
def guide(data, total_data_len):
loc1 = pyro.param("loc1", torch.tensor(12.0).cuda())
loc2 = pyro.param("loc2", torch.tensor(7.0).cuda())
scale1 = pyro.param("scale1", torch.tensor(5.0).cuda(),
constraint=constraints.positive)
scale2 = pyro.param("scale2", torch.tensor(5.0).cuda(),
constraint=constraints.positive)
alpha = torch.functional.F.softplus(pyro.sample("alpha", dist.Normal(loc1, scale1)))
beta = torch.functional.F.softplus(pyro.sample("beta", dist.Normal(loc2, scale2)))
#with pyro.iarange('observed_data_inter_coins', total_data_len, len(data)):
# f = pyro.sample("latent_fairness",
# dist.Beta(alpha, beta).expand_by([len(data)]))
# setup the optimizer
adam_params = {"lr": 0.5, "betas": (0.90, 0.999)}
optimizer = Adam(adam_params)
# setup the inference algorithm
svi = SVI(model, guide, optimizer, loss=Trace_ELBO())
# do gradient steps
for step in range(100):
if step == 10:
adam_params = {"lr": 0.05, "betas": (0.90, 0.999)}
optimizer = Adam(adam_params)
if step == 50:
adam_params = {"lr": 0.005, "betas": (0.90, 0.999)}
optimizer = Adam(adam_params)
sampler = data.DataLoader(dataset, batch_size=100_000, shuffle=True,
drop_last=True, pin_memory=True, num_workers=1)
for databat in sampler:
svi.step(databat.cuda(async=True), len(dataset))
#print('.', end='', flush=True)
print('Status of step', step)
# grab the learned variational parameters
print(pyro.param("loc1").item())
print(pyro.param("loc2").item())
print(">>", pyro.param("loc1").item() / pyro.param("loc2").item())
print(pyro.param("scale1").item())
print(pyro.param("scale2").item(), flush=True)