Sorry for the double reply, but Iāve continued to work on the suggestions given above, and have tried to fit a better joint model. I took out the second simple linear model and tried to fit a multivariate normal model to predict both latent variables (z) given group membership (beta[group]). The output is still strange, but strange in a (potentially) interesting way. the covariance structure of the predictors, their relative loadings on the LVs compared to the raw simulated data, and the correlation between the raw simulated latent factor scores and estimated scores, all check out. However, the estimates are super inflated for the factor model, and super deflated (z) for the second linear model. Iāve played with the priors, but canāt get it to change. Maybe as some of the estimates shrink, others inflate to balance the outcome estimates in the posterior (?), Iām just not sure why, and whether itās fixable. Other than this, I donāt see how I can replace the LF model with a multivariate normal (tried a bit, but was hopeless, nothing really made sense or approximated the LF posterior). As for iterating the draws, am I looping this in R (like for (I in n_draws) {run stan model and replace the data with another draw}? or should I be loading a 3D array into stan and looping over the iterations in Stan? Sorry this is probably a dumb question, Iām just relatively new to raw Stan coding, and am still working my way around the syntax.
Hereās the code Iām referring to
//
data {
int<lower = 0> m; // dimension of observed data (# of biomarkers)
int<lower = 0> k; // number of latent factors
int<lower = 0> n; // number of participants
int<lower = 0> n_obs; // number of observations
int<lower = 1, upper = 2> group[n]; //group variable
vector[m] y[n];
}
transformed data {
int<lower = 1> p; // number of nonzero lower triangular factor loadings
vector[m] zeros;
zeros = rep_vector(0, m);
p = k * (m - k) + k * (k - 1) / 2;
}
parameters {
vector<lower = 0>[k] beta_diag;
vector[p] beta_lower_tri;
vector<lower = 0>[m] sigma_y; // residual error
real<lower = 0> sigma_L; // hyperparameter for loading matrix elements
matrix[2,2] beta;
vector<lower = 0>[2] sigma_beta;
corr_matrix[k] omega;
}
transformed parameters {
matrix[m, k] L;
cov_matrix[m] Sigma;
matrix[m, m] L_Sigma;
matrix[n,k] z; // factor scores
{ // temporary scope to define loading matrix L
int idx = 0;
for (i in 1:m){
for (j in (i + 1):k){
L[i, j] = 0; // constrain upper tri elements to zero
}
}
for (j in 1:k){
L[j, j] = beta_diag[j];
for (i in (j + 1):m){
idx = idx + 1;
L[i, j] = beta_lower_tri[idx];
}
}
}
Sigma = multiply_lower_tri_self_transpose(L);
for (i in 1:m) Sigma[i, i] = Sigma[i, i] + sigma_y[i];
L_Sigma = cholesky_decompose(Sigma);
//z scores
for (i in 1:n) {
for (j in 1:k) {
z[i, j] = (1 / sigma_L) * L[, j]' * inverse(Sigma) * y[i,];
}
}
}
model {
// priors for model 2
to_vector(beta) ~ normal(mean(z),1);
sigma_beta ~ exponential(1);
omega ~ lkj_corr(4);
//priors for model 1
beta_lower_tri ~ normal(0, sigma_L);
sigma_L ~ normal(0, 1);
sigma_y ~ normal(0, 1);
// priors for diagonal entries (Leung and Drton 2016)
for (i in 1:k) {
target += (k - i) * log(beta_diag[i]) - .5 * beta_diag[i] ^ 2 / sigma_L;
}
// likelihood for factor model
y ~ multi_normal_cholesky(zeros,L_Sigma);
// second linear model
for (i in 1:n) {
z[i, 1:2] ~ multi_normal(beta[group[i], ], quad_form_diag(omega,sigma_beta));
}
}