Skip to content

Commit

Permalink
Attempt to fix TuringLang#41.
Browse files Browse the repository at this point in the history
  • Loading branch information
luiarthur committed Dec 8, 2020
1 parent 2bad97c commit fe1091d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
66 changes: 64 additions & 2 deletions src/mh-core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,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 @@ -213,3 +212,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 @@ -42,6 +42,10 @@ using Test
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

0 comments on commit fe1091d

Please sign in to comment.