-
Notifications
You must be signed in to change notification settings - Fork 18
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
Add getparameters
and setparameters!!
#86
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #86 +/- ##
==========================================
- Coverage 97.37% 96.42% -0.95%
==========================================
Files 8 8
Lines 305 308 +3
==========================================
Hits 297 297
- Misses 8 11 +3
☔ View full report in Codecov by Sentry. |
Maybe call it |
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 added some comments.
We should also add tests and update the documentation.
src/AbstractMCMC.jl
Outdated
@@ -79,6 +79,36 @@ The `MCMCSerial` algorithm allows users to sample serially, with no thread or pr | |||
""" | |||
struct MCMCSerial <: AbstractMCMCEnsemble end | |||
|
|||
""" | |||
state_from_transiton(state, transition_prev[, state_prev]) |
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 one seems a bit confusing - so one already needs a state
to return it? Based on the name I would have assumed a function signature state_from_transition(transition) -> state
.
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.
Well if you already have the state, wouldn't it just be an identity call? i.e.
state_from_transition(state, a, b) = state
You could just dispatch to a different state
type. For example, state=nothing
would try to reconstruct the state from the transitions. Maybe? Not sure. Perhaps I am just playing devils advocate here.
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.
Hmm, maybe update_from_transition!!(state, transition_prev, state_prev)
is more descriptive?
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.
Yo, whadda yah guys think?
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.
Oh, sorry, my bad. Yeah your proposed name change is clearer, let's do that.
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.
Or maybe just update!!
? Given that we might also want to pass in state_prev
?
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.
Yeah, since we don't want to export any of these functions anyway I'm fine with update!!
. Is a bit nicer than update_from_transition!!
IMO, and as you say we might not only update based on the transition.
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.
Cool, I'll make that change then 👍
As you mention, the main problem is that it is not clear which |
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'm happy with it after David's comments are addressed, but in general I think this is slick. Thanks for the PR!
src/AbstractMCMC.jl
Outdated
@@ -79,6 +79,36 @@ The `MCMCSerial` algorithm allows users to sample serially, with no thread or pr | |||
""" | |||
struct MCMCSerial <: AbstractMCMCEnsemble end | |||
|
|||
""" | |||
state_from_transiton(state, transition_prev[, state_prev]) |
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.
Well if you already have the state, wouldn't it just be an identity call? i.e.
state_from_transition(state, a, b) = state
You could just dispatch to a different state
type. For example, state=nothing
would try to reconstruct the state from the transitions. Maybe? Not sure. Perhaps I am just playing devils advocate here.
Co-authored-by: David Widmann <[email protected]>
Though I agree with "parameters" not being a good choice, "samples" can be a bit confusing IMO given all the other sample-related functions we have. Would
Happy with this 👍 |
Do you have ideas for alternatives to the use of I think I'm leaning towards |
I dunno I feel like I wouldn't mind using |
I've added some docs + motivating example: https://turinglang.github.io/AbstractMCMC.jl/previews/PR86/api/#Interacting-with-states-of-samplers (Btw, I love the fact that I can preview docs in the PRs; I'm guessing this is your doing @devmotion ? ❤️ ) |
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.
Mhm yep I love it. Could you move us up a major version?
I think the only thing that's left is the discussion of |
I prefer |
On additional thing we might want to consider adding:
Of course, this can be dealt with on a case-by-case basis by simply defining What do you say @devmotion @cpfiffer ? Add or not add, that is the question. |
Also, @devmotion you mentioned tests. Do you have anything particular in mind? I have a test for the struct TestState
params
logp
end
setvalues!!(s::TestState) = ... etc. seems quite useless 🤷 We could potentially take the test I have for the |
Yo boys @devmotion @cpfiffer! You got any thoughts on the above? AFAIK this is the only thing that's holding this PR back. |
src/AbstractMCMC.jl
Outdated
@doc """ | ||
values(transition) | ||
|
||
Return values in `transition`. | ||
""" | ||
Base.values |
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.
Do we really want to use Base.values
here? I think adding this documentation should be considered type piracy and would only be allowed if we define it only for our own types as arguments (which we can't do here).
Unrelated, why did you use @doc
?
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.
Do we really want to use Base.values here? I think adding this documentation should be considered type piracy and would only be allowed if we define it only for our own types as arguments (which we can't do here).
Hmm, I do agree with this. I'm coming around to values
not being the best idea.
Unrelated, why did you use @doc?
IIRC you need @doc
here to be able to add the docstring? I.e. if you remove the @doc
it won't be added to the docstring of Base.values
.
Woops, sorry, missed this one. Full support from me on this one! |
Ah I also missed this question. I think it would probably be useful but I would leave it for a separate PR. There were quite many discussions about |
Yeah I was actually looking at the newly introduced |
I renamed Even if we're not completely happy with these names, we can instead just change these at a later stage. |
After looking into DensityInterface.jl I don't think there's anything that should be relevant for AbstractMCMC's functionality for setting and extracting log-probabilities from states/transitions. For the So maybe we should just introduce EDIT: I added EDIT 2: Maybe something like """
target_logdensity(model, transition)
Return the log-density of the target `model` represented at `transition`.
Note that this does not necessarily compute the log-density of `model` at
`transition`, but may simply return a cached result from `transition`.
"""
function target_logdensity(model::AbstractModel, transition)
return DensityInterface.logdensityof(model, realize(transition))
end
"""
set_target_logdensity!!(state, logp)
Update the log-density in `state` by setting it to `logp`.
If `state` is mutable, this function mutates `state` directly and returns `state`.
Otherwise a new and updated instance of `state` is returned.
"""
function set_target_logdensity!! end |
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.
Let's make a final push to get this merged!
Apologize for the amount of comments. My proposal here is, in spirit, the same as what the PR already has. The differences are:
- not defining
updatestates!!
: sampler packages can define there own internal functions - renaming
realize
andrealize!!
togetparams
andsetparams!!
: there are no perfect names here, these are the names we are currently using inTuring.jl
, they are self-explanatory enough - no longer taking
model
as argument, also force returning and receivingVector
: this makes the proposed interface less flexible, but I think they are sufficient, when needs arise, we can always add version withmodel
arguements
Co-authored-by: Xianda Sun <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Xianda Sun <[email protected]>
Co-authored-by: Xianda Sun <[email protected]>
Co-authored-by: Xianda Sun <[email protected]>
@hong @devmotion can you give a quick look? |
state_from_transition
, parameters
and setparameters!!
getparameters
and setparameters!!
Test errors are not related to this PR. Minor version bumped for added features, merging now. |
See #85.
Currently, almost every package implementing a
AbstractSampler
comes with their custom state and transition types. Since there currently are no "interface" or "guidelines" about what the types ofstate
andtransition
should implement, it means that interaction across different samplers, e.g. composing two samplers from different packages, is annoying.This PR introduces some methods which aims to alleviate this issue. In particular it sampler-implementations to also implement
parameters(transition)
for the transition-type which returns the parameters in the sample, where by "parameters" I mean the realizations of the random variables we're targeting present in thetransition
, andsetparameters!!
for the state-type which updates the current state of the Markov chain, thus likely (this might depend on the sampler) conditioning the sampler/kernel on the provided parameters.Why
parameters
fortransition
butsetparameters!!
forstate
? Atransition
should (AFAIK) always contain a realization of the random variables we're sampling while thestate
might not, e.g. MH with aMvNormal(zeros(n), I)
as proposal distribution (not dependent on current position/state/parameters). Of course there might be more properties one would like to use when converting fromPackageA.Transition
toPackageB.State
, but this seems like the lowest common denominator that we can come up with. Maaaybe we should have the same forlogdensity
, i.e.logdensity(transition)
andsetlogdensity!!(state)
, but this might not always be available nor correspond directly to the same thing for both samplers. Might be worth including though. They could also obviously be implemented for both if the implementer so chooses.But for the cases where you want to make use of more than just the parameters (and potentially logdensity), one can overload the
state_from_transition
directly (which is what should be used by packages making these "meta-samplers", e.g. composition), e.g.AdvancedHMC
might want to implementstate_from_transition(::AdvancedHMC.HMCState, ::AdvancedHMC.Transition)
to not only update the parameters in thestate
but the entirePhasePoint
fromAdvnacedHMC.Transition
, etc.Thoughts?