This is a test case for regularization of SEM in OpenMx. Expect regular changes to the interface until we manage to get things right.
We need to load the appropriate libraries and a data set from lavaan. We'll want to switch to a different example just to avoid the dependency, but for now we can assume everybody comfortable with OpenMx is comfortable installing lavaan as well. We'll also be using regsem with lavaan as the test case, so the dependency is there regardless.
We load the example from the HolzingerSwineford data set.
library(mxregsem) # library(regsem) HS <- as.matrix(scale(get(data(HolzingerSwineford1939, package="lavaan"))[,7:15]))
The OpenMx model is a typical CFA with latent variances and a saturated manifest means model.
nVars <- 9 manifest = paste0("x", 1:nVars) # manifest variable names latent = c("f1") # latent variable name # Regularization choice from nowhere. pen.seq = c(0,(seq(1,sqrt(nrow(HS)),length.out=99)**2)) pen.val <- pen.seq[40] # Model cfaModel <- mxModel("cfaModel", type = "RAM", manifestVars = manifest, latentVars = latent, # Means mxPath(from='one',to=manifest,arrows=1,free=T), # Variances mxPath(from = "f1", arrows = 2, free = T, values = 1, labels="F1_Var"), mxPath(from= manifest, arrows = 2, free = T, values = 1), #Loadings mxPath(from = "f1", to = manifest, values = 1, free = c(FALSE,rep(TRUE,nVars-1))), #Data mxData(observed = cov(HS), type = "cov", means=colMeans(HS), numObs=nrow(HS)))
In the new construction, we simply add a penalty directly.
tLasso <- mxRegularizeLASSO(what = getParamsInMatrix(cfaModel, "A"), name="LASSO", lambda = pen.val, lambda.min = 0, lambda.max = nrow(HS), lambda.step = 1) regModel <- mxModel(cfaModel, tLasso)
We run normally, but need to use the specialized regularization function until we get around to integrating this into the underlying OpenMx code.
regFit <- mxPenaltySearchExternal(regModel) (regsum <- summary(regFit, verbose=TRUE))
The regsem version of the same model is this one:
library(regsem) mod.lav <- " f =~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9" lav.out <- cfa(mod.lav,HS) summary(lav.out) cv.out <- cv_regsem(lav.out,pars_pen="loadings", metric= "BIC") cv.out
Checking for close enough fit:
omxCheckCloseEnough(cv.out$parameters[19,1:8], coef(regFit)[1:8], .002) cbind(regsem=cv.out$parameters[19,1:8], mxregsem=round(coef(regFit)[1:8], 3), pcterror=round(abs(cv.out$parameters[19,1:8]-coef(regFit)[1:8])/cv.out$parameters[19,1:8]*100, 1))
Close enough!
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.