General Usage

This package implements the AbstractMCMC interface. AbstractMCMC provides a unifying interface for MCMC algorithms applied to LogDensityProblems.

Examples

Drawing Samples From a LogDensityProblems Through AbstractMCMC

SliceSampling.jl implements the AbstractMCMC interface through LogDensityProblems. That is, one simply needs to define a LogDensityProblems and pass it to AbstractMCMC:

using AbstractMCMC
using Distributions
using LinearAlgebra
using LogDensityProblems
using Plots

using SliceSampling

struct Target{D}
	dist::D
end

LogDensityProblems.logdensity(target::Target, x) = logpdf(target.dist, x)

LogDensityProblems.dimension(target::Target) = length(target.distx)

LogDensityProblems.capabilities(::Type{<:Target}) = LogDensityProblems.LogDensityOrder{0}()

sampler         = GibbsPolarSlice(2.0)
n_samples       = 10000
model           = Target(MvTDist(5, zeros(10), Matrix(I, 10, 10)))
logdensitymodel = AbstractMCMC.LogDensityModel(model)

chain   = sample(logdensitymodel, sampler, n_samples; initial_params=randn(10))
samples = hcat([transition.params for transition in chain]...)

plot(samples[1,:], xlabel="Iteration", ylabel="Trace")
savefig("abstractmcmc_demo.svg")
"/home/runner/work/SliceSampling.jl/SliceSampling.jl/docs/build/abstractmcmc_demo.svg"

Drawing Samples From Turing Models

SliceSampling.jl can also be used to sample from Turing models through Turing's externalsampler interface:

using Distributions
using Turing
using SliceSampling

@model function demo()
    s ~ InverseGamma(3, 3)
    m ~ Normal(0, sqrt(s))
end

sampler   = RandPermGibbs(SliceSteppingOut(2.))
n_samples = 10000
model     = demo()
chain     = sample(model, externalsampler(sampler), n_samples; progress=false)
describe(chain)
Chains MCMC chain (10000×5×1 Array{Float64, 3}):

Iterations        = 1:1:10000
Number of chains  = 1
Samples per chain = 10000
Wall duration     = 4.61 seconds
Compute duration  = 4.61 seconds
parameters        = s, m
internals         = lp, logprior, loglikelihood

Summary Statistics
  parameters      mean       std      mcse    ess_bulk    ess_tail      rhat   ess_per_sec
      Symbol   Float64   Float64   Float64     Float64     Float64   Float64       Float64

           s    1.4865    1.3636    0.0210   5938.4449   5123.6205    1.0000     1289.2846
           m    0.0164    1.1855    0.0124   9162.9357   6392.6739    1.0002     1989.3477

Quantiles
  parameters      2.5%     25.0%     50.0%     75.0%     97.5%
      Symbol   Float64   Float64   Float64   Float64   Float64

           s    0.4211    0.7629    1.1140    1.7232    4.9784
           m   -2.3505   -0.6941    0.0328    0.7377    2.3454

Conditional sampling in a Turing.Gibbs sampler

SliceSampling.jl be used as a conditional sampler in Turing.Gibbs.

using Distributions
using Turing
using SliceSampling

@model function simple_choice(xs)
    p ~ Beta(2, 2)
    z ~ Bernoulli(p)
    for i in 1:length(xs)
        if z == 1
            xs[i] ~ Normal(0, 1)
        else
            xs[i] ~ Normal(2, 1)
        end
    end
end

sampler = Turing.Gibbs(
    :p => externalsampler(SliceSteppingOut(2.0)),
    :z => PG(20),
)

n_samples = 1000
model     = simple_choice([1.5, 2.0, 0.3])
chain     = sample(model, sampler, n_samples; progress=false)
describe(chain)
Chains MCMC chain (1000×5×1 Array{Float64, 3}):

Iterations        = 1:1:1000
Number of chains  = 1
Samples per chain = 1000
Wall duration     = 29.23 seconds
Compute duration  = 29.23 seconds
parameters        = p, z
internals         = lp, logprior, loglikelihood

Summary Statistics
  parameters      mean       std      mcse   ess_bulk   ess_tail      rhat   ess_per_sec
      Symbol   Float64   Float64   Float64    Float64    Float64   Float64       Float64

           p    0.4356    0.2110    0.0073   846.4987   603.4851    1.0058       28.9629
           z    0.1570    0.3640    0.0134   733.5490        NaN    0.9990       25.0983

Quantiles
  parameters      2.5%     25.0%     50.0%     75.0%     97.5%
      Symbol   Float64   Float64   Float64   Float64   Float64

           p    0.0733    0.2712    0.4327    0.5885    0.8342
           z    0.0000    0.0000    0.0000    0.0000    1.0000

Drawing Samples

For drawing samples using the algorithms provided by SliceSampling, the user only needs to call:

sample([rng,] model, slice, N; initial_params)
  • slice::AbstractSliceSampling: Any slice sampling algorithm provided by SliceSampling.
  • model: A model implementing the LogDensityProblems interface.
  • N: The number of samples

The output is a SliceSampling.Transition object, which contains the following:

SliceSampling.TransitionType
struct Transition

Struct containing the results of the transition.

Fields

  • params: Samples generated by the transition.
  • lp::Real: Log-target density of the samples.
  • info::NamedTuple: Named tuple containing information about the transition.
source

For the keyword arguments, SliceSampling allows:

  • initial_params: The intial state of the Markov chain (default: nothing).

If initial_params is nothing, the following function can be implemented to provide an initialization:

SliceSampling.initial_sampleFunction
initial_sample(rng, model)

Return the initial sample for the model using the random number generator rng.

Arguments

  • rng::Random.AbstractRNG: Random number generator.
  • model: The target LogDensityProblem.
source

Performing a Single Transition

For more fined-grained control, the user can call AbstractMCMC.step. That is, the chain can be initialized by calling:

transition, state = AbstractMCMC.steps([rng,] model, slice; initial_params)

and then each MCMC transition on state can be performed by calling:

transition, state = AbstractMCMC.steps([rng,] model, slice, state)

For more details, refer to the documentation of AbstractMCMC.