Adding correlation between parameters by introducing correlation matrix with LKJ prior

Hi all,

I have the following Stan-code where independence is assumed between the lambda-parameters

data {
    int<lower=1> n_fights;
    int<lower=2> n_fighters;
    int<lower=1, upper=n_fighters> fighter_id[n_fights];
    int<lower=1, upper=n_fighters> opponent_id[n_fights];
    int n_strikes_attempted[n_fights];
    int n_strikes_landed[n_fights];
    int n_punches_attempted[n_fights];
    int n_punches_landed[n_fights];
    int n_kicks_attempted[n_fights];
    int n_kicks_landed[n_fights];
}


parameters {
    vector[n_fighters] raw_lambda_strike;
    vector[n_fighters] raw_lambda_punch;
    vector[n_fighters] raw_lambda_kick;
}

transformed parameters {
    vector[n_fighters] lambda_strike = raw_lamda_strike * sigma_strike;
    vector[n_fighters] lambda_punch = raw_lamda_punch * sigma_punch;
    vector[n_fighters] lambda_kick = raw_lamda_kick * sigma_kick;
    vector<lower=0,upper=1>[n_fights] theta_strike = inv_logit(lambda_strike[fighter_id] - lambda_strike[opponent_id]);
    vector<lower=0,upper=1>[n_fights] theta_punch = inv_logit(lambda_punch[fighter_id] - lambda_punch[opponent_id]);
    vector<lower=0,upper=1>[n_fights] theta_kick = inv_logit(lambda_kick[fighter_id] - lambda_kick[opponent_id]);
}


model {
    // priors
    raw_lambda_strike ~ std_normal();
    raw_lambda_punch ~ std_normal();
    raw_lambda_kick ~ std_normal();
    sigma_strike ~ exponential(1);
    sigma_punch ~ exponential(1);
    sigma_kick ~ exponential(1);

    // likelihood
    n_strikes_landed ~ binomial(n_strikes_attempted, theta_strike);
    n_punches_landed ~ binomial(n_punches_attempted, theta_punch);
    n_kicks_landed ~ binomial(n_kicks_attempted, theta_kick);
}

Next, I want to introduce correlation between the parameters by introducing a correlation matrix with a LKJ prior. I have read this blogpost and the Stan documentation but there are still things unclear to me.

In the parameters-block I need to introduce cholesky_factor_corr[] L_Omega;
Should the size be equal to n_fighters or 3 (the number of different skills)?
In addition, how should I define the necessary variables in transformed parameters to apply the Cholesky factorization?

Thank you

Sorry this didn’t get answered sooner—I just saw it when it went to the list of old posts not answered.

The answer is 3. What you want to do is organize this way

transformed data {
  vector[3] zeros3 = rep_vector(0, 3);
}
parameters {
  array[n_fighters] vector[3] lambda;
  cholesky_factor_corr[3] L_Omega;
  vector<lower=0>[3] sigma;
  ...
}
transformed parameters {
  cholesky_factor[3] L_Sigma = diag_pre_multiply(sigma, L_Omega);
  ...
}
model {
  sigma ~ exponential(1);  // or whatever prior for scales you want
  L_Omega ~ lkj_cholesky(5);  // or whatever prior parameter other than 5 you want
  lambda ~ multi_normal_cholesky(zeros3, L_Sigma);
  ...
}

The principle is that if lambda[n] is 3-dimensional, then the location parameter zeros3 also has to be 3-dimensional and L_Sigma has to be 3 x 3. In other words, it’s just like having a covariance matrix.

1 Like