> On Apr 30, 2015, at 1:17 AM, Rick Farouni <rfar...@gmail.com> wrote:
>
> Hi Bob,
>
>
> I tried to use multiply_lower_tri_self_transpose but I got an error regarding variable type.
> My guess is that the error is due to declaring L as a cholesky_factor_cov type, instead of a matrix.
I see --- that's not a square matrix. We need to generalize
the multiply_lower_tri_self_transpose function, so I added
an issue:
https://github.com/stan-dev/stan/issues/1434
> If I don't diagnoalize the matrix I would have to use two for loops and a comment describing what the for loops imply. I thought that additional code optimization wasn't necessary since the sampling for this model was surprisingly really fast.
Good point --- we'd always recommend clarity over optimization.
But to add to a diagonal, all you need is:
Q <- L * L';
for (i in 1:rows(Q))
Q[i,i] <- Q[i,i] + psi[i];
But as you say, clarity first if you don't need the speed.!
> Also, on page 87 (section 7.4) of the Stan manual, the code provided assumes a square lower triangular matrix L. Is that a mistake or is there a full-rank matrix factorization step required (i.e. A=B*C) that need to be added to the final model code?
I'm not sure what you mean. I don't see an A, B or C there --- that
code's just to build a square Cholesky factor for a covariance matrix
with a unit diagonal. Should it be non-square?
Correct me if I am wrong but since Factor analysis is mainly a dimensionality reduction technique, the n x p loading matrix L will have n larger than p, so the rank of L is at most p, (when L has full column rank) and the n x n matrix LL' would have the same rank of L and so isn't positive definite. That is , if we consider L*L' as a covariance matrix, then it would be rank deficient and won't have a Cholesky factor. As for A=B*C, I was referring to this rank decomposition result.
> stats:::factanal.fit.mle
function (cmat, factors, start = NULL, lower = 0.005, control = NULL,
...)
{
FAout <- function(Psi, S, q) {
sc <- diag(1/sqrt(Psi))
Sstar <- sc %*% S %*% sc
E <- eigen(Sstar, symmetric = TRUE)
L <- E$vectors[, 1L:q, drop = FALSE]
load <- L %*% diag(sqrt(pmax(E$values[1L:q] - 1, 0)),
q)
diag(sqrt(Psi)) %*% load
}
FAfn <- function(Psi, S, q) {
sc <- diag(1/sqrt(Psi))
Sstar <- sc %*% S %*% sc
E <- eigen(Sstar, symmetric = TRUE, only.values = TRUE)
e <- E$values[-(1L:q)]
e <- sum(log(e) - e) - q + nrow(S)
-e
}
...