Slice Sampling
SliceSampling.jl provides a family of derivative-free slice samplers. Once using SliceSampling, they can sample any compiled BUGSModel, so you get gradient-free inference without configuring an AD backend. This is handy for models with awkward geometry, non-differentiable pieces, or as a robust component sampler inside JuliaBUGS.Gibbs.
Slice samplers are used two ways:
- Standalone — pass a slice sampler to
AbstractMCMC.sampleto update the whole model. - Inside
JuliaBUGS.Gibbs— assign a slice sampler to one or more variable groups in thesampler_map; JuliaBUGS drives it through the Gibbs sweep.
Setup
using JuliaBUGS
using JuliaBUGS: Gibbs
using SliceSampling
using AbstractMCMC
using MCMCChains
using OrderedCollections: OrderedDict
model_def = @bugs begin
mu ~ dnorm(0, 0.0001)
y ~ dnorm(mu, 1)
end
model = model_def((; y = 1.5))BUGSModel (parameters are in transformed (unconstrained) space, with dimension 1):
Model parameters:
mu
Variable sizes and types:
y: type = Float64
mu: type = Float64
Standalone sampling
Univariate slice samplers such as SliceSteppingOut and SliceDoublingOut update one coordinate at a time. On a single-parameter model you can pass one directly:
chain = AbstractMCMC.sample(
model,
SliceSteppingOut(1.0), # 1.0 is the initial slice window width
500;
chain_type = Chains,
progress = false,
)
summarystats(chain)Summary Statistics
parameters mean std mcse ess_bulk ess_tail rhat e ⋯
Symbol Float64 Float64 Float64 Real Float64 Float64 ⋯
mu 1.2611 1.9714 0.1312 426.3167 235.6800 1.0023 ⋯
1 column omitted
No initial_params is required: the extension implements SliceSampling.initial_sample, which seeds the sampler from the model's current parameter values.
For a model with more than one parameter, wrap a univariate sampler in a multivariate strategy (e.g. RandPermGibbs, which cycles through coordinates in a random order), or use a genuinely multivariate slice sampler:
multi_def = @bugs begin
a ~ dnorm(0, 1)
b ~ dnorm(0, 1)
y ~ dnorm(a + b, 1)
end
multi_model = multi_def((; y = 0.5))
multi_chain = AbstractMCMC.sample(
multi_model,
RandPermGibbs(SliceSteppingOut(1.0)),
500;
chain_type = Chains,
progress = false,
)
summarystats(multi_chain)Summary Statistics
parameters mean std mcse ess_bulk ess_tail rhat e ⋯
Symbol Float64 Float64 Float64 Real Float64 Float64 ⋯
b 0.2249 0.8074 0.0571 202.1302 245.3813 0.9994 ⋯
a 0.1198 0.8243 0.0531 241.1146 262.6275 1.0062 ⋯
1 column omitted
Inside Gibbs
Because each single-site conditional in JuliaBUGS.Gibbs is univariate, a bare univariate slice sampler works per site — no multivariate wrapper needed. Map variable groups to samplers in an OrderedDict:
sampler_map = OrderedDict(
@varname(a) => SliceSteppingOut(1.0),
@varname(b) => SliceSteppingOut(1.0),
)
gibbs = Gibbs(multi_model, sampler_map)
gibbs_chain = AbstractMCMC.sample(
multi_model,
gibbs,
500;
chain_type = Chains,
progress = false,
)
summarystats(gibbs_chain)Summary Statistics
parameters mean std mcse ess_bulk ess_tail rhat e ⋯
Symbol Float64 Float64 Float64 Real Float64 Float64 ⋯
b 0.0753 0.7751 0.0490 249.9038 296.7838 1.0012 ⋯
a 0.2623 0.7823 0.0463 285.6554 216.9296 0.9983 ⋯
1 column omitted
Slice samplers can be freely mixed with HMC and AdvancedMH samplers in the same sampler_map. They update continuous blocks. Gibbs updates finite discrete blocks exactly by enumerating and normalizing their full conditional, without invoking SliceSampling or AdvancedMH.
Output formats and statistics
Both chain backends are supported:
chain_type = Chainsreturns anMCMCChains.Chains(shown above).chain_type = VNChainreturns aFlexiChains.FlexiChainkeyed byVarName(requiresusing FlexiChains):
using FlexiChains
chain = AbstractMCMC.sample(model, SliceSteppingOut(1.0), 500; chain_type = VNChain, progress = false)In either case the sampler's own statistics are recorded alongside the draws: the log density lp and num_proposals (the number of proposals the slice sampler evaluated per step). Under MCMCChains these appear as internals; under FlexiChains they are FlexiChains.Extra entries. For a multivariate sampler the per-coordinate num_proposals is flattened into num_proposals[i] columns for MCMCChains.