Known beta parameters in IRT model


Dear stan forum users,

I’d like to estimate irt model under the assumption that the item parameters are known and fixed. This is the case that items from an item pool with known item parameters are administered to new test-takers and an ability estimation for every test-taker is needed. How can I introduce known beta parametrs to the stan code instead of estimation them?

thank you for any help!


Pass them into the data block rather than declaring them in the parameters block.


If you really want to fix them, then doing what @bgoodri suggests will work.

I’m guessing you probably have some estimates of these beta from previous data, so that there’s some residual uncertainty. You could then use that uncertainty to put priors on these beta in the new model. Of you can just take all the data and combine it to run a bigger model.



In line with what @Bob_Carpenter suggested: how would I go about setting up my code if I want to compare the predicted latent trait of respondents with the same response behavior across different item parameter values (for example stemming from models with different identifying constraints) while accomodating the uncertainty in the parameters from previous estimation?

If I had new observed data, then I’d probably run the script below to update the posterior distributions of the item parameters (discrimination, difficulty, and cutpoint) and obtain the distributions of the latent trait (theta).

But if I manually generated new response data where my only interest is to obtain the latent trait and not update the distribution of the items, then the script below will not get that job done.

Do you have suggestions as to how to proceed or examples I could look at?


data { 
  int<lower=1> J;                 // total number of respondents
  int<lower=1> K;                 // total number of items 
  int<lower=1> N;                 // total number of responses

  int<lower=0> jj[N];             // respondent for observation n 
  int<lower=0> kk[N];             // item for observation n
  int<lower=1,upper=C> z[N];      // response for observation n; z in {1 ... C}
  int<lower=1> C;                 // max categories of items
  int<lower=1> D;                 // dimensions

  matrix[K, 2] beta_prior;        // priors for discrimination parameters, mu and sd
  matrix[K, 2] alpha_prior;       // priors for difficulty parameters
  matrix[K*(C-1), 2] tau_prior;   // priors for cutpoint parameters
  int tau_pl[K,C-1];              // match the format of tau_prior to tau
parameters {
  ordered[C-1] tau[K];               // threshold parameters
  matrix[J,D] theta;              // theta in of person j

  vector[K] alpha;
  matrix[K,D] beta;
model {
  vector[C] prob;   // probabilities
  real eta;         // linear predictor

  for (k in 1:K){
    beta[k,1] ~ normal(beta_prior[k,1], beta_prior[k,2]);
    alpha[k] ~ normal(alpha_prior[k,1], alpha_prior[k,2]);
    for (i in 1:(C-1)){
      tau[k,i] ~ normal(tau_prior[tau_pl[k,i],1], tau_prior[tau_pl[k,i],2]);
  for (n in 1:N){
  eta = beta[kk[n],1]* theta[jj[n],1] + alpha[kk[n]];
  prob[1] = Phi_approx((tau[kk[n],1] - eta));
  for (c in 2:(C-1)){
  prob[c] =  Phi_approx((tau[kk[n],c] - eta)) - Phi_approx((tau[kk[n],c-1] - eta));
  prob[C] =  1 - Phi_approx((tau[kk[n],C-1] - eta));
  z[n] ~ categorical(prob);


This comes up a lot but Stan has no way to deal with this. The joint fit gives the right answer, but is expensive. after that, you are in approximate algorithm territory.