-
Notifications
You must be signed in to change notification settings - Fork 32
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
:=
to keep track of generated quantities
#594
Conversation
Maybe we can push this a bit further by introducing a block syntax for julia> @model function demo()
x ~ Normal(0, 1)
generated_quantities := let
# users could put arbitrary code in this block.
c = 5*x
d = 2*x
z = x
(c, z) # variables to track
end
return x
end
julia> model = demo();
julia> model()
julia> generated_quantities(model, (x = 1,))
Then, we can conditionally evaluate this block during MCMC. The variable name This would provide an alternative to #589, which is a bit unsatisfactory, I think. |
Not a big fan because it will:
Compared to the simple |
I'm not sure it will involve a lot of extra work, but I don't think this is a major issue even if that is true. Also, we can do this block-syntax in a separate PR.
They are mostly equivalent to if-else blocks. I am not aware of any let-block limitations. Can you clarify? EDIT: Apart from requiring an additional macro |
If we consider a block syntax, maybe something like julia> @model function demo()
x ~ Normal(0, 1)
@generated_quantities begin
# users could put arbitrary code in this block.
c = 5*x
d = 2*x
z = x
(c, z) # variables to track
end
return x
end would be a slightly simpler syntax? |
But won't this make our lives much more difficult? It will be additional macro-related stuff to maintain + the beautify of the current way with |
I didn't focus on the @model function demo()
x ~ Normal()
@generated_quantities begin
y = 100 + x
end
return nothing
end or even @model function demo()
x ~ Normal()
@generated_quantities begin
y := 100 + x
end
return nothing
end In principle different such blocks could be used for defining additional computations in other scenarios. |
IMO if tell the user "use |
I find the syntax Tor posted pretty cool and intuitive. 😅 Why make it more complicated? |
Seconded 👀 |
I'm happy to merge this PR and leave the block syntax for future work.
@trappmartin the |
Thanks for the context. |
So is this actually something we want to move forward? |
29053f0
to
4c61bcf
Compare
Pull Request Test Coverage Report for Build 8969088761Details
💛 - Coveralls |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #594 +/- ##
==========================================
- Coverage 81.06% 76.61% -4.45%
==========================================
Files 30 30
Lines 3517 3545 +28
==========================================
- Hits 2851 2716 -135
- Misses 666 829 +163 ☔ View full report in Codecov by Sentry. |
I don't think it's a good idea but I want to bring it up anyways: What about the opposite behaviour and making everything that is defined with |
What about aliasing? For instance, given @model function m()
x := 1
y ~ Normal(x, 1)
x := y
end The current implementation will be tracking the value of the second Also the use of |
It's probably sensible to simply throw an error for such scenarios. |
We actually have |
Naaaaaah, that's going to be too crazy I think. Too many gotchas and annoyances. Also, we've had tons of requests to "filter out variables that I need for inference but am not actually interested in to save mem footprint", and this would make those people way less happy 😅 |
Let’s try to get this PR merged soon-ish. |
:=
to keep track of generated quantities:=
to keep track of generated quantities
Let's make a final push to get this merged and released -- it looks like some GSoC projects might benefit from this new feature. |
Added tests + marked ready for review. Combining this PR with TuringLang/Turing.jl#2202, automatic inclusion of tracked variables will be included. |
Looks good to me. Tiny concern on a technicality: we are using the |
So there are two aspects:
I'm definitively open to maybe make a more explicit approach to (2), i.e. introduce some |
@yebai Please don't merge PRs opened by others without consulting with the author (unless they're super unrespnosive ofc) |
Note that this is more of a fun idea rather than something I think we necessarily should do.
But due to a bunch of issues with invlinking (TuringLang/Turing.jl#2195), we're likely going to make it so that we always re-evaluate the model to get the properly linked realizations before passing it to the user (TuringLang/Turing.jl#2202) using
values_as_in_model
(#590).Now, if we indeed decide to always do this re-evaluation, it opens a can of cute worms, one amongst them which is the possibility of the following with very little work 👀 (note the example is also using TuringLang/Turing.jl#2202)
That is, we can finally "track" quantities in a nice manner + get easy integration with
Chains
(generated_quantities
lacks this).This is highly relevant to the age-old issue: #94
fix #94