Skip to content

Skipping the Hastings computation for symmetric proposals #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 64 additions & 2 deletions src/mh-core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ function AbstractMCMC.step(
params = propose(rng, spl, model, params_prev)

# Calculate the log acceptance probability.
logα = logdensity(model, params) - logdensity(model, params_prev) +
q(spl, params_prev, params) - q(spl, params, params_prev)
logα = compute_log_acceptance_prob(model, params, spl, params_prev)

# Decide whether to return the previous params or the new one.
if -Random.randexp(rng) < logα
Expand All @@ -216,3 +215,66 @@ function AbstractMCMC.step(
return params_prev, params_prev
end
end

"""
Type alias for symmetric distributions. This is not an exhaustive list. (e.g.
`Uniform` can be symmetric.)
"""
const SymmetricDistribution = Union{Normal,MvNormal,MvTDist,Cauchy,TDist}

"""
Type alias for symmetric random walk proposals
"""
const SymmetricRandomWalkProposal = let
Union{RandomWalkProposal{<:SymmetricDistribution},
RandomWalkProposal{<:AbstractVector{<:SymmetricDistribution}}}
end

"""
Type alias for symmetric proposals.

NOTE to developers: Currently, this is `SymmetricRandomWalkProposal`, but new
proposals (e.g. an adaptive random walk proposal) can be added to the `Union`.
"""
const SymmetricProposal = Union{SymmetricRandomWalkProposal}

"""
Computes metropolis acceptance ratio (without Hastings).
"""
function compute_log_metropolis_ratio(
model::DensityModel,
params::T,
spl::MetropolisHastings,
params_prev::Transition
) where T
return logdensity(model, params) - logdensity(model, params_prev)
end

"""
Computes log acceptance ratio for symmetric proposals. This is simply
the log Metropolis ratio.
"""
function compute_log_acceptance_prob(
model::DensityModel,
params::T,
spl::MetropolisHastings{<:SymmetricProposal},
params_prev::Transition) where T

# Don't compute Hastings ratio for symmetric proposal distributions.
return compute_log_metropolis_ratio(model, params, spl, params_prev)
end

"""
Computes log acceptance ratio for symmetric proposals. This is the
full log-Metropolis-Hastings acceptance probability.
"""
function compute_log_acceptance_prob(
model::DensityModel,
params::T,
spl::MetropolisHastings,
params_prev::Transition) where T

metropolis_ratio = compute_log_metropolis_ratio(model, params, spl, params_prev)
hastings_ratio = q(spl, params_prev, params) - q(spl, params, params_prev)
return metropolis_ratio + hastings_ratio
end
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ using ForwardDiff
spl1 = RWMH([Normal(0,1), Normal(0, 1)])
spl2 = RWMH(MvNormal([0.0, 0.0], 1))

# Ensure that these are `SymmetricProposal`s.
@test spl1 isa AdvancedMH.MetropolisHastings{<:AdvancedMH.SymmetricProposal}
@test spl2 isa AdvancedMH.MetropolisHastings{<:AdvancedMH.SymmetricProposal}

# Sample from the posterior.
chain1 = sample(model, spl1, 100000; chain_type=StructArray, param_names=["μ", "σ"])
chain2 = sample(model, spl2, 100000; chain_type=StructArray, param_names=["μ", "σ"])
Expand Down