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!Method
pf_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.

source

Updating with a custom proposal

GenParticleFilters.pf_update!Method
pf_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...), where t_old is the old model trace, and produces its own trace t_prop.
  • The old model trace is replaced by a new model trace t_new, constructed by merging the choices in t_old and t_prop, and sampling any remaining choices from the model's default proposal.

The choicemap of t_new satisfies the following conditions:

  1. observations is a subset of get_choices(t_new);
  2. get_choices(t_old) is a subset of get_choices(t_new);
  3. get_choices(t_prop) is a subset of get_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.

source

Updating with custom forward and backward proposals

GenParticleFilters.pf_update!Method
pf_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...), where t_old is the old model trace, and produces its own trace t_fwd.
  • The old model trace is replaced by a new model trace t_new, constructed by merging the choices in t_old and t_fwd, sampling any remaining choices from the model's default proposal, and discarding disc_choices, the choices in t_old inconsistent with those in t_fwd.
  • The probability of disc_choices is assessed under bwd_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:

  1. observations is a subset of get_choices(t_new);
  2. get_choices(t_old) ∖ disc_choices is a subset of get_choices(t_new);
  3. get_choices(t_fwd) is a subset of get_choices(t_new).
  4. disc_choices is within the support of bwd_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.

source

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!Method
pf_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.

source

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!Method
pf_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.

source

For convenience, strata can be generated using the choiceproduct function.