probcomp/Gen.jl

Discrete single-site map optimize and gibbs sampling

Open

#81 opened on 2019年2月24日

GitHub で見る
 (0 comments) (0 reactions) (0 assignees)Julia (1,840 stars) (163 forks)batch import
good first issue

説明

It's easy to implement single-site versions of these, where the user provides a (finite) set of values of the variable to consider. These would go into the inference library:

Map optimization:

function Gen.map_optimize(trace, addr, values)
    args = get_args(trace)
    argdiffs = map((_) -> NoChange(), args)
    weights = Vector{Float64}(undef, length(values))
    traces = Vector{Any}(undef, length(values))
    for (i, val) in enumerate(values)
        (traces[i], weights[i], _, _) = update(trace, args, argdiffs, choicemap((addr, val)))
    end
    idx = argmax(weights)
    return traces[idx]
end

Computing probabilities for Gibbs sampling:

function Gen.discrete_conditional_dist(trace, addr, values)
    args = get_args(trace)
    argdiffs = map((_) -> NoChange(), args)
    weights = Vector{Float64}(undef, length(values))
    for (i, val) in enumerate(values)
        (_, weights[i]) = update(trace, args, argdiffs, choicemap((addr, val)))
    end
    exp.(weights .- logsumexp(weights))
end

Then, a built-in Gibbs sampling procedure would be:

function Gen.discrete_conditional_update(trace, addr, values)
    probs = discrete_conditional_dist(trace, addr, values)
    idx = uniform_discrete(probs)
    val = values[idx]
    args = get_args(trace)
    argdiffs = map((_) -> NoChange(), args)
    new_trace, = update(trace, args, argdiffs, choicemap((addr, val)))
    return new_trace
end

Note that both the MAP and Gibbs sampling procedures assume that the set of addresses in the trace (i.e. control flow) is not affected by the choice being changed. This is an important requirement, as doing "Gibbs" in the presence of stochastic structure would need to be carefully defined, and could end up requiring auxiliary-variable based approximation (note: I think that the old fix-update could be useful for that).

Alternatively, discrete conditional probabilities (from discrete_conditional_dist) could be used directly in a custom proposal (which is useful for block proposals when some of the variables are proposed using Gibbs updates, conditioned on the value proposed for earlier variables).

For best performance, generating a static choice map just once per call, or statically, should be considered.

コントリビューターガイド