-
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 |
@@ -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 |
in addition to method `to_submodel`
…cro' into torfjelde/returned-quantities-macro
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
fixed docs for `returned`
…cro' into torfjelde/returned-quantities-macro
Encountered another problem with If julia> @model demo_inner() = m ~ Normal()
demo_inner (generic function with 2 methods)
julia> @model function demo_outer()
m ~ to_submodel(demo_inner())
return m
end
demo_outer (generic function with 2 methods)
julia> model = demo_outer();
julia> model() ≠ 1.0
true
julia> conditioned_model = model | (m = 1.0, );
julia> conditioned_model()
ERROR: ArgumentError: `~` with a model on the right-hand side of an observe statement is not supported
... |
:/ Does prefixing help? |
Aye, this was the first solution that popped into my mind too. Though this will technically fix it, we don't have a way of warning the user about this properly 😕 |
A bit stumped by this at first sight. I think the desired user experience would be an error saying "variable names in the outer and inner model conflict, you must use prefixing", but not sure how to implement that neatly. I'm guessing there's a reason you haven't implemented that already when e.g. the user uses the same submodel twice without prefixing. |
In general, for errors that are hard or impossible to catch (at compile time), we could add a tool to https://turinglang.org/DynamicPPL.jl/stable/api/#Debugging-Utilities |
Exactly 😕
This crossed my mind, but the issue is ofc that this is only done upon explicit call by the user or in But yeah, don't see a better solution atm. The other solution is to either force usage of prefixing or just always prefix (none of which are ideal either). |
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