Hello, I am a bit puzzled by the behaviour of CustomDist and am looking for some input.
Background: I am trying to model a set of data as being drawn from a well-behaved intrinsic distribution where the observations have added noise. I usually do this with a Gaussian, so I have a model
v ~ N(mu, sigma^2)
v_obs ~ N(v, sigma_obs^2)
with Gaussian priors on mu and sigma and known sigma_obs. I now wanted to extend this to a generalised Gaussian and since that is not a built-in distribution, I implemented a CustomDist with the following logp & random functions:
def logp(value: TensorVariable, mu: TensorVariable,
alpha: TensorVariable, beta: TensorVariable) -> TensorVariable:
lp = gennorm.pdf(value, beta, loc=mu, scale=alpha)
return lp
# Function to draw a random value from the distribution
def random(
mu: np.ndarray | float,
alpha: np.ndarray | float,
beta: np.ndarray | float,
rng: Optional[np.random.Generator] = None,
size : Optional[Tuple[int]]=None,
) -> np.ndarray | float :
return gennorm.rvs(beta, loc=mu, scale=alpha, size=size, random_state=rng)
That seems to work fine and I can run an example model with the CustomDist as an observed stochastic variable just fine. However, that is not quite enough for my needs and when I implement the following model:
def fit_to_general_gaussian(t, w, dw, sample=2000, tune=1500):
# w = observed velocity
# dv = uncertainty on observed velocitiy
# We cheat a bit in that we draw for the full sample but we subset
# subsequently to be consistent.
Ntotal = len(w)
with pm.Model() as model:
# Mean velocity
mu = pm.Normal("mu", mu=130, sigma=20)
# Prior on the intrinsic velocity dispersion
alpha = pm.Uniform("alpha", lower=0, upper=100.0)
# Prior on generalised Gaussian shape
beta = pm.Uniform("beta", lower=0, upper=4.0)
# Draw the true velocity
v = pm.CustomDist(
'v',
mu, alpha, beta,
logp=logp,
random=random,
shape=Ntotal
)
# Then the observed velocity
vobs = pm.Normal("vobs", mu=v, tau=1.0/dw**2,
observed=w, shape=Ntotal)
idata = pm.sample(sample, tune=tune, return_inferencedata=True, chains=2)
return model, idata
I get a (to me, hopefully not to others!) puzzling error:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/miniforge3/envs/pymc/lib/python3.11/site-packages/pytensor/tensor/type.py:293, in TensorType.dtype_specs(self)
292 try:
--> 293 return self.dtype_specs_map[self.dtype]
294 except KeyError:
KeyError: 'object'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
Cell In[25], line 1
<.... Lots of possibly irrelevant error messages ....>
TypeError: Unsupported dtype for TensorType: object
I presume I have misunderstood how to use the CustomDist function - I thought it would be a straight swap-in for
v = pm.Normal("v", mu=mu, tau=1.0/sigmav**2, shape=Ntotal)
but that does not seem to be the case?
The pymc version is 5.10.0
Any suggestions most welcome!