Inference Syntax Reference¶
Introduction¶
The VentureScript inference language is the language in which the toplevel VentureScript program is written. It is actually the same language as the VentureScript modeling language, except with several additional predefined procedures and special forms.
VentureScript inference programs are effectively evaluated in a context where the underlying model trace is available as a reified object, on which built-in inference procedures can operate. [1]
Block Structure¶
Like JavaScript, the organizing syntactic element of VentureScript is the block: a list of statements surrounded by curly braces and separated by parentheses. VentureScript has the following kinds of statements:
-
let <var> = <expression>;
Bind the variable on the left hand side to the value of the expression on the right hand side for the remainder of the block.
Note 1: This is not assignment: if the variable was already in scope, it is shadowed, not mutated; at the end of the block, the old value will be visible again.
Note 2: If the expression produces an inference action, that action is not performed, but stored in the variable for later use. See
<-
.
-
<var> <- <action>;
Perform the inference action on the right hand side and bind the returned value to the variable on the left hand side.
Note 1: This is not assignment: if the variable was already in scope, it is shadowed, not mutated; at the end of the block, the old value will be visible again.
Note 2: It is an error for the expression to produce a value that is not an inference action. For binding the results of pure computations, see
let
.
-
let (<var1>, <var2>, ...) = <expression>;
Multiple value bind. The expression must return a list of
ref
s of the same length as the number of variables. See alsovalues_list
.
-
letrec <var1> = <expression1>;
-
and <var2> = <expression2>;
-
...
Mutually recursive binding. The contiguous chain of
and
statements are grouped together with theletrec
statement at the beginning, and all the variables are in scope in all the defining expressions and the rest of the block, analogously to the same construct in Scheme. The name stands for “let, recursively”. This is useful for defining mutually recursive procedures:letrec even = (n) -> { if (n == 0) { true } else { odd(n - 1) } }; and odd = (n) -> { if (n == 0) { false } else { even(n - 1) } };
-
<action>
Just evaluate the expression. If this is the last statement of the block, the return value of the whole block is the result of evaluating the expression.
Note that all of these affordances appear as expressions as well. In fact, the block structure in VentureScript is just syntactic sugar for nested binding expressions of various kinds.
Inference control with tags and subproblems¶
VentureScript permits the user to control the strategy and focus of
inference activity with the notion of the subproblem. Any set of
random choices in a VentureScript model defines a local subproblem
,
which is the problem of sampling from the posterior on those choices,
conditioned on keeping the rest of the execution history fixed.
Subproblem decomposition is useful because progress in distribution on
a subproblem constitutes progress on the overall problem as well.
It is typical to prepare a model for inference control by tagging some expressions with tags that can later be referenced when selecting a subproblem to operate on. VentureScript provides syntactic sugar for tagging model expressions:
something #tag1
something_else #tag2:value
The first form just associates the something
expression with the tag
named tag1
. The second form associates the something_else
expression with the tag named tag2
with the value computed by the
value
expression.
For example, a typical simple Dirichlet process mixture model (over Bernoulli vectors) might be implemented and tagged like this:
assume assign = make_crp(1);
assume z = mem((i) ~> { assign() #clustering }); // The partition induced by the DP
assume pct = mem((d) ~> { gamma(1.0, 1.0) #hyper:d }); // Per-dimension hyper prior
assume theta = mem((z, d) ~> { beta(pct(d), pct(d)) #compt:d }); // Per-component latent
assume datum = mem((i, d) ~> {{
cmpt ~ z(i);
weight ~ theta(cmpt, d);
flip(weight)} #row:i #col:d }); // Per-datapoint random choices
VentureScript provides a path-like syntax for identifying random
choices in a model on which inference might then be applied. The /
(forward slash) operator is analogous to a UNIX directory separator:
it means “apply the pattern on the right to subchoices of the choices
selected on the left” (and a leading /
means “search for the
choices on right in the whole model”). By “subchoices” I mean the choices
made in the dynamic extent of evaluating that one. For example:
/?hyper // select all choices tagged with the "hyper" tag
/?row==3 // select all choices involved in the third row
/?row==3/?clustering // select only the cluster assignment for the third row
Random choice selections can also be computed programmatically with
the procedures beginning with by_
, below.
A complete subproblem definition includes not only the random choices
of interest, but also additional information, such as how to treat
which of their consequences (likelihood-free choices have to be
resampled, choices that can report likelihoods may be resampled or may
be kept, contributing to the acceptance ratio, etc). VentureScript
currently provides one operation to convert a selection of random
choices into a subproblem, namely minimal_subproblem
. That
subproblem may then be passed to an inference operation like resimulation_mh
to
actually operate on those choices.
Randomized proposal targets may be obtained with the
random_singleton
procedure, which correctly accounts for the
acceptance correction due to the probability of selecting that
particular subproblem to work on.
Putting it all together, the inference tactic default_markov_chain
might be defined as:
define default_markov_chain = (n) -> {
repeat(n, resimulation_mh(minimal_subproblem(random_singleton(by_extent(by_top())))))}
For compatibility with previous versions of VentureScript, all the
inference operators will also accept a tag and a tag value as two
separate arguments, and treat them as minimal_subproblem(/?<tag>==<value>)
.
Note: The argument lists of the inference operators below come out of Sphinx a bit weird. The intent is that the “tag_value” argument is required if and only if the “subproblem” argument is actually a raw tag, and immediately follows it.
Note 2: The subproblem selection subsystem is not (yet) implemented in the Puma backend. If using Puma, use the tag/value invocation form.
Any given random choice in an execution history can be tagged by an arbitrary number of tags; but for each tag it has, it must be given a unique value (if any). The most locally assigned value wins.
Built-in Procedures for Inference¶
All the procedures available in the modeling language can be used in the inference language, too. In addition, the following inference procedures are available.
-
resimulation_mh
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Run a Metropolis-Hastings kernel, proposing by resimulating the prior.
The
transitions
argument specifies how many transitions of the chain to run.Returns the average number of nodes touched per transition in each particle.
-
mh
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Run a Metropolis-Hastings kernel, proposing by resimulating the prior.
The
transitions
argument specifies how many transitions of the chain to run.Returns the average number of nodes touched per transition in each particle.
-
func_mh
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Like mh, but functional.
To wit, represent the proposal with a new trace (sharing common structure) instead of modifying the existing particle in place.
Up to log factors, there is no asymptotic difference between this and
mh
, but the distinction is exposed for those who know what they are doing.
-
gibbs
(subproblem[, tag_value : object[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Run a Gibbs sampler that computes the local conditional by enumeration.
All the random choices identified by the scope-block pair must be discrete.
The
transitions
argument specifies how many transitions of the chain to run.The
in-parallel
argument, if supplied, toggles parallel evaluation of the local conditional. Parallel evaluation is only available in the Puma backend, and is on by default.Returns the average number of nodes touched per transition in each particle.
-
emap
(subproblem[, tag_value : object[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Deterministically move to the local conditional maximum (computed by enumeration).
All the random choices identified by the scope-block pair must be discrete.
The
transitions
argument specifies how many times to do this. Specifying more than one transition is redundant unless theblock
isone
.The
in-parallel
argument, if supplied, toggles parallel evaluation of the local conditional. Parallel evaluation is only available in the Puma backend, and is on by default.Returns the average number of nodes touched per transition in each particle.
-
func_pgibbs
(subproblem, tag_value : object[, particles : int[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Move to a sample of the local conditional by particle Gibbs.
The
block
must indicate a sequential grouping of the random choices in thescope
. This can be done by supplying the keywordordered
as the block, or the value of callingordered_range
.The
particles
argument specifies how many particles to use in the particle Gibbs filter.The
transitions
argument specifies how many times to do this.The
in-parallel
argument, if supplied, toggles per-particle parallelism. Parallel evaluation is only available in the Puma backend, and is on by default.Returns the average number of nodes touched per transition in each particle.
-
pgibbs
(subproblem, tag_value : object[, particles : int[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Like
func_pgibbs
but reuse a single trace instead of having several.The performance is asymptotically worse in the sequence length, but does not rely on stochastic procedures being able to functionally clone their auxiliary state.
The only reason to use this is if you know you want to.
Returns the average number of nodes touched per transition in each particle.
-
func_pmap
(subproblem, tag_value : object[, particles : int[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Like func_pgibbs, but deterministically select the maximum-likelihood particle at the end instead of sampling.
Iterated applications of func_pmap are guaranteed to grow in likelihood (and therefore do not converge to the conditional).
Returns the average number of nodes touched per transition in each particle.
-
meanfield
(subproblem[, tag_value : object[, training_steps : int[, transitions : int]]])¶ Return type: <inference_action returning <array <number>>> Sample from a mean-field variational approximation of the local conditional.
The mean-field approximation is optimized with gradient ascent. The
training_steps
argument specifies how many steps to take.The
transitions
argument specifies how many times to do this.Note: There is currently no way to save the result of training the variational approximation to be able to sample from it many times.
Returns the average number of nodes touched per transition in each particle.
-
print_scaffold_stats
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Print some statistics about the requested scaffold.
This may be useful as a diagnostic.
The
transitions
argument specifies how many times to do this; this is not redundant if theblock
argument isone
.Returns the average number of nodes touched per transition in each particle.
-
nesterov
(subproblem[, tag_value : object[, step_size : number[, steps : int[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Move deterministically toward the maximum of the local conditional by Nesterov-accelerated gradient ascent.
Not available in the Puma backend. Not all the builtin procedures support all the gradient information necessary for this.
The gradient is of the log conditional.
The presence of discrete random choices in the scope-block pair will not prevent this inference strategy, but none of the discrete choices will be moved by the gradient steps.
The
step_size
argument gives how far to move along the gradient at each point.The
steps
argument gives how many steps to take.The
transitions
argument specifies how many times to do this.Note: the Nesterov acceleration is applied across steps within one transition, not across transitions.
Returns the average number of nodes touched per transition in each particle.
-
gradient_ascent
(subproblem[, tag_value : object[, step_size : number[, steps : int[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Move deterministically toward the maximum of the local conditional by gradient ascent.
Not available in the Puma backend. Not all the builtin procedures support all the gradient information necessary for this.
This is just like
nesterov
, except without the Nesterov correction.Returns the average number of nodes touched per transition in each particle.
-
hmc
(subproblem[, tag_value : object[, step_size : number[, steps : int[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Run a Hamiltonian Monte Carlo transition kernel.
Not available in the Puma backend. Not all the builtin procedures support all the gradient information necessary for this.
The presence of discrete random choices in the scope-block pair will not prevent this inference strategy, but none of the discrete choices will be moved.
The
step_size
argument gives the step size of the integrator used by HMC.The
steps
argument gives how many steps to take in each HMC trajectory.The
transitions
argument specifies how many times to do this.Returns the average number of nodes touched per transition in each particle.
-
rejection
(subproblem[, tag_value : object[, density_bound : maybe number[, attempt_bound : number[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Sample from the local conditional by rejection sampling.
Not available in the Puma backend. Not all the builtin procedures support all the density bound information necessary for this.
The
density_bound
argument, if supplied, indicates the maximum density the requested subproblem could obtain (in log space). If omitted ornil
, Venture will attempt to compute this bound automatically, but this process may be somewhat brittle.The
attempt_bound
argument, if supplied, indicates how many attempts to make. If no sample is accepted after that many trials, stop, and leave the local state as it was. Warning: bounded rejection is not a Bayes-sound inference algorithm. Ifattempt_bound
is not given, keep trying until acceptance (possibly leaving the session unresponsive).Note: Regardless of whether some arguments are omitted, the last optional argument given is taken to be the number of transitions, not the density or attempt bound.
The
transitions
argument specifies how many times to do this. Specifying more than 1 transition is redundant if theblock
is anything other thanone
.Returns the average number of nodes touched per transition in each particle.
-
bogo_possibilize
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Initialize the local inference problem to a possible state.
If the current local likelihood is 0, resimulate the local prior until a non-zero likelihood state is found.
Notes:
If the current state is possible, do nothing.
This is different from rejection sampling because the distribution on results is not the conditional, but the prior conditioned on the likelihood being non-zero. As such, it is likely to complete faster.
This is different from likelihood weighting because a) it keeps trying automatically until it finds a possible state, and b) it does not modify the weight of the particle it is applied to (because if the scope and block are other than
default all
it is not clear what the weight should become).Does not change the particle weight, because the right one is not obvious for general scaffolds, or for the case where the state was possible to begin with. If you’re using
bogo_possibilize(default, all)
for pure initialization from the prior, consider following it with:do(l <- global_log_likelihood, set_particle_log_weights(l))
The
transitions
argument specifies how many times to do this. Specifying more than 1 transition is redundant if theblock
is anything other thanone
.Returns the average number of nodes touched per transition in each particle.
-
log_rejection_bound_at
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Compute an upper bound on the density obtainable in the given subproblem.
This is the same bound that rejection sampling on that subproblem would use as the acceptance criterion.
-
slice
(subproblem[, tag_value : object[, w : number[, m : int[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Slice sample from the local conditonal of the selected random choice.
The scope-block pair must identify a single random choice, which must be continuous and one-dimensional.
This kernel uses the stepping-out procedure to find the slice. The
w
andm
arguments parameterize the slice sampler in the standard way.The
transitions
argument specifies how many transitions of the chain to run.Returns the average number of nodes touched per transition in each particle.
-
slice_doubling
(subproblem[, tag_value : object[, w : number[, p : int[, transitions : int]]]])¶ Return type: <inference_action returning <array <number>>> Slice sample from the local conditional of the selected random choice.
The scope-block pair must identify a single random choice, which must be continuous and one-dimensional.
This kernel uses the interval-doubling procedure to find the slice. The
w
andp
arguments parameterize the slice sampler in the standard way.The
transitions
argument specifies how many transitions of the chain to run.Returns the average number of nodes touched per transition in each particle.
-
resample
(particles : int)¶ Return type: <inference_action returning ()> Perform an SMC-style resampling step.
The
particles
argument gives the number of particles to make. Subsequent modeling and inference commands will be applied to each result particle independently.Future observations will have the effect of weighting the particles relative to each other by the relative likelihoods of observing those values in those particles. The resampling step respects those weights.
The new particles will be handled in series. See the next procedures for alternatives.
-
resample_multiprocess
(particles : int[, max_processes : int])¶ Return type: <inference_action returning ()> Like
resample
, but fork multiple OS processes to simulate the resulting particles in parallel.The
max_processes
argument, if supplied, puts a cap on the number of processes to make. The particles are distributed evenly among the processes. If no cap is given, fork one process per particle.Subtlety: Collecting results (and especially performing further resampling steps) requires inter-process communication, and therefore requires serializing and deserializing any state that needs transmitting.
resample_multiprocess
is therefore not a drop-in replacement forresample
, as the former will handle internal states that cannot be serialized, whereas the latter will not.
-
resample_serializing
(particles : int)¶ Return type: <inference_action returning ()> Like
resample
, but performs serialization the same wayresample_multiprocess
does.Use this to debug serialization problems without messing with actually spawning multiple processes.
-
resample_threaded
(particles : int)¶ Return type: <inference_action returning ()> Like
resample_multiprocess
but uses threads rather than actual processes, and does not serialize, transmitting objects in shared memory instead.Python’s global interpreter lock is likely to prevent any speed gains this might have produced.
Might be useful for debugging concurrency problems without messing with serialization and multiprocessing, but we expect such problems to be rare.
-
resample_thread_ser
(particles : int)¶ Return type: <inference_action returning ()> Like
resample_threaded
, but serializes the same wayresample_multiprocess
does.Python’s global interpreter lock is likely to prevent any speed gains this might have produced.
Might be useful for debugging concurrency+serialization problems without messing with actual multiprocessing, but then one is messing with multithreading.
-
likelihood_weight
()¶ Return type: <inference_action returning ()> Likelihood-weight the full particle set.
Resample all particles in the current set from the prior and reset their weights to the likelihood.
-
enumerative_diversify
(scope : object, block : object)¶ Return type: <inference_action returning ()> Diversify the current particle set to represent the local conditional exactly.
Specifically:
- Compute the local conditional by enumeration of all possible values in the given scope and block
- Fork every extant particle as many times are there are values
- Give each new particle a relative weight proportional to the relative weight of its ancestor particle times the conditional probability of the chosen value.
Unlike most inference SPs, this transformation is deterministic.
This is useful together with
collapse_equal
andcollapse_equal_map
for implementing certain kinds of dynamic programs in Venture.
-
collapse_equal
(scope : object, block : object)¶ Return type: <inference_action returning ()> Collapse the current particle set to represent the local conditional less redundantly.
Specifically:
- Bin all extant particles by the (joint) values they exhibit on all random variables in the given scope and block (specify a block of “none” to have one bin)
- Resample by relative weight within each bin, retaining one particle
- Set the relative weight of the retained particle to the sum of the weights of the particles that formed the bin
Viewed as an operation on only the random variables in the given scope and block, this is deterministic (the randomness only affects other values).
This is useful together with
enumerative_diversify
for implementing certain kinds of dynamic programs in Venture.
-
collapse_equal_map
(scope : object, block : object)¶ Return type: <inference_action returning ()> Like
collapse_equal
but deterministically retain the max-weight particle.And leave its weight unaltered, instead of adding in the weights of all the other particles in the bin.
-
checkInvariants
()¶ Return type: <inference_action returning ()> Run a trace self-check looking for contract violations in derived data fields.
O(#nodes).
-
draw_scaffold
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Draw a visual representation of the scaffold indicated by the given scope and block.
This is useful for debugging. The transition count is ignored.
Returns the number of nodes in the drawing.
-
subsampled_mh
(subproblem[, tag_value : object[, Nbatch : int[, k0 : int[, epsilon : number[, useDeltaKernels : bool[, deltaKernelArgs : number[, updateValues : bool[, transitions : int]]]]]]]])¶ Return type: <inference_action returning <array <number>>> Run a subsampled Metropolis-Hastings kernel
per the Austerity MCMC paper.
Note: not all dependency structures that might occur in a scaffold are supported. See
subsampled_mh_check_applicability
.Note: the resulting execution history may not actually be possible, so may confuse other transition kernels. See
subsampled_mh_make_consistent
and*_update
.Returns the average number of nodes touched per transition in each particle.
-
subsampled_mh_check_applicability
(subproblem[, tag_value : object[, transitions : int]])¶ Return type: <inference_action returning <array <number>>> Raise a warning if the given scope and block obviously do not admit subsampled MH
From the source:
# Raise three types of warnings: # - SubsampledScaffoldNotEffectiveWarning: calling subsampled_mh will be the # same as calling mh. # - SubsampledScaffoldNotApplicableWarning: calling subsampled_mh will cause # incorrect behavior. # - SubsampledScaffoldStaleNodesWarning: stale node will affect the # inference of other random variables. This is not a critical # problem but requires one to call makeConsistent before other # random nodes are selected as principal nodes. # # This method cannot check all potential problems caused by stale nodes.
-
subsampled_mh_make_consistent
(subproblem[, tag_value : object[, useDeltaKernels : bool[, deltaKernelArgs : number[, updateValues : bool[, transitions : int]]]]])¶ Return type: <inference_action returning <array <number>>> Fix inconsistencies introduced by subsampled MH.
Returns the number of nodes touched.
-
mh_kernel_update
(subproblem[, tag_value : object[, useDeltaKernels : bool[, deltaKernelArgs : number[, updateValues : bool[, transitions : int]]]]])¶ Return type: <inference_action returning <array <number>>> Run a normal
mh
kernel, tolerating inconsistencies introduced by previous subsampled MH.Returns the average number of nodes touched per transition in each particle.
-
gibbs_update
(subproblem[, tag_value : object[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Run a normal
gibbs
kernel, tolerating inconsistencies introduced by previous subsampled MH.Returns the average number of nodes touched per transition in each particle.
-
pgibbs_update
(subproblem, tag_value : object[, particles : int[, transitions : int[, in_parallel : bool]]])¶ Return type: <inference_action returning ()> Run a normal
pgibbs
kernel, tolerating inconsistencies introduced by previous subsampled MH.Returns the average number of nodes touched per transition in each particle.
-
incorporate
()¶ Return type: <inference_action returning ()> Explicitly make the history consistent with observations.
Specifically, modify the execution history so that the values of variables that have been observed since the last
incorporate
match the given observations. If there are multiple particles, also adjust their relative weights by the relative likelihoods of the observations being incorporated.This is done automatically at the end of every
observe
command, but is also provided explicitly in case is proves needful.Note: In the future, VentureScript may implement various different incorporation algorithms, in which case explicit incorporation may become necessary again.
-
log_likelihood_at
(scope : object[, block : object])¶ Return type: <inference_action returning <array <number>>> Compute and return the value of the local log likelihood at the given scope and block.
If there are stochastic nodes in the conditional regeneration graph, reuses their current values. This could be viewed as a one-sample estimate of the local likelihood.
log_likelihood_at(default, all) is not the same as
getGlobalLogScore
because it does not count the scores of any nodes that cannot report likelihoods, or whose existence is conditional.log_likelihood_at
also treats exchangeably coupled nodes correctly.Compare
log_joint_at
.
-
log_joint_at
(scope : object[, block : object])¶ Return type: <inference_action returning <array <number>>> Compute and return the value of the local log joint density at the given scope and block.
The principal nodes must be able to assess. Otherwise behaves like log_likelihood_at, except that it includes the log densities of non-observed stochastic nodes.
-
particle_log_weights
()¶ Return type: <inference_action returning <array <number>>> Return the weights of all extant particles as an array of numbers (in log space).
-
equalize_particle_log_weights
()¶ Return type: <inference_action returning <array <number>>> Make all the particle weights equal, conserving their logsumexp.
Return the old particle weights.
-
set_particle_log_weights
(<array <number>>)¶ Return type: <inference_action returning ()> Set the weights of the particles to the given array. It is an error if the length of the array differs from the number of particles.
-
increment_particle_log_weights
(<array <number>>)¶ Return type: <inference_action returning ()> Add the given array to the weights of the particles pointwise. It is an error if the length of the array differs from the number of particles.
-
for_each_particle
(<action>)¶ Return type: <inference_action returning <list>> Run the given inference action once for each particle in the model. The inference action is evaluated independently for each particle, and is not allowed to contain modeling commands (
assume
,observe
,predict
,forget
,freeze
).
-
on_particle
(<integer>, <action>)¶ Return type: <inference_action returning <object>> Run the given inference action on the particle with the given index. The inference action is not allowed to contain modeling commands (
assume
,observe
,predict
,forget
,freeze
).
-
load_plugin
(filename, ...)¶ Return type: <inference_action returning <object>> Load the plugin located at <filename>.
Any additional arguments to
load_plugin
are passed to the plugin’s__venture_start__
function, whose result is returned.XXX: Currently, extra arguments must be VentureSymbols, which are unwrapped to Python strings for the plugin.
-
_call_back
(<object>, ...)¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_assume
(<symbol>, <expression>[, <label>])¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_observe
(<expression>, <object>[, <label>])¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_force
(<expression>, <object>)¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_predict
(<expression>[, <label>])¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_predict_all
(<expression>[, <label>])¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_sample
(<expression>)¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_sample_all
(<expression>)¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
_extract_stats
(<expression>)¶ Return type: <inference_action returning <object>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
forget
(<label>)¶ Return type: <inference_action returning <object>> Forget an observation, prediction, or unused assumption.
Removes the directive indicated by the label argument from the model. If an assumption is forgotten, the symbol it binds disappears from scope; the behavior if that symbol was still referenced is unspecified.
If the directive being forgotten was an observation, returns an array containing the log probability of the observed value in each particle. Otherwise returns an array of zeroes of the same length as the particle set.
The particle weights are not modified, even if an observation is forgotten.
-
freeze
(<label>)¶ Return type: <inference_action returning ()> Freeze an assumption to its current sample.
Replaces the assumption indicated by the label argument with a constant whose value is that assumption’s current value (which may differ across particles). This has the effect of preventing future inference on that assumption, and decoupling it from its (former) dependecies, as well as reclaiming any memory of random choices that can no longer influence any toplevel value.
Together with forget, freeze makes it possible for particle filters in Venture to use model memory independent of the sequence length.
-
report
(<label>)¶ Return type: <inference_action returning <object>> Report the current value of the given directive.
The directive can be specified by label or by directive id.
-
endloop
()¶ Return type: <inference_action returning <object>> Stop any continuous inference that may be running.
-
ordered_range
(<object>, ...)¶ Return type: <list> deterministic ordered_range
-
assert
(<bool>[, message])¶ Return type: <inference_action returning ()> Check the given boolean condition and raise an error if it fails.
-
convert_model
(<symbol>)¶ Return type: <inference_action returning <model>> Convert the implicit model to a different tracing backend.
The symbol gives the name of the backend to use, either
puma
orlite
.
-
new_model
([<symbol>])¶ Return type: <inference_action returning <model>> Create an new empty model.
The symbol, if supplied, gives the name of the backend to use, either
puma
orlite
. If omitted, defaults to the same backend as the current implicit model.This is an inference action rather than a pure operation due to implementation accidents. [It reads the Engine to determine the default backend to use and for the registry of bound foreign sps.]
-
fork_model
([<symbol>])¶ Return type: <inference_action returning <model>> Create an new model by copying the state of the current implicit model.
The symbol, if supplied, gives the name of the backend to use, either
puma
orlite
. If omitted, defaults to the same backend as the current implicit model.
-
in_model
(<model>, <action>)¶ Return type: <inference_action returning <pair <object> <model>>> Run the given inference action against the given model.
Returns a pair consisting of the result of the action and the model, which is also mutated.
This is itself an inference action rather than a pure operation due to implementation accidents. [It invokes a method on the Engine to actually run the given action].
-
model_import_foreign
(<name>)¶ Return type: <inference_action returning ()> Import the named registered foregin SP into the current model.
This is typically only necessary in conjunction with
new_model
, because foreign SPs are automatically imported into the model that is ambient at the time the foreign SP is bound by the ripl (which is usually the toplevel model).The name must refer to an SP that was previously registered with Venture via
ripl.register_foreign_sp
orripl.bind_foreign_sp
. Binds that symbol to that procedure in the current model.
-
select
(scope : object[, block : object])¶ Return type: <inference_action returning subproblem> Select the subproblem indicated by the given scope and block from the current model.
Does not interoperate with multiple particles.
-
detach
(<subproblem>)¶ Return type: <inference_action returning <pair weight <rhoDB>>> Detach the current model along the given subproblem.
Return the current likelihood at the fringe, and a database of the old values that is suitable for restoring the current state (e.g., for rejecting a proposal).
Does not interoperate with multiple particles, or with custom proposals.
-
regen
(<subproblem>)¶ Return type: <inference_action returning weight> Regenerate the current model along the given subproblem.
Return the new likelihood at the fringe.
Does not interoperate with multiple particles, or with custom proposals.
-
restore
(<subproblem>, <rhoDB>)¶ Return type: <inference_action returning weight> Restore a former state of the current model along the given subproblem.
Does not interoperate with multiple particles.
-
detach_for_proposal
(<subproblem>)¶ Return type: <inference_action returning <pair weight <rhoDB>>> Detach the current model along the given subproblem, returning the local posterior.
Differs from detach in that it includes the log densities of the principal nodes in the returned weight, so as to match regen_with_proposal. The principal nodes must be able to assess.
Return the current posterior at the fringe, and a database of the old values for restoring the current state.
Does not interoperate with multiple particles.
-
regen_with_proposal
(<subproblem>, <list>)¶ Return type: <inference_action returning weight> Regenerate the current model along the given subproblem from the given values.
Differs from regen in that it deterministically moves the principal nodes to the given values rather than resimulating them from the prior, and includes the log densities of those nodes in the returned weight. The principal nodes must be able to assess.
Return the new posterior at the fringe.
Does not interoperate with multiple particles.
-
get_current_values
(<subproblem>)¶ Return type: <inference_action returning <list>> Get the current values of the principal nodes of the given subproblem.
Does not interoperate with multiple particles.
-
num_blocks
(scope : object)¶ Return type: <inference_action returning <array <number>>> Report the number of blocks in the given scope in each particle.
-
draw_subproblem
(<subproblem>)¶ Return type: <inference_action returning ()> Draw a subproblem by printing out the source code of affected random choices.
-
save_model
(<filename>)¶ Return type: <inference_action returning ()> Save the current model to a file.
Note:
save_model
andload_model
rely on Python’spickle
module.
-
load_model
(<filename>)¶ Return type: <inference_action returning ()> Load from a file created by
save_model
, clobbering the current model.Note:
save_model
andload_model
rely on Python’spickle
module.
-
pyexec
(<code>)¶ Return type: <inference_action returning ()> Execute the given string as Python code, via exec.
The code is executed in an environment where the RIPL is accessible via the name
ripl
. Values from the ambient inference program are not directly accessible. The environment against whichpyexec
is executed persists across invocations ofpyexec
andpyeval
.
-
pyeval
(<code>)¶ Return type: <inference_action returning <object>> Evaluate the given string as a Python expression, via eval.
The code is executed in an environment where the RIPL is accessible via the name
ripl
. Values from the ambient inference program are not directly accessible. The environment against whichpyeval
is evaluated persists across invocations ofpyexec
andpyeval
.
-
save_model_string
(model)¶ Return type: <inference_action returning model_string> Save a model to a string which can later be loaded with load_model_string.
-
load_model_string
(model_string)¶ Return type: <inference_action returning model> Load a model saved with save_model_string.
-
parallel_mapv_action
(proc(a) -> b, <array a>[, parallelism])¶ Return type: <inference_action returning <array b>>
-
print
(<object>, ...)¶ Return type: () Print the given values to the terminal.
If you are trying to add a debugging print statement to a VentureScript expression that is not already an inference action, consider using
debug
, which does not require sequencing.
-
plot
(<spec>, <dataset>)¶ Return type: () Plot a data set according to a plot specification.
Example:
define d = empty() assume x = normal(0, 1) infer accumulate_dataset(1000, do(resimulation_mh(default, one, 1), collect(x))) plot("c0s", d)
will do 1000 iterations of
mh
collecting some standard data and the value ofx
, and then show a plot of thex
variable (which should be a scalar) against the iteration number (from 1 to 1000), colored according to the global log score. Seecollect
for details on collecting and labeling data to be plotted.The format specifications are inspired loosely by the classic printf. To wit, each individual plot that appears on a page is specified by some line noise consisting of format characters matching the following regex:
[<geom>]*(<stream>?<scale>?){1,3}
specifying
- the geometric objects to draw the plot with, and
- for each dimension (x, y, and color, respectively)
- the data stream to use
- the scale
The possible geometric objects are:
- _p_oint,
- _l_ine,
- _b_ar, and
- _h_istogram
The possible data streams are:
- _<an integer>_ that column in the data set, 0-indexed,
- _%_ the next column after the last used one
- iteration _c_ounter,
- _t_ime (wall clock, since the beginning of the Venture program), and
- pa_r_ticle
The possible scales are:
- _d_irect, and
- _l_ogarithmic
If one stream is indicated for a 2-D plot (points or lines), the x axis is filled in with the iteration counter. If three streams are indicated, the third is mapped to color.
If the given specification is a list, make all those plots at once.
-
plotf
(<spec>, <dataset>)¶ Return type: <inference_action returning ()> Plot a data set according to a plot specification.
This is identical to
plot
, except it’s an inference action, so can participate indo
blocks.Example:
do(assume x, normal(0, 1), ... plotf("c0s", d))
-
plot_to_file
(<basename>, <spec>, <dataset>)¶ Return type: () Save plot(s) to file(s).
Like
plot
, but save the resulting plot(s) instead of displaying on screen. Just as<spec>
may be either a single expression or a list,<basenames>
may either be a single symbol or a list of symbols. The number of basenames must be the same as the number of specifications.- Examples:
- plot_to_file(“basename”, “spec”, <expression> …) saves the plot specified by
- the spec in the file “basename.png”
- plot_to_file(quote(basename1, basename2), (quote(spec1, spec2)), <expression> …) saves
- the spec1 plot in the file basename1.png, and the spec2 plot in basename2.png.
-
plotf_to_file
(<basename>, <spec>, <dataset>)¶ Return type: <inference_action returning ()> Save plot(s) to file(s).
Like
plotf
, but save the resulting plot(s) instead of displaying on screen. Seeplot_to_file
.
-
empty
()¶ Return type: <dataset> Create an empty dataset
into
which furthercollect
ed stuff may be merged.
-
into
(<foreignblob>, <foreignblob>)¶ Return type: <inference_action returning ()> Destructively merge the contents of the second argument into the first.
Right now only implemented on datasets created by
empty
andcollect
, but in principle generalizable to any monoid.
-
_collect
(<object>, ...)¶ Return type: <inference_action returning <dataset>> A helper function for implementing the eponymous inference macro.
Calling it directly is likely to be difficult and unproductive.
-
sweep
(<dataset>)¶ Return type: <inference_action returning ()> Print the iteration count.
Extracts the last row of the supplied inference Dataset and prints its iteration count.
-
printf
(<dataset>)¶ Return type: <inference_action returning ()> Print model values collected in a dataset.
This is a basic debugging facility.
-
p_p_plot_2samp
(<array <number>>, <array <number>>)¶ Return type: () Render a P-P plot comparing the two observed samples.
-
p_p_plot_2samp_to_file
(<string>, <array <number>>, <array <number>>)¶ Return type: () Render a P-P plot comparing the two observed samples and save it in the given file.
-
by_intersection
(<foreignblob>, <foreignblob>)¶ Return type: <foreignblob> Intersect the selected choices.
-
by_tag
(<tag>)¶ Return type: <foreignblob> Select the choices tagged by the given tag.
They remain keyed by their values, so that
random_singleton
will pick all the choices given by a random tag value, rather than a single choice at random from all choices under that tag.
-
by_tag_value
(<tag>, <value>)¶ Return type: <foreignblob> Select the choices tagged by the given tag at the given value.
-
by_walk
(<foreignblob>, <edge>)¶ Return type: <foreignblob> Walk along the given edge in the dependency graph pointwise.
Possible edges are
operator
, for the operator position of an expressionsource
, for the expression a variable is bound torequest
, for the request node corresponding to a procedure application- <an integer>, for that index subexpression of an expression
- <a tag search expression>, for choices in the dynamic extent of a node that were given in that tag
-
by_extent
(<foreignblob>)¶ Return type: <foreignblob> Select the choices in the dynamic extent of the current selection.
-
by_union
(<foreignblob>, ...)¶ Return type: <foreignblob> Union the given selections.
-
by_top
()¶ Return type: <foreignblob> Select the “top” of the model, whose dynamic extent is all random choices.
-
by_star
()¶ Return type: <foreignblob> Walk to all the random choices in the dynamic extent of the source.
-
minimal_subproblem
(<foreignblob>)¶ Return type: <foreignblob> Construct the minimal subproblem from the given selection.
-
random_singleton
(<foreignblob>)¶ Return type: <foreignblob> Randomly select one component of the current selection.
Correctly account for the acceptance correction due to possible changes in the probability of selecting a particular subproblem to work on.
A “component” may be a single random choice, if the current selection is a set, or a set, if the current selection is a dictionary of tag values to sets of variables.
-
esr
(<integer>)¶ Return type: <foreignblob> Walk to the given requested result.
-
iterate
(f : <inference action>, iterations : int)¶ Return type: <inference action> Repeatedly apply the given action, suppressing the returned values.
-
repeat
(iterations : int, f : <inference action>)¶ Return type: <inference action> Repeatedly apply the given action, suppressing the returned values. This is the same as
iterate
, except for taking its arguments in the opposite order, as a convenience.
-
sequence
(ks : list<inference action returning a>)¶ Return type: <inference action returning list<a>> Apply the given list of actions in sequence, returning the values. This is Haskell’s sequence.
-
sequence
(ks : list<inference action>) Return type: <inference action> Apply the given list of actions in sequence, discarding the values. This is Haskell’s sequence_.
-
mapM
(act : proc(a) -> <inference action returning b>, objs : list<a>)¶ Return type: <inference action returning list<b>> Apply the given action function to each given object and perform those actions in order. Return a list of the resulting values. The nomenclature is borrowed from Haskell.
-
imapM
(act : proc(int, a) -> <inference action returning b>, objs : list<a>)¶ Return type: <inference action returning list<b>> Apply the given action function to each given object and its index in the list and perform those actions in order. Return a list of the resulting values.
-
for_each
(objs : list<a>, act : proc(a) -> <inference action>)¶ Return type: <inference action> Apply the given action function to each given object and perform those actions in order. Discard the results.
-
for_each_indexed
(objs : list<a>, act : proc(int, a) -> <inference action>)¶ Return type: <inference action> Apply the given action function to each given object and its index in the list and perform those actions in order. Discard the results.
-
pass <inference action>
An inference action that does nothing and returns nil. Useful in the same sorts of situations as Python’s
pass
statement.
-
bind
(<inference action returning a>, proc(a) -> <inference action returning b>)¶ Return type: <inference action returning b> Chain two inference actions sequentially, passing the value of the first into the procedure computing the second. This is Haskell’s
bind
, specialized to inference actions.
-
bind_
(<inference action>, proc() -> <inference action returning a>)¶ Return type: <inference action returning a> Chain two inference actions sequentially, ignoring the value of the first. This is Haskell’s
>>
operator, specialized to inference actions.Note that the second argument is a thunk that computes an inference action. This is important, because it defers computing the action to take until it is actually time to take it, preventing infinite loops in, e.g., unrolling the future action spaces of recursive procedures.
-
return
(<object>)¶ Return type: <inference action returning <object>> An inference action that does nothing and just returns the argument passed to
return
.
-
curry
(proc(<a>, <b>) -> <c>, <a>)¶ Return type: proc(<b>) -> <c> Curry a two-argument function into two one-argument stages. Supports the idiom (bind (collect …) (curry plotf (quote spec))).
-
curry3
(proc(<a>, <b>, <c>) -> <d>, <a>, <b>)¶ Return type: proc(<c>) -> <d> Curry a three-argument function into a two-argument stage and a one-argument stage. Supports the idiom (bind (collect …) (curry plotf_to_file (quote name) (quote spec))).
-
global_log_likelihood <inference action returning <array <number>>>
An inference action that computes and returns the global likelihood (in log space). Cost: O(size of trace).
-
global_log_joint <inference action returning <array <number>>>
An inference action that computes and returns the global joint density (in log space). Cost: O(size of trace).
-
conditional <inference action>
An inference action that sets each particle to an independent sample from the full conditional (with respect to currently incorporated observations).
This is implemented by global rejection sampling (generalized to continuous equality constraints), so may take a while for problems where the conditional is far from the prior in KL divergence.
-
join_datasets
(datasets : list<dataset>)¶ Return type: <inference action returning <dataset>> Merge all the given datasets into one.
-
accumulate_dataset
(iterations : int, a : <inference action returning <dataset>>)¶ Return type: <inference action returning <dataset>> Run the given inference action the given number of times, accumulating all the returned datasets into one.
For example:
accumulate_dataset(1000, do(default_markov_chain(10), collect(x)))
will return a dataset consisting of the values of
x
that occur at 10-step intervals in the history of a 10000-step default Markov chain on the current model.
-
duplicate_particle
(<int>)¶ Return type: <inference action returning ()>
Duplicate the given particle, conserving its weight. The copy is initialized with zero weight (negative infinity in log space).
-
add_particle <inference action returning ()>
Add a new particle, sampled from the prior and weighted by its likelihood. In case different extant particles have different priors, as can happen if freeze was used, it’s the prior of particle 0.
-
run
(<inference action returning a>)¶ Return type: a Run the given inference action and return its value.
-
autorun
(<object>)¶ Return type: <object> If the argument is an inference action, run it and return the result. Otherwise, return the argument.
-
default_markov_chain
(transitions : int)¶ Return type: <inference action> Take the requested number of steps of the default Markov chain.
The default Markov chain is single-site resimulation M-H.
default_markov_chain(k)is equivalent to
resimulation_mh(default, one, k)See
mh
.
-
regeneration_local_proposal
(<list>)¶ Return type: proc(<subproblem>) -> <inference action returning <result>> Propose the given values for the given subproblem. Changes the underlying model to represent the proposed state, and returns a proposal result (see
mh_correct
).
-
mh_correct
(<inference action returning <result>>)¶ Return type: <inference action> Run the given proposal, and accept or reject it according to the Metropolis-Hastings acceptance ratio returned in its result.
The action must return a list of three items:
- The local acceptance ratio (in log space)
- An action to run to accept the proposal
- An action to run to reject the proposal
-
symmetric_local_proposal
(proc(<value>) -> <value>)¶ Return type: proc(<subproblem>) -> <inference action returning <result>> Propose using the given kernel for the given subproblem. Changes the underlying model to represent the proposed state, and returns a proposal result (see
mh_correct
).The kernel function must be symmetric, but need not be assessable.
-
on_subproblem
(scope: object, block: object, proposal: proc(<subproblem>) -> <inference action returning <result>>)¶ Return type: <inference action returning <result>> Select the subproblem indicated by the given scope and block, and apply the given proposal procedure to that subproblem. Returns a proposal result (see
mh_correct
).The given proposal function must accept a subproblem and produce an action that returns a proposal result. The result returned by
on_subproblem
consists of modifying the acceptance ratio to account for any change in the probability of selecting the same subproblem from the given scope and block.
-
value_at
(selector: object)¶ Return type: object Return the value the current model has at the choice indicated by the given selector. If the selector identifies more than one random choice, return one of their values arbitrarily.
Does not interoperate with multiple particles (use
on_particle
if needed).
-
value_at2
(scope: object, block:object)¶ Return type: object Return the value the current model has at the choice indicated by the given scope and block. If the scope-block pair identifies more than one random choice, return one of their values arbitrarily.
Does not interoperate with multiple particles (use
on_particle
if needed).
-
set_value_at
(selector: object, value: object)¶ Return type: <inference_action returning weight> Set the value of the random choice at the given selector in the current model to the given object. Return the probability density thereof in the local posterior around that random choice. It is an error if the selector identifies more than one random choice.
Does not interoperate with multiple particles (use
on_particle
if needed).
-
set_value_at
(scope: object, block: object, value: object) Return type: <inference_action returning weight> Set the value of the random choice at the given scope and block in the current model to the given object. Return the probability density thereof in the local posterior around that random choice. It is an error if the scope-block pair identifies more than one random choice.
Does not interoperate with multiple particles (use
on_particle
if needed).
Built-in Helpers¶
default
: The default scope.The default scope contains all the random choices, each in its own block.
one
: Mix over individual blocks in the scope.If given as a block keyword,
one
causes the inference procedure to uniformly choose one of the blocks in the scope on which it is invoked and apply to that.all
: Affect all choices in the scope.If given as a block keyword,
all
causes the inference procedure to apply to all random choices in the scope.none
: Affect no choices in the scope.If given as a block keyword,
none
causes the inference procedure to apply to no random choices. This is useful only forcollapse_equal
andcollapse_equal_map
.ordered
: Make particle Gibbs operate on all blocks in order of block ID.ordered_range(<block>, <block>)
: Make particle Gibbs operate on a range of blocks in order of block ID.Specifically, all the blocks whose IDs lie between the given lower and upper bounds.
Special Forms¶
All the macros available in the modeling language can be used in the inference language, too. In addition, the following inference macros are available.
-
loop
(<kernel>)¶ Run the given kernel continuously in a background thread.
Available in Lite and Puma.
Can only be used as the top level of the
infer
instruction:infer loop(something)
.Execute the
stop_continuous_inference
instruction to stop.
-
(do <stmt> <stmt> ...)
Sequence actions that may return results.
Note: The above template is abstract syntax.
do
is what curly-delimited blocks expand to.Each <stmt> except the last may be
- an action, in which case it is performed and any value it returns is dropped, or
- a binder of the form
(<variable> <- <action>)
in which case the action is performed and its value is made available to the remainder of thedo
form by being bound to the variable, or - a let binder of the form
(let <variable> <expression>)
in which case the value of the expression is just bound to the variable (without performing any actions), or - a multivalue binder of the form
(let_values (<var1> <var2> ...) <expression>)
in which case the expression is expected to return a list ofref
s, whose values are unpacked into the variables, or - a letrec or mutrec binder of the form
(letrec <var> <exp>)
or(mutrec <var> <exp>)
. All mutrec binders headed by a single letrec form a block, which functions like letrec in scheme, with the rest of thedo
expression as its body.
The last <stmt> may not be a binder and must be an action. The whole
do
expression is then a single compound heterogeneous action, whose value is the value returned by the last <stmt>.If you need an action that produces a value without doing anything, use
return(<value>)
(seereturn
). If you need an action that evaluates an expression and returns its value, useaction(<exp>)
(seeaction
). If you need an action that does nothing and produces no useful value, you can usepass
.For example, to make a kernel that does inference until some variable in the model becomes “true” (why would anyone want to do that?), you can write:
1 define my_strange_kernel = proc () { 2 do(finish <- sample(something_from_the_model), 3 if (finish) { 4 pass 5 } else { 6 do(default_markov_chain(1), 7 my_strange_kernel()) 8 })}
Line 2 is a binder for the
do
, which makesfinish
a variable usable by the remainder of the procedure. Theif
starting on line 3 is an action, and is the last statement of the outerdo
. Line 6 is a non-binder statement for the innerdo
.The nomenclature is borrowed from the (in)famous
do
notation of Haskell. If this helps you think about it, Venture’sdo
is exactly Haskelldo
, except there is only one monad, which is essentiallyState ModelHistory
. Randomness and actual i/o are not treated monadically, but just executed, which we can get away with because VentureScript is strict and doesn’t aspire to complete functional purity.
-
begin
(<kernel>, ...)¶ Perform the given kernels in sequence.
-
action
(<exp>)¶ Wrap an object, usually a non-inference function like plotf, as an inference action, so it can be used inside a do(…) block.
The difference between
action
andreturn
is thataction
defers evaluation of its argument until the action is performed, whereasreturn
evaluates its argument eagerly.
-
call_back
(<name>, <model-expression>, ...)¶ Invoke a user-defined callback.
Locate the callback registered under the name
name
and invoke it with- First, the
Infer
instance in which the present inference program is being run - Then, for each expression in the
call_back
form, a list of values for that expression, represented as stack dicts, sampled across all extant particles. The lists are parallel to each other.
Return the value returned by the callback, or
Nil
if the callback returnedNone
.To bind a callback, call the
bind_callback
method on theRipl
object:ripl.bind_callback(<name>, <callable>): Bind the given Python callable as a callback function that can be referred to by `call_back` by the given name (which is a string).
There is an example in the source in
test/inference_language/test_callback.py
.- First, the
-
collect
(<model-expression> ...)¶ Extract data from the underlying model during inference.
When a
collect
inference command is executed, the given expressions are sampled and their values are returned in aDataset
object. This is the way to get data into datasets; seeaccumulate_dataset
andinto
for accumulating datasets, andprint
,plot
, andplot_to_file
for using them.Each
<model-expression>
may optionally be given in the formlabelled( <model-expression>, <name>)
, in which case the givenname
serves as the key in the returned table of data. Otherwise, the key defaults to a string representation of the givenexpression
.Note: The
<model-expression>
s are sampled in the model, not the inference program. For example, they may refer to variablesassume
d in the model, but may not refer to variablesdefine
d in the inference program. The<model-expression>
s may be constructed programmatically: seeunquote
.collect
also automatically collects some standard items: the iteration count (maintained by merging datasets), the particle id, the wall clock time that passed since the VentureScript program began, the global log score, the particle weights in log space, and the normalized weights of the particles in direct space.If you want to do something custom with the data, you will want to use the
asPandas()
method of theDataset
object from your callback or foreign inference sp.
-
[<label>:] assume <symbol> = <model-expression>;
Programmatically add an assumption.
Extend the underlying model by adding a new generative random variable, like the
assume
directive. The given model expression may be constructed programmatically – seeunquote
.The
<label>
, if supplied, may be used tofreeze
orforget
this directive.
-
assume_values (<symbol> ...) = <model-expression>;
Multiple-value
assume
.The expression is expected to produce a list of references (see
ref
) of the same length as the list of symbols given toassume_values
.assume_values
binds those symbols to thederef
s of the corresponding references.For example:
(assume_values (a b) (list (ref (normal 0 1)) (ref (normal 1 2))))
is equivalent to:
(assume _some_name_432_ (list (ref (normal 0 1)) (ref (normal 1 2)))) (assume a (deref (first _some_name_432_))) (assume b (deref (second _some_name_432_)))
which has the same effect as:
(assume a (normal 0 1)) (assume b (normal 0 1))
assume_values
does not accept a customlabel
argument.
-
[<label>:] observe <model-expression> = <value>;
Programmatically add an observation.
Condition the underlying model by adding a new observation, like the
observe
directive. The given model expression may be constructed programmatically – seeunquote
. The given value is computed in the inference program, and may be stochastic. This corresponds to conditioning a model on randomly chosen data.The
<label>
, if supplied, may be used toforget
this observation.This is an action returning an array containing the log probability of the observed value in each particle. The particle weights are incremented by this difference automatically.
-
[<label>:] predict <model-expression>;
Programmatically add a prediction.
Extend the underlying model by adding a new generative random variable, like the
predict
directive. The given model expression may be constructed programmatically – seeunquote
.The
<label>
, if supplied, may be used tofreeze
orforget
this directive.
-
predict_all
(<model-expression>[, <label>])¶ Programmatically add a prediction and return results from all particles.
Extend the underlying model by adding a new generative random variable,
predict
. Unlikepredict
, return the values of the expression from all the particles, as a list.The
<label>
, if supplied, may be used tofreeze
orforget
this directive.
-
force <model-expression> = <value>;
Programatically force the state of the model.
Force the model to set the requested variable to the given value, without constraining it to stay that way. Implemented as an
observe
followed by aforget
.This is an action returning an array containing the log probability of the observed value in each particle. The particle weights are incremented by this difference automatically, even though the observation is immediately forgotten.
-
sample <model-expression>
Programmatically sample from the model.
Sample an expression from the underlying model by simulating a new generative random variable without adding it to the model, like the
sample
directive. If there are multiple particles, refers to the distinguished one.The given model expression may be constructed programmatically – see
unquote
.
-
sample_all
(<model-expression>)¶ Programmatically sample from the model in all particles.
Sample an expression from the underlying model by simulating a new generative random variable without adding it to the model, like the
sample
directive.Unlike the
sample
directive, interacts with all the particles, and returns values from all of them as a list.The given model expression may be constructed programmatically – see
unquote
.
-
extract_stats
(<model-expression>)¶ Extract maintained statistics.
Specifically, sample the given model expression, like
sample
, but expect it to return a stochastic procedure and reify and return the statistics about its applications that it has collected.The exact VentureScript-level representation of the returned statistics depends on the procedure in question. If the procedure does not collect statistics, return
nil
.For example:
assume coin = make_beta_bernoulli(1, 1) observe coin() = true extract_stats(coin) --> list(1, 0)
-
unquote
(<object>)¶ Programmatically construct part of a model expression.
All the
<model-expression>
s in the above special forms may be constructed programmatically. An undecorated expression is taken literally, but ifunquote(...)
appears in such an expression, the code inside the unquote is executed in the inference program, and its result is spliced in to the model program.For example, suppose one wanted to observe every value in a data set, but allow the model to know the index of the observation (e.g., to select observation models). For this, every observed model expression needs to be different, but in a programmable manner. Here is a way to do that:
define data = ... define observe_after = proc(i) { if (i < length(data)) { do(observe(obs_fun(unquote(i)), lookup(data, i)), // (*) observe_after(i + 1)) } else { pass }} infer observe_after(0)
Note the use of unquote on the like marked
(*)
to construct different observe expressions for each data element. To the underlying model, this will look like:observe obs_fun(0) = <val0> observe obs_fun(1) = <val1> observe obs_fun(2) = <val2> ...
Footnotes
[1] | For the interested, the way this is actually done is that each of the primitives documented here actually returns a procedure that accepts a reified object representing the sampled execution history of the model program, affects it, and returns a pair consisting of whatever value it wishes to return in the first slot, and the reified execution history in the second. This is relevant if you wish to define additional inference abstractions in Venture, or more complex combinations of them than the provided ones. For those readers for whom this analogy is helpful, the above is
exactly the type signature one would get by implementing a
|