# Multilevel model with 2 dimensions parameter

Hi!
I am trying to build a kind of a IRT model using multiple parameters for each person, one for each required skill.

I wanted to model it in a hierarchical way, so that every person parameter has a prior and latter these people share a common prior as well.

My question is:
How to do that in an efficient way, since my parameter has 2 dimensions? My attempt was this:

matrix[J, K] theta;
for (i in 1:J){
theta[i] = to_row_vector(rep_array(theta_g[i], K));
}


is it correct? Does it makes sense?

Full code:

   data{
int<lower=1> J;  // # of students
int<lower=1> K;  // # of skills
int<lower=1> I;  // # of questions
int<lower=1> N; // total # of answers
int Q[I, K];  // Q matrix
int<lower=0, upper=1> y[N];   // correctness for n
int ii[N];   // question index
int jj[N];   // person for n
}

parameters {
vector[I] beta;
vector[J] theta_g;
}
transformed parameters{
matrix[J, K] theta;
for (i in 1:J){
theta[i] = to_row_vector(rep_array(theta_g[i], K));
}
}
model {
theta_g ~ normal(0, 10);
beta ~ normal(0, 1);
for (n in 1:N){
real alpha;
// skills required by the question
alpha = dot_product(to_row_vector(Q[ii[n]]), theta[jj[n]]);
y[n] ~ bernoulli_logit(alpha - beta[ii[n]]);
}
}


Thanks

I donâ€™t think your code implements any kind of reasonable model. If you want each of J students to be associated with K latent skill values, then you need a parameter variable with J\times K values. The way you have it now, each student gets the identical value for all their skills. I think what you want is:

...
parameters {
vector[I] beta;
matrix[J, K] theta;
}
model {
to_vector(theta) ~ normal(0, 10) ;
beta ~ normal(0, 1);
for (n in 1:N){
real alpha;
// skills required by the question
alpha = dot_product(to_row_vector(Q[ii[n]]), theta[jj[n]]);
y[n] ~ bernoulli_logit(alpha - beta[ii[n]]);
}
}


Now, thatâ€™s an â€śunpooledâ€ť model, where the different students donâ€™t mutually inform at all. I suspect you will want a â€śpartially-pooledâ€ť model instead. Hereâ€™s one that has partial-pooling for both student and skill

...
parameters {
vector[I] beta;
matrix[J, K] theta;
vector[J] mu_j ;
vector<lower=0>[J] sigma_j ;
vector[K] mu_k ;
vector<lower=0>[K] sigma_k ;
}
model {
mu_j ~ normal(0,1) ;
mu_k ~ normal(0,1) ;
sigma_k ~ weibull(2,1) ; #peaked around .8, zero at zero, 2%>2
sigma_j ~ weibull(2,1) ; #peaked around .8, zero at zero, 2%>2
for(j in 1:J){
theta[j,] ~ normal(mu_j, sigma_j) ;
}
for(k in 1:K){
theta[,k] ~ normal(mu_k, sigma_k) ;
}
beta ~ normal(0, 1);
for (n in 1:N){
real alpha;
// skills required by the question
alpha = dot_product(to_row_vector(Q[ii[n]]), theta[jj[n]]);
y[n] ~ bernoulli_logit(alpha - beta[ii[n]]);
}
}

1 Like

perfect, makes sense!!!

thanks!!!

@mike-lawrence
just one detail, it should be like this, right ?

for(j in 1:J){
theta[j,] ~ normal(mu_j[j], sigma_j[j]);
}
for(k in 1:K){
theta[,k] ~ normal(mu_k[k], sigma_k[k]) ;
}

Ah, yes, good catch