Accessing MxModel objects by other than name

Posted on
Picture of user. neale 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?

Replied on Sat, 07/02/2011 - 09:18
Picture of user. Ryne Joined: 07/31/2009

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.

Replied on Sat, 07/02/2011 - 12:10
Picture of user. mspiegel Joined: 07/31/2009

In reply to by Ryne

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]])
Replied on Sun, 07/03/2011 - 08:11
Picture of user. neale Joined: 07/31/2009

In reply to by neale

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.