I am new to Pyro, and bumping into what I assume is a simple error when trying to predict on data not seen by the model during training (i.e. sample from the predictive posterior for new data points). After reading forum help [1-4] and the Pyro codebase [5] I am still stumped. A toy example:
import os
import torch
from torch.distributions import constraints
import numpy as np
import pandas as pd
import pyro
import pyro.distributions as dist
from pyro.infer import SVI, Trace_ELBO, Predictive
def model(predictors, pheno):
n_predictors = predictors.shape[1]
gamma_0 = pyro.sample("g0", dist.Normal(0., 1.))
covs = pyro.sample("covs", dist.Normal(torch.zeros(n_predictors), torch.ones(n_predictors)).to_event(1))
l = (gamma_0 + torch.matmul(predictors, covs.squeeze())).squeeze(-1)
with pyro.plate("pheno", predictors.shape[0]):
p = pyro.sample("obs", dist.Bernoulli(logits=l), obs=pheno)
return p
def guide(predictors, pheno):
n_predictors = predictors.shape[1]
g0_loc = pyro.param("g0_loc", torch.tensor(0.))
g0_scale = pyro.param("g0_scale", torch.tensor(1.), constraint=constraints.positive)
gamma_0 = pyro.sample("g0", dist.Normal(g0_loc, g0_scale))
covs_loc = pyro.param("covs_loc", torch.zeros(n_predictors))
covs = pyro.sample("covs", dist.Normal(covs_loc, 1.).independent(1))
torch.manual_seed(1)
predictors = torch.rand([100, 3])
coefs = torch.tensor([1., -5, 0.2])
pheno = torch.bernoulli(torch.sigmoid(0.2 + torch.matmul(predictors, coefs)))
pyro.clear_param_store()
# optim = pyro.optim.Adam({"lr": 0.01})
num_steps = 5000
lr0 = 0.01
gamma = 0.1
lrd = gamma ** (1/num_steps)
optim = pyro.optim.ClippedAdam({'lr': lr0, 'lrd': lrd})
svi = SVI(model, guide, optim, loss=Trace_ELBO())
for i in range(num_steps):
loss = svi.step(predictors, pheno)
if i % 100 == 0:
print(loss)
predictive = Predictive(model, guide=guide, num_samples=100)
samples = predictive(predictors, pheno)
This all works, and then I go to generate new data and predict on it.
oob_predictors = torch.rand([5, 3])
oob_data = torch.bernoulli(torch.sigmoid(0.2 + torch.matmul(oob_predictors, coefs)))
oob_predictive = Predictive(model, posterior_samples=samples, return_sites=['obs'])
oob_preds = oob_predictive(oob_predictors, None)
## eliding most of the Traceback, but for completeness the Traceback points me to _predictive_sequential() inside the Predictive module.
site: torch.stack([s[site] for s in collected]).reshape(shape)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: shape '[100, 5]' is invalid for input of size 10000
I do not know how to trouble shoot this: [100,5]
seems to be what I want the function to return. I don’t know where this input size of 10000 is coming from, though, as the samples
object contains only 400 samples total…:
> samples['covs'].shape
torch.Size([100, 1, 3])
> samples['g0'].shape
torch.Size([100, 1])
Any help is greatly appreciated
[1] Bayesian regression predictions
[2] Fast posterior point estimates without Predictive
[3] Bayesian Hierarchical Linear Regression: how to predict on a new patient having observations?
[4] Out of sample predictions in Pyro
[5] pyro/baseball.py at 0029941c2d35f353506301a996a8e6e637c83e6a · pyro-ppl/pyro · GitHub