Defining non-standard likelihood

Hi, I am new to Pymc3, I am trying to sample from the posterior of a 1d parameter(phi) using Metropolis. The prior of the parameter is normal and the likelihood is a non-standard distribution. The likelihood is calculated on a vector of 1d residuals. I was following this discussion How to set up a custom likelihood function for two variables - #4 by junpenglao.

np.random.seed(123)

def Likelihood(phi,d,value):
	logp = 0.0;
	for val in value:
		logp = logp + (d/2-1)*np.log(val) - 0.5*func1(val, phi)
	return logp
		
def func1(value, phi):
	if value <= phi:
		return value
	else :
		return 2*np.sqrt(phi*value) - phi


data = np.loadtxt("residualsnew.txt", dtype=np.float64)


with Model() as func_model:
# Priors for unknown model parameters
	phi = Normal('phi', mu=3.0, sd=2.0)
	like = DensityDist('like',Likelihood, observed=dict(phi = phi, d = 1, value = data))
        #step1 = find_MAP(model = Huber_model)                                               
	step2 = Metropolis([phi])
	trace = sample(10000, step= [step2], tune = true, tune_interval = 500, chains = 5)

The error I am getting is

    if value <= phi:
  File "/home/navlab-shounak/.local/lib/python3.8/site-packages/theano/tensor/var.py", line 67, in __bool__
    raise TypeError("Variables do not support boolean operations.")
TypeError: Variables do not support boolean operations.

You’ll need to use the conditionals made available in theano.tensor . You will also likely need to use scan rather than a python for loop.

Do I replace value <= phi by tt.le(value, phi) ?

For your func1(), you will probably end up using tt.switch() instead of the if/then. For your likelihood(), you can probably just calculate the logp of every datapoint in value and then tt.sum() the logps. No need to loop (I don’t think).

I changed that, but still getting this error

File "/home/pymc3 codes/pyenv/lib/python3.8/site-packages/theano/graph/fg.py", line 342, in import_var
    raise MissingInputError("Undeclared input", variable=var)
theano.graph.fg.MissingInputError: Undeclared input

I saw this was a version problem with pymc3 and theano. Currently I have
python 3.8.12
pymc3 3.11.2
theano-pymc 1.1.2

Can you post the code that is raising this error?

import numpy as np
import matplotlib.pyplot as plt
import pymc3 as pm
import arviz as az

# Intialize random number generator
np.random.seed(123)

def Likelihood(phi,d,value):
	return (d/2-1)*pm.math.log(value) - 0.5*func1(value, phi)
		
def func1(value, phi):
	b = pm.math.switch(value <= phi, value, 2*pm.math.sqrt(phi*value) - phi)
	return b

data = np.loadtxt("residualsnew.txt", dtype=np.float64)

with pm.Model() as model:
	phi = pm.Normal('phi', mu=4.0, sd=1.0)
	like = pm.DensityDist('like',Likelihood, observed=dict(phi = phi, d = 1, value = data))
	trace = pm.sample(10000, return_inferencedata=False)
	
with model:
    az.plot_trace(trace, var_names=['phi']);
plt.show()   

It looks like you may be mixing the Potential and DensityDist approaches outlined in Junpeng’s original post. Changing this line:

like = pm.DensityDist('like',
                      Likelihood,
                      observed=dict(phi = phi,
                                    d = 1,
                                    value = data)
                     )

to this:

like = pm.Potential('like', Likelihood(phi, 1, data))

at least gets it sampling. Is that what you intended?

1 Like

Yes,thank you ! It is working now.

1 Like