Simple model inference problem
andreaRapuzzi opened this issue · 2 comments
Issue Description
I'm building a very simple model to generate a signal and a corresponding BeanMachine model to infer its parameters. But in some specific configurations, the inference does not work.
Steps to Reproduce
import beanmachine.ppl as bm
import torch.distributions as dist
from torch import tensor
# an average signal property that our model shall infer
signal_avg = 116
# our signal is modeled as a Poisson function with lambda = signal_avg
s1 = dist.Poisson(signal_avg)
# let's generate some observations
s1_obs = s1.sample((100, )).tolist()
# BeanMachine Model
@bm.random_variable
def signal_avg_rv():
# our priori knowledge is deliberately foresighted
return dist.Normal(116, 0.1)
@bm.random_variable
def s1_rv(i):
return dist.Poisson(signal_avg_rv())
observations = {s1_rv(i): tensor(s1_obs[i]) for i in range(len(s1_obs))}
samples = bm.CompositionalInference().infer(
queries=[signal_avg_rv()],
observations=observations,
num_samples=700,
num_adaptive_samples=300,
num_chains=3,
)
Expected Behavior
I expect that all the traces provide sensible values for the posterior distribution of signal_avg_rv
. Instead, a lot of the traces are stuck at small values (like 0.2
, -0.2
, etc) instead of being around 116
.
Additional Info
- If
s1
ands1_rv
follow a Normal distribution (instead of a Poisson) everything works fine and a good posterior forsignal_avg_rv
is always inferred. - If the prior on
signal_avg_rv
is bounded (likedist.Uniform(100, 150)
) everything works fine. The prior we have set has, yes, an unbounded domain, but is, in practice super-informative (e.g. we have a very strong and precise belief about it). - When we use other samplers (like
SingleSiteNoUTurnSampler
orGlobalNoUTurnSampler
) the inference sometimes get stuck (does not progress). Bonus track :-) : is it possible to verify which sampler has been used (e.g. querying the samples)? - The same simple model seems to run with other engines (e.g.
pymc3
) - Adding samples (up to a quarter of a million) does not help.
System Info
Python: 3.8.12
PyTorch: 1.10.1+cpu
BeanMachine: 0.1.0.post1
Thanks for the detailed issue @andreaRapuzzi! There are a few possible issues I see:
Bean Machine initializes from Uniform(-2, 2)
, which is the same initialization used in Stan . Since your prior has very low probability at 0 , after transforming the initialized value, the sampler does not do a good job moving in the right direction. You can initialize from the prior instead:
from beanmachine.ppl.world import init_from_prior
bm.GlobalNoUTurnSampler(..., initialize_fn=init_from_prior)
Or reparameterize your model:
@bm.random_variable
def signal_avg_shifted():
# our priori knowledge is deliberately foresighted
return dist.Normal(0., 0.1)
@bm.functional
def signal_avg_rv():
# shift the mean
return signal_avg_shifted() + 116.0
@bm.random_variable
def s1_rv(i):
return dist.Poisson(signal_avg_rv())
is it possible to verify which sampler has been used
Compositional uses Newtonian Monte Carlo for continuous RVs and uniform for discrete RVs by default, which we will change to use GlobalNoUTurnSampler in future releases which may be more robust. Since proposers (and their transforms) are assigned per random variable, you can call the get_proposers
method after specifying which random variable and world you are looking at (You can construct a random world to see what Compositional
will assign them).
Fantastic @jpchen !!!
Both the proposed solutions work and the get_proposers
method is what I needed for diagnostics.
Thanks a lot!!!