Trying a LISREL example in OpenMx

1 reply [Last post]
wcyee's picture
Offline
Joined: 08/02/2010

Hi, I haven't used OpenMx before, but I started by trying an example from the LISREL book (Joreskog & Sorbom).

I've reproduced the LISREL sample below and my translation to OpenMx based on reading the beginners section in the help. The error message I get is:

"Error: The job for model 'ex6' exited abnormally with the error message: Backing out of parameter space region where expected covariance is non-positive-definite."

I'm probably doing something silly here. Any help much appreciated!

======= lisrel code ========

Stability of Alienation
Observed Variables
ANOMIA67 POWERL67 ANOMIA71 POWERL71 EDUC SEI
Covariance Matrix
11.834
6.947 9.364
6.819 5.091 12.532
4.783 5.028 7.495 9.986
-3.839 -3.889 -3.841 -3.625 9.610
-2.190 -1.883 -2.175 -1.878 3.552 4.503
Sample Size 932
Latent Variables Alien67 Alien71 Ses
Relationships
ANOMIA67 = 1*Alien67
POWERL67 = Alien67
ANOMIA71 = 1*Alien71
POWERL71 = Alien71
EDUC = 1*Ses
SEI = Ses

Alien67 = Ses
Alien71 = Alien67 Ses

Let the Errors of ANOMIA67 and ANOMIA71 Correlate
Let the Errors of POWERL67 and POWERL71 Correlate
Path Diagram
End of Problem

======= end lisrel code ========

======= openmx code ========

library(OpenMx)

varnames <- c('ANO67', 'POW67', 'ANO71', 'POW71', 'EDUC', 'SEI')
dat <- read.table('ex1-6.cov', header=FALSE, fill=TRUE, col.names=varnames)
mat <- as.matrix(dat)
rownames(mat) <- colnames(mat)
for (i in 1:6) {
for (j in 1:6) {
if (i < j) {
mat[i, j] <- mat[j, i]
}
}
}

manifests <- varnames
latents <- c('Ses', 'Alien67', 'Alien71')

model <- mxModel(name='ex6',
type='RAM',
manifestVars=manifests,
latentVars=latents,

mxPath(from=c('Ses'), to=c('SEI', 'Alien67', 'Alien71'), arrows=1, free=TRUE),
mxPath(from=c('Ses'), to=c('EDUC'), arrows=1, free=FALSE, values=1.0),

mxPath(from=c('Alien67'), to=c('Alien71', 'POW67'), arrows=1, free=TRUE),
mxPath(from=c('Alien67'), to=c('ANO67'), arrows=1, free=FALSE, values=1.0),

mxPath(from=c('Alien71'), to=c('POW71'), arrows=1, free=TRUE),
mxPath(from=c('Alien71'), to=c('ANO71'), arrows=1, free=FALSE, values=1.0),

mxPath(from=c('Alien67', 'Alien71'), arrows=2, free=TRUE),

mxPath(from=c('ANO67'), to=c('ANO71'), arrows=2, free=TRUE),
mxPath(from=c('POW67'), to=c('POW71'), arrows=2, free=TRUE),

mxPath(from=manifests, arrows=2, free=TRUE),

mxData(observed=mat, type='cov', numObs=932)
)

fit <- mxRun(model)

======= end openmx code ========

tbrick's picture
Offline
Joined: 07/31/2009
I see a few things that might

I see a few things that might be going wrong here.

First of all, double-check that your covariance matrix is reading in correctly. It would be easy to get some of the values into the wrong places.

To check, just type mat after running your for loops, and make sure the numbers are in the right places to be the full covariance matrix.

If it's not coming out right, you can type out the whole thing:

dat <- c(
11.834, 6.947, 6.819,   4.783, -3.839, -2.19, 
6.947,   9.364, 5.091,   5.028, -3.889, -1.883,
6.819,   5.091, 12.532, 7.495, -3.841, -2.175, 
4.783,   5.028, 7.495,   9.986, -3.625, -1.878, 
-3.839, -3.889, -3.841, -3.625, 9.61,   3.552, 
-2.19,  -1.883, -2.175,  -1.878, 3.552, 4.503) 
mat <- matrix(dat, nrow=6, ncol=6)
varnames <- c('ANO67', 'POW67', 'ANO71', 'POW71', 'EDUC', 'SEI')
dimnames(mat) <- list(varnames, varnames)

