-
Notifications
You must be signed in to change notification settings - Fork 219
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
Remove (duplicate) samplers being defined explicitly in Turing.jl #2413
Comments
Would it be possible to:
If someone then defines One point of awkwardness might be that if they then want to get the nice Turing bells and whistles, they have to declare (I should say that before posting this comment I had around 3 different ideas, each of which I started to write down before immediately realising that they were terrible. I haven't yet found a fatal flaw in this one, so I'm optimistic 😄 but it might just be the 4th terrible idea) |
That is not a bad idea for sure, but my immediate worries are: a) where does this Turing-managed sampler go, and b) how would people hook into this functionality in, say, a Turing.jl extension? Issue (b) seems like an annoying one that is difficult to circumvent when we do subtyping (as is the issue with |
(a) I think it would have to live in AbstractMCMC. Sure, it's not really AbstractMCMC's business but I don't really think it's unfair to declare a single abstract supertype for internal use in another package we do control. (b) Yeah I think that's the same as what I wrote. You can't automatically derive the functionality of Turing's |
Btw - usually I'm all in favour of renaming and disambiguating functions. I like breaking changes. :D But I think that renaming If that's what we end up deciding on, I'm happy to go with it (renaming will indeed solve the problem once and for all) but (imo :)) we must really carefully evaluate and rule out every other possibility first. |
This one still feels a bit weird to me unfortunately 😕 What about when someone else comes along and goes "Can we make our custom model in AbstractMCMC.jl? We think it would benefit us you see." Maaaaybe it would make sense to put it in AbstractPPL.jl? 😬 Don't like this either, but does feel slightly more appropriate. Or even just a TuringBase.jl package or something stupid, though this also feels "bad".
Aye, but this will be "overkill" for integrating with Turing.jl, e.g. see That is fine tbf, and might be what we want 🤷
Aye, this is really the worst part of it 😕 And tbf, it is really, really bad. All in all, I think I agree with you @penelopeysm that it would be better to do the subtyping stuff, most definitively. If we could go with a slightly better solution than putting it in AbstractMCMC.jl, I think it's an easy choice (and it might still be the preferred choice even if we do put it in AbstractMCMC.jl 😬 ) |
We're duplicating a lot of code and a lot of effort by having a bunch of sampler (or rather,
InferenceAlgorithm
) implementations in Turing.jl itself.There are a few reasons for this is / was the case:
assume
andobserve
statements for samplers and to mutate the varinfo in a particular, even if the functionality of the sampler itself (when used outside of Gibbs) didn't require it.InferenceAlgorithm
allows us to overload thesample
call explicitly to do some "non-standard" things, e.g. usechain_type=MCMCChains.Chains
as the default, instead ofchain_type=Vector
as is default in AbstractMCMC.jl.Everything but (3) is "easily" addressable (i.e. only requires dev-time, not necessarily any discussion on how to do it):
DensityModel
? AdvancedMH.jl#108chain_type=Chains
for Turing.jl models (ref: Remove overly specialized bundle_samples AbstractMCMC.jl#120, Defaultbundle_samples
is quite annoying AbstractMCMC.jl#118), b) how to allow extraction of other interesting information than just the realizations for the variables fromsample
calls, and c) extraction of parameter names used to construct the chain. See the section below for more extensive discussion of this issue. Relevant issues: Removehmc.jl
andmh.jl
in light of upstreamed "getparams" into AbstractMCMC #2367Removing the
InferenceAlgorithm
type (3)Problem
Currently, all the samplers in Turing.jl have most of their code living outside of Turing.jl + inside Turing.jl we define a "duplicate" which is not an
AbstractMCMC.AbstractSampler
(as typically expected byAbstractMCMC.sample
), but instead a subtype ofTuring.Infernece.InferenceAlgorithm
:Turing.jl/src/mcmc/Inference.jl
Lines 91 to 95 in c0a4ee9
But exactly because these are not
AbstractMCMC.AbstractSampler
, we can overloadsample
calls to do more than whatsample
does for a givenAbstractSampler
.One of the things we do is to make
chain_type=Chains
rather thanchain_type=Vector
(as is the default in AbstractMCMC.jl):Turing.jl/src/mcmc/Inference.jl
Lines 337 to 359 in c0a4ee9
Another is to perform some simple model checks to stop the user from doing things they shouldn't, e.g. accidentally using a model twice (this is done using
DynamicPPL.check_model
):Turing.jl/src/mcmc/Inference.jl
Lines 296 to 306 in c0a4ee9
However, as mentioned before, having to repeat all these sampler constructors just to go from working with a
AbstractSampler
toInferenceAlgorithm
so we can do these things is a) very annoying to maintain, and b) makes it all very confusing for newcomers to contribute.Now, the problem is that cannot simple start overloading
sample(model::DynamicPPL.Model, sampler::AbstractMCMC.AbstractSampler, ...)
calls since sampler packages might define something likesample(model::AbstractMCMC.AbstractModel, sampler::MySampler, ...)
(we haveDynamicPPL.Model <: AbstractMCMC.AbstractModel
btw) which would give rise to a host of method ambiguities.Someone might say "oh, but nobody is going to impelment
sample(model::AbstractMCMC.AbstractModel, sampler::MySampler, ...)
; they're always going to implement a sampler for a specific model type, e.g.AbstractMCMC.LogDensityModel
", but this is not great for two reasons: a) "meta" samplers, i.e. samplers that use other samplers as components, might want to be agnostic to what the underlying model is as this "meta" sampler doesn't interact directly with the model itself, and b) if we do so, we're claiming thatDynamicPPL.Model
is, in some way, a special and more important model type than all other subtypes ofAbstractModel
, which is the exact opposite of what we wanted to do with AbstractMCMC.jl (we wanted it to be a "sampler package for all, not just Turing.jl").externalsampler
introduced in #2008 is a step towards this, but in the end we don't want to requireexternalsampler
to wrap everysampler
passed to Turing.jl; we really only want this to have to wrap samplers which do not support all the additional niceties that Turing.jl's currentsample
provides.Solution 1: rename or duplicate
sample
The only true solution I see, which is very, very annoying, is to either
AbstractMCMC.sample
from Turing.jl, and instead define and export a separateTuring.sample
which is a fancy wrapper aroundAbstractMCMC.sample
.sample
from Turing.jl with a different name, e.g.infer
ormcmc
(or even use the internalmcmcsample
from AbstractMCMC.jl naming but making it public).None of these are ideal tbh.
(1) sucks because so many of the packages are using
StatsBase.sample
(as we are in AbstractMCMC.jl) for this very reasonable interface, and so diverging from this is confusing + we'll easily end up with naming collisions in the namespace of the user, e.g.using Turing, AbstractMCMC
would immediately cause twosample
methods to be imported.(2) is also a bit annoying as this would be a highly breaking change. It's also a bit annoying because, well,
sample
is a much better name 🤷IMHO, I think (2) is best here though. If we define a method called
mcmc
ormcmcsample
(ideally we'd do something withAbstractMCMC.mcmcsample
) which is exported from Turing.jl, we could do away with all ofInferenceAlgorithm
and its implementations in favour of a single (or a few) overloads of this method.The text was updated successfully, but these errors were encountered: