Closed torfjelde closed 1 year ago
Great stuff, small comment first of all wrt your write up above, could you add a bullet for repeated samplers (sampler^2
) similar to the product and composed samplers. This would add a bit of clarity I think as its a lot of new terms.
Just had a proper go through and tested it out a bit, all seems to work and all looks great, happy to merge pending the suggestions and comments above.
As we've spoken about before, it should be possible to make things much more composable than it currently is.
Much of this functionality is useful beyond just MCMCTempering, and so this package will provide a great "testing-ground" for functionality that we can eventually move to something like AbstractMCMC proper.
To achieve the above we need the following:
sampler_outer ∘ sampler_inner
whosestep
first stepssampler_inner
and then, using the resulting state from steppingsampler_inner
, takes a step withsampler_outer
.sampler_1 × sampler_2
which targetsmodel_1 × model_2
whosestep
simply runssampler_1
onmodel_1
andsampler_2
onmodel_2
in "parallel".SequentialState
) which represents a sequence of states so we can later "unroll" these to obtain the full chain, if so desired. E.g. in the case ofsampler_outer ∘ sampler_inner
it's not completely obvious if we only want the iterations corresponding to the full composition, or if we actually want the iterations of each of the samplers.All in all, it's now possible to do some neat thingies.
Neat thingies
Some setup.
Compositions:
Same with "repeated" samplers (useful to avoid insane compilation times):
Products:
And of course, combining all of these:
MultiSampler
also works withAbstractArray
, etc.Drawbacks
foldl(∘, repeat(sampler, 1000))
and cry. This is fixable though (see for example how Julia handlesFunction
without compositions blowing up compilation times), probably by sprinkling@nospecialize
in the right places.sample
and/orAbstractMCMC.bundle_samples
. In the case where we wantMCMCChains.Chains
as the return-type, it seems reasonable to "unroll" things likeSequentialTransition
, but in the case where a simpleVector
of transitions is wanted, then it seems less so, i.e. in this case we probably want to return aVector{<:SequentialTransition}
which can later be "unrolled" if so desired.All in all, it's worth pointing out that we're not expecting users to nest these "meta"-samplers very often; in practice we'll probably look at a nested depth of 2 or 3 at most (e.g. mixture of composition of repeated).
Next steps
This PR on its own doesn't bring us all the way to just doing
sampler_outer ∘ sampler_swapper
, but this should now be straight forward to implement by just overloadingstep
forCompositionSampler{<:AbstractMCMC.AbstractSampler,<:TemperedSampler}
to performstep
forsampler_outer
and then a swap-step, finally returning aSequentialTransition
andSequentialState
, or just aCompositionState
withtransition
fromsampler_outer
(in the case where we don't want to further inspect the swapping statistics, etc.).I'll do this in another PR, as it will change
TemperedSampler
quite a bit.