Compositional probabilistic inference algorithms.
Every method runs a probabilistic program as a savepoint handler: SMC
(foerster.smc) for the particle methods — smc-infer,
importance-sampling, pimh-infer, pgibbs-infer, pgas-infer, ipmcmc-infer,
bbvi-infer and kernel-infer with a PInferenceKernel — and replay plus
accept over traces (foerster.trace) for the Markov-chain kernels.
Pure inference (:world-policy :fresh, the default) runs in fresh worlds;
:world-policy :fork in canonical forks of the caller's world (see
in-canonical-worlds). Particle measures hold Samples (result, trace,
and a canonical particle's world descriptor).
All functions return Spin<EmpiricalMeasure> for composability; post-processing is measure-centric (query, predict).
Compositional probabilistic inference algorithms. Every method runs a probabilistic program as a savepoint handler: SMC (`foerster.smc`) for the particle methods — smc-infer, importance-sampling, pimh-infer, pgibbs-infer, pgas-infer, ipmcmc-infer, bbvi-infer and kernel-infer with a PInferenceKernel — and replay plus accept over traces (`foerster.trace`) for the Markov-chain kernels. Pure inference (`:world-policy :fresh`, the default) runs in fresh worlds; `:world-policy :fork` in canonical forks of the caller's world (see `in-canonical-worlds`). Particle measures hold `Sample`s (result, trace, and a canonical particle's world descriptor). All functions return Spin<EmpiricalMeasure> for composability; post-processing is measure-centric (query, predict).
(bbvi-infer model-task num-particles num-iterations & [opts])Black Box Variational Inference (Ranganath et al., AISTATS 2014).
Learns a mean-field q(z) = Π_addr q_addr by stochastic ascent on the ELBO
with the score-function estimator and control variates: num-iterations
updates, each from num-particles programs that sample latents from q
and weight by p(x, y)/q(x). Each site's q starts as the prior it has when
first reached and from then on moves by gradient only: mean-field, it
does not follow a prior that depends on other latents.
Args: model-task, num-particles, num-iterations opts: :base-lr (1.0) — step size at iteration t is base-lr / (t+1)^robbins-monro :robbins-monro (0.0) :adagrad (true) — true: AdaGrad, γ ∈ (0,1): RMSprop with decay γ, false: plain steps :executor
Returns: Spin<EmpiricalMeasure> — num-particles importance-weighted
samples from the final q (with 0 iterations: from the priors); the learned
q is under :variational-dists (see get-variational-dists).
Black Box Variational Inference (Ranganath et al., AISTATS 2014).
Learns a mean-field q(z) = Π_addr q_addr by stochastic ascent on the ELBO
with the score-function estimator and control variates: `num-iterations`
updates, each from `num-particles` programs that sample latents from q
and weight by p(x, y)/q(x). Each site's q starts as the prior it has when
first reached and from then on moves by gradient only: mean-field, it
does not follow a prior that depends on other latents.
Args:
model-task, num-particles, num-iterations
opts: :base-lr (1.0) — step size at iteration t is
base-lr / (t+1)^robbins-monro
:robbins-monro (0.0)
:adagrad (true) — true: AdaGrad, γ ∈ (0,1): RMSprop with decay γ,
false: plain steps
:executor
Returns: Spin<EmpiricalMeasure> — `num-particles` importance-weighted
samples from the final q (with 0 iterations: from the priors); the learned
q is under `:variational-dists` (see `get-variational-dists`).(conditional model opts)Nested inference: a spin resolving the posterior of model's value under
opts (as for infer) as a distribution — a categorical over the values
the inner inference found, weighted (Anglican's conditional). The outer
program samples from it, or observes against it:
(let [guess (await (infer/conditional (inner-model x) {:method :enumerate}))] (sample guess :id :their-guess))
The inner inference runs in fresh worlds of its own. Under exact
enumeration the distribution is exact; otherwise it is the inner measure,
so it has as many atoms as distinct values. Memoize it (process/mem) when
the outer program asks the same question repeatedly.
Nested inference: a spin resolving the posterior of `model`'s value under
`opts` (as for `infer`) as a distribution — a categorical over the values
the inner inference found, weighted (Anglican's `conditional`). The outer
program samples from it, or observes against it:
(let [guess (await (infer/conditional (inner-model x) {:method :enumerate}))]
(sample guess :id :their-guess))
The inner inference runs in fresh worlds of its own. Under exact
enumeration the distribution is exact; otherwise it is the inner measure,
so it has as many atoms as distinct values. Memoize it (`process/mem`) when
the outer program asks the same question repeatedly.(get-variational-dists measure)The learned {address -> distribution} of a bbvi-infer result.
The learned {address -> distribution} of a `bbvi-infer` result.
(importance-sampling model-task num-samples & [opts])Importance sampling: num-samples runs of model-task, each weighted by
its observations, never resampled (savepoint SMC with
:resample-threshold 0). Options and result as for smc-infer.
Importance sampling: `num-samples` runs of `model-task`, each weighted by its observations, never resampled (savepoint SMC with `:resample-threshold` 0). Options and result as for `smc-infer`.
(infer model
{:keys [method particles iterations chains burn step-size kernel]
:as opts})Run model under the inference method (:method opts) — one call shape
for every method, as Anglican's doquery:
(infer/infer (model) {:method :smc :particles 1000}) (infer/infer (model) {:method :mh :iterations 4000 :chains 4 :burn 1000}) (infer/infer (model) {:method :pmmh :particles 100 :iterations 2000 :params #{:drift}})
Methods and their sizes:
:enumerate (exact; finite supports only,
:max-branches)
:importance :smc :tempered :particles
:pimh :pgibbs :pgas :ipmcmc :bbvi :particles :iterations
:mh :rmh :nuts :iterations per chain, :chains (default
4), :burn, :step-size (:rmh); every
draw after :burn is kept; :nuts adapts
during :burn (block sites)
:kernel :kernel (a foerster.kernel kernel)
and :chains or :particles
:pmmh :particles per SMC, :iterations,
:params (and smc2/pmmh options)
The other options go to the method (see its function). Returns a spin
resolving the measure.
Run `model` under the inference method `(:method opts)` — one call shape
for every method, as Anglican's `doquery`:
(infer/infer (model) {:method :smc :particles 1000})
(infer/infer (model) {:method :mh :iterations 4000 :chains 4 :burn 1000})
(infer/infer (model) {:method :pmmh :particles 100 :iterations 2000
:params #{:drift}})
Methods and their sizes:
:enumerate (exact; finite supports only,
:max-branches)
:importance :smc :tempered :particles
:pimh :pgibbs :pgas :ipmcmc :bbvi :particles :iterations
:mh :rmh :nuts :iterations per chain, :chains (default
4), :burn, :step-size (:rmh); every
draw after :burn is kept; :nuts adapts
during :burn (block sites)
:kernel :kernel (a `foerster.kernel` kernel)
and :chains or :particles
:pmmh :particles per SMC, :iterations,
:params (and `smc2/pmmh` options)
The other options go to the method (see its function). Returns a spin
resolving the measure.(ipmcmc-infer model-task num-particles num-iterations & [opts])Interacting Particle MCMC inference.
Runs M nodes in parallel, where M_c nodes run conditional SMC (with retained particles) and M_s nodes run plain SMC. After each sweep, performs Gibbs updates on which nodes become CSMC based on marginal likelihood estimates.
This creates 'interaction' between parallel chains: nodes with higher log-Z are more likely to have their particles retained in future sweeps.
Algorithm:
Args: model-task - Spin representing probabilistic program num-particles - Number of particles per sweep (per node) num-iterations - Number of IPMCMC iterations opts - Optional map with: :num-nodes - Total number of nodes (default 8) :num-csmc-nodes - Number of CSMC nodes (default num-nodes/2) :executor - Shared executor :all-particles? - Return all particles or one per node (default true)
Returns: Spin<EmpiricalMeasure>
Reference: Rainforth et al., 'Interacting Particle Markov Chain Monte Carlo', ICML 2016
Interacting Particle MCMC inference.
Runs M nodes in parallel, where M_c nodes run conditional SMC (with retained
particles) and M_s nodes run plain SMC. After each sweep, performs Gibbs
updates on which nodes become CSMC based on marginal likelihood estimates.
This creates 'interaction' between parallel chains: nodes with higher log-Z
are more likely to have their particles retained in future sweeps.
Algorithm:
1. Initialize: Run SMC on all nodes
2. For each iteration:
a. Run CSMC on M_c nodes (with retained particles from previous sweep)
b. Run SMC on M_s nodes (fresh)
c. Collect log-Z estimates from each node
d. Gibbs update: sample which nodes become CSMC for next sweep
e. Extract retained particles for selected CSMC nodes
3. Output: Weighted samples from all nodes with Rao-Blackwellized weights
Args:
model-task - Spin representing probabilistic program
num-particles - Number of particles per sweep (per node)
num-iterations - Number of IPMCMC iterations
opts - Optional map with:
:num-nodes - Total number of nodes (default 8)
:num-csmc-nodes - Number of CSMC nodes (default num-nodes/2)
:executor - Shared executor
:all-particles? - Return all particles or one per node (default true)
Returns: Spin<EmpiricalMeasure>
Reference:
Rainforth et al., 'Interacting Particle Markov Chain Monte Carlo', ICML 2016(kernel-infer model-task kernel num-particles & [opts])Run inference with a kernel.
Markov-chain kernels (single-site-mh-kernel, random-walk-mh-kernel,
block-gibbs-kernel, hmc-kernel) run num-particles independent chains.
Any other PInferenceKernel runs savepoint SMC whose latent sites take the
value the kernel's step gives (the prior kernel: a draw from the prior).
Args:
Returns: Spin<EmpiricalMeasure>
Examples: ;; Importance sampling with prior kernel (spin (let [model (coin-flip-model) measure (await (kernel-infer model (prior-kernel) 100 {:barrier-policy :none}))] (query measure identity)))
Run inference with a kernel.
Markov-chain kernels (`single-site-mh-kernel`, `random-walk-mh-kernel`,
`block-gibbs-kernel`, `hmc-kernel`) run `num-particles` independent chains.
Any other PInferenceKernel runs savepoint SMC whose latent sites take the
value the kernel's `step` gives (the prior kernel: a draw from the prior).
Args:
- model-task: Spin (from model function) - Probabilistic program to infer
- kernel: a kernel (e.g., prior-kernel, single-site-mh-kernel)
- num-particles: Number of particles (chains)
- opts: Optional map with:
- :barrier-policy - :every-observe (default, SMC) | :none (importance
sampling)
- :resample-threshold - ESS threshold (default 0.5)
- :executor - Shared executor for all particles
- :world-policy - :fresh (default) for pure inference, or :fork to
execute each particle in a frozen canonical Yggdrasil world that is
discarded after the final particle values are captured
- :world-opts - Optional :systems/:rights/:snapshots policy forwarded to
canonical particle forks; lifecycle fields are owned by inference
Returns: Spin<EmpiricalMeasure>
Examples:
;; Importance sampling with prior kernel
(spin
(let [model (coin-flip-model)
measure (await (kernel-infer model (prior-kernel) 100
{:barrier-policy :none}))]
(query measure identity)))(pgas-infer model-task num-particles num-iterations & [opts])Particle Gibbs with Ancestor Sampling (Lindsten et al. 2014).
Like pgibbs-infer, but at every barrier the retained particle redraws
which particle's past it continues from, with weights
w_i · p(retained future | particle i's past) computed by re-running each
particle's future on the retained values. Improves mixing on state-space
models; costs a forward re-run per particle per barrier.
Returns: Spin<EmpiricalMeasure> of every sweep's particles, each sweep normalized to total weight one.
Particle Gibbs with Ancestor Sampling (Lindsten et al. 2014). Like `pgibbs-infer`, but at every barrier the retained particle redraws which particle's past it continues from, with weights w_i · p(retained future | particle i's past) computed by re-running each particle's future on the retained values. Improves mixing on state-space models; costs a forward re-run per particle per barrier. Returns: Spin<EmpiricalMeasure> of every sweep's particles, each sweep normalized to total weight one.
(pgibbs-infer model-task num-particles num-iterations & [opts])Particle Gibbs (conditional SMC, Andrieu et al. 2010).
Args: model-task, num-particles (per sweep, including the retained one), num-iterations (sweeps) opts: :executor
Returns: Spin<EmpiricalMeasure> of every sweep's particles, each sweep normalized to total weight one.
Particle Gibbs (conditional SMC, Andrieu et al. 2010). Args: model-task, num-particles (per sweep, including the retained one), num-iterations (sweeps) opts: :executor Returns: Spin<EmpiricalMeasure> of every sweep's particles, each sweep normalized to total weight one.
(pimh-infer model-task num-particles num-iterations & [opts])Particle Independent Metropolis-Hastings (Andrieu et al. 2010).
Each iteration proposes a fresh SMC sweep and accepts it with probability min(1, Ẑ_new / Ẑ_current); the current sweep's particles, normalized, are emitted every iteration.
Args: model-task, num-particles (per sweep), num-iterations opts: :executor, :resample-threshold
Returns: Spin<EmpiricalMeasure>
Particle Independent Metropolis-Hastings (Andrieu et al. 2010). Each iteration proposes a fresh SMC sweep and accepts it with probability min(1, Ẑ_new / Ẑ_current); the current sweep's particles, normalized, are emitted every iteration. Args: model-task, num-particles (per sweep), num-iterations opts: :executor, :resample-threshold Returns: Spin<EmpiricalMeasure>
(predict measure pred-fn num-samples)num-samples draws from measure, resampled by weight, each passed to
pred-fn — which gets the particle (a Sample, or a context), so
m/get-value reads its program value and m/get-trace its trace.
`num-samples` draws from `measure`, resampled by weight, each passed to `pred-fn` — which gets the particle (a `Sample`, or a context), so `m/get-value` reads its program value and `m/get-trace` its trace.
(predictive model measure n & [{:keys [interventions]}])n posterior predictive draws: particles of measure drawn by weight,
each replayed through model with its latent choices held and its
observed sites drawing fresh values instead of scoring the data. A prior
predictive draw is the same with model simply run (gfi/simulate).
model need not be the program that was conditioned: the same program on
new inputs (more weeks, other covariates) predicts them, its latent sites
held where the posterior has them and drawn from their prior where it
does not (a new group's effect). :interventions ({selector transform},
as foerster.trace/policy takes them) sets sites by the do-operator
first — a scenario under the posterior.
Returns a spin resolving a vector of {:value v :observations {address x}}: the program's value and what each observed site drew.
`n` posterior predictive draws: particles of `measure` drawn by weight,
each replayed through `model` with its latent choices held and its
observed sites drawing fresh values instead of scoring the data. A prior
predictive draw is the same with `model` simply run (`gfi/simulate`).
`model` need not be the program that was conditioned: the same program on
new inputs (more weeks, other covariates) predicts them, its latent sites
held where the posterior has them and drawn from their prior where it
does not (a new group's effect). `:interventions` ({selector transform},
as `foerster.trace/policy` takes them) sets sites by the do-operator
first — a scenario under the posterior.
Returns a spin resolving a vector of {:value v :observations {address x}}:
the program's value and what each observed site drew.(query measure query-fn)Weighted statistics of a numeric function of the program's value over
measure: query-fn is identity (the value itself), a keyword (a field
of a map value) or a function of the value.
Returns {:mean :variance :std-dev :quantiles :samples :weights :type};
:samples and :weights are the particles' values and normalized
weights.
Weighted statistics of a numeric function of the program's value over
`measure`: `query-fn` is `identity` (the value itself), a keyword (a field
of a map value) or a function of the value.
Returns {:mean :variance :std-dev :quantiles :samples :weights :type};
`:samples` and `:weights` are the particles' values and normalized
weights.(smc-infer model-task num-particles & [opts])Sequential Monte Carlo: num-particles particles run model-task (a
spin); at every observation the population is resampled when its
effective sample size falls below :resample-threshold·N. Runs on
savepoints (foerster.smc/smc); the measure holds Samples, and its
m/log-marginal estimates the evidence.
Options:
:resample-threshold ESS fraction below which to resample (default 0.5)
:world-policy :fresh (default): fresh worlds; :fork: canonical
forks of the caller's world (doc/worlds.md)
:world-opts fork options for :fork (:systems, :rights, :snapshots)
:authority, :grant a world.scope/PResourceAuthority and the budget the
inference draws from the caller's wallet (:fork)
:executor the executor the worlds run on (default: spindel's)
:policy a foerster.trace/policy deciding the sites
(constraints, interventions, proposals)
:anchors, :rejuvenate resample-move: after each resampling, MH moves
from anchored sites (foerster.smc/smc; :fresh only)
Returns a spin resolving the EmpiricalMeasure.
(sp/with-context world @(smc-infer (model) 1000)) ; at the REPL (spin (query (await (smc-infer (model) 1000)) identity))
Sequential Monte Carlo: `num-particles` particles run `model-task` (a
spin); at every observation the population is resampled when its
effective sample size falls below `:resample-threshold`·N. Runs on
savepoints (`foerster.smc/smc`); the measure holds `Sample`s, and its
`m/log-marginal` estimates the evidence.
Options:
:resample-threshold ESS fraction below which to resample (default 0.5)
:world-policy :fresh (default): fresh worlds; :fork: canonical
forks of the caller's world (doc/worlds.md)
:world-opts fork options for :fork (:systems, :rights, :snapshots)
:authority, :grant a world.scope/PResourceAuthority and the budget the
inference draws from the caller's wallet (:fork)
:executor the executor the worlds run on (default: spindel's)
:policy a `foerster.trace/policy` deciding the sites
(constraints, interventions, proposals)
:anchors, :rejuvenate resample-move: after each resampling, MH moves
from anchored sites (`foerster.smc/smc`; :fresh only)
Returns a spin resolving the EmpiricalMeasure.
(sp/with-context world @(smc-infer (model) 1000)) ; at the REPL
(spin (query (await (smc-infer (model) 1000)) identity))(tempered-infer model-task num-particles & [opts])Tempered SMC (foerster.tempering): num-particles complete runs of
model-task, moved from the prior to the posterior through the targets
p(x)·L(x)^β with an adaptive schedule of β. Explores posteriors whose
modes a Markov chain cannot cross, and estimates the evidence.
Options: :ess-target (0.5), :moves (single-site MH moves per particle
per step; default a sweep), :scale (2.38), :waste-free P, :max-steps,
:executor; fresh worlds only.
Returns a spin resolving the EmpiricalMeasure; :temperatures holds the
schedule.
Tempered SMC (`foerster.tempering`): `num-particles` complete runs of `model-task`, moved from the prior to the posterior through the targets p(x)·L(x)^β with an adaptive schedule of β. Explores posteriors whose modes a Markov chain cannot cross, and estimates the evidence. Options: `:ess-target` (0.5), `:moves` (single-site MH moves per particle per step; default a sweep), `:scale` (2.38), `:waste-free` P, `:max-steps`, `:executor`; fresh worlds only. Returns a spin resolving the EmpiricalMeasure; `:temperatures` holds the schedule.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |