-
Notifications
You must be signed in to change notification settings - Fork 36
Description
See #810 (comment) for more concrete usecases. I think the general idea here is that @seabbs et al would like a way to control the contents of a deeply nested submodel so that it behaves differently at inference and prediction time.
Right now we can do this one of two ways: by either including a conditional block, or by passing in different submodels. See: https://turinglang.org/docs/usage/tracking-extra-quantities/#which-to-use. For example:
# Conditional
@model function inner(do_this::Bool)
if do_this
...
else
...
end
end
@model function parent(do_this::Bool)
x ~ to_submodel(inner(do_this))
...
end
inference_model = parent(true)
prediction_model = parent(false)
# Different submodels
@model inference() = ...
@model prediction() = ...
@model function parent(submodel)
x ~ to_submodel(submodel)
...
end
inference_model = parent(inference())
prediction_model = parent(prediction())
As I understand it, the problem with scaling to multiple levels of submodels is that either the submodel object, or the boolean value, has to be threaded through the function calls in every single layer. This becomes even more clunky if there are multiple submodels in a model, etc. (i.e. something like a tree of models rather than a stack). It would be more user-friendly to have a way of controlling this behaviour from the top-level. The obvious solution is an evaluation context, as was suggested in #510. I don't know if DynamicPPL necessarily needs to provide this context, or if it'd be possible for an external library to define and manage their own context, if we want to avoid being opinionated on this.
(Note though that the library would need to overload things like predict
to first contextualize the model before calling original predict
, which if not carefully done, would lead to infinite recursion -- indeed it may be necessary to give the two predict
s different names.)