MissingInputError when trying to build a custom dist for sampling in PYMC3

Viewed 124

I have been trying to use pymc3 to build a MCMC procedure. So that I can estimate the parameter of the distribution of a rainfall dataset. Except the distribution already contained in this module, I tried to build some other distribution likelihood to fit this data. For example, a three-parameters Normal Distribution. And actually, I made it to run the model, but somehow this “MissingInputError” occurs anyway after the sampling process. Besides, I am really a beginner user for pymc3, hope it’s not so silly a question to bother you guys. Thank you so much!

with pm.Model() as model:
    a = pm.Normal('a',0,1)
    b = pm.Normal("b",0,1)
    c = pm.HalfCauchy('c' , 2)
    def logp(x, a=0, b=0 , c =1 ):
        return -0.5*np.log(2*np.pi) - np.log(c) - np.log(x-a) - (np.log(x-a)-b)**2/(2*c**2)
    obs = pm.DensityDist("obs" , logp , observed=dict(x = X , a = a , b = b , c=c))

    trace = pm.sample(draws = 10 , chains = 1)

Here is the total traceback:

<ipython-input-9-8200b9d8270c>:12: FutureWarning: In v4.0, pm.sample will return an `arviz.InferenceData` object instead of a `MultiTrace` by default. You can pass return_inferencedata=True or return_inferencedata=False to be safe and silence this warning.
  trace = pm.sample(draws = 10 , chains = 1)
Only 10 samples in chain.
WARNING:pymc3:Only 10 samples in chain.
Auto-assigning NUTS sampler...
INFO:pymc3:Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
INFO:pymc3:Initializing NUTS using jitter+adapt_diag...
Sequential sampling (1 chains in 1 job)
INFO:pymc3:Sequential sampling (1 chains in 1 job)
NUTS: [c, b, a]
INFO:pymc3:NUTS: [c, b, a]

Sampling 1 chain for 1_000 tune and 10 draw iterations (1_000 + 10 draws total) took 3060 seconds.
INFO:pymc3:Sampling 1 chain for 1_000 tune and 10 draw iterations (1_000 + 10 draws total) took 3060 seconds.
---------------------------------------------------------------------------
MissingInputError                         Traceback (most recent call last)
<ipython-input-9-8200b9d8270c> in <module>
     10     obs = pm.DensityDist("obs" , logp , observed=dict(x = X , a = a , b = b , c=c))
     11 
---> 12     trace = pm.sample(draws = 10 , chains = 1)
     13 
     14 

C:\A_contents\TOOLS\anaconda3\lib\site-packages\pymc3\sampling.py in sample(draws, step, init, n_init, start, trace, chain_idx, chains, cores, tune, progressbar, model, random_seed, discard_tuned_samples, compute_convergence_checks, callback, jitter_max_retries, return_inferencedata, idata_kwargs, mp_ctx, pickle_backend, **kwargs)
    637         if idata_kwargs:
    638             ikwargs.update(idata_kwargs)
--> 639         idata = arviz.from_pymc3(trace, **ikwargs)
    640 
    641     if compute_convergence_checks:

