Datasets used:sleepstudy, kb07, dyestuff (see the dataset catalog).
The speed of MixedModels.jl relative to its predecessors makes the parametric bootstrap much more computationally tractable. This is valuable because the parametric bootstrap can be used to produce more accurate confidence intervals than methods based on standard errors or profiling of the likelihood surface.
Bootstrapping is a family of procedures for generating sample values of a statistic, allowing for visualization of the distribution of the statistic or for inference from this sample of values. Bootstrapping also belongs to a larger family of procedures called resampling, which are based on creating new samples of data from an existing one, then computing statistics on the new samples, in order to examine the distribution of the relevant statistics.
A parametric bootstrap is used with a parametric model, m, that has been fit to data. The procedure is to simulate n response vectors from m using the estimated parameter values and refit m to these responses in turn, accumulating the statistics of interest at each iteration.
The parameters of a LinearMixedModel object are the fixed-effects parameters (β), the standard deviation (σ), of the per-observation noise, and the covariance parameter (θ), that defines the variance-covariance matrices of the random effects. A technical description of the covariance parameter can be found in the MixedModels.jl docs. Lisa Schwetlick and Daniel Backhaus have provided a more beginner-friendly description of the covariance parameter in the documentation for MixedModelsSim.jl. For today’s purposes – looking at the uncertainty in the estimates from a fitted model – we can simply use values from the fitted model, but we will revisit the parametric bootstrap in power simulation as a convenient way to simulate new data, potentially with different parameter values, for power analysis.
Attach the packages to be used
Code
usingAlgebraOfGraphicsusingCairoMakieusingDataFramesusingMixedModelsusingMixedModelsMakieusingRandomusingMixedModelsDatasets: datasetusingSMLP2026: fit_or_restoreusingAlgebraOfGraphics: AlgebraOfGraphics as AoGconst progress =isinteractive()
Note that the precise stream of random numbers generated for a given seed can change between Julia versions. For exact reproducibility, you either need to have the exact same Julia version or use the StableRNGs package.
2 A model of moderate complexity
The kb07 data (Kronmüller & Barr, 2007) are one of the datasets provided by the MixedModels package.
The default display in Quarto uses the pretty MIME show method for the model and omits the estimated correlations of the random effects.
The VarCorr extractor displays these.
VarCorr(m0)
Column
Variance
Std.Dev
Corr.
subj
(Intercept)
91087.5446
301.8071
spkr: old
1841.1736
42.9089
+0.78
prec: maintain
3845.7309
62.0140
-0.59
+0.02
load: yes
4243.2715
65.1404
+0.36
+0.83
+0.53
item
(Intercept)
131147.0985
362.1424
spkr: old
1657.6012
40.7136
+0.44
prec: maintain
60972.1927
246.9255
-0.69
+0.35
load: yes
1794.5887
42.3626
+0.32
+0.16
-0.14
Residual
446891.5597
668.4995
None of the two-factor or three-factor interaction terms in the fixed-effects are significant. In the random-effects terms only the scalar random effects and the prec random effect for item appear to be warranted, leading to the reduced formula
The p-value of approximately 20% leads us to prefer the simpler model, m1, to the more complex, m0.
3 Bootstrap basics
To bootstrap the model parameters, first initialize a random number generator then create a bootstrap sample and extract the table of parameter estimates from it.
Tipoptsum_overrides: faster replicates at reduced precision
The keyword argument optsum_overrides passes additional arguments controlling the model fitting of each replicate, e.g. parametricbootstrap(RNG, 5_000, m1; optsum_overrides=(; ftol_rel=1e-8)). ftol_rel=1e-8 lowers the threshold for changes in the objective – more directly, the optimizer considers the model converged if the change in the deviance is less than \(10^{-8}\), which is a very small change, but larger than the default \(10^{-12}\). Because the majority of the optimization time is spent in final fine-tuning, changing this threshold can greatly speed up the fitting time at the cost of a small loss of quality in fit. For a stochastic process like the bootstrap, that change in quality just adds to the general noise, but that’s an acceptable tradeoff in order to get many more replicates. The MixedModels.jl documentation also includes a little note on the reduced precision bootstrap.
An empirical density plot of the estimates of the residual standard deviation is obtained as
plt =data(tbl) *mapping(:σ) * AoG.density()draw(plt; axis=(;title="Parametric bootstrap estimates of σ"))
A density plot of the estimates of the standard deviation of the random effects is obtained as
plt =data(tbl) *mapping( [:σ1, :σ2, :σ3] .=>"Bootstrap replicates of standard deviations"; color=dims(1) =>renamer(["Item intercept", "Item speaker", "Subj"])) * AoG.density()draw(plt; figure=(;supertitle="Parametric bootstrap estimates of variance components"))
The bootstrap sample can be used to generate intervals that cover a certain percentage of the bootstrapped values. We refer to these as “coverage intervals”, similar to a confidence interval. The shortest such intervals, obtained with the confint extractor, correspond to a highest posterior density interval in Bayesian inference.
We generate these for all random and fixed effects:
plt =data(tbldye) *mapping(:σ1) * AoG.density()draw(plt; axis=(;title="Parametric bootstrap estimates of σ_batch"))
Notice that this density plot has a spike, or mode, at zero. Although this mode appears to be diffuse, this is an artifact of the way that density plots are created. In fact, it is a pulse, as can be seen from a histogram.
plt =data(tbldye) *mapping(:σ1) * AoG.histogram(;bins=100)draw(plt; axis=(;title="Parametric bootstrap estimates of σ_batch"))
A value of zero for the standard deviation of the random effects is an example of a singular covariance. It is easy to detect the singularity in the case of a scalar random-effects term. However, it is not as straightforward to detect singularity in vector-valued random-effects terms.
For example, if we bootstrap a model fit to the sleepstudy data
sleepstudy =dataset(:sleepstudy)msleep =fit(MixedModel, @formula(reaction ~1+ days + (1+ days | subj)), sleepstudy)
A histogram of the estimated correlations from the bootstrap sample has a spike at +1.
plt =data(tblsleep) *mapping(:ρ1) * AoG.histogram(;bins=100)draw(plt; axis=(;title="Parametric bootstrap samples of correlation of random effects"))
or, as a count,
count(tblsleep.ρ1.≈1)
312
Close examination of the histogram shows a few values of -1.
count(tblsleep.ρ1.≈-1)
0
Furthermore there are even a few cases where the estimate of the standard deviation of the random effect for the intercept is zero.
count(tblsleep.σ1.≈0)
1
There is a general condition to check for singularity of an estimated covariance matrix or matrices in a bootstrap sample. The parameter optimized in the estimation is θ, the relative covariance parameter. Some of the elements of this parameter vector must be non-negative and, when one of these components is approximately zero, one of the covariance matrices will be singular.
The issingular method for a MixedModel object that tests if a parameter vector θ corresponds to a boundary or singular fit.
This operation is encapsulated in a method for the issingular function that works on MixedModelBootstrap objects.
The introductory chapter of Embrace Uncertainty — the theory behind the parametric bootstrap and coverage intervals, on the simplest possible example.
6 References
Kronmüller, E., & Barr, D. J. (2007). Perspective-free pragmatics: Broken precedents and the recovery-from-preemption hypothesis. Journal of Memory and Language, 56(3), 436–455. https://doi.org/10.1016/j.jml.2006.05.002
6.1 Exercises
A small bootstrap. Run a parametric bootstrap with a modest number of replicates on the sleepstudy random-slope model and report a 95% confidence interval for the days effect.
NoteSolution
Use a fixed RNG for reproducibility and shortestcovint (or the confint method) on the bootstrap object.
usingRandomdf =DataFrame(dataset(:sleepstudy))m =fit(MixedModel, @formula(reaction ~1+ days + (1+ days | subj)), df)boot =parametricbootstrap(MersenneTwister(42), 1000, m)DataFrame(shortestcovint(boot))
Count the singular fits. Of your bootstrap replicates, how many produced a singular fit? Why does that matter for interpreting the bootstrap distribution of the correlation parameter?
NoteSolution
count(issingular, boot) (or inspecting the relevant column) gives the number of singular replicates. A large fraction of singular fits means the correlation parameter is poorly identified, so its bootstrap distribution piles up at ±1 and its confidence interval should be read with caution.
This page was rendered from git revision 29e8d33
using Quarto 1.10.18 and Julia 1.12.7.