Problem with Categorical distribution with tensor probabilities
Description of your problem
Hi, I can't seem to use the Categorical distribution with tensor probabilities.
import pymc3 as pm
with pm.Model() as model:
p = pm.Uniform('p', 0, 1)
c = pm.Categorical('c', [p, 1-p])
Complete error traceback
Traceback (most recent call last):
File "/home/virgile/.miniconda3/envs/gadX/lib/python3.9/site-packages/pymc3/theanof.py", line 83, in floatX
return X.astype(theano.config.floatX)
AttributeError: 'list' object has no attribute 'astype'
During handling of the above exception, another exception occurred:
TypeError: float() argument must be a string or a number, not 'TransformedRV'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/virgile/src/airthings/t.py", line 7, in <module>
c = pm.Categorical('c', [p, 1-p])
File "/home/virgile/.miniconda3/envs/gadX/lib/python3.9/site-packages/pymc3/distributions/distribution.py", line 121, in __new__
dist = cls.dist(*args, **kwargs)
File "/home/virgile/.miniconda3/envs/gadX/lib/python3.9/site-packages/pymc3/distributions/distribution.py", line 130, in dist
dist.__init__(*args, **kwargs)
File "/home/virgile/.miniconda3/envs/gadX/lib/python3.9/site-packages/pymc3/distributions/discrete.py", line 1347, in __init__
p = tt.as_tensor_variable(floatX(p))
File "/home/virgile/.miniconda3/envs/gadX/lib/python3.9/site-packages/pymc3/theanof.py", line 86, in floatX
return np.asarray(X, dtype=theano.config.floatX)
ValueError: setting an array element with a sequence.
Please provide any additional information below.
Versions and main components
- PyMC/PyMC3 Version: 3.11.4
- Aesara/Theano Version: 1.1.2 (theano)
- Python Version: 3.9.10
- Operating system: linux
- How did you install PyMC/PyMC3: conda
Try with c = pm.Categorical('c', pm.math.stack([p, 1-p])), otherwise it's probably trying to convert that list of TensorVariables to a numpy array
Thank you, it is working now. Would you like me to add this snippet of code somewhere in the documentation so that other people can find it too and not be confused like me? Or would it make sense to make the distribution recognize what we are trying to do and apply the stack operation automatically?
@Armavica We should check what happens in version 4, as many things have changed. If it still fails we should fix it.
Still failing in here, but with a different error message. Seems like the .dist() method is checking about whether p is a list (true in this case), but then asking for Boolean operations on the elements in p without checking whether the elements in p are themselves tensors? Does that seem right?
Error
TypeError Traceback (most recent call last) Input In [3], in <cell line: 1>() 1 with pm.Model() as model: 2 p = pm.Uniform('p', 0, 1) ----> 3 c = pm.Categorical('c', [p, 1-p])
File ~/Documents/code/pymc/pymc/pymc/distributions/distribution.py:649, in Discrete.new(cls, name, *args, **kwargs) 646 if kwargs.get("transform", None): 647 raise ValueError("Transformations for discrete distributions") --> 649 return super().new(cls, name, *args, **kwargs)
File ~/Documents/code/pymc/pymc/pymc/distributions/distribution.py:267, in Distribution.new(cls, name, rng, dims, initval, observed, total_size, transform, *args, **kwargs)
263 rng = model.next_rng()
265 # Create the RV and process dims and observed to determine
266 # a shape by which the created RV may need to be resized.
--> 267 rv_out, dims, observed, resize_shape = _make_rv_and_resize_shape(
268 cls=cls, dims=dims, model=model, observed=observed, args=args, rng=rng, **kwargs
269 )
271 if resize_shape:
272 # A batch size was specified through dims, or implied by observed.
273 rv_out = change_rv_size(rv_var=rv_out, new_size=resize_shape, expand=True)
File ~/Documents/code/pymc/pymc/pymc/distributions/distribution.py:166, in _make_rv_and_resize_shape(cls, dims, model, observed, args, **kwargs) 163 """Creates the RV and processes dims or observed to determine a resize shape.""" 164 # Create the RV without dims information, because that's not something tracked at the Aesara level. 165 # If necessary we'll later replicate to a different size implied by already known dims. --> 166 rv_out = cls.dist(*args, **kwargs) 167 ndim_actual = rv_out.ndim 168 resize_shape = None
File ~/Documents/code/pymc/pymc/pymc/distributions/discrete.py:1257, in Categorical.dist(cls, p, **kwargs)
1254 @classmethod
1255 def dist(cls, p, **kwargs):
1256 if isinstance(p, np.ndarray) or isinstance(p, list):
-> 1257 if (np.asarray(p) < 0).any():
1258 raise ValueError(f"Negative p parameters are not valid, got: {p}")
1259 p_sum = np.sum([p], axis=-1)
File ~/anaconda3/envs/pymc-dev-py39/lib/python3.9/site-packages/aesara/tensor/var.py:67, in _tensor_py_operators.bool(self) 65 return True 66 else: ---> 67 raise TypeError("Variables do not support boolean operations.")
Yes it was a recent check we added. We should check if the list elements are not TensorVariables before attempting that check
Same for the multinomial I think