How to specify a random intercept cross-lagged panel model in OpenMx?

Posted on
No user picture. cjvanlissa Joined: 04/10/2019
Dear readers,

I am trying to specify an RI-CLPM in OpenMx. However, if I constrain the variance of the observed indicators to zero, the model implied covariance matrix is not positive definite - but these variances are supposed to be zero, as they are partialized into a time-invariant component and a time-variant component. E.g., the variance x1 <-> x1 should be split up into RIx <-> RIx and cx1 <-> cx1.

Can anyone help me correctly specify this model in OpenMx?


df <- data.frame(matrix(rnorm(500*8), ncol = 8))
names(df) <- paste0(rep(c("x", "y"), each = 4), 1:4)

xobs <- grep("^x", names(df), value = TRUE)
yobs <- grep("^y", names(df), value = TRUE)
xvars <- paste0("c", grep("^x", names(df), value = TRUE))
yvars <- paste0("c", grep("^y", names(df), value = TRUE))
xminone <- xvars[-1]
xminend <- xvars[-length(xvars)]
yminone <- yvars[-1]
yminend <- yvars[-length(yvars)]
riclpm<-mxModel("riclpm",
type="RAM",
manifestVars=c(xobs, yobs),
latentVars = c("RIx", "RIy", xvars, yvars),
mxData(observed=df, type="raw"),
mxPath(from="RIx", to=xobs, arrows=1, free=FALSE, values=1),
mxPath(from="RIy", to=yobs, arrows=1, free=FALSE, values=1),

mxPath(from=xvars, to=xobs, arrows=1, free=FALSE, values=1),
mxPath(from=yvars, to=yobs, arrows=1, free=FALSE, values=1),

# RI cors
mxPath(from="RIy", to="RIx", arrows=2, free=TRUE, values=0),
mxPath(from=c("RIy", "RIx"), arrows=2, free=TRUE, values=0),

mxPath(from=xminend, to=xminone, arrows=1, free=TRUE, values=c(.1), labels="x_x"),
mxPath(from=yminend, to=yminone, arrows=1, free=TRUE, values=c(.1), labels="y_y"),
mxPath(from=xminend, to=yminone, arrows=1, free=TRUE, values=c(.1), labels="y_x"),
mxPath(from=yminend, to=xminone, arrows=1, free=TRUE, values=c(.1), labels="x_y"),
# Vars
mxPath(from=xvars[1], arrows=2, free=TRUE, values=c(.1), labels = "vx1"),
mxPath(from=yvars[1], arrows=2, free=TRUE, values=c(.1), labels = "vy1"),

mxPath(from=xminone, arrows=2, free=TRUE, values=c(.1), labels = "vx"),
mxPath(from=yminone, arrows=2, free=TRUE, values=c(.1), labels = "vy"),
#mxPath(from=c(xobs, yobs), arrows=2, free=TRUE, values=c(.1)),
mxPath(from=c(xobs, yobs), arrows=2, free=FALSE, values=0),
# Covars
mxPath(from=xvars[1], to = yvars[1], arrows=2, free=TRUE, values=0, labels = "rxy1"),
mxPath(from=xminone, to = yminone, arrows=2, free=TRUE, values=0, labels = "rxy"),

mxPath(from = 'one', to = c(xvars, yvars))
)
res <- mxRun(riclpm)

Replied on Fri, 02/03/2023 - 11:02
Picture of user. mhunter Joined: 07/31/2009

I ran


require(umx)
plot(riclpm)

It looked like you set the variances of `RIx` and `RIy` to zero. So, I added


mxPath(c('RIx', 'RIy'), arrows=2, values=1.5),

into your model and it ran, only giving a warning about the Hessian being non-positive definite (probably because the data were nonsense).

Does that help?

Replied on Fri, 02/03/2023 - 11:59
No user picture. cjvanlissa Joined: 04/10/2019

Dear mhunter, thank you! My code already contained the line:

mxPath(from=c("RIy", "RIx"), arrows=2, free=TRUE, values=0)

If I set this to

mxPath(from=c("RIy", "RIx"), arrows=2, free=TRUE, values=1.5)

I indeed also get the error about the Hessian (also with the real data). Also, there are no estimates - instead, the starting values are returned:


Warning message:
In model 'riclpm' Optimizer returned a non-zero status code 5. The Hessian at the solution does not appear to be convex. See ?mxCheckIdentification for possible diagnosis (Mx status RED).
> summary(res)
Summary of riclpm

The Hessian at the solution does not appear to be convex. See ?mxCheckIdentification for possible diagnosis (Mx status RED).

