Two Factor CFA with Loading Constraints

5 replies [Last post]
AN's picture
AN
Offline
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

tbrick's picture
Offline
Joined: 07/31/2009
I'd first try adding lower bounds

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.

AN's picture
AN
Offline
Joined: 12/03/2011
Two Factor CFA w Loading Constraints

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?

neale's picture
Offline
Joined: 07/31/2009
Run with them fixed to zero, then free them up.

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

AN's picture
AN
Offline
Joined: 12/03/2011
That was one value I did not try

Thank you. That worked. Zero was one value that I did not try. Since I knew the estimates were far from zero I kept trying positive values.

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

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.