Two Factor CFA with Loading Constraints

Posted on
No user picture. AN Joined: 12/03/2011
I am new to OpenMx and trying to resolve a problem with non-positive definite covariance matrix. I have looked at other postings in this forum and it looks like it is a starting value problem although not sure. I have tried several combinations and keep getting the same error. I am listing my code and would appreciate any help.

Thanks

I keep getting the following error:

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

# -----------------------------------------------------------------------------
# Load Library #
require(OpenMx)
#-----------------------------------------------------------------------------
# read Data #
polidem.data <- read.csv('POLIDEM.csv')
head(polidem.data)

polidem.cfa <- polidem.data[,c("PRESS60","FREOP60","FREEL60","LEGIS60","PRESS65","FREOP65","FREEL65","LEGIS65")]

#-----------------------------------------------------------------------------
manifde60=c("PRESS60","FREOP60","FREEL60","LEGIS60")
manifde65=c("PRESS65","FREOP65","FREEL65","LEGIS65")
manifest=c(manifde60,manifde65)
latents=c("demo60","demo65")

#--start model-------
PolidemModel <- mxModel("Political Democracy CFA",
type="RAM",
mxData( observed=cov(polidem.cfa),
type="cov",numObs=75 ),
manifestVars=manifest,
latentVars=latents,
# residual variances #
mxPath(
from=manifest,
arrows=2,
free=TRUE,
values=c(1,0.8,0.8,0.8,0.8,0.8,0.8,0.8),
labels=c("e1","e2","e3","e4","e5","e6","e7","e8") ),
# latent variances for exogenous #
mxPath(
from=latents,
arrows=2,
free=TRUE,
values=c(0.6,0.6),
labels=c("varF1","varF2") ),
#latent covariance
mxPath(
from="demo60",
to="demo65",
arrows=2,
free=TRUE,
values=c(0.5),
labels=c("covF1F2") ),
# error covariance #
mxPath(
from="PRESS60",to="PRESS65",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the15") ),
# error covariance #
mxPath(
from="FREOP60",to="FREOP65",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the26") ),
# error covariance #
mxPath(
from="FREEL60",to="FREEL65",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the37") ),
# error covariance #
mxPath(
from="LEGIS60",to="LEGIS65",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the48") ),
# error covariance #
mxPath(
from="FREOP60",to="LEGIS60",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the24") ),
# error covariance #
mxPath(
from="FREOP65",to="LEGIS65",
arrows=2,
free=TRUE,
values=c(.5),
labels=c("the68") ),
#-------------------------------------
# factor loadings for demo60 variables #
mxPath(
from="demo60",
to=manifde60,
arrows=1,
free=c(FALSE,TRUE,TRUE,TRUE),
values=c(1,0.2,0.2,0.2),
labels=c("l1","l2","l3","l4") ),
# factor loadings for demo65 variables #
mxPath(
from="demo65",
to=manifde65,
arrows=1,
free=c(FALSE,TRUE,TRUE,TRUE),
values=c(1,0.2,0.2,0.2),
labels=c("l1","l2","l3","l4") )

# -----------------------------------------------------------------------------
)
# close model #

# -----------------------------------------------------------------------------
##run model
PolidemFit <- mxRun(PolidemModel)
##get summary
summary(PolidemFit)
##get estmates
PolidemFit@output$estimate

Replied on Sun, 12/04/2011 - 05:38
Picture of user. tbrick Joined: 07/31/2009

I'd first try adding lower bounds to your residual variances. Just add the argument lbound=.001 (or .01, or .0001) to the mxPath command for your residuals. Often that's enough to keep the optimizer in valid likelihood space.

If it works, be sure to check your results. If you find that one of your estimated variances is right up against the lower bound you set, there may be other problems with the model.

What's happening is that the optimizer is moving away from the starting values, but is getting stuck in a bad area of the likelihood space. Restricting variances to be positive may be enough to nudge it into the valid area of the space. I'll talk to the rest of the dev team about making that error message more informative.

Replied on Sun, 12/04/2011 - 14:38
No user picture. AN Joined: 12/03/2011

In reply to by tbrick

Thank you for the quick reply.

The problem seems to be with the two error covariance terms (labels="the24" & "the68" in mycode). I am able to estimate all other parameters. I tried different start values and lbounds for these two parameters and still cannot get it to work.

Any suggestions?

Replied on Wed, 12/07/2011 - 15:58
Picture of user. neale Joined: 07/31/2009

In reply to by AN

So, change the initial script lines defining these paths to
mxPath(
from="FREOP60",to="LEGIS60",
arrows=2,
free=F,
values=c(0),
labels=c("the24") ),
# error covariance #
mxPath(
from="FREOP65",to="LEGIS65",
arrows=2,
free=F,
values=c(0),
labels=c("the68") ),

And then after

##run model
PolidemFit <- mxRun(PolidemModel)
##get summary
summary(PolidemFit)
##get estmates
PolidemFit@output$estimate

Add:

PolidemModel2 <- mxModel(PolidemModel,
mxPath(from="FREOP60",to="LEGIS60", arrows=2, free=TRUE, values=c(0), labels=c("the24") ),
# error covariance #
mxPath(from="FREOP65",to="LEGIS65", arrows=2, free=TRUE, values=c(0), labels=c("the68") )
)

##run revised model
PolidemFit2 <- mxRun(PolidemModel2)
##get summary
summary(PolidemFit2)
##get estmates
PolidemFit2@output$estimate

Replied on Thu, 12/08/2011 - 15:37
Picture of user. neale Joined: 07/31/2009

In reply to by AN

I'm glad it did. In general, specifying covariances directly in a model runs the risk of generating covariances that exceed the (square root of the product of the corresponding) variances. Usually, starting estimation where the model is positive definite solves the problem (as it did in your case). Inspection of the predicted covariance matrices at the start values is a valuable diagnostic tool.

Sometimes starting certain parameters at zero does not work, especially when the input matrices (or raw data) are not positive definite. In such cases, wherever you start optimization, the optimizer will sail towards the non-positive definite region and either partially or completely fail to find a solution. OpenMx has some built-in algorithms to help steer optimization away from such regions, but if the data are saying that is where it should go, it will, albeit with some complaining and instability of solution.

In many instances it is possible to avoid such problems altogether by re-specifying the model. For example, rather than adding a covariance path between residuals (or observed variables), a latent factor can be added with directional paths to both variables, and with these paths set equal to each other. Doing so would add variance to the targeted variables, as well as covariance to them, so non-positive definiteness would be less of a liability. There would be the possibly unwanted side-effect of forcing the covariance to be positive, but that could be switched to being forced to be negative instead, if needed.