Open itsdfish opened 11 months ago
This is an unfortunate interaction between ForwardDiff.jl and Distributions.jl :confused:
I'd probably just do something like:
@model function test_model_inference()
μ ~ Gamma(2, 2)
σ ~ Gamma(2, 2)
return μ, σ
end
@model function test_model()
@submodel μ, σ = test_model_inference()
return rand(InverseGaussian(μ, σ), 1)
end
# Use `test_model_inference` for, well, inference.
chain = sample(test_model_inference(), NUTS(1000, .85), MCMCThreads(), 1000, 1)
# Use `test_model` for everything else.
generated_quantities(test_model(), chain)
Thanks for the suggestion. I came up with my own (see below).
My goal was to develop a general function for my package which generates a predictive quantity:
function my_function(dist, n, parms...)
sim_data = rand(dist(parms...), n)
# some cool stuff here
end
From my perspective, generated_quantities
is not as useful if it cannot process arbitrary functions. There are two workarounds I can think of. One is the two step process that you proposed. This adds extra steps and makes this specific function different from others, and complicates things for users. Another is to use map(rand))
or a for loop instead of rand(dist(parms...), n)
, which is a somewhat annoying exception on the developer side, but makes the user experience better.
I think it would be a good idea to fix this issue if feasible. I'd be glad to help if I can.
From my perspective, generated_quantities is not as useful if it cannot process arbitrary functions.
I'm confused by this; generated_quantities
supports arbitrary Julia code.
I think it would be a good idea to fix this issue if feasible. I'd be glad to help if I can.
It's quite inconvenient to fix tbh. It's an issue that shows up in the interaction with Distributions.jl and ForwardDiff.jl. We could fix it in Turing.jl but this would be type-piracy. And fixing this in Distribution.jl is somewhat non-trivial because ForwardDiff is the one that is being "weird" in this scenario (if my hunch is correct).
Another thing you can do, is to check whether you're running inference or not:
# Generic.
isinference(ctx::DynamicPPL.AbstractContext) = isinference(DynamicPPL.NodeTrait(ctx), ctx)
isinference(::DynamicPPL.IsParent, ctx::DynamicPPL.AbstractContext) = isinference(DynamicPPL.childcontext(ctx))
isinference(::DynamicPPL.IsLeaf, ctx::DynamicPPL.AbstractContext) = false
# Special cases: assume everything that isn't using `SampleFromPrior` to be performing inference.
isinference(ctx::DynamicPPL.SamplingContext) = ctx.sampler isa DynamicPPL.SampleFromPrior
@model function test_model()
μ ~ Gamma(2, 2)
σ ~ Gamma(2, 2)
if isinference(__context__)
return nothing
else
return rand(InverseGaussian(μ, σ))
end
end
If these things garner enough interest, we can easily add such functionality to DynamicPPL.jl (and thus Turing.jl).
Related issue: https://github.com/TuringLang/DynamicPPL.jl/issues/510
But I will point out that the usage of @submodel
I demonstrated above is also just good practice in general: put the stuff you want to run during inference inside one model, and then the stuff you don't need to run during inference but you're only interested in for post-processing you put in a parent model. This way you avoid unnecessary computations when you're performing inference; in your example, you're unnecessarily calling rand
when you're doing inference.
@torfjelde, thank you for your explanation. The case you made for using generated quantities with a submodel is compelling. I'll give that a try and if it works out, I will use it as a general approach/recommendation.
I wonder if it would be worth adding another example in the docs explaining the benefits of using submodels. If so, I can submit a PR to that effect.
Thanks again!
Hi all,
I believe I found a bug while trying to generate posterior predictive distributions. As shown below, it is possible to sample from distributions unless they are bounded and more than one sample is drawn. The error occurs with other bounded distributions, such as
Gamma
. It looks like it could be an issue with either Turing or Distributions. Sorry if I filed to the wrong package.works
works
works
Fails
truncated error
versions