Custom R fit function with algebras - possible?

Posted on
No user picture. CharlesD Joined: 04/30/2013
Forums
My attempts to specify a custom R objective function with mxFitFunctionR (using latest build from the git mirror) are not working, because it seems as though the model that gets passed into the fitfunction is with all the algebras unevaluated. Am I doing something wrong, or thinking about this completely wrong? Is there a way I can achieve similar with the algebras evaluated? Below is a minimal example modified from the mxFitFunctionR example. Thanks!

A <- mxMatrix(nrow = 4, ncol = 1, values = c(6:9), free = TRUE, name = 'A')
B <- mxMatrix(nrow = 4, ncol = 1, values = c(10:13), free = FALSE, labels=paste0("testalg[",1:4,",1]"),name = 'B')
testalg<-mxAlgebra(A%x%2,name="testalg")
squared <- function(x) { x ^ 2 }

# Define the objective function in R

objFunction <- function(model, state) {
# browser()
values <- model[['B']]@values
print("i")
return(squared(values[1,1] - 4) + squared(values[2,1] + 3)+
squared(values[3,1] - 30)+squared(values[4,1] - 2))
}

# Define the expectation function

fitFunction <- mxFitFunctionR(objFunction)

# Define the model

tmpModel <- mxModel('exampleModel', A, B,testalg, fitFunction)

# Fit the model and print a summary

tmpModelOut <- mxRun(tmpModel)
summary(tmpModelOut)

Replied on Sun, 04/06/2014 - 10:48
Picture of user. mhunter Joined: 07/31/2009

Hi Charles,

I'll give you some code that works, and then explain the key difference from the code that did not work. Here's the code.


require(OpenMx)

A <- mxMatrix(nrow = 4, ncol = 1, values = c(6:9), free = TRUE, name = 'A')
B <- mxMatrix(nrow = 4, ncol = 1, values = c(10:13), free = FALSE, labels=paste("testalg[",1:4,",1]", sep=''),name = 'B')
testalg<-mxAlgebra(A%x%2,name="testalg")
squared <- function(x) { x ^ 2 }

# Define the objective function in R

objFunction <- function(model, state) {
# browser()
#values <- model[['B']]@values
values <- mxEval(B, model=model, compute=TRUE) #### Key Difference
print("i")
return(squared(values[1,1] - 4) + squared(values[2,1] + 3)+
squared(values[3,1] - 30)+squared(values[4,1] - 2))
}

# Define the expectation function

fitFunction <- mxFitFunctionR(objFunction)

# Define the model

tmpModel <- mxModel('exampleModel', A, B,testalg, fitFunction)

# Fit the model and print a summary

tmpModelOut <- mxRun(tmpModel)
summary(tmpModelOut)

The key difference is using mxEval. This is the preferred method for getting the values of a mxMatrix or the result of an mxAlgebra. OpenMx does not automatically evaluate mxAlgebras in the frontend, or when you use R fit functions. OpenMx has a system of knowing in the backend when mxAlgebras need to be evaluated and when they can be left alone. So, when you're using mxAlgebra's with an R fit function, the R fit function should probably use mxEval with compute=TRUE.