-
Notifications
You must be signed in to change notification settings - Fork 29
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
Adds @returned_quantities
macro
#696
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #696 +/- ##
==========================================
- Coverage 79.22% 77.78% -1.45%
==========================================
Files 30 30
Lines 4212 3938 -274
==========================================
- Hits 3337 3063 -274
Misses 875 875 ☔ View full report in Codecov by Sentry. |
Pull Request Test Coverage Report for Build 11627641486Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Co-authored-by: Xianda Sun <[email protected]>
@torfjelde I suggest we change the prefix feature to a # submodel prefixing
julia> @model function demo2(x, y, z)
a = @returned_quantities prefix_variables(demo1(x), "sub1")
b = @returned_quantities prefix_variables(demo1(y), "sub2")
return z ~ Uniform(-a, b)
end;
julia> rand(demo2(missing, missing, 0.4))
(var"sub1.x" = 0.5865756059371534, var"sub2.x" = -0.25563799658500047)
# rand prefixing
julia> ret = rand(prefix_variables(demo1(1.), "prior_sample"))
# generated quantities / predict
julia> returned_quantities(prefix_variables(demo1(1.), "generated_var_"), chain)
This would also help unify the syntax of This could be further unified with |
We already have prefix(model::Model, x) = contextualize(model, PrefixContext(model.context, Symbol(x))) or something as an additional definition. However, I'm a bit worred about
|
I like the
Point taken, but this is very minor and a bit subjective. |
But this means that the user needs to be careful and do |
It is a standard Julia performance trick, so it is okay. By default, we can print a performance warning message when users call |
I'm also happy to turn @returned_quantities @prefix(model, :prefix_) |
make things easier to basic users
before wrapping in `Val`
contexts in `model.context`
Added a |
…cro' into torfjelde/returned-quantities-macro
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Thanks, @torfjelde; I'm happy with the changes. To minimise interface confusion ( Thoughts? @mhauru and @penelopeysm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For prefix
/@prefix
, maybe keep both but only export the macro? It sounds like unless you know what you are doing, you should use @prefix
. And if you know what you're doing, you don't need it be exported. I do generally think it's a good idea to have a macro-free option available if possible.
For returned_quantities
/@returned_quantities
we still need both, because one is to be used outside of @model
, the other inside, right? I forget what we concluded about this in our call, but I do worry users will mix the two up and get confusing errors.
src/submodel_macro.jl
Outdated
true | ||
julia> # Or using some arbitrary expression. | ||
@model submodel_prefix_expr() = a = @returned_quantities prefix=1 + 2 inner() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found
@returned_quantities prefix=1 + 2 inner()
hard and unintuitive to parse. I think
@returned_quantities prefix=(1 + 2) inner()
would be much clearer. Not sure if this a documentation issue, or if we should disallow the former.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a documentation issue IMO, as this is not doing any special parsing but reliying on Julia's expression parsing.
Then, |
Just so we're all on the same page: |
Deprecated |
I like the |
After some discussion on Slack, I understand from @yebai that we are now going with this: # To be implemented now
returned(model_instance, chain) # Replaces generated_quantities(model_instance, chain)
x ~ to_sampleable(returned(submodel_instance))
x ~ to_submodel(submodel_instance) # short-hand for the above
# To be implemented some time in the future
x ~ to_distribution(returned(submodel_instance))
x ~ to_sampleable(latent(submodel_instance))
x ~ to_distribution(latent(submodel_instance))
|
`ReturnedModelWrapper` + introduced `rand_like!!` to hide explicit calls to `_evaluate!!`
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Alrighty! I've now moved the handling of the "submodels" into the tilde pipeline; specifically, I've added it to This means that we:
And the syntax is as follows: @model outer() = a ~ returned(inner()) I've also added the option of doing @model outer() = a ~ to_sampleable(returned(inner())) as @yebai requested. However, this is unnecessary for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing all the work for this @torfjelde. Could we also have a @test_throws
for "
~ with a model on the right-hand side of an observe statement is not supported"
?
This is in the doctest:) |
@@ -141,8 +141,12 @@ By default, calls `tilde_assume(context, right, vn, vi)` and accumulates the log | |||
probability of `vi` with the returned value. | |||
""" | |||
function tilde_assume!!(context, right, vn, vi) | |||
value, logp, vi = tilde_assume(context, right, vn, vi) | |||
return value, acclogp_assume!!(context, vi, logp) | |||
return if is_rhs_model(right) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be generalized as we desire, e.g. if want to do something special with lantent(model)
, we can overload this to be true
and then overload rand_like!!
@@ -197,6 +201,11 @@ Falls back to `tilde_observe!!(context, right, left, vi)` ignoring the informati | |||
and indices; if needed, these can be accessed through this function, though. | |||
""" | |||
function tilde_observe!!(context, right, left, vname, vi) | |||
is_rhs_model(right) && throw( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we want "more" things to be allowed on right
, we can easily deal with this by just generalizing is_rhs_model
.
Co-authored-by: Penelope Yong <[email protected]>
Accepted your suggestions @penelopeysm 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to approve once you're happy and if CI passes 😄
""" | ||
is_rhs_model(x) | ||
Return `true` if `x` is a model or model wrapper, and `false` otherwise. | ||
""" | ||
is_rhs_model(x) = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this return true
for Model
s themselves? It seems to me that it's only true
for a ReturnedModelWrapper
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We dont't want to allow usage of Model
on the RHS. So yeah, should probably rename the function. Long-term we probably just want something like is_valid_rhs_tilde(...)
,etc.
Okay, so the final call has been made and we'll introduce several wrappers:
In combination with these types, we'll introduce the following functionality to_sampleable(x) = Sampleable(x)
returned(model::Model) = ReturnedModelWrapper(model)
to_submodel(model::Model) = to_sampleable(returned(model)) At the moment, the Moreover, the way we do it currently is that anything is allowed to on the RHS of a @yebai also mentioned that we want methods such as |
This adds the
@returned_quantities
macro as discussed @yebai @mhauruThis is meant to be a replacement for
@submodel
macro, but without the ability to do automatic prefixing. It ends up looking likeLikely TODOs:
@submodel
telling the user to use@returned_quantities
.generated_quantities
toreturned_quantities
in this PR?Fix #691