# Drawing and adding samples of random size

Hi,

Apologizes for coming here with a basic question like this, but all the attempts has failed.

I am trying to draw a number of events using Poisson distribution:
N = pyro.sample(“N”, dist.Poisson(torch.as_tensor([10.]))
and then draw N times from a normal distribution and add the numbers.
At the end I want to sample from a model using Predictive with parallel=True.

Can this be achieved in a simple way?

Thanks!

I’m trying this as well and got this far:

``````def model():
N = pyro.sample('N', dist.Poisson(10))
locs = torch.zeros((N.int().item()))
scales = torch.ones((N.int().item()))
normals = pyro.sample('normals', dist.Normal(locs, scales))
return(normals)
results = model()
print(results)
print(torch.sum(results))
``````

Just so I understand correctly, are you trying to predict the sum given a fixed “N” as an input?

Hi,

Yes, this is just to get the distribution for sum of normals based on fixed N.
So I want to include torch.sum(results) inside a model() and make it all in a vectorised way, so that could draw k samples from resulting sum.

Here is a complete example:

``````def model():
p = pyro.sample("p", dist.Poisson(torch.as_tensor([10.])))
x = pyro.sample("x", dist.Normal(40*torch.ones(p.int().item()),10.))
y = pyro.sample("y", dist.Normal(35*torch.ones(p.int().item()),20.))
ev = torch.sum(x>y)
if ev>0:
reward = pyro.sample("reward", dist.Normal(torch.as_tensor([100.]),torch.as_tensor([5.])).expand([ev]))
s = torch.sum(reward)
else:
s = 0
return s
``````

Executing model() works but Predictive(model, {}, num_samples=1000)() fails.

I’ve been working with variables of changing dimension in Pyro as well, so far I haven’t had much luck changing the dimension on-the-fly. Here’s a work-around that might fit in your use case:

``````def model():
N = pyro.sample('N', dist.Poisson(10))
M = torch.zeros(30 - N.int().item())
locs = torch.zeros(30)
scales = torch.ones(30)
normals = pyro.sample('normals', dist.Normal(locs, scales))
normals[N.int().item():] = M
sum_normals = pyro.deterministic('sum', torch.sum(normals))

pyro.infer.Predictive(model, {}, num_samples=1000)()['sum']
``````

The idea is to set your maximum theoretical N (30 seems to work fine for Poisson(10)) and send the whole loc and scale vectors (size = 30) through the Normal sampling operation. You then zero out M = 30 - N of your values, and use the Deterministic function to produce the sum of the normals.

The code worked for me - not the cleanest solution, but it might work for you.

1 Like

Yes, that is a good workaround!
Can anyone advice if the same can be obtained with a more elegant approach? Problem seems to be pretty simple in theory…

This is likely an issue with `Predictive` – see this post and this associated issue. In particular, when I attempt to use `Predictive`, I get an error like

``````/opt/anaconda3/lib/python3.7/site-packages/pyro/infer/predictive.py in _predictive_sequential(model, posterior_samples, model_args, model_kwargs, num_samples, return_site_shapes, return_trace)
46     else:
47         return {site: torch.stack([s[site] for s in collected]).reshape(shape)
---> 48                 for site, shape in return_site_shapes.items()}
``````

which makes sense because the `shape` is itself an rv.

If your only goal is simulation, a model like

``````def model():
N = pyro.sample("N", dist.Poisson(10.))
noise = pyro.sample("noise", dist.Normal(0, 1).expand((int(N),)))
randsum = pyro.deterministic("rand_sum", noise.sum())
return randsum
``````

should be fine. As far as sampling from the prior predictive, since this is just calling `model()` and we can do this with

``````samples = torch.stack(list(map(lambda x: model(), range(100))))
``````

then replacing `map` with something like

``````import multiprocessing
pool = multiprocessing.Pool(None)
...
samples = torch.stack(list(pool.map(lambda x: model(), range(100))))
``````

would be okay.