Getting generated quantities variable in original dimensions

Hey all, thanks for the help!

I’ve been trying to use generated quantities output and it seems that stan automatically transforms my matrices to vectors column-by-column. I need the output the other way around (row-by-row), so is there a way to fix it (like getting a matrix and not a vector) other than transposing the matrices’ dimensions?

Here’s the generated quantities block of the code.



generated quantities {
  matrix [Nsubjects,Ntrials] temp_log_lik;
  matrix [Ntrials,Nsubjects] log_lik; //this has the good dimensions
  matrix [Nsubjects,Ntrials] temp_y_rep;
  matrix [Ntrials,Nsubjects] y_rep; //this has the good dimensions
  matrix[Ntrials,Nraffle] Qoffer;
  vector[Ntrials] Qdiff;
   for (subject in 1:Nsubjects){
    for (trial in 1:Ntrials_per_subject[subject]){
    Qoffer = null_model(Ntrials, Ntrials_per_subject[subject], Narms, Qvalue_initial, Nraffle, choice[subject], reward[subject], offer1[subject], offer2[subject], selected_offer[subject], first_trial_in_block[subject], alpha[subject] );
    Qdiff  = Qoffer[,2]-Qoffer[,1];
    temp_log_lik[subject,trial]= bernoulli_logit_lpmf(selected_offer[subject,trial ]|Qdiff[trial]*beta[subject]);
    temp_y_rep[subject,trial] = bernoulli_logit_rng(logit(exp(temp_log_lik[subject,trial])));
    //transposing the matrices to get a subject by subject vector.
    log_lik = temp_log_lik'; 
    y_rep = temp_y_rep';
  } 
   }
}

You just need to change your indexing when you’re allocating values to matrix elements.

So currently you have:

  matrix [Nsubjects,Ntrials] temp_log_lik;
  matrix [Ntrials,Nsubjects] log_lik;

  for(subject in 1:Nsubjects) {
    for(trial in 1:Ntrials) {
      temp_log_lik[subject, trial] = ...;
    }
  }

log_lik = temp_log_lik';

You could instead just do:

  matrix [Ntrials,Nsubjects] log_lik;

  for(subject in 1:Nsubjects) {
    for(trial in 1:Ntrials) {
      log_lik[trial, subject] = ...;
    }
  }

Thanks for your reply. The whole code uses [subjects, trial] notation. Therefore, I wanted to know if there’s a walkaround to changing the dimensions just for the generated quantities block to avoid confusion.

I’m not sure I entirely understand, you want to specify that a value will be assigned to log_lik[subject, trial], but you want the value to actually be assigned to log_lik[trial, subject]?

Is there a possibility for the generated quantities output to be a matrix and not a vector? When I try to use the output using fit$draws(variables =‘log_lik’) I am getting the variable of interest as a vector and not as a matrix as it was originally.

Matrices are stored column-wise in Stan. As you realize, you can get what you want by transposing the matrix, either during construction, per @andrjohns good answer, or after construction via transposition. If both of these solutions feel cumbersome, a third solution is to store the output not in a matrix but rather in a 2-D array of reals, which is stored row-wise, or to be even more explicit, in a 1-D array of row vectors. Both of these objects will be indexed in the same way as your matrix, but should get collapsed by rows rather than by columns in the output. (NB, I haven’t tested this explicitly, but it really should be the case).

Another option is to use appropriate post-processing software that understands the matrix-like structure of your output. If you’re in R, then the rvars format from the posterior package might be what you need.

This thread also has a discussion of how to extract variables in the correct dimensions using the posterior package (which is what the $draws() method uses): Posterior draws objects => recover original array data structure?

1 Like

fwiw, CmdStanPy lets you extract variables as structured objects - API Reference — CmdStanPy 1.0.1 documentation