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, ))
-1.4020427180880297

Write a function to return properly dimensioned transformation.

problem_transformation(p::BernoulliProblem) =
    as((α = as𝕀, ),  )
problem_transformation (generic function with 1 method)

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

P = TransformedLogDensity(problem_transformation(p), p)
∇P = ADgradient(:ForwardDiff, P);

#import Zygote
#∇P = ADgradient(:Zygote, P);

Sample

chain, NUTS_tuned = NUTS_init_tune_mcmc(∇P, 1000)
(NUTS_Transition{Array{Float64,1},Float64}[NUTS_Transition{Array{Float64,1},Float64}([-1.016922479913577], -3.6541274324595574, 2, DynamicHMC.AdjacentTurn, 0.9124966260039936, 7), NUTS_Transition{Array{Float64,1},Float64}([-1.1645638780220735], -4.059328872229385, 1, DynamicHMC.DoubledTurn, 0.9466891548535735, 1), NUTS_Transition{Array{Float64,1},Float64}([0.15940491125123024], -3.758395824570598, 2, DynamicHMC.AdjacentTurn, 1.0, 7), NUTS_Transition{Array{Float64,1},Float64}([-0.3576996218592686], -3.3541649131014077, 2, DynamicHMC.DoubledTurn, 0.9461739470411451, 3), NUTS_Transition{Array{Float64,1},Float64}([0.5444872285799939], -4.005115368887483, 1, DynamicHMC.AdjacentTurn, 0.8154464316916088, 3), NUTS_Transition{Array{Float64,1},Float64}([-0.30135496918986016], -3.7486528761570113, 1, DynamicHMC.AdjacentTurn, 0.962415822425741, 3), NUTS_Transition{Array{Float64,1},Float64}([-0.5404634180568781], -2.981801219918469, 2, DynamicHMC.DoubledTurn, 0.9745912674970318, 3), NUTS_Transition{Array{Float64,1},Float64}([0.07563336698986356], -3.2295665159818667, 1, DynamicHMC.AdjacentTurn, 0.9676914252790375, 3), NUTS_Transition{Array{Float64,1},Float64}([-1.0946238294401176], -3.812365020723312, 2, DynamicHMC.DoubledTurn, 0.8861414854003081, 3), NUTS_Transition{Array{Float64,1},Float64}([-1.0246405874094588], -3.9168628313708553, 1, DynamicHMC.DoubledTurn, 1.0, 1)  …  NUTS_Transition{Array{Float64,1},Float64}([-0.3822466568968601], -2.811852938305918, 1, DynamicHMC.AdjacentTurn, 0.9881013676229246, 3), NUTS_Transition{Array{Float64,1},Float64}([-0.14477322951527954], -2.8211756529395973, 1, DynamicHMC.AdjacentTurn, 0.9966308713812483, 3), NUTS_Transition{Array{Float64,1},Float64}([-0.08138014620247075], -3.1474509395494947, 2, DynamicHMC.DoubledTurn, 0.9428735439491662, 3), NUTS_Transition{Array{Float64,1},Float64}([-1.0841070992761512], -3.8150943647166087, 2, DynamicHMC.DoubledTurn, 0.8719370768920228, 3), NUTS_Transition{Array{Float64,1},Float64}([0.24528450295798265], -5.03355389015074, 1, DynamicHMC.AdjacentTurn, 0.8970438564320938, 3), NUTS_Transition{Array{Float64,1},Float64}([0.47745328256923114], -3.3420991161287077, 2, DynamicHMC.DoubledTurn, 0.9763685922138214, 3), NUTS_Transition{Array{Float64,1},Float64}([0.47745328256923114], -4.01444021266594, 1, DynamicHMC.DoubledTurn, 0.8454214415932366, 1), NUTS_Transition{Array{Float64,1},Float64}([0.4865087898585469], -3.4770453136027366, 1, DynamicHMC.DoubledTurn, 0.9966223264496923, 1), NUTS_Transition{Array{Float64,1},Float64}([-1.2366661395167877], -6.87402131162114, 1, DynamicHMC.AdjacentTurn, 0.5925825853237678, 3), NUTS_Transition{Array{Float64,1},Float64}([-0.943951051310396], -4.060580888336315, 1, DynamicHMC.DoubledTurn, 1.0, 1)], NUTS sampler in 1 dimensions
  stepsize (ϵ) ≈ 0.933
  maximum depth = 10
  Gaussian kinetic energy, √diag(M⁻¹): [0.6060977800908485]
)

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.26562729747081265,)
 (α = 0.23783899406558046,)
 (α = 0.5397670569556116,) 
 (α = 0.41151653645788216,)
 (α = 0.632855642678423,)  
 (α = 0.4252262831657244,) 
 (α = 0.3680797859995336,) 
 (α = 0.5188993332843538,) 
 (α = 0.25074858153462365,)
 (α = 0.26412445656198774,)
 ⋮                         
 (α = 0.4638697759024505,) 
 (α = 0.4796661843220961,) 
 (α = 0.25272957339729346,)
 (α = 0.5610155181058538,) 
 (α = 0.617146324471203,)  
 (α = 0.617146324471203,)  
 (α = 0.6192836482804898,) 
 (α = 0.22501682547729007,)
 (α = 0.2801029399583933,) 

Extract the parameter.

posterior_α = first.(posterior);
1000-element Array{Float64,1}:
 0.26562729747081265
 0.23783899406558046
 0.5397670569556116 
 0.41151653645788216
 0.632855642678423  
 0.4252262831657244 
 0.3680797859995336 
 0.5188993332843538 
 0.25074858153462365
 0.26412445656198774
 ⋮                  
 0.4638697759024505 
 0.4796661843220961 
 0.25272957339729346
 0.5610155181058538 
 0.617146324471203  
 0.617146324471203  
 0.6192836482804898 
 0.22501682547729007
 0.2801029399583933 

check the effective sample size

ess_α = effective_sample_size(posterior_α)
352.0211439484193

NUTS-specific statistics

NUTS_statistics(chain)
Hamiltonian Monte Carlo sample of length 1000
  acceptance rate mean: 0.94, min/25%/median/75%/max: 0.28 0.92 0.98 1.0 1.0
  termination: AdjacentTurn => 42% DoubledTurn => 58%
  depth: 1 => 64% 2 => 35% 3 => 0%

check the mean

mean(posterior_α)
0.4565266715691886

This page was generated using Literate.jl.