TypeError when combining constant and Normal distribution in function within deterministic node

testexample.py (1.2 KB)

/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/aesaraf.py:1005: UserWarning: The parameter ‘updates’ of aesara.function() expects an OrderedDict, got <class ‘dict’>. Using a standard dictionary here results in non-deterministic behavior. You should use an OrderedDict if you are using Python 2.7 (collections.OrderedDict for older python), or use a list of (shared, update) pairs. Do not just convert your dictionary to this type before the call as the conversion will still be non-deterministic.
aesara_function = aesara.function(
Multiprocess sampling (4 chains in 4 jobs)
CompoundStep
Metropolis: [Number of Engines]
NUTS: [Electric motor power]
pymc.parallel_sampling.RemoteTraceback: ----------------------------------------------------------| 0.00% [0/24000 00:00<00:00 Sampling 4 chains, 0 divergences]
“”"
Traceback (most recent call last):
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/aesara/compile/function/types.py”, line 964, in call
self.fn()
TypeError: expected type_num 1 (NPY_INT8) got 7

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/parallel_sampling.py”, line 125, in run
self._start_loop()
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/parallel_sampling.py”, line 178, in _start_loop
point, stats = self._compute_point()
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/parallel_sampling.py”, line 203, in _compute_point
point, stats = self._step_method.step(self._point)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/step_methods/compound.py”, line 42, in step
point, state = method.step(point)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/step_methods/arraystep.py”, line 208, in step
step_res = self.astep(q)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/step_methods/metropolis.py”, line 240, in astep
accept = self.delta_logp(q, q0)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/aesara/compile/function/types.py”, line 977, in call
raise_with_op(
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/aesara/link/utils.py”, line 538, in raise_with_op
raise exc_value.with_traceback(exc_trace)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/aesara/compile/function/types.py”, line 964, in call
self.fn()
TypeError: expected type_num 1 (NPY_INT8) got 7
Apply node that caused the error: Elemwise{Composite{Switch(EQ(i0, i1), i2, i3)}}(InplaceDimShuffle{}.0, TensorConstant{2}, TensorConstant{0}, TensorConstant{-inf})
Toposort index: 6
Inputs types: [TensorType(int8, ()), TensorType(int8, ()), TensorType(int8, ()), TensorType(float64, ())]
Inputs shapes: [(), (), (), ()]
Inputs strides: [(), (), (), ()]
Inputs values: [array(4), array(2, dtype=int8), array(0, dtype=int8), array(-inf)]
Outputs clients: [[MakeVector{dtype=‘float64’}(Elemwise{Composite{Switch(EQ(i0, i1), i2, i3)}}.0, Electric motor power_logprob)]]

HINT: Re-running with most Aesara optimizations disabled could provide a back-trace showing when this node was created. This can be done by setting the Aesara flag ‘optimizer=fast_compile’. If that does not work, Aesara optimizations can be disabled with ‘optimizer=None’.
HINT: Use the Aesara flag exception_verbosity=high for a debug print-out and storage map footprint of this Apply node.
“”"

The above exception was the direct cause of the following exception:

TypeError: expected type_num 1 (NPY_INT8) got 7
Apply node that caused the error: Elemwise{Composite{Switch(EQ(i0, i1), i2, i3)}}(InplaceDimShuffle{}.0, TensorConstant{2}, TensorConstant{0}, TensorConstant{-inf})
Toposort index: 6
Inputs types: [TensorType(int8, ()), TensorType(int8, ()), TensorType(int8, ()), TensorType(float64, ())]
Inputs shapes: [(), (), (), ()]
Inputs strides: [(), (), (), ()]
Inputs values: [array(4), array(2, dtype=int8), array(0, dtype=int8), array(-inf)]
Outputs clients: [[MakeVector{dtype=‘float64’}(Elemwise{Composite{Switch(EQ(i0, i1), i2, i3)}}.0, Electric motor power_logprob)]]

HINT: Re-running with most Aesara optimizations disabled could provide a back-trace showing when this node was created. This can be done by setting the Aesara flag ‘optimizer=fast_compile’. If that does not work, Aesara optimizations can be disabled with ‘optimizer=None’.
HINT: Use the Aesara flag exception_verbosity=high for a debug print-out and storage map footprint of this Apply node.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “/home/jonititan/Projects/Napkin/testexample.py”, line 38, in
samples = pm.sample(draws=nb_samples, random_seed=1000)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/sampling.py”, line 542, in sample
mtrace = _mp_sample(**sample_args, **parallel_args)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/sampling.py”, line 1469, in _mp_sample
for draw in sampler:
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/parallel_sampling.py”, line 460, in iter
draw = ProcessAdapter.recv_draw(self._active)
File “/home/jonititan/miniconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/pymc/parallel_sampling.py”, line 349, in recv_draw
raise error from old_error
RuntimeError: Chain 2 failed.

Welcome!

Can you provide a minimal example that yields this error?

The problem probably comes from the use of pm.Constant. There is no PyMC sampler that is specialized for it, and the generic samplers are likely to suggest other values which will have zero probability.

Is there any reason why you are using it? It’s mostly an internal distribution and users shouldn’t really need it outside of specialized cases like in Mixtures.

In your example you can simply use python numerical values as constants. If you want something that shows in graphviz you can use pm.Data instead.

Also Constant output dtype is whatever the constant passed to it is. In you case it would be at.as_tensor_variable(2) why gets converted to 8bit integer. However, Metropolis, (the generic sampler that gets assigned to this variable), does not respect this and sends a 32 or 64 bit proposal which is rejected.

You can specify c=at.constant(2, dtype="int64") to avoid this error but it is still inefficient to sample constants in the graph.

Thank you I suspected it might be something of that nature but lacked experience with PyMC.
I will have a go with those two proposed alternatives and update.

I’ll try using pm.Data first but naively it doesn’t make sense to me that a single discrete value provided via data should be computationally more efficient than a single discrete value provided as a constant.

You are being mislead by the name in pm.Constant. That is not a constant but a distribution that outputs always a constant value in prior predictive and that when sampled has logp 0 for the value and -inf everywhere else.

The problem with that is that PyMC tries to sample it, the same way it tries to sample a Normal or Categorical variable, but that’s very inefficient because only one proposed value can ever be accepted and PyMC samplers don’t know that.

It is not treated as a constant, in the same way that pm.Data or a pure Pyhton number would be, but as a random variable

2 Likes

Yes that solved my issue thank you.
I am now using ConstantData
https://docs.pymc.io/en/latest/api/generated/pymc.ConstantData.html#pymc.ConstantData