free parameters:
name matrix row col Estimate Std.Error A
1 x_x A cx2 cx1 0.1 NA !
2 y_x A cy2 cx1 0.1 NA !
3 x_y A cx2 cy1 0.1 NA !
4 y_y A cy2 cy1 0.1 NA !
5 riclpm.S[9,9] S RIx RIx 1.5 NA !
6 riclpm.S[9,10] S RIx RIy 0.1 NA !
7 riclpm.S[10,10] S RIy RIy 1.5 NA !
8 vx1 S cx1 cx1 0.1 NA !
9 vx S cx2 cx2 0.1 NA !
10 rxy1 S cx1 cy1 0.1 NA !
11 vy1 S cy1 cy1 0.1 NA !
12 rxy S cx2 cy2 0.1 NA !
13 vy S cy2 cy2 0.1 NA !
14 riclpm.M[1,11] M 1 cx1 0.1 8601467937 !
15 riclpm.M[1,12] M 1 cx2 0.1 8866184397 !
16 riclpm.M[1,13] M 1 cx3 0.1 9126759905 !
17 riclpm.M[1,14] M 1 cx4 0.1 7286763147 !
18 riclpm.M[1,15] M 1 cy1 0.1 8601467226 !
19 riclpm.M[1,16] M 1 cy2 0.1 8866192940 !
20 riclpm.M[1,17] M 1 cy3 0.1 9126760586 !
21 riclpm.M[1,18] M 1 cy4 0.1 7286752751 !

Replied on Fri, 02/03/2023 - 12:04
No user picture. cjvanlissa Joined: 04/10/2019

Interestingly, if I re-run that model with mxTryHard, the results are identical to the lavaan solution. So... I guess this points to a problem of bad starting values? I still don't understand why the error about the Hessian appears, nor why the model doesn't converge with mxRun.
Replied on Fri, 02/03/2023 - 13:21
Picture of user. AdminRobK Joined: 01/24/2014

In reply to by cjvanlissa

If I use `mxOption(NULL,"Default optimizer","NPSOL")` to switch optimizers to NPSOL, and then run the model, NPSOL returns status code 10 ("Starting values are not feasible"). Looking at the gradient with `res$output$gradient` reveals that some of the gradient elements are `NA` at the start values.

I'm not sure why there's no warning about the infeasible start when running the model with SLSQP, which is the on-load default optimizer. I think there ought to be such a warning. It's a useful diagnostic.

Replied on Fri, 02/03/2023 - 14:40
Picture of user. AdminRobK Joined: 01/24/2014

In reply to by cjvanlissa

I don't have any specific advice, beyond adjusting the start values. It looks like the set of start values you chose initialized optimization near the boundary of the feasible space, so that numerically differentiating the fitfunction led to non-finite values of some of the gradient elements.

As far as finding good start values is concerned, mhunter has already in this thread mentioned `mxTryHard()` and `mxAutoStart()`.

Replied on Fri, 02/03/2023 - 13:58
Picture of user. mhunter Joined: 07/31/2009

Ahh! I missed that you already had the variances for `RIx` and `RIy`. The problem seems to have been bad starting values.

As a general rule, starting values of zero are not a good idea for many parameters in many models. The initial problem was that you started a covariance matrix at all zeros. OpenMx probably (depending on mxOptions) moved these starting values to all 0.1. However, a covariance matrix of all 0.1 is also nonsense. So, you gave OpenMx nonsense implausible starting values and OpenMx did not work.

When I changed the starting value of the variances of `RIx` and `RIy` to 1.5, OpenMx did not find a reasonable solution, but at least it was able to start. `mxTryHard()` tries several "random" starting values, and at lease one of those worked to get a reasonable solution.

OpenMx requires users to think about plausible starting values for their parameters. lavaan generally does not. One option, if you're really struggling to think of plausible starting values is to use `mxAutoStart()` which uses unweighted (or optionally weighted) least squares to find starting values on many models.


ss <- mxAutoStart(riclpm)
res <- mxRun(ss)

Replied on Mon, 04/17/2023 - 10:02
No user picture. lf-araujo Joined: 11/25/2020

I came across this discussion this morning after trying to specify Hamaker2015 model exactly, and I reach the same specs as you. However, there aren't variances associated with ps and qs on hers (p. 115 on the paper)! But I couldn't get this to work in OpenMx.

The relevant lines in your code are:

mxPath(from=xminone, arrows=2, free=TRUE, values=c(.1), labels = "vx"),
mxPath(from=yminone, arrows=2, free=TRUE, values=c(.1), labels = "vy"),

Also the are no covars between xminone and yminone, it should be between vx and vy (or I am missing something). The line below would need to be edited too.

mxPath(from=xminone, to = yminone, arrows=2, free=TRUE, values=0, labels = "rxy"),

Anyway, if I make both changes so to be exactly the paper's spec I always end up with "All fit attempts resulted in errors - check starting values or model specification".

- Have you tried to reproduce Hamaker's exact specification?

Thanks