Can OpenMx fit Factor Mixture Models (FMM)?

Posted on
No user picture. ZZ Joined: 07/22/2018
Dear Users and Maintainers,

Have you used OpenMx to fit Factor Mixture Models (FMM)? I saw that feature in Mplus but I couldn't figure out whether OpenMx can do it or not. Hence the question. Guidance on how to fit FMM using OpenMx would be much appreciated.

Replied on Mon, 07/23/2018 - 15:14
Picture of user. jpritikin Joined: 05/23/2012

Yeah, I bet OpenMx can do it. Is there a specific model from the Mplus user guide that you'd like to see translated into OpenMx?
Replied on Wed, 07/25/2018 - 17:04
Picture of user. mhunter Joined: 07/31/2009

Here's an example Growth Mixture Model. A growth mixture model is a factor mixture model with fixed factor loadings. It's probably easy enough to modify this script to freely estimate the loadings.

The latest version of the demo script is run-able with

require(OpenMx)
demo(package='OpenMx', 'GrowthMixtureModel_PathRaw')

Here' the code for inspection.


# -----------------------------------------------------------------------------

require(OpenMx)
# Load Libraries
# -----------------------------------------------------------------------------

data(myGrowthMixtureData)
# Prepare Data
# -----------------------------------------------------------------------------

# residual variances
resVars <- mxPath( from=c("x1","x2","x3","x4","x5"), arrows=2,
free=TRUE, values = c(1,1,1,1,1),
labels=c("residual","residual","residual","residual","residual") )
# latent variances and covariance
latVars <- mxPath( from=c("intercept","slope"), arrows=2, connect="unique.pairs",
free=TRUE, values=c(1,.4,1), labels=c("vari1","cov1","vars1") )
# intercept loadings
intLoads <- mxPath( from="intercept", to=c("x1","x2","x3","x4","x5"), arrows=1,
free=FALSE, values=c(1,1,1,1,1) )
# slope loadings
sloLoads <- mxPath( from="slope", to=c("x1","x2","x3","x4","x5"), arrows=1,
free=FALSE, values=c(0,1,2,3,4) )
# manifest means
manMeans <- mxPath( from="one", to=c("x1","x2", "x3", "x4","x5"), arrows=1,
free=FALSE, values=c(0,0,0,0,0) )
# latent means
latMeans <- mxPath( from="one", to=c("intercept","slope"), arrows=1,
free=TRUE, values=c(0,-1), labels=c("meani1","means1") )
# enable the likelihood vector
funML <- mxFitFunctionML(vector=TRUE)
class1 <- mxModel("Class1", type="RAM",
manifestVars=c("x1","x2","x3","x4","x5"),
latentVars=c("intercept","slope"),
resVars, latVars, intLoads, sloLoads, manMeans, latMeans,
funML)

# latent variances and covariance
latVars2 <- mxPath( from=c("intercept","slope"), arrows=2, connect="unique.pairs",
free=TRUE, values=c(1,.5,1), labels=c("vari2","cov2","vars2") )
# latent means
latMeans2 <- mxPath( from="one", to=c("intercept", "slope"), arrows=1,
free=TRUE, values=c(5,1), labels=c("meani2","means2") )
class2 <- mxModel(class1, name="Class2", latVars2, latMeans2)

# Create an MxModel object
# -----------------------------------------------------------------------------

# request that individual likelihoods are used
# required for correct parameterization of class probabilities
classP <- mxMatrix( type="Full", nrow=2, ncol=1,
free=c(TRUE, FALSE), values=1, lbound=0.001,
labels = c("p1","p2"), name="Props" )
mixExp <- mxExpectationMixture(components=c('Class1', 'Class2'), weights='Props', scale='sum')
fit <- mxFitFunctionML()
dataRaw <- mxData( observed=myGrowthMixtureData, type="raw" )

gmm <- mxModel("Growth Mixture Model",
dataRaw, class1, class2, classP, mixExp, fit)

gmmFit <- mxRun(gmm, suppressWarnings=TRUE)

summary(gmmFit)

# Unscaled mixture proportions
mxEval(Props, gmmFit)

# Scaled mixture proportions
gmmFit$expectation$output$weights

omxCheckCloseEnough(-2*logLik(gmmFit), 8739.05, 0.01)
omxCheckCloseEnough(max(gmmFit$expectation$output$weights), 0.6009, 0.01)
omxCheckCloseEnough(min(gmmFit$expectation$output$weights), 0.3991, 0.01)
# Check to see if results match within the specified bounds
# -----------------------------------------------------------------------------

Note that you could scale the mixture proportions differently if you want. See the scale argument of ?mxExpectationMixture for details. Many other software packages only allow "multinomial logisitc regression" or what we call "softmax" scaling.