NotImplementedError: Cannot transform _IntegerGreaterThan constraints

Edit:
I’m using pyro-ppl-0.2.1+8a9f0e68 and pytorch-0.4.1

Hi,

I’m trying to recreate a question from “Probabilistic Programming and Bayesian Methods for Hackers” (10/10 would recommend). The problem’s link is given below

Basically, the task is to model rate of messages in a day, where on some day the rate changes for some reason. I used two dist.Exponentials to sample lambdas for two dist.Poissons and a dist.Uniform to sample a day after which model switchs from one lambda to another. data is a global variable having observed messages for 70 odd days. My code looks like this:

class NMessages(TorchDistribution):
    def __init__(self):
        self.l1 = dist.Exponential(1/data.mean())
        self.l2 = dist.Exponential(1/data.mean())
        self.tau = dist.Uniform(0, len(data)+1)
        
    def sample(self, sample_shape=torch.Size([]), obs=None):
        tau = self.tau.sample()
        samples = []
        obs = [None for _ in range(len(data))] if obs is None else obs
        l1 = pyro.sample('l1', self.l1)
        l2 = pyro.sample('l2', self.l2)
        
        for t in pyro.irange("data_loop", len(data)):
            if t < tau:
                samples.append(pyro.sample(f'msg_{t+1}', dist.Poisson(l1), obs=obs[t]))
            else:
                samples.append(pyro.sample(f'msg_{t+1}', dist.Poisson(l2), obs=obs[t]))
        return torch.tensor(samples)

When I try to run MCMC inference using

n = NMessages()

nuts_kernel = NUTS(n, adapt_step_size=True)
mcmc_run = MCMC(nuts_kernel, num_samples=500, warmup_steps=300).run(torch.tensor(data))

I get the error stated in the title. I’m attaching the stack trace as well…

NotImplementedError                       Traceback (most recent call last)
<ipython-input-7-cac768c3181f> in <module>()
      4 
      5 nuts_kernel = NUTS(n, adapt_step_size=True)
----> 6 mcmc_run = MCMC(nuts_kernel, num_samples=500, warmup_steps=300).run(torch.tensor(d))
      7 
      8 def infer(parameter):

~/anaconda3/envs/fastai/lib/python3.6/site-packages/pyro/infer/abstract_infer.py in run(self, *args, **kwargs)
     82         self._init()
     83         with poutine.block():
---> 84             for tr, logit in self._traces(*args, **kwargs):
     85                 self.exec_traces.append(tr)
     86                 self.log_weights.append(logit)

~/anaconda3/envs/fastai/lib/python3.6/site-packages/pyro/infer/mcmc/mcmc.py in _traces(self, *args, **kwargs)
    255 
    256     def _traces(self, *args, **kwargs):
--> 257         for sample in self.sampler._traces(*args, **kwargs):
    258             yield sample

~/anaconda3/envs/fastai/lib/python3.6/site-packages/pyro/infer/mcmc/mcmc.py in _traces(self, *args, **kwargs)
    198             if not is_multiprocessing else None
    199         self.logger = initialize_logger(self.logger, logger_id, progress_bar, log_queue)
--> 200         self.kernel.setup(self.warmup_steps, *args, **kwargs)
    201         trace = self.kernel.initial_trace()
    202         with optional(progress_bar, not is_multiprocessing):

~/anaconda3/envs/fastai/lib/python3.6/site-packages/pyro/infer/mcmc/hmc.py in setup(self, warmup_steps, *args, **kwargs)
    368             site_value = node["value"]
    369             if node["fn"].support is not constraints.real and self._automatic_transform_enabled:
--> 370                 self.transforms[name] = biject_to(node["fn"].support).inv
    371                 site_value = self.transforms[name](node["value"])
    372             self._r_shapes[name] = site_value.shape

~/anaconda3/envs/fastai/lib/python3.6/site-packages/torch/distributions/constraint_registry.py in __call__(self, constraint)
    140         except KeyError:
    141             raise NotImplementedError(
--> 142                 'Cannot transform {} constraints'.format(type(constraint).__name__))
    143         return factory(constraint)
    144 

NotImplementedError: Cannot transform _IntegerGreaterThan constraints

I’m not sure what I’m missing, or doing wrong.

The issue is that some of your Poisson variables are not observed, but HMC can only handle discrete variables if they are observed. There are a couple ways to work around this, one is to wrap in a poutine.block:

from pyro.util import optional
from pyro import poutine
...
lt = l1 if t < tau else l2
with optional(poutine.block(), obs[t] is None):
    x = pyro.sample(f'msg_{t+1}', dist.Poisson(lt), obs=obs[t]))
samples.append(x)
1 Like