Which is the more verbose way of doing it.

The other problems I see are with your variance paths:

  1. The variance of SES is fixed to zero. This is because there is no two-headed arrow from SES to itself. Most likely, this was a copy-and-paste error.
    You can fix it by changing:
    mxPath(from=c('Alien67', 'Alien71'), arrows=2, free=TRUE),

    into
    mxPath(from=latents, arrows=2, free=TRUE),

    Because latents is c('SES','Aliens67', 'Aliens71'), this creates paths for all three latent variables, not just the two 'Alien' variables.
  2. The error variances for manifest variables should generally be bounded to be above zero.
    This is likely an assumption that LISREL was making for you. OpenMx requires you to specify this explicitly, because OpenMx tries not to make assumptions--it does only what you tell it to do. I usually set a lower bound at .0001.
    To specify a lower bound on your manifest variable error variances, change this line:
    mxPath(from=manifests, arrows=2, free=TRUE),

    into:
    mxPath(from=manifests, arrows=2, free=TRUE, lbound=.0001),

  3. You should specify a non-zero starting value for the variance paths in your model. Again, LISREL was picking a starting value for you based on some assumptions it made about your model. OpenMx doesn't make these assumptions--it does only what you say to do. I'll pick .2 as a starting value, but in this case it probably won't matter much what you pick, as long as it's a positive number.
    You can add starting values by changing these lines:
    mxPath(from=manifests, arrows=2, free=TRUE, lbound=.0001),
    mxPath(from=latents, arrows=2, free=TRUE, lbound=.0001),

    into:
    mxPath(from=manifests, arrows=2, free=TRUE, lbound=.0001, values=.2),
    mxPath(from=latents, arrows=2, free=TRUE, lbound=.0001, values=.2),

I've pasted the final code below, and it runs on my machine without an error. Hope that helps!


require(OpenMx)
# Set up observed covariance (NEW)
dat <- c(
11.834, 6.947, 6.819, 4.783, -3.839, -2.19,
6.947, 9.364, 5.091, 5.028, -3.889, -1.883,
6.819, 5.091, 12.532, 7.495, -3.841, -2.175,
4.783, 5.028, 7.495, 9.986, -3.625, -1.878,
-3.839, -3.889, -3.841, -3.625, 9.61, 3.552,
-2.19, -1.883, -2.175, -1.878, 3.552, 4.503)
mat <- matrix(dat, nrow=6, ncol=6)
varnames <- c('ANO67', 'POW67', 'ANO71', 'POW71', 'EDUC', 'SEI')
dimnames(mat) <- list(varnames, varnames)
 
manifests <- varnames
latents <- c('Ses', 'Alien67', 'Alien71')
model <- mxModel(name='ex6',
type='RAM',
manifestVars=manifests,
latentVars=latents,
mxPath(from=c('Ses'), to=c('SEI', 'Alien67', 'Alien71'), arrows=1, free=TRUE),
mxPath(from=c('Ses'), to=c('EDUC'), arrows=1, free=FALSE, values=1.0),
mxPath(from=c('Alien67'), to=c('Alien71', 'POW67'), arrows=1, free=TRUE),
mxPath(from=c('Alien67'), to=c('ANO67'), arrows=1, free=FALSE, values=1.0),
mxPath(from=c('Alien71'), to=c('POW71'), arrows=1, free=TRUE),
mxPath(from=c('Alien71'), to=c('ANO71'), arrows=1, free=FALSE, values=1.0),
mxPath(from=c('ANO67'), to=c('ANO71'), arrows=2, free=TRUE),
mxPath(from=c('POW67'), to=c('POW71'), arrows=2, free=TRUE),
 
# Latent variable variances (NEW)
mxPath(from=latents, arrows=2, free=TRUE, value=.2),
 
# Manifest variable variances (NEW)
mxPath(from=manifests, arrows=2, free=TRUE, lbound=.0001, value=.2),
mxData(observed=mat, type='cov', numObs=932)
)
fit <- mxRun(model)