pymc icon indicating copy to clipboard operation
pymc copied to clipboard

Mixture.dist compilation fails on first attempt

Open katosh opened this issue 4 years ago • 0 comments

Mixture.dist fails on first attempt if components are defined out of context

import numpy as np
import pymc3 as pm

def make_model():
    comps = [
        pm.Lognormal.dist(1),
        pm.Lognormal.dist(2),
    ]
    with pm.Model() as model:
        weights = pm.Dirichlet('weights', np.array([1, 1]))
        l_like = pm.Mixture.dist(w=weights, comp_dists=comps)
    return model

try:
    model = make_model()
except Exception as e:
    print(f'First compilation failed with:\n{e}')
    model = make_model()
    print('Second compilation successful.')
print(model)
First compilation failed with:
Cannot compute test value: input 0 (Elemwise{exp,no_inplace}.0) of Op MakeVector{dtype='float64'}(Elemwise{exp,no_inplace}.0, Elemwise{exp,no_inplace}.0) missing default value.  
Backtrace when that variable is created:

  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner
    coro.send(None)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3169, in run_cell_async
    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3361, in run_ast_nodes
    if (await self.run_code(code, result,  async_=asy)):
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3441, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/loc/scratch/37508145/ipykernel_989/1481143961.py", line 2, in <module>
    model = make_model()
  File "/loc/scratch/37508145/ipykernel_989/3740946427.py", line 3, in make_model
    pm.Lognormal.dist(1),
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/distribution.py", line 130, in dist
    dist.__init__(*args, **kwargs)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/continuous.py", line 1854, in __init__
    self.mean = tt.exp(self.mu + 1.0 / (2 * self.tau))

Second compilation successful.
weights_stickbreaking__ ~ TransformedDistribution
                weights ~ Dirichlet
Complete error traceback
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/mixture.py in _comp_means(self)
    305         try:
--> 306             return tt.as_tensor_variable(self.comp_dists.mean)
    307         except AttributeError:

AttributeError: 'list' object has no attribute 'mean'

During handling of the above exception, another exception occurred:

TestValueError                            Traceback (most recent call last)
~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/theano/graph/op.py in compute_test_value(node)
     80         try:
---> 81             storage_map[ins] = [ins.get_test_value()]
     82             compute_map[ins] = [True]

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/theano/graph/basic.py in get_test_value(self)
    421             detailed_err_msg = get_variable_trace_string(self)
--> 422             raise TestValueError(f"{self} has no test value {detailed_err_msg}")
    423 

TestValueError: Elemwise{exp,no_inplace}.0 has no test value  
Backtrace when that variable is created:

  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2944, in _run_cell
    return runner(coro)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner
    coro.send(None)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3169, in run_cell_async
    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3361, in run_ast_nodes
    if (await self.run_code(code, result,  async_=asy)):
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3441, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/loc/scratch/37508145/ipykernel_643/1369965341.py", line 8, in <module>
    pm.Lognormal.dist(1),
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/distribution.py", line 130, in dist
    dist.__init__(*args, **kwargs)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/continuous.py", line 1854, in __init__
    self.mean = tt.exp(self.mu + 1.0 / (2 * self.tau))


During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
/loc/scratch/37508145/ipykernel_643/1938979322.py in <module>
----> 1 make_model(comps)

/loc/scratch/37508145/ipykernel_643/1369965341.py in make_model(comps)
      2     with pm.Model() as model:
      3         weights = pm.Dirichlet('weights', np.array([1, 1]))
----> 4         l_like = pm.Mixture.dist(w=weights, comp_dists=comps)
      5     return model
      6 

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/distribution.py in dist(cls, *args, **kwargs)
    128     def dist(cls, *args, **kwargs):
    129         dist = object.__new__(cls)
--> 130         dist.__init__(*args, **kwargs)
    131         return dist
    132 

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/mixture.py in __init__(self, w, comp_dists, *args, **kwargs)
    155 
    156             try:
--> 157                 self.mean = (w * self._comp_means()).sum(axis=-1)
    158 
    159                 if "mean" not in defaults:

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/mixture.py in _comp_means(self)
    306             return tt.as_tensor_variable(self.comp_dists.mean)
    307         except AttributeError:
--> 308             return tt.squeeze(tt.stack([comp_dist.mean for comp_dist in self.comp_dists], axis=-1))
    309 
    310     def _comp_modes(self):

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/theano/tensor/basic.py in stack(*tensors, **kwargs)
   4771         tensors = list(map(as_tensor_variable, tensors))
   4772         dtype = scal.upcast(*[i.dtype for i in tensors])
-> 4773         return theano.tensor.opt.MakeVector(dtype)(*tensors)
   4774     return join(axis, *[shape_padaxis(t, axis) for t in tensors])
   4775 

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/theano/graph/op.py in __call__(self, *inputs, **kwargs)
    251 
    252         if config.compute_test_value != "off":
--> 253             compute_test_value(node)
    254 
    255         if self.default_output is not None:

~/.conda/envs/pymc3_test3/lib/python3.9/site-packages/theano/graph/op.py in compute_test_value(node)
     92                 detailed_err_msg = get_variable_trace_string(ins)
     93 
---> 94                 raise ValueError(
     95                     f"Cannot compute test value: input {i} ({ins}) of Op {node} missing default value. {detailed_err_msg}"
     96                 )

ValueError: Cannot compute test value: input 0 (Elemwise{exp,no_inplace}.0) of Op MakeVector{dtype='float64'}(Elemwise{exp,no_inplace}.0, Elemwise{exp,no_inplace}.0) missing default value.  
Backtrace when that variable is created:

  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2944, in _run_cell
    return runner(coro)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner
    coro.send(None)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3169, in run_cell_async
    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3361, in run_ast_nodes
    if (await self.run_code(code, result,  async_=asy)):
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3441, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/loc/scratch/37508145/ipykernel_643/1369965341.py", line 8, in <module>
    pm.Lognormal.dist(1),
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/distribution.py", line 130, in dist
    dist.__init__(*args, **kwargs)
  File "/home/dotto/.conda/envs/pymc3_test3/lib/python3.9/site-packages/pymc3/distributions/continuous.py", line 1854, in __init__
    self.mean = tt.exp(self.mu + 1.0 / (2 * self.tau))
  • The error only occurs when the components comps are defined out of the model context. However, I would not expect the components to be related to the model in any way.
  • comps have to be defined again to resolve the error on the second attempt.
  • Passing testval= to the components does not resolve the error.
  • Since I want to use the log-density logp of the mixture distribution and not sample an RV from it I need to use the .dist method.

Since the next release will likely be v4 this may not get fixed. However, I do not know how to access the log-density of mixture distributions without producing an RV in v4 yet.

Versions and main components

  • PyMC3 Version: 3.11.4 bfc3813367592e62cc25be5abf0484d417972d84
  • Aesara/Theano Version: 1.1.2
  • Python Version: 3.9.7
  • Operating system: Ubuntu 18.04.4 LTS
  • How did you install PyMC3: pip install 'git+https://github.com/pymc-devs/pymc3@v3'

katosh avatar Sep 15 '21 21:09 katosh