-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Hierarchical/partially pooled models #255
Comments
OK quick thoughts back here.
|
As of #249 we have the concept of stacked observation models. So a sketch idea would be to have
Some vague pseudo-codeobs = StackObservationModels(...)
hier = Hierarchy(obs; loc_prior = some_dist, scale_prior = other_dist)
EpiAwareBase.generate_observations(obs, data, loc, scale)
params ~ function_that_returns_a_prior_based_on_type_loc_scale(obs, loc, scale)
....
end
@model function EpiAwareBase.generate_observations(hier::Hierarchy,..)
loc ~ some_dist
scale ~ other_dist
@submodel observations prefix="something" generate_observations(obs, data, loc, scale)
...
end
|
Ideally the more general case but the less general case would obviously be good to solve and if the general case requires a difficult interface etc it could make sense to solve differently.
Yes we really really want to avoid this if we can or at least automate it |
obs = StackObservationModels(...)
hier = Hierarchy(obs; loc_prior = some_dist, scale_prior = other_dist)
EpiAwareBase.generate_observations(obs, data, loc, scale)
params ~ function_that_returns_a_prior_based_on_type_loc_scale(obs, loc, scale)
....
end
@model function EpiAwareBase.generate_observations(hier::Hierarchy,..)
loc ~ some_dist
scale ~ other_dist
@submodel observations prefix="something" generate_observations(obs, data, loc, scale)
...
end
The problem I see here is telling obs that it should use the hierarchy vs what it has as default prior from the various submodels. As you are saying doing that without new shadow structs seems hard unless we make Hierarchy take non-instantiated structs and instantiated them with the For simple problems this seems fine... obs = Hierarchy(NegativeBinomial, ...)
generate_observations(h::Hierarchy, ..)
disp_mean ~
disp_sd ~
disp_raw ~
NB = h.model(disp = disp_mean + disp_sd * disp_raw)
Stacked = StackObservationModel(NB...)
@submodel generate_observations(Stacked...) but obviously is it ideal to be passing these different kind of structs around, even here it would be hard to do non-centred parallelization and what happens when you have a complicated obs model (i.e with latent delays that differ). |
That pattern would work generatively but you be asking the grad call to go through struct construction (alot)... I'm not sure how that would work out. Edit: effectively we do that a lot with |
My thinking was that the only place a shadow version of the struct and the self-contained version differ is on the instantiated value of the prior; but the type-information of the prior is useful can we can access that. E.g. an observation struct with a |
If we centre on the question of "how do we create a prior for sampling one chunk of model, given passed variables of other level?" then I think we can generalise |
One option is to use The upside of this would be no shadow structs and support for nesting. The downside is that you would need to define priors that would then not be used. Thinking more about this problem more generally it seems like if we work out what we want I.D.D models to look like (i.e how we compose them together) and then tackle this it will be easier to make good choices. This means. Ithink we should deprioritise in favour of new issues targeting metadata, constructing models based on metadata, composing independent infection processes etc. |
#372 partially handles this for some cases but will still need ways to connect structs for other models |
This feels a bit clunky? As far as I am aware we don't have an issue for this so shall we split out and discuss? A good test case for this feels like it might be trying to fit to counts and deaths with a partially pooled overdispersion parameter. Another sensible toy could be trying to fit to cases and deaths with both having 3 age groups (and pooling by dataset and age group both nested and independently).
Another option might be allowing structs to be partially instantiated but that feels very bug prone
Originally posted by @seabbs in #249 (comment)
See above comment.
The aim is to support arbitrarily partially pooled models. Ideally we can do this using our current struct based dispatch but we may also want to programme over the generated turning model.
As a first step we should throw out some proposed designs for the target examples given in the comments.
The text was updated successfully, but these errors were encountered: