m2.1d

Estimate Binomial draw probabilility

using DynamicHMCModels

Define a structure to hold the data.

struct BernoulliProblem
    "Total number of draws in the data."
    n::Int
    "Number of draws `==1` in the data"
    s::Vector{Int}
end;

Make the type callable with the parameters as a single argument.

function (problem::BernoulliProblem)((α, )::NamedTuple{(:α, )})
    @unpack n, s = problem        # extract the data
    loglikelihood(Binomial(n, α), s)
end

Create the data and complete setting up the problem.

obs = rand(Binomial(9, 2/3), 1)
p = BernoulliProblem(9, obs)
p((α = 0.5, ))
-4.041100047703289

Write a function to return properly dimensioned transformation.

problem_transformation(p::BernoulliProblem) =
    as((α = as𝕀, ),  )

Use a flat priors (the default, omitted) for α

P = TransformedLogDensity(problem_transformation(p), p)
∇P = LogDensityRejectErrors(ADgradient(:ForwardDiff, P));
LogDensityRejectErrors{InvalidLogDensityException,LogDensityProblems.ForwardDiffLogDensity{TransformedLogDensity{TransformVariables.TransformNamedTuple{(:α,),Tuple{TransformVariables.ScaledShiftedLogistic{Float64}}},Main.ex-m2.1d.BernoulliProblem},ForwardDiff.GradientConfig{ForwardDiff.Tag{getfield(LogDensityProblems, Symbol("##1#2")){TransformedLogDensity{TransformVariables.TransformNamedTuple{(:α,),Tuple{TransformVariables.ScaledShiftedLogistic{Float64}}},Main.ex-m2.1d.BernoulliProblem}},Float64},Float64,1,Array{ForwardDiff.Dual{ForwardDiff.Tag{getfield(LogDensityProblems, Symbol("##1#2")){TransformedLogDensity{TransformVariables.TransformNamedTuple{(:α,),Tuple{TransformVariables.ScaledShiftedLogistic{Float64}}},Main.ex-m2.1d.BernoulliProblem}},Float64},Float64,1},1}}}}(ForwardDiff AD wrapper for TransformedLogDensity of dimension 1, w/ chunk size 1)

Sample