C:\A_contents\TOOLS\anaconda3\lib\site-packages\arviz\data\io_pymc3.py in from_pymc3(trace, prior, posterior_predictive, log_likelihood, coords, dims, model, save_warmup, density_dist_obs)
    561     InferenceData
    562     """
--> 563     return PyMC3Converter(
    564         trace=trace,
    565         prior=prior,

C:\A_contents\TOOLS\anaconda3\lib\site-packages\arviz\data\io_pymc3.py in __init__(self, trace, prior, posterior_predictive, log_likelihood, predictions, coords, dims, model, save_warmup, density_dist_obs)
    169 
    170         self.density_dist_obs = density_dist_obs
--> 171         self.observations, self.multi_observations = self.find_observations()
    172 
    173     def find_observations(self) -> Tuple[Optional[Dict[str, Var]], Optional[Dict[str, Var]]]:

C:\A_contents\TOOLS\anaconda3\lib\site-packages\arviz\data\io_pymc3.py in find_observations(self)
    182             elif hasattr(obs, "data") and self.density_dist_obs:
    183                 for key, val in obs.data.items():
--> 184                     multi_observations[key] = val.eval() if hasattr(val, "eval") else val
    185         return observations, multi_observations
    186 

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\graph\basic.py in eval(self, inputs_to_values)
    552         inputs = tuple(sorted(inputs_to_values.keys(), key=id))
    553         if inputs not in self._fn_cache:
--> 554             self._fn_cache[inputs] = theano.function(inputs, self)
    555         args = [inputs_to_values[param] for param in inputs]
    556 

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\compile\function\__init__.py in function(inputs, outputs, mode, updates, givens, no_default_updates, accept_inplace, name, rebuild_strict, allow_input_downcast, profile, on_unused_input)
    335         # note: pfunc will also call orig_function -- orig_function is
    336         #      a choke point that all compilation must pass through
--> 337         fn = pfunc(
    338             params=inputs,
    339             outputs=outputs,

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\compile\function\pfunc.py in pfunc(params, outputs, mode, updates, givens, no_default_updates, accept_inplace, name, rebuild_strict, allow_input_downcast, profile, on_unused_input, output_keys)
    522         inputs.append(si)
    523 
--> 524     return orig_function(
    525         inputs,
    526         cloned_outputs,

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\compile\function\types.py in orig_function(inputs, outputs, mode, accept_inplace, name, profile, on_unused_input, output_keys)
   1968     try:
   1969         Maker = getattr(mode, "function_maker", FunctionMaker)
-> 1970         m = Maker(
   1971             inputs,
   1972             outputs,

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\compile\function\types.py in __init__(self, inputs, outputs, mode, accept_inplace, function_builder, profile, on_unused_input, fgraph, output_keys, name)
   1582             # make the fgraph (copies the graph, creates NEW INPUT AND
   1583             # OUTPUT VARIABLES)
-> 1584             fgraph, additional_outputs = std_fgraph(inputs, outputs, accept_inplace)
   1585             fgraph.profile = profile
   1586         else:

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\compile\function\types.py in std_fgraph(input_specs, output_specs, accept_inplace)
    186     orig_outputs = [spec.variable for spec in output_specs] + updates
    187 
--> 188     fgraph = FunctionGraph(orig_inputs, orig_outputs, update_mapping=update_mapping)
    189 
    190     for node in fgraph.apply_nodes:

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\graph\fg.py in __init__(self, inputs, outputs, features, clone, update_mapping)
    160 
    161         for output in outputs:
--> 162             self.import_var(output, reason="init")
    163         for i, output in enumerate(outputs):
    164             self.clients[output].append(("output", i))

C:\A_contents\TOOLS\anaconda3\lib\site-packages\theano\graph\fg.py in import_var(self, var, reason)
    340                     "Computation graph contains a NaN. " + var.type.why_null
    341                 )
--> 342             raise MissingInputError("Undeclared input", variable=var)
    343         self.setup_var(var)
    344         self.variables.add(var)

MissingInputError: Undeclared input


  • PyMC3 Version: 3.11.2
  • Aesara/Theano Version: 1.1.2
  • Python Version: python3.8.8
  • Operating system: Windows 10
  • How did you install PyMC3: (conda/pip) pip
1 Answers

You are probably getting the error because a, b, c are not observed values, but you are still passing them into the observed keyword argument when defining the obs variable on line 10. Replace lines 8-10 in your code with the following:

def logp(x):
    return -0.5*np.log(2*np.pi) - np.log(c) - np.log(x-a) - (np.log(x-a)-b)**2/(2*c**2)
obs = pm.DensityDist("obs" , logp , observed=X)
Related