Turing Sampling specified parameters
Copied from https://discourse.julialang.org/t/turing-sampling-specified-parameters/90360
In my model, I have
@model function runmodel(stuff, parameters)
parameters ~ Product([Uniform(0,5),
Uniform(0, 1),
...])
predictions, otherstuff = model(stuff, parameters)
obs, var = findobsvar(stuff, otherstuff)
obs ~ MvNormal(predictions, Diagonal(var))
where findobsvar is a function which takes in stuff and returns my observations and variances which I need for my multivariate normal distribution.
However, when I run my model using sample, I find that it has obs as a parameter in addition to parameters.
How do I stop that? I only want parameters as my variable since I’m only trying to constrain parameters of my model. findobsvar is just a helper function in getting the values of obs and var within the model.
Edit: I have added how I define my priors for parameters.
How do you run sample and what exactly do you want to do? If you want to perform Bayesian inference of parameters you would have to specify a prior for parameters, it seems? Or do you want to perform only maximum likelihood estimation?
Generally, in a standard Turing model everything on the left hand side of a ~ statement is a (observed or unobserved) parameter of the model. And every LHS that is not a literal or appears as a model argument is considered an unobserved variable.
I'm trying to run an MCMC, so I'm calling sample like this.
chain = sample(runmodel(stuff, parameters)), MH(), num_iter)
stuff and num_iter are variables defined outside.
I have
parameters ~ Product([Uniform(0,5),
Uniform(0, 1),
...])
inside runmodel (edited to add in OP).
A previous version I had worked because I had obs as a variable of runmodel. However, my current version of my code have my data in bins, and which bin I go into to look for obs depends on the result of model. But clearly I'm not trying to infer anything about obs, it's just my storage variable for my data, which I'm getting from findobsvar.
But clearly I'm not trying to infer anything about obs, it's just my storage variable for my data, which I'm getting from findobsvar.
Well, it's not clear from the line obs ~ MvNormal(...) - Turing will always make the LHS a model parameter. One way around it would be to replace this line with
Turing.@addlogprob! logpdf(MvNormal(...), obs)
That will just add the log probability to the accumulated log density without adding any new variables. But there are some drawbacks to that approach (e.g. https://github.com/TuringLang/DynamicPPL.jl/issues/390) and, I think, should only be used if there is no better alternative. Maybe that's the case here.
Another workaround - which relies on even more internals if it works at all, I haven't tested it - would be to keep the model but add something like
DynamicPPL.inargnames(::VarName{:obs}, ::Model{typeof(runmodel)}) = true
The idea is that Turing checks if the LHS is an argument to the model, and if it is, then it is treated as an observation (if it is not missing...). So maybe in that way one could avoid that Turing treats it as an unobserved model parameter. But as I said, it's a quite dangerous workaround (IMO) as it relies on the internals - which might change.