Particle Updating
GenParticleFilters.jl provides numerous methods for updating particles with new observations or input arguments, ranging from simply conditioning on the new observations, to complex SMC moves that allow for the use of auxiliary randomness and deterministic transformations.
Updating with the default proposal
GenParticleFilters.pf_update!
— Methodpf_update!(state::ParticleFilterState, new_args::Tuple,
argdiffs::Tuple, observations::ChoiceMap)
Perform a particle filter update, where the model arguments are adjusted and new observations are conditioned upon. New latent choices are sampled from the model's default proposal.
Updating with a custom proposal
GenParticleFilters.pf_update!
— Methodpf_update!(state::ParticleFilterState, new_args::Tuple,
argdiffs::Tuple, observations::ChoiceMap,
proposal::GenerativeFunction, proposal_args::Tuple,
[transform::TraceTransformDSLProgram];
check::Bool=true)
Perform a particle filter update, where the model arguments are adjusted and new observations are conditioned upon. New latent choices are sampled from a custom proposal
distribution in conjuction with the model's default proposal. For each particle:
proposal
is evaluated with arguments(t_old, proposal_args...)
, wheret_old
is the old model trace, and produces its own tracet_prop
.- The old model trace is replaced by a new model trace
t_new
, constructed by merging the choices int_old
andt_prop
, and sampling any remaining choices from the model's default proposal.
The choicemap of t_new
satisfies the following conditions:
observations
is a subset ofget_choices(t_new)
;get_choices(t_old)
is a subset ofget_choices(t_new)
;get_choices(t_prop)
is a subset ofget_choices(t_new)
.
where one choicemap a
is a "subset" of another choicemap b
, when all keys that occur in a
also occur in b
, and the values at those addresses are equal. It is an error if no trace t_new
satisfying the above conditions exists in the support of the model (with the new arguments).
If a deterministic trace transform
is also provided, t_prop
is transformed by a deterministic function before its choices are merged with t_old
.
By default, a check
is performed to ensure that no choices are discarded as a result of updating the trace. Setting check = false
allows for updates where previous observations are replaced with new ones.
Updating with custom forward and backward proposals
GenParticleFilters.pf_update!
— Methodpf_update!(state::ParticleFilterState, new_args::Tuple,
argdiffs::Tuple, observations::ChoiceMap,
fwd_proposal::GenerativeFunction, fwd_args::Tuple,
bwd_proposal::GenerativeFunction, bwd_args::Tuple,
[transform::TraceTransformDSLProgram];
check::Bool=false, prev_observations=EmptyChoiceMap())
Perform a particle filter update, with a custom forward and backward kernel. New latent choices are sampled from fwd_proposal
, and any discarded choices are evaluated under bwd_proposal
. For each particle:
fwd_proposal
is evaluated with arguments(t_old, fwd_args...)
, wheret_old
is the old model trace, and produces its own tracet_fwd
.- The old model trace is replaced by a new model trace
t_new
, constructed by merging the choices int_old
andt_fwd
, sampling any remaining choices from the model's default proposal, and discardingdisc_choices
, the choices int_old
inconsistent with those int_fwd
. - The probability of
disc_choices
is assessed underbwd_proposal
with the arguments(t_new, bwd_args)
, giving a backward weight. This weight is used as a correction within the importance weight update, ensuring that the particle filter remains a valid approximation of the posterior.
The choicemap of t_new
and disc_choices
satisfy the following conditions:
observations
is a subset ofget_choices(t_new)
;get_choices(t_old) ∖ disc_choices
is a subset ofget_choices(t_new)
;get_choices(t_fwd)
is a subset ofget_choices(t_new)
.disc_choices
is within the support ofbwd_proposal
For valid posterior inference conditioned on prior observations, note that fwd_proposal
should not cause any of those observations to be discarded, (i.e., disc_choices
should not contain any observations
given in previous calls to pf_update!
).
If a trace transform
is also provided, then more general forward and backward kernels can be used: t_new
(the model's new trace) and t_bwd
(the trace for the backward kernel) are constructed as a function of t_old
, t_fwd
, and any new observations
. The check
and prev_observations
keyword arguments can also be set to true
to check for correctness. (See UpdatingTraceTranslator
for more details.)
Similar functionality is provided by move_reweight
, except that pf_update!
also allows model arguments to be updated.
Updating with a trace translator
Trace translators can be used to update particles in a highly general fashion, including the translation of traces from one generative function into traces of a different generative function.
GenParticleFilters.pf_update!
— Methodpf_update!(state::ParticleFilterState, translator; translator_args...)
Perform a particle filter update using an arbitrary trace translator
, which takes in each previous trace and returns a new trace and incremental log. importance weight. translator_args
are additional keyword arguments which are passed to the translator
when it is called.
Updating with stratified sampling
All of the above methods can also be combined with stratified sampling. This can be used to ensure deterministic coverage of the sample space of newly introduced random variables, thereby reducing variance.
GenParticleFilters.pf_update!
— Methodpf_update!(state::ParticleFilterState, new_args::Tuple,
argdiffs::Tuple, observations::ChoiceMap, strata,
[fwd_proposal::GenerativeFunction, fwd_args::Tuple,
bwd_proposal::GenerativeFunction, bwd_args::Tuple,
transform::TraceTransformDSLProgram];
layout=:interleaved, kwargs...)
pf_update!(state::ParticleFilterState, translator::TraceTranslator, strata;
layout=:interleaved, translator_args...)
Perform a stratified particle filter update, given a set of strata
specified as an iterator over choicemaps. Each generated trace is constrained to both the provided observations
and the choicemap for the stratum it belongs to. Forward proposals, backward proposals, trace transforms, or trace translators can also be specified, as in the non-stratified versions of pf_update!
.
For a filter with N
particles and K
strata, each stratum is assigned at least B = ⌊N / K⌋
particles. If layout
is :contiguous
, these particles will be assigned in contiguous blocks (e.g., the particles for the first stratum will have indices 1:B
). If layout
is :interleaved
, then particles from each stratum will have interleaved indices (e.g., the first stratum will have indices 1:K:B*K
). The remaining R
particles are distributed at random among the strata, and allocated the indices N-R:N
.
By default the layout
is :interleaved
, as this allows for convenient sub-stratification of the contiguous blocks allocated to each stratum when performing stratified initialization with pf_initialize
.
For convenience, strata can be generated using the choiceproduct
function.