Mode Estimation
Mode estimation can be useful when full Bayesian inference is not desired, or when one wishes to initialize an MCMC sampling algorithm near the mode of the posterior distribution. Below, we show how to estimate the mode of a posterior distribution using Turing's capabilities for maximum likelihood estimation (MLE) and maximum a postiori (MAP).
Example
For this simple example, we will estimate the mode of the posterior distribution of the Wald model. In the code block below, we will load the required packages.
Load Packages
using Turing
using SequentialSamplingModels
using Random
Random.seed!(654)
Generate Data
We will generate 50 simulated reaction times from the Wald model.
n_samples = 50
rts = rand(Wald(ν=1.5, α=.8, τ=.3), n_samples)
Define Turing Model
Below, we define a Turing model with prior distributions specified. Note that the prior distributions are only applicable to MAP.
@model function model(rts; min_rt = minimum(rts))
ν ~ truncated(Normal(1.5, 1), 0, Inf)
α ~ truncated(Normal(.8, 1), 0, Inf)
τ ~ Uniform(0, min_rt)
rts ~ Wald(ν, α, τ)
return (;ν, α, τ)
end
Set Parameter Bounds
Specifying lower and upper bounds for the parameters is necessary to prevent the MLE and MAP estimators from searching invalid regions of the parameter space.
lb = [0,0,0]
ub = [10, 10, minimum(rts)]
MLE
MLE is performed via the function maximum_likelihood
.
mle_estimate = maximum_likelihood(model(rts); lb, ub)
ModeResult with maximized lp of -7.62
[1.441581500744421, 0.6990063775377103, 0.32611139519154697]
MAP
MAP is performed via the function maximum_a_posteriori
.
map_estimate = maximum_a_posteriori(model(rts); lb, ub)
ModeResult with maximized lp of -8.20
[1.4488716348067334, 0.7022870580892082, 0.3255810892442324]
In both cases, the estimates are in the proximity of the data-generating values.
Accessing Estimates
The estimates are located in the field values
, which can be accessed as follows:
map_estimate.values
which returns a named vector. To obtain a regular vector, append .array
to the code above.
Seeding MCMC Sampler
You can seed the MCMC sampler as illustrated below:
chain = sample(model(rts), NUTS(), 1_000; initial_params=map_estimate.values.array)
┌ Info: Found initial step size
└ ϵ = 0.05
Chains MCMC chain (1000×15×1 Array{Float64, 3}):
Iterations = 501:1:1500
Number of chains = 1
Samples per chain = 1000
Wall duration = 3.97 seconds
Compute duration = 3.97 seconds
parameters = ν, α, τ
internals = lp, n_steps, is_accept, acceptance_rate, log_density, hamiltonian_energy, hamiltonian_energy_error, max_hamiltonian_energy_error, tree_depth, numerical_error, step_size, nom_step_size
Summary Statistics
parameters mean std mcse ess_bulk ess_tail rhat ess_per_sec
Symbol Float64 Float64 Float64 Float64 Float64 Float64 Float64
ν 1.5597 0.3184 0.0228 202.3201 154.0195 1.0087 50.9366
α 0.8230 0.2030 0.0185 163.9590 80.6732 1.0096 41.2787
τ 0.2937 0.0474 0.0043 174.7682 106.7551 1.0117 44.0000
Quantiles
parameters 2.5% 25.0% 50.0% 75.0% 97.5%
Symbol Float64 Float64 Float64 Float64 Float64
ν 0.9220 1.3475 1.5532 1.7466 2.2150
α 0.5375 0.6884 0.7853 0.9231 1.3999
τ 0.1533 0.2720 0.3055 0.3261 0.3516
Additional details can be found in the Turing documentation