The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
A MIMIC (multiple-indicators multiple-causes) model adds a structural
part to the factor model: observed covariates \(X\) predict the factors, which in turn
produce the item responses \(Y\).
vbmimic() implements the extended MIMIC model of Jin &
Chen (2025, Multivariate Behavioral Research), whose
contribution is to regularize both parts:
spike-and-slab priors select unspecified entries of the measurement
design Q_A (items on factors, J x K)
and of the structural design Q_B (factors on
covariates, K x P). Both matrices use the same
-1/0/1 codes as vbfa().
With the default settings, vbmimic() reproduces the
published estimator exactly.
sim_lvm() (absorbed from the LAWBL package) generates
the data. Supply the structural coefficients as a matrix — a sparse
design where each factor is predicted by its own covariates is both
realistic and estimable:
B <- matrix(0, 3, 9)
for (k in 1:3) B[k, (k * 3 - 2):(k * 3)] <- .3 # 3 covariates per factor
sim <- sim_lvm(N = 500, K = 3, J = 18, P = 9, b = B, phx = 0, rseed = 1)
Y <- sim$dat[, 1:18] # items first ...
X <- sim$dat[, 19:27] # ... covariates last(A scalar b would make every covariate predict
every factor, which quickly leaves no disturbance variance —
sim_lvm() stops with an informative error if the design is
infeasible.)
One modelling caution, learned the empirical way: with
both Q_A and Q_B fully
exploratory the model converges cleanly but the solution is rotationally
ambiguous — factors can merge or swap. Anchoring either part resolves
it. Here we anchor two items per factor in the measurement part and
leave the whole structural part to the data:
## Q_A is an AZ (anchor-zero) design: each anchor is specified (1) on its own
## factor and fixed to zero on the other two
Q_A <- matrix(-1L, 18, 3)
for (k in 1:3) {
a <- which(rep(1:3, each = 6) == k)[1:2]
Q_A[a, ] <- 0L
Q_A[a, k] <- 1L
}
Q_B <- matrix(-1L, 3, 9) # structural selection is the questionAZ (anchor-zero) and AO (anchor-only) are the two anchor conventions
vbpm’s documentation uses throughout: AO codes each
anchor’s intended cell 1 and leaves its cells on the other
factors -1, while AZ additionally fixes those cells to
0. AZ is the stronger claim, and it is what anchors the
measurement part here; vignette("bifactor") compares the
two.
fit <- vbmimic(Y, X, Q_A, Q_B)
fit
#> vbmimic: regularized VB MIMIC model
#> 18 items, 3 factors, 9 covariates, N = 500
#> converged in 19 iterations (0.19 secs)
#> ELBO: NA (not available for this model)
#> active unspecified loadings (PIP >= 0.5): 12 of 36
#> active structural coefficients (PIP >= 0.5): 11 of 27
#>
#> Components: model, call, nobs, nitem, nfactor, converged, A, B, pi_A, pi_B, Q_A, Q_B, eta, Phi, Sig, U, V, rho, theta, A_var, B_var, iter, flag, time, ELBO, objective, objective_type, standardize, preprocess, path
#> Access them with $ as usual; see ?vbpm_fit.The structural question — which covariates predict which
factors? — is answered by B and its posterior
inclusion probabilities pi_B:
round(fit$B, 2)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#> [1,] 0.25 0.30 0.32 0.00 0.01 0.00 0.02 0.00 -0.01
#> [2,] 0.00 0.01 -0.18 0.39 0.34 0.30 0.02 -0.01 0.00
#> [3,] 0.03 -0.02 0.01 -0.14 -0.01 -0.01 0.38 0.30 0.30
round(fit$pi_B, 2)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#> [1,] 1.00 1.00 1.00 0.03 0.03 0.03 0.04 0.03 0.03
#> [2,] 0.03 0.03 1.00 1.00 1.00 1.00 0.04 0.03 0.03
#> [3,] 0.05 0.04 0.03 1.00 0.03 0.04 1.00 1.00 1.00Compare PIP-based selection with the generating design:
selected <- fit$pi_B >= .5
table(truth = B != 0, selected = selected)
#> selected
#> truth FALSE TRUE
#> FALSE 16 2
#> TRUE 0 9Read that table both ways. All nine generating coefficients are
selected — no false negatives — but so are two of the eighteen true
zeros, and not marginally: both sit at PIP 1.00 in the matrix above
(B[2, 3] and B[3, 4], each a factor picking up
a covariate from a neighbouring block). Exploratory structural selection
at this N is therefore not free of false positives, and a
PIP at the ceiling is not on its own evidence that a coefficient is
real. Magnitude is the useful second filter here: the two false
positives are estimated at -0.18 and -0.14, below every one of the nine
true coefficients, whose smallest estimate is 0.25 against a generating
value of 0.30.
The measurement side reads exactly as in vbfa():
round(fit$A, 2)[1:6, ]
#> [,1] [,2] [,3]
#> [1,] 0.64 0.00 0.00
#> [2,] 0.63 0.00 0.00
#> [3,] 0.62 -0.02 -0.01
#> [4,] 0.62 0.00 0.01
#> [5,] 0.59 0.01 -0.01
#> [6,] 0.71 0.01 -0.03
round(fit$Phi, 2) # factor correlations, from the disturbances
#> [,1] [,2] [,3]
#> [1,] 1.00 -0.05 -0.03
#> [2,] -0.05 1.00 -0.01
#> [3,] -0.03 -0.01 1.00vbmimic() accepts NA in Y; a
handful of missing item responses is enough to demonstrate it:
Ym <- Y
Ym[cbind(1:20, rep(1:4, each = 5))] <- NA
sum(is.na(Ym))
#> [1] 20
fitm <- vbmimic(Ym, X, Q_A, Q_B)
fitm$preprocess$n_missing
#> [1] 20
## structural and measurement recovery are essentially unaffected
max(abs(fitm$B - fit$B))
#> [1] 0.002613604
max(abs(fitm$A - fit$A))
#> [1] 0.005325698The residual covariance here is diagonal (vbmimic() has
no LD branch), so a missing response is replaced in-loop by its
conditional mean eta_i A', with the conditional variance
1 / V_j carried into the residual sum of squares — the same
conditional-moment logic as vbfa()’s diagonal case,
simplified because there is no cross-item residual covariance to
condition on. As with vbfa(), this in-loop treatment is
valid under missing at random (MAR) (Chen, 2021).
X must be complete. Covariates are
conditioned on, not modelled, so there is no distribution to impute them
from:
v0 path. As in vbfa(), a
decreasing vector gives a warm-started regularization path over both
parts; the scalar default 0.001 is the published fixed
spike.standardize. The default
FALSE is the published estimator’s behaviour.
vbfa() by contrast always standardizes internally; set
standardize = TRUE for the analogous behaviour.vbfa(), the
estimator consumes no random numbers — no seed argument, bit-identical
reruns.fit$ELBO is
NA. fit_stats() accepts a vbmimic
fit (it dispatches to a dedicated method) but returns a deliberately
limited result: NA for every SEM-like index
(RMSEA, BIC, ELBO,
objective, …) and a single n_active_coef — the
count of soft-selected measurement plus structural coefficients, not a
full parameter count, and not to be fed to an information criterion.
pefa() sweeps vbfa() from one backbone
Q0; it does not sweep MIMIC models.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.