API
AbstractMCMC defines an interface for sampling Markov chains.
Model
AbstractMCMC.AbstractModel
— TypeAbstractModel
An AbstractModel
represents a generic model type that can be used to perform inference.
AbstractMCMC.LogDensityModel
— TypeLogDensityModel <: AbstractMCMC.AbstractModel
Wrapper around something that implements the LogDensityProblem.jl interface.
Note that this does not implement the LogDensityProblems.jl interface itself, but it simply useful for indicating to the sample
and other AbstractMCMC
methods that the wrapped object implements the LogDensityProblems.jl interface.
Fields
logdensity
: The object that implements the LogDensityProblems.jl interface.
Sampler
AbstractMCMC.AbstractSampler
— TypeAbstractSampler
The AbstractSampler
type is intended to be inherited from when implementing a custom sampler. Any persistent state information should be saved in a subtype of AbstractSampler
.
When defining a new sampler, you should also overload the function transition_type
, which tells the sample
function what type of parameter it should expect to receive.
Sampling a single chain
StatsBase.sample
— Methodsample(
+API · AbstractMCMC API
AbstractMCMC defines an interface for sampling Markov chains.
Model
AbstractMCMC.AbstractModel
— TypeAbstractModel
An AbstractModel
represents a generic model type that can be used to perform inference.
sourceAbstractMCMC.LogDensityModel
— TypeLogDensityModel <: AbstractMCMC.AbstractModel
Wrapper around something that implements the LogDensityProblem.jl interface.
Note that this does not implement the LogDensityProblems.jl interface itself, but it simply useful for indicating to the sample
and other AbstractMCMC
methods that the wrapped object implements the LogDensityProblems.jl interface.
Fields
logdensity
: The object that implements the LogDensityProblems.jl interface.
sourceSampler
AbstractMCMC.AbstractSampler
— TypeAbstractSampler
The AbstractSampler
type is intended to be inherited from when implementing a custom sampler. Any persistent state information should be saved in a subtype of AbstractSampler
.
When defining a new sampler, you should also overload the function transition_type
, which tells the sample
function what type of parameter it should expect to receive.
sourceSampling a single chain
StatsBase.sample
— Methodsample(
rng::Random.AbatractRNG=Random.default_rng(),
model::AbstractModel,
sampler::AbstractSampler,
N_or_isdone;
kwargs...,
-)
Sample from the model
with the Markov chain Monte Carlo sampler
and return the samples.
If N_or_isdone
is an Integer
, exactly N_or_isdone
samples are returned.
Otherwise, sampling is performed until a convergence criterion N_or_isdone
returns true
. The convergence criterion has to be a function with the signature
isdone(rng, model, sampler, samples, state, iteration; kwargs...)
where state
and iteration
are the current state and iteration of the sampler, respectively. It should return true
when sampling should end, and false
otherwise.
Keyword arguments
See https://turinglang.org/AbstractMCMC.jl/dev/api/#Common-keyword-arguments for common keyword arguments.
sourceStatsBase.sample
— Methodsample(
+)
Sample from the model
with the Markov chain Monte Carlo sampler
and return the samples.
If N_or_isdone
is an Integer
, exactly N_or_isdone
samples are returned.
Otherwise, sampling is performed until a convergence criterion N_or_isdone
returns true
. The convergence criterion has to be a function with the signature
isdone(rng, model, sampler, samples, state, iteration; kwargs...)
where state
and iteration
are the current state and iteration of the sampler, respectively. It should return true
when sampling should end, and false
otherwise.
Keyword arguments
See https://turinglang.org/AbstractMCMC.jl/dev/api/#Common-keyword-arguments for common keyword arguments.
sourceStatsBase.sample
— Methodsample(
rng::Random.AbstractRNG=Random.default_rng(),
logdensity,
sampler::AbstractSampler,
N_or_isdone;
kwargs...,
-)
Wrap the logdensity
function in a LogDensityModel
, and call sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceIterator
AbstractMCMC.steps
— Methodsteps(
+)
Wrap the logdensity
function in a LogDensityModel
, and call sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceIterator
AbstractMCMC.steps
— Methodsteps(
rng::Random.AbstractRNG=Random.default_rng(),
model::AbstractModel,
sampler::AbstractSampler;
@@ -486,12 +28,12 @@
julia> iterator = steps(MyModel(), MySampler());
julia> collect(Iterators.take(iterator, 10)) == zeros(10)
-true
sourceAbstractMCMC.steps
— Methodsteps(
+true
sourceAbstractMCMC.steps
— Methodsteps(
rng::Random.AbstractRNG=Random.default_rng(),
logdensity,
sampler::AbstractSampler;
kwargs...,
-)
Wrap the logdensity
function in a LogDensityModel
, and call steps
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceTransducer
AbstractMCMC.Sample
— MethodSample(
+)
Wrap the logdensity
function in a LogDensityModel
, and call steps
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceTransducer
AbstractMCMC.Sample
— MethodSample(
rng::Random.AbstractRNG=Random.default_rng(),
model::AbstractModel,
sampler::AbstractSampler;
@@ -508,12 +50,12 @@
julia> transducer = Sample(MyModel(), MySampler());
julia> collect(transducer(1:10)) == zeros(10)
-true
sourceAbstractMCMC.Sample
— MethodSample(
+true
sourceAbstractMCMC.Sample
— MethodSample(
rng::Random.AbstractRNG=Random.default_rng(),
logdensity,
sampler::AbstractSampler;
kwargs...,
-)
Wrap the logdensity
function in a LogDensityModel
, and call Sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceSampling multiple chains in parallel
StatsBase.sample
— Methodsample(
+)
Wrap the logdensity
function in a LogDensityModel
, and call Sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceSampling multiple chains in parallel
StatsBase.sample
— Methodsample(
rng::Random.AbstractRNG=Random.default_rng(),
model::AbstractModel,
sampler::AbstractSampler,
@@ -521,7 +63,7 @@
N::Integer,
nchains::Integer;
kwargs...,
-)
Sample nchains
Monte Carlo Markov chains from the model
with the sampler
in parallel using the parallel
algorithm, and combine them into a single chain.
Keyword arguments
See https://turinglang.org/AbstractMCMC.jl/dev/api/#Common-keyword-arguments for common keyword arguments.
sourceStatsBase.sample
— Methodsample(
+)
Sample nchains
Monte Carlo Markov chains from the model
with the sampler
in parallel using the parallel
algorithm, and combine them into a single chain.
Keyword arguments
See https://turinglang.org/AbstractMCMC.jl/dev/api/#Common-keyword-arguments for common keyword arguments.
sourceStatsBase.sample
— Methodsample(
rng::Random.AbstractRNG=Random.default_rng(),
logdensity,
sampler::AbstractSampler,
@@ -529,7 +71,7 @@
N::Integer,
nchains::Integer;
kwargs...,
-)
Wrap the logdensity
function in a LogDensityModel
, and call sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceTwo algorithms are provided for parallel sampling with multiple threads and multiple processes, and one allows for the user to sample multiple chains in serial (no parallelization):
AbstractMCMC.MCMCThreads
— TypeMCMCThreads
The MCMCThreads
algorithm allows users to sample MCMC chains in parallel using multiple threads.
sourceAbstractMCMC.MCMCDistributed
— TypeMCMCDistributed
The MCMCDistributed
algorithm allows users to sample MCMC chains in parallel using multiple processes.
sourceAbstractMCMC.MCMCSerial
— TypeMCMCSerial
The MCMCSerial
algorithm allows users to sample serially, with no thread or process parallelism.
sourceCommon keyword arguments
Common keyword arguments for regular and parallel sampling are:
progress
(default: AbstractMCMC.PROGRESS[]
which is true
initially): toggles progress loggingchain_type
(default: Any
): determines the type of the returned chaincallback
(default: nothing
): if callback !== nothing
, then callback(rng, model, sampler, sample, iteration)
is called after every sampling step, where sample
is the most recent sample of the Markov chain and iteration
is the current iterationnum_warmup
(default: 0
): number of "warm-up" steps to take before the first "regular" step, i.e. number of times to call AbstractMCMC.step_warmup
before the first call to AbstractMCMC.step
.discard_initial
(default: num_warmup
): number of initial samples that are discarded. Note that if discard_initial < num_warmup
, warm-up samples will also be included in the resulting samples.thinning
(default: 1
): factor by which to thin samples.initial_state
(default: nothing
): if initial_state !== nothing
, the first call to AbstractMCMC.step
is passed initial_state
as the state
argument.
Info The common keyword arguments progress
, chain_type
, and callback
are not supported by the iterator AbstractMCMC.steps
and the transducer AbstractMCMC.Sample
.
There is no "official" way for providing initial parameter values yet. However, multiple packages such as EllipticalSliceSampling.jl and AdvancedMH.jl support an initial_params
keyword argument for setting the initial values when sampling a single chain. To ensure that sampling multiple chains "just works" when sampling of a single chain is implemented, we decided to support initial_params
in the default implementations of the ensemble methods:
initial_params
(default: nothing
): if initial_params isa AbstractArray
, then the i
th element of initial_params
is used as initial parameters of the i
th chain. If one wants to use the same initial parameters x
for every chain, one can specify e.g. initial_params = FillArrays.Fill(x, N)
.
Progress logging can be enabled and disabled globally with AbstractMCMC.setprogress!(progress)
.
AbstractMCMC.setprogress!
— Functionsetprogress!(progress::Bool; silent::Bool=false)
Enable progress logging globally if progress
is true
, and disable it otherwise. Optionally disable informational message if silent
is true
.
sourceChains
The chain_type
keyword argument allows to set the type of the returned chain. A common choice is to return chains of type Chains
from MCMCChains.jl.
AbstractMCMC defines the abstract type AbstractChains
for Markov chains.
AbstractMCMC.AbstractChains
— TypeAbstractChains
AbstractChains
is an abstract type for an object that stores parameter samples generated through a MCMC process.
sourceFor chains of this type, AbstractMCMC defines the following two methods.
AbstractMCMC.chainscat
— Functionchainscat(c::AbstractChains...)
Concatenate multiple chains.
By default, the chains are concatenated along the third dimension by calling cat(c...; dims=3)
.
sourceAbstractMCMC.chainsstack
— Functionchainsstack(c::AbstractVector)
Stack chains in c
.
By default, the vector of chains is returned unmodified. If eltype(c) <: AbstractChains
, then reduce(chainscat, c)
is called.
sourceInteracting with states of samplers
To make it a bit easier to interact with some arbitrary sampler state, we encourage implementations of AbstractSampler
to implement the following methods:
AbstractMCMC.getparams
— Functiongetparams([model::AbstractModel, ]state)
Retrieve the values of parameters from the sampler's state
as a Vector{<:Real}
.
sourceAbstractMCMC.setparams!!
— Functionsetparams!!([model::AbstractModel, ]state, params)
Set the values of parameters in the sampler's state
from a Vector{<:Real}
.
This function should follow the BangBang
interface: mutate state
in-place if possible and return the mutated state
. Otherwise, it should return a new state
containing the updated parameters.
Although not enforced, it should hold that setparams!!(state, getparams(state)) == state
. In other words, the sampler should implement a consistent transformation between its internal representation and the vector representation of the parameter values.
Sometimes, to maintain the consistency of the log density and parameter values, a model
should be provided. This is useful for samplers that need to evaluate the log density at the new parameter values.
sourcegetparams
and setparams!!
provide a generic interface for interacting with the parameters of a sampler's state, regardless of how that state is represented internally. If the model
argument is not provided, the functions will be dispatched to the implementations without the model
argument.
This allows generic code to be written that works with any sampler implementing this interface. For example, a generic ensemble sampler could use getparams
to extract the parameters from each of its component samplers' states, and setparams!!
to initialize each component sampler with a different set of parameters.
The optional model
argument to these functions allows sampler implementations to customize their behavior based on the model being used. This is useful for samplers that need to access or modify the model in order to extract or set the parameters.
These methods are particularly useful for implementing samplers which wrap some inner samplers, such as a mixture of samplers. In the next section, we will see how getparams
and setparams!!
can be used to implement a MixtureSampler
.
Example: MixtureSampler
In a MixtureSampler
we need two things:
components
: collection of samplers.weights
: collection of weights representing the probability of choosing the corresponding sampler.
struct MixtureSampler{W,C} <: AbstractMCMC.AbstractSampler
+)
Wrap the logdensity
function in a LogDensityModel
, and call sample
with the resulting model instead of logdensity
.
The logdensity
function has to support the LogDensityProblems.jl interface.
sourceTwo algorithms are provided for parallel sampling with multiple threads and multiple processes, and one allows for the user to sample multiple chains in serial (no parallelization):
AbstractMCMC.MCMCThreads
— TypeMCMCThreads
The MCMCThreads
algorithm allows users to sample MCMC chains in parallel using multiple threads.
sourceAbstractMCMC.MCMCDistributed
— TypeMCMCDistributed
The MCMCDistributed
algorithm allows users to sample MCMC chains in parallel using multiple processes.
sourceAbstractMCMC.MCMCSerial
— TypeMCMCSerial
The MCMCSerial
algorithm allows users to sample serially, with no thread or process parallelism.
sourceCommon keyword arguments
Common keyword arguments for regular and parallel sampling are:
progress
(default: AbstractMCMC.PROGRESS[]
which is true
initially): toggles progress loggingchain_type
(default: Any
): determines the type of the returned chaincallback
(default: nothing
): if callback !== nothing
, then callback(rng, model, sampler, sample, iteration)
is called after every sampling step, where sample
is the most recent sample of the Markov chain and iteration
is the current iterationnum_warmup
(default: 0
): number of "warm-up" steps to take before the first "regular" step, i.e. number of times to call AbstractMCMC.step_warmup
before the first call to AbstractMCMC.step
.discard_initial
(default: num_warmup
): number of initial samples that are discarded. Note that if discard_initial < num_warmup
, warm-up samples will also be included in the resulting samples.thinning
(default: 1
): factor by which to thin samples.initial_state
(default: nothing
): if initial_state !== nothing
, the first call to AbstractMCMC.step
is passed initial_state
as the state
argument.
Info The common keyword arguments progress
, chain_type
, and callback
are not supported by the iterator AbstractMCMC.steps
and the transducer AbstractMCMC.Sample
.
There is no "official" way for providing initial parameter values yet. However, multiple packages such as EllipticalSliceSampling.jl and AdvancedMH.jl support an initial_params
keyword argument for setting the initial values when sampling a single chain. To ensure that sampling multiple chains "just works" when sampling of a single chain is implemented, we decided to support initial_params
in the default implementations of the ensemble methods:
initial_params
(default: nothing
): if initial_params isa AbstractArray
, then the i
th element of initial_params
is used as initial parameters of the i
th chain. If one wants to use the same initial parameters x
for every chain, one can specify e.g. initial_params = FillArrays.Fill(x, N)
.
Progress logging can be enabled and disabled globally with AbstractMCMC.setprogress!(progress)
.
AbstractMCMC.setprogress!
— Functionsetprogress!(progress::Bool; silent::Bool=false)
Enable progress logging globally if progress
is true
, and disable it otherwise. Optionally disable informational message if silent
is true
.
sourceChains
The chain_type
keyword argument allows to set the type of the returned chain. A common choice is to return chains of type Chains
from MCMCChains.jl.
AbstractMCMC defines the abstract type AbstractChains
for Markov chains.
AbstractMCMC.AbstractChains
— TypeAbstractChains
AbstractChains
is an abstract type for an object that stores parameter samples generated through a MCMC process.
sourceFor chains of this type, AbstractMCMC defines the following two methods.
AbstractMCMC.chainscat
— Functionchainscat(c::AbstractChains...)
Concatenate multiple chains.
By default, the chains are concatenated along the third dimension by calling cat(c...; dims=3)
.
sourceAbstractMCMC.chainsstack
— Functionchainsstack(c::AbstractVector)
Stack chains in c
.
By default, the vector of chains is returned unmodified. If eltype(c) <: AbstractChains
, then reduce(chainscat, c)
is called.
sourceInteracting with states of samplers
To make it a bit easier to interact with some arbitrary sampler state, we encourage implementations of AbstractSampler
to implement the following methods:
AbstractMCMC.getparams
— Functiongetparams([model::AbstractModel, ]state)
Retrieve the values of parameters from the sampler's state
as a Vector{<:Real}
.
sourceAbstractMCMC.setparams!!
— Functionsetparams!!([model::AbstractModel, ]state, params)
Set the values of parameters in the sampler's state
from a Vector{<:Real}
.
This function should follow the BangBang
interface: mutate state
in-place if possible and return the mutated state
. Otherwise, it should return a new state
containing the updated parameters.
Although not enforced, it should hold that setparams!!(state, getparams(state)) == state
. In other words, the sampler should implement a consistent transformation between its internal representation and the vector representation of the parameter values.
Sometimes, to maintain the consistency of the log density and parameter values, a model
should be provided. This is useful for samplers that need to evaluate the log density at the new parameter values.
sourcegetparams
and setparams!!
provide a generic interface for interacting with the parameters of a sampler's state, regardless of how that state is represented internally.
This allows generic code to be written that works with any sampler implementing this interface. For example, a generic ensemble sampler could use getparams
to extract the parameters from each of its component samplers' states, and setparams!!
to initialize each component sampler with a different set of parameters.
The optional model
argument to these functions allows sampler implementations to customize their behavior based on the model being used. For example, some samplers may need to evaluate the log density at new parameter values when setting parameters, which requires access to the model. If access to model
is not needed, the sampler only needs to implement the version without the model
argument - the default implementations will then call those methods directly.
These methods are particularly useful for implementing samplers which wrap some inner samplers, such as a mixture of samplers. In the next section, we will see how getparams
and setparams!!
can be used to implement a MixtureSampler
.
Example: MixtureSampler
In a MixtureSampler
we need two things:
components
: collection of samplers.weights
: collection of weights representing the probability of choosing the corresponding sampler.
struct MixtureSampler{W,C} <: AbstractMCMC.AbstractSampler
components::C
weights::W
end
To implement the state, we need to keep track of a couple of things:
index
: the index of the sampler used in this step
.states
: the current states of all the components.
We need to keep track of the states of all components rather than just the state for the sampler we used previously. The reason is that lots of samplers keep track of more than just the previous realizations of the variables, e.g. in AdvancedHMC.jl
we keep track of the momentum used, the metric used, etc.
struct MixtureState{S}
@@ -607,5 +149,4 @@
transition, state = AbstractMCMC.step(rng, model, sampler)
while ...
transition, state = AbstractMCMC.step(rng, model, sampler, state)
-end
Settings
This document was generated with Documenter.jl version 1.7.0 on Sunday 27 October 2024. Using Julia version 1.11.1.