Accessing MxModel objects by other than name

4 replies [Last post]
neale's picture
Offline
Joined: 07/31/2009

So I am familiar with being able to refer to an MxModel object, and in particular its objective function, by name, thusly:

algObj <- mxAlgebra(-2*sum(log(classProbs[1,1]%x%Class1.objective + classProbs[2,1]%x%Class2.objective)), name="mixtureObj")

where Class1 and Class2 are models, and their vector=T (individual observation vector) likelihoods are returned in Class1.objective & Class2.objective vectors. However, I am trying to specify a model with hundreds of models, and it would be much more convenient to be able to refer to them by an array index variable, so that I could use something like

algObj <- mxAlgebra(-2*sum(log(classProbs[1,1]%x%submodels[1].objective + classProbs[2,1]%x%submodels[2].objective)), name="mixtureObj")

with a view to having a much simplified matrix algebra form for the -2lnL, constructed by, e.g., cbind'ing all the vector=TRUE'd likelihoods (not quite sure how to do this within mxAlgebra() either), and post-multiplying that matrix by the classProbs matrix.

I have a feeling I may be needing mxRowObjective() but perhaps someone else has tackled this problem?

Ryne's picture
Offline
Joined: 07/31/2009
Ooh. Fun problem. I don't

Ooh. Fun problem.

I don't think you can get at the submodels in the way you like. However, I assume that you're not specifying hundreds of models manually, which gives you Rish ways of dealing with this. To make this brief, I'll assume that your submodels written with an intuitive naming scheme ("Model1", "Model2", etc), and already exist someplace/can be added to your model. Furthermore, assume myModelNames is a vector of these model names.

So use paste. Or rather, two paste functions: one to make the n-length set of operations to be summed, and one to collapse them all together.

paste("algObj <- mxAlgebra(-2*sum(log(", 
paste(paste("classProbs[", 1:n, ",1]%x%", myModelNames, ".objective", sep="), collapse=" + "),
")), name="mixtureObj")", sep="")

The middle line will yield everything from the first classProbs[1,1] to the last model.objective, while the first and last put the header and footer on. There may also be a way to make a matrix of objective results through square bracket substitution.

mspiegel's picture
Offline
Joined: 07/31/2009
Umm, let's split this into

Umm, let's split this into small pieces.

objectives <- paste(myModelNames, 'objective', sep=".")
modelnumbers <- 1:length(myModelNames)
components <- paste("classProbs[", modelnumbers, ",1]", 
     " %x% ", objectives, sep = '')
componentsSum <- paste(components, collapse = " + ")
algebraString <- paste("mxAlgebra(-2*sum(log(", 
    componentsSum, ")), name='mixtureObj')", sep = "")
algebraObjective <- eval(parse(text=algebraString)[[1]])

neale's picture
Offline
Joined: 07/31/2009
nice

Thanks guys, I'll give these ideas a whirl & let you know how I get on.

neale's picture
Offline
Joined: 07/31/2009
Success!

So I followed the advice of my esteemed colleagues Michael Spiegel and Ryne Estabrook, and rebuilt Ryne's Latent Growth Mixture Model script GrowthMixtureModel_MatrixRaw.R so that it generalizes to nclasses. It also takes advantage of mxAlgebra() calls to set up the model more succinctly. The script now returns same results when nclass <- 2, but also runs for nclass <- 3. Without a few different starting values, I can't be sure that where it ends up with nclass <- 3 is the global minimum for this model, but at least it fits better than when nclass <- 2. Script is attached.

AttachmentSize
GrowthMixtureModel_MatrixRawMCN3.R 5.11 KB