chain, NUTS_tuned = NUTS_init_tune_mcmc(∇P, 1000)
MCMC, adapting ϵ (75 steps)
7.7e-6 s/step ...done
MCMC, adapting ϵ (25 steps)
1.1e-5 s/step ...done
MCMC, adapting ϵ (50 steps)
1.1e-5 s/step ...done
MCMC, adapting ϵ (100 steps)
8.2e-6 s/step ...done
MCMC, adapting ϵ (200 steps)
7.4e-6 s/step ...done
MCMC, adapting ϵ (400 steps)
7.2e-6 s/step ...done
MCMC, adapting ϵ (50 steps)
1.1e-5 s/step ...done
MCMC (1000 steps)
2.5e-5 s/step ...done
(NUTS_Transition{Array{Float64,1},Float64}[NUTS_Transition{Array{Float64,1},Float64}([0.5187651583081581], -6.0039256003423205, 3, DynamicHMC.DoubledTurn, 0.9568639963730302, 7), NUTS_Transition{Array{Float64,1},Float64}([0.4800575569919328], -4.299410194009949, 3, DynamicHMC.DoubledTurn, 0.9896739337965794, 7), NUTS_Transition{Array{Float64,1},Float64}([0.5152698220994292], -7.406571898512166, 2, DynamicHMC.DoubledTurn, 0.568656586077137, 3), NUTS_Transition{Array{Float64,1},Float64}([0.446350604094641], -7.593555845209533, 2, DynamicHMC.DoubledTurn, 0.5373341567359532, 3), NUTS_Transition{Array{Float64,1},Float64}([1.4446384641495005], -4.318026065286275, 3, DynamicHMC.DoubledTurn, 0.98242939923541, 7), NUTS_Transition{Array{Float64,1},Float64}([2.4039008643124866], -4.108823654610657, 1, DynamicHMC.AdjacentTurn, 0.8510336101125864, 3), NUTS_Transition{Array{Float64,1},Float64}([3.0614493770901934], -5.317809276995575, 2, DynamicHMC.DoubledTurn, 0.8861027129909909, 3), NUTS_Transition{Array{Float64,1},Float64}([3.1025888303451175], -4.595889124243939, 1, DynamicHMC.DoubledTurn, 0.9966924978150328, 1), NUTS_Transition{Array{Float64,1},Float64}([1.7368528840209168], -5.336918293360772, 1, DynamicHMC.AdjacentTurn, 0.9699074731627851, 3), NUTS_Transition{Array{Float64,1},Float64}([1.3072294974056502], -3.185215453228261, 1, DynamicHMC.AdjacentTurn, 0.9885717641517943, 3)  …  NUTS_Transition{Array{Float64,1},Float64}([2.225218302320921], -3.507108795630021, 1, DynamicHMC.AdjacentTurn, 0.9434186598338342, 3), NUTS_Transition{Array{Float64,1},Float64}([1.4905633822045956], -3.5971759131287167, 1, DynamicHMC.AdjacentTurn, 0.9846346370030418, 3), NUTS_Transition{Array{Float64,1},Float64}([1.2844215946159028], -3.074692445095468, 1, DynamicHMC.AdjacentTurn, 0.9917777068901036, 3), NUTS_Transition{Array{Float64,1},Float64}([1.308594458277571], -3.062265242752257, 1, DynamicHMC.DoubledTurn, 1.0, 1), NUTS_Transition{Array{Float64,1},Float64}([1.986776015413361], -6.675772712720139, 2, DynamicHMC.DoubledTurn, 0.5788853725967943, 3), NUTS_Transition{Array{Float64,1},Float64}([1.3250316304740573], -3.424694751845297, 1, DynamicHMC.AdjacentTurn, 0.9805257126654666, 3), NUTS_Transition{Array{Float64,1},Float64}([1.602397294812485], -3.0894807315273853, 1, DynamicHMC.AdjacentTurn, 0.9956056110912389, 3), NUTS_Transition{Array{Float64,1},Float64}([1.5930743858643759], -3.085870281254036, 2, DynamicHMC.DoubledTurn, 0.9931355308691909, 3), NUTS_Transition{Array{Float64,1},Float64}([1.3228922032644785], -3.6615677625271403, 2, DynamicHMC.DoubledTurn, 0.9334596403443948, 3), NUTS_Transition{Array{Float64,1},Float64}([2.280744114647607], -4.018201718990587, 1, DynamicHMC.AdjacentTurn, 0.8607707611456691, 3)], NUTS sampler in 1 dimensions
  stepsize (ϵ) ≈ 0.743
  maximum depth = 10
  Gaussian kinetic energy, √diag(M⁻¹): [0.912518904171551]
)

To get the posterior for $α$ use get_position and then transform back.

posterior = TransformVariables.transform.(Ref(problem_transformation(p)), get_position.(chain));
1000-element Array{NamedTuple{(:α,),Tuple{Float64}},1}:
 (α = 0.6268589737198517,)
 (α = 0.6177614659226344,)
 (α = 0.6260410289535695,)
 (α = 0.6097712078580889,)
 (α = 0.8091719166638041,)
 (α = 0.9171242806530356,)
 (α = 0.955274262965425,)
 (α = 0.956999405552833,)
 (α = 0.8502868819263306,)
 (α = 0.7870491812572781,)
 ⋮
 (α = 0.8161628181077263,)
 (α = 0.7832014896261205,)
 (α = 0.7872778628415527,)
 (α = 0.8794016378033822,)
 (α = 0.7900176206469055,)
 (α = 0.8323531735135069,)
 (α = 0.8310482080632231,)
 (α = 0.7896624913261964,)
 (α = 0.9072696692773354,)

Extract the parameter.

posterior_α = first.(posterior);
1000-element Array{Float64,1}:
 0.6268589737198517
 0.6177614659226344
 0.6260410289535695
 0.6097712078580889
 0.8091719166638041
 0.9171242806530356
 0.955274262965425
 0.956999405552833
 0.8502868819263306
 0.7870491812572781
 ⋮
 0.8161628181077263
 0.7832014896261205
 0.7872778628415527
 0.8794016378033822
 0.7900176206469055
 0.8323531735135069
 0.8310482080632231
 0.7896624913261964
 0.9072696692773354

check the effective sample size

ess_α = effective_sample_size(posterior_α)
314.8400894366724

NUTS-specific statistics

NUTS_statistics(chain)
Hamiltonian Monte Carlo sample of length 1000
  acceptance rate mean: 0.94, min/25%/median/75%/max: 0.26 0.93 0.98 1.0 1.0
  termination: AdjacentTurn => 37% DoubledTurn => 63%
  depth: 1 => 55% 2 => 36% 3 => 9%

check the mean

mean(posterior_α)
0.8184135795821647

This page was generated using Literate.jl.