Reputation: 8982
Fairly simple question: How should I use @pm.stochastic
? I have read some blog posts that claim @pm.stochastic
expects a negative log value:
@pm.stochastic(observed=True)
def loglike(value=data):
# some calculations that generate a numeric result
return -np.log(result)
I tried this recently but found really bad results. Since I also noticed that some people used np.log instead of -np.log, I give it a try and worked much better. What is really expecting @pm.stochastic
? I'm guessing there was a small confusion on the sign required due to a very popular example using something like np.log(1/(1+t_1-t_0))
which was written as -np.log(1+t_1-t_0)
Another question: What is this decorator doing with the value
argument? As I understand it, we start with some proposed value for the priors that need to enter in the likelihood and the idea of @pm.stochastic
is basically produce some number to compare this likelihood to the number generated by the previous iteration in the sampling process. The likelihood should receive the value
argument and some values for the priors, but I'm not sure if this is all value
is doing because that's the only required argument and yet I can write:
@pm.stochastic(observed=True)
def loglike(value=[1]):
data = [3,5,1] # some data
# some calculations that generate a numeric result
return np.log(result)
And as far as I can tell, that produces the same result as before. Maybe, it works in this way because I added observed=True
to the decorator. If I would have tried this in a stochastic variable with observed=False
by default, value
would be changed in each iteration trying to obtain a better likelihood.
Upvotes: 1
Views: 1175
Reputation: 377
Yes confusion is easy since the @stochastic returns a likelihood which is the opposite of the error essentially. So you take the negative log of your custom error function and return THAT as your log-likelihood.
Upvotes: 0
Reputation: 2979
@pm.stochastic
is a decorator, so it is expecting a function. The simplest way to use it is to give it a function that includes value
as one of its arguments, and returns a log-likelihood.
You should use the @pm.stochastic
decorator to define a custom prior for a parameter in your model. You should use the @pm.observed
decorator to define a custom likelihood for data. Both of these decorators will create a pm.Stochastic
object, which takes its name from the function it decorates, and has all the familiar methods and attributes (here is a nice article on Python decorators).
Examples:
A parameter a
that has a triangular distribution a priori:
@pm.stochastic
def a(value=.5):
if 0 <= value < 1:
return np.log(1.-value)
else:
return -np.inf
Here value=.5
is used as the initial value of the parameter, and changing it to value=1
raises an exception, because it is outside of the support of the distribution.
A likelihood b
that has is normal distribution centered at a
, with a fixed precision:
@pm.observed
def b(value=[.2,.3], mu=a):
return pm.normal_like(value, mu, 100.)
Here value=[.2,.3]
is used to represent the observed data.
I've put this together in a notebook that shows it all in action here.
Upvotes: 3