parameter constraints

Dear all,
sorry for this simple question. What I want to do is to impose a simple parameter constraint. If I want to set two parameters equal, I simply use the same label. However, what if I want to set parameter a = 2*b, so that actually only one parameter is freely estimated?
After searching the archives, the only cumbersome way I came up with is to define two new matrices with a single element but new names, use the mxAlgebra function to multiply by two and then use the mxConstraint function to set the matrices equal. So I did something like that
mxMatrix(type = "Full", nrow=1, ncol=1, free=F, values = 0, label="a", name="con_a"),
mxMatrix(type = "Full", nrow=1, ncol=1, free=T, values = 1, label="b", name="con_b"),
mxAlgebra(expression= 2*con_b, name="con"),
mxConstraint("con", "=", "con_a"),
But then something goes wrong, and I am not sure why. Do I have to define the elements of both matrices as free? fixed? Is not there a simpler way? This seems overly complicated.
Thank you very much!
This is a great question.
This is a great question. Don't apologize for it!
Both parameters should be free in the specification you gave above. The code you gave above fixes the "a" parameter to a value of zero.
You have two alternatives, one new and OpenMx-y, and one old school and LISREL-y. The novel way would be to define the "b" parameter not in a matrix, but in an algebra. OpenMx can treat the output of an mxAlgebra as a matrix. So you could define your "b" parameter as:
mxMatrix("Full", 1, 1, T, 0, name="a")
mxAlgebra(a * 2, name="b")
Technically, "a" and "b" aren't parameters in what I have you above; they're 1 x 1 matrices with unnamed parameters in them. Feel free to adjust the names as needed, remembering that it's the matrix name that appears in the algebra. You can then use square bracket substitution to throw the "b" parameter into other matrices.
http://openmx.psyc.virginia.edu/thread/193
The historical way of dealing with this is a dummy latent variable. Whatever path is supposed to get a value of "b" gets interrupted by a mediating latent variable with zero variance. The regression from the exogenous variable to the dummy gets a value of "a", while the regression from the dummy to the endogenous variable gets a 2 (or visa versa). Unless your model takes a form very conducive to the dummy variable trick and you want all of the constraints to be explicitly in the model, I'd avoid this, but it's good to know its there.
ryne
Log in or register to post comments
This specification would also
This specification would also work:
WRT your question, both the matrices have to include free parameters. Note that the mxAlgebra expression "twob" uses the name of the free parameter (b) instead of the name of the matrix (con_b). Either way would work, I find this easier to read. We are toying around with a mxConstraint() specification such that the left-hand and right-hand side are specified explicitly as algebras inside the constraint declaration. However this has not been implemented.
Also your constraint is not satisfied by the starting values. You should change the starting values.
Log in or register to post comments
In reply to This specification would also by mspiegel
It would be very nice, and
It would be very nice, and very natural to be able to say
mxConstraint("con_a", "=", "2*con_b")
You would need some trigger to let the machine know that "a" was not the name of an algebra, but rather an algebra itself: maybe the presence of a dot, or similarly to "data." specifying a definition variable, using "alg." as a prefix
mxConstraint("alg.con_a.a", "=", alg.con_b.b*2")
Log in or register to post comments
In reply to It would be very nice, and by tbates
We were thinking more
We were thinking more like:
The constraint gets formatted like a MxAlgebra. Note the lack of quotes around the first argument. If the outermost operator in the MxConstraint is neither <, ==, nor >, then an error would be thrown.
Log in or register to post comments
In reply to We were thinking more by mspiegel
I like this formatting. If
I like this formatting.
If this is being interpreted like an algebra, then people could actually use their free parameters directly. For example, to constrain the parameters "a" and "b" in manu's example above, the code would just be:
mxConstraint(a == 2*b, name="constraint1")
without the need to build the
con_a
andcon_b
matrices at all.Log in or register to post comments
In reply to I like this formatting. If by tbrick
Well, yes provided that the
Well, yes provided that the free parameters 'a' and 'b' were defined in some other matrix. There is currently no mechanism for declaring free or fixed parameters outside of a matrix declaration. Yes, it would be cool if there was a mechanism. In fact, there is: write a function that builds a matrix for you!
Log in or register to post comments
In reply to Well, yes provided that the by mspiegel
That's not a problem. If 'b'
That's not a problem. If 'b' isn't used elsewhere in the model, then the constraint is worthless anyway.
Log in or register to post comments
In reply to That's not a problem. If 'b' by Ryne
thanks for the fantastic
thanks for the fantastic responses!!! I think having a simple constraint
mxConstraint(a == 2*b, name="constraint1") would be great!
However, I do have a quick follow-up question/comment: While I am now able to impose the constraints using the approach described above, it appears that OpenMx counts the two additional 1x1 matrices as free parameters, i.e. the number of estimated parameters and degrees of freedom in the summary() function are incorrect. I.e., in the upper example the number of estimated parameters would be two, while in fact I am only estimating one parameter, or am I missing something?
Log in or register to post comments
In reply to thanks for the fantastic by manu
Does the mxVersion() function
Does the mxVersion() function return 0.2.10-1172? The summary() function has been reimplemented.
Log in or register to post comments
In reply to Does the mxVersion() function by mspiegel
ah, that's it - in the
ah, that's it - in the updated version the constraint is explicity noted and the df are correct - thank you!
Log in or register to post comments
In reply to We were thinking more by mspiegel
Excellent - and very
Excellent - and very readable.
People will make the mistake of putting the algebra in quotes out of habit a few times, but the logic is very memorable: names in quotes, algebras are algebras... nice!
Should return a nice error when only two parameters are provided and the first is in quotes. Something like "you passed in an algebra to mxConstraint, but put it in quotes: remove the quotes for this to work."
Log in or register to post comments
Another topic --- right now a
Another topic --- right now a constraint must be of the form: 'exp1 [<, ==, >] exp2'
Any chance of allowing for >= or <=?
Log in or register to post comments
In reply to Another topic --- right now a by pdeboeck
Equality constraints are kind
Equality constraints are kind of a hack in any numeric optimizer. Since we use floating point representations of real numbers, a == b is really implemented as abs(a - b) < epsilon. So, the difference between A < B and A <= B is the epsilon threshold, which is supposed to be a very small value. We haven't seen a need for A <= B, but we could be wrong.
Log in or register to post comments
In reply to Equality constraints are kind by mspiegel
Ahhh --- I should have
Ahhh --- I should have guessed. I'm getting by without it. I just have a situation where A>=B would be technically more accurate than A>B. However, on the practical side: When I use conditions where A=B in the data but specify A>B, it seems to be fine. I typically get estimates of A and B that differ by an inconsequential amount. So it is probably not worth the time to make this edit. Perhaps someone will find a more compelling reason to include >=.
Log in or register to post comments
I am trying to learn OpenMx
I am trying to learn OpenMx while replicating a SEM-model, i.e. the example-model in Raykov & Shrout (2002) "Reliability of Scales With General Structure".
I think the pathspecification & basic constraints are more or less ok (see syntax below), but I'm not sure how to specify the contraints on the parameters between eta1/eta2 and eta4 (see image: http://i.imgur.com/7VGbA.png).
The constraint is that the parameter should be equal to the sum of the different loadings on eta1, eta2. Is this possible using the path-specification? Is there an appropriate example where I can start from?
thanks,
Maarten
# Raykov & Shrout (2002) example
# ==============================
require(OpenMx)
fn <- 'http://kanut.studentenweb.org/OpenMx/raykov_table1.cm' # covariance matrix, lower
n <- max(count.fields(fn)) # 6 observed vars
X <- data.matrix(read.table(fn, fill = TRUE, col.names = 1:n))
X[upper.tri(X)] <- t(X)[upper.tri(t(X))] # fill upper tri (full matrix)
rownames(X) <- colnames(X)
X <- as.matrix(X) # otherwise error, known bug
manifests <- rownames(X)
latents <- c('eta1', 'eta2', 'eta3', 'eta4')
raykov.rel.model.constr <- mxModel(name="Raykov reliability model, constrained",
type="RAM",
manifestVars = manifests ,
latentVars = latents,
mxPath(from='eta1', to=manifests[1:4]),
mxPath(from='eta2', to=manifests[3:6]),
mxPath(from=c('eta1', 'eta2'), to='eta4'),
mxPath(from=manifests, arrows=2),
mxPath(from=manifests, to='eta3', free=FALSE, values=1.0),
mxPath(from=c('eta1', 'eta2'), arrows=2, free=FALSE, values=1.0),
mxPath(from=c('eta3', 'eta4'), arrows=2, free=TRUE),
mxPath(from='eta1', to='eta2', arrows=2),
mxData(observed=X, type="cov", numObs=300)
)
Log in or register to post comments
In reply to I am trying to learn OpenMx by mhermans
Hi. Thanks for including the
Hi. Thanks for including the link to the path diagram. OK, sadly my background is computer science and I didn't sit through enough of the SEM class to determine the desired constraint. But what you want to introduce is the argument 'labels = ' on those mxPath() functions that you would like to give labels to the free parameters. In OpenMx, a free parameter can either by anonymous (its label is NA) or have a unique label.
For example, lets say we have assigned labels 'a', 'b' and 'c' to 3 free parameters. Now assume we have a fourth parameter, 'd' such that a + b + c + d = 1. Note that 'd' is not a free parameter, because it is uniquely determined by the free parameters 'a', 'b', 'and 'c'. We would declare 'd' as an algebra: mxAlgebra(a + b + c, name = 'd'). You may find the following information helpful: in the algebra specification, the free parameters 'a', 'b', and 'c' are secretly converted into 1 x 1 matrices that consist of a single cell with the free parameter. You may ignore this information if it just confuses the matter.
Now you want to use 'd' in a mxPath() statement. You should use the special square-bracket notation in a label= argument. So the label of the cell will be "d[1,1]". Make sure that free=FALSE for that cell (it should throw an error otherwise).
Log in or register to post comments
In reply to Hi. Thanks for including the by mspiegel
Thanks for your comments. I
Thanks for your comments.
I have updated (see highlighted part: http://pastebin.org/447417) the model specification based on your suggestions. mxModel() returns no errors, but mxRun() gives
Error: The label '`reliability model.llambda14`[1, 1]' of matrix 'A' in model 'reliability model' generated the error message: object 'model' not found
neale: ... there is no need to specify the additional latent variables eta3 and eta4
The idea is that in such a "strange" SEM model, the values for the variances of eta3 and eta4 will allow you to calculate the reliability of a scale based on the items X1-X6. I'm not SEM-savvy enough to figure out how to do this without including eta3 & eta4, but suggestions are welcome.
neale: A great feature of OpenMx is that it is possible to request likelihood-based confidence intervals ...
That is indeed a nice feature, it'll save me from implementing a bootstrap procedure as described in the paper.
Log in or register to post comments
In reply to Thanks for your comments. I by mhermans
Try renaming your model
Try renaming your model "reliabilityModel" and changing all the appropriate references from "reliability model" to "reliabilityModel". We try to escape whitespace as best we can, but this could be a bug.
Log in or register to post comments
In reply to Try renaming your model by mspiegel
That unfortunately gives the
That unfortunately gives the same error...
Log in or register to post comments
In reply to That unfortunately gives the by mhermans
Oops. This was a bug in our
Oops. This was a bug in our library. I've committed a patch to our source code repository. We will have a binary release by the end of this week, including this fix. Does the following output look correct? If it is working correctly, I'll add this model to our test suite.
Log in or register to post comments
In reply to Oops. This was a bug in our by mspiegel
The error is indeed gone in
The error is indeed gone in the svn-version, thanks for the quick fix.
If it is working correctly, I'll add this model to our test suite.
I have not yet---even including the suggestions from neale, thanks---been able to reproduce the values from the worked example from the paper, but I'm guessing it has to do with my specification, not OpenMx. I'll post an update if I get closer.
Log in or register to post comments
In reply to Thanks for your comments. I by mhermans
Hi mhermans I have tweaked
Hi mhermans
I have tweaked your script so that it runs (but have not compared results with those of Raykov & Shrout). There was an error in that this line:
mxPath(from=c('eta3', 'eta4'), arrows=2, free=TRUE),
specifies residual error on the eta3 and eta4 latent variables, whereas I believe they are neither required nor identified. This issue may stem from rather sloppy conventions commonly encountered in path diagrams. That is, a mathematically sufficient diagram should be drawn with double-headed variance terms throughout (on all latent and observed variables), and these should be omitted ONLY when they are fixed at zero. Many path diagrams leave out variance paths on all latent variables - in many cases these are all fixed at 1.0 and this is assumed (but without explicitly saying so in the Figure caption for example). Such tacit assumptions/conventions are dangerous because they lead to ambiguity about the model specification, something that should be avoided. A lesson I learned from Jack McArdle & Steve Boker many moons ago.
Note in the script that the equality constrained paths do not appear in the parameter list of the output. However, as I requested CIs on these algebras they are immediately visible in the summary().
Good luck!
Log in or register to post comments
In reply to I am trying to learn OpenMx by mhermans
I think it can be done as
I think it can be done as mspiegel suggests. However, I have to say that as it stands, the model is a bit weird from an SEM point of view. The two latent variables eta4 and eta3 have no "indicators" - that is, they are not a cause (neither direct nor indirect) of any measured observation. Therefore, their existence in the model will have no effect on the fit of the model, and the same fit could be achieved by omitting them. I have only skimmed the article in question, but in essence I don't see any need to set up the model this way in OpenMx. Rather, simply set up the two factor model, and the algebras per mspiegel. Thus there is no need to specify the additional latent variables eta3 and eta4. A great feature of OpenMx is that it is possible to request likelihood-based confidence intervals on any parameter or function of parameters. So 95% CI's on the composites, e.g., lambda11+lambda21 etc. could be readily obtained using the mxCI function and the argument (model,Intervals=T) to the mxRun command.
Log in or register to post comments