Non-centered multivariate normal

222 views
Skip to first unread message

Matthijs Hollanders

unread,
Mar 9, 2022, 9:55:46 PM3/9/22
to nimble-users
Hi all,

I've been practising specifying multivariate normal distributions following the NIMBLE Manual, section 5.2.4.1.2. This is working well. Consequently, I tried to code it with non-centered parameterization following McElreath's Statistical Rethinking, section 14.2, Overthinking box. Let's suppose we're trying to estimate random intercepts and slopes beta[i, j] where i indexes intercept and slope (1, 2), and j indexes over ten individual (1, 2, ..., 10). The formula for non-centered parameterization is:

beta[1:2, j] <- t(diag(sd[1:2]) * Ustar[1:2, 1:2] * z[j, 1:2]),

where t is the transpose function, Ustar is the "Cholesky factor of the correlation matrix across treatments", and z are the standardised z-scores (note that the indexing here is swapped). Now, my concern is that in that formula, Ustar should be the lower triangular Cholesky factor, where dlkj_corr_cholesky takes the upper triangular Cholesky factor.

Is there a straightforward way to use non-centered parameterization in conjunction with dlkj_corr_cholesky?

Kind regards,

Matt

Chris Paciorek

unread,
Mar 10, 2022, 12:10:48 PM3/10/22
to Matthijs Hollanders, nimble-users
Hi Matt,

Is there a reason not to just transpose the matrix, i.e.,

Ustar[1:2, 1:2] ~ dlkj_corr_cholesky(....)
beta[1:2, j] <- diag(sd[1:2]) * (t(Ustar[1:2, 1:2]) %*% z[j, 1:2])[,1]

(I've modified the multiplications to get it to what you need for actual nimble model code, and you shouldn't need to transpose the vector, but you should need to use "[,1]" to change the result of matrix multiplication to a vector.)

-chris

--
You received this message because you are subscribed to the Google Groups "nimble-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nimble-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nimble-users/4ca0f4b0-a010-4710-835a-cf39b6552f8cn%40googlegroups.com.

Matthijs Hollanders

unread,
Mar 10, 2022, 3:10:30 PM3/10/22
to Chris Paciorek, nimble-users
Hi Chris,

No, there definitely wasn't a good reason, unless my pre-elementary knowledge of matrices constitutes a good reason!

Thanks, your modification worked! However, are you sure the [,1] is necessary at the end, because beta is a 2 x j matrix? I ended up getting it to work like: t(diag(sd[1:2]) * t(Ustar[1:2, 1:2]) * z[j, 1:2]), also still transposing the whole vector... and my outputs match the centered approach!

Also, and this is perhaps another elementary questions, but is there any way to derive the correlations between variables from any of these structures or outputs?

Kind regards,

Matt

Chris Paciorek

unread,
Mar 11, 2022, 8:21:06 PM3/11/22
to Matthijs Hollanders, nimble-users
Hi Matt,

It looks like your approach keeps the right-hand side as a (one-column) and it works to assign into the column of a matrix on the left-hand side, so that's great.

I'm not quite sure what you mean by derive correlations. You can of course compute the correlation from the Cholesky factor (i.e., Ustar) in the obvious fashion.
If you have some covariance matrix and you need to derive correlations within the model, you could write a nimbleFunction to do it, potentially using nimbleRcall to call out to R's 'cov2cor' function. 

-chris
Reply all
Reply to author
Forward
0 new messages