I am thinking about estimating the item discrimination parameter for the one parameter logistic model, not the Rasch model. The one logistic model is scaled on the person/theta scale, while the Rasch model is scaled on the item scale for model identification. The one parameter logistic model also has a common item discrimination parameter, which is not necessarily 1 as assumed by the Rasch model. I wonder how could I set an equality constraint on the item discrimination parameter across all items in Stan. In the end, I want to fit a hiearchical 1PL model with Stan. Any help would be highly appreciated!
The following is the 2PL code from Dr. Daniel Fur (https://mc-stan.org/users/documentation/case-studies/tutorial_twopl.html#twoplstancode). How could I set a equality constraint based on his code as attached below:
data {
int<lower=1> I; // # questions
int<lower=1> J; // # persons
int<lower=1> N; // # observations
int<lower=1, upper=I> ii[N]; // question for n
int<lower=1, upper=J> jj[N]; // person for n
int<lower=0, upper=1> y[N]; // correctness for n
}
parameters {
vector<lower=0>[I] alpha; // discrimination for item i
vector[I] beta; // difficulty for item i
vector[J] theta; // ability for person j
}
model {
vector[N] eta;
alpha ~ lognormal(0.5,1);
beta ~ normal(0,10);
theta ~ normal(0,1);
for (n in 1:N)
eta[n] <- alpha[ii[n]] * (theta[jj[n]] - beta[ii[n]]);
y ~ bernoulli_logit(eta);
}
If you just want all items to have the same discrimination parameter, just replace vector<lower = 0>[I] alpha;
with real<lower = 0> alpha;
and replace alpha[ii[n]]
with alpha
.
You can identify either of theta
or beta
and make the other one hierarchical. We often try to reparameterize so that rather than alpha[i] * (theta[j] - beta[i])
, we use alpha[i] * theta[j] - gamma[i]
, where now gamma[i]
does the job of alpha[i] * beta[i]
.
1 Like
Thank you so much for your quick response, Dr Carpenter. Does the following code look correct to you if I am going to fit a multilevel 1PL model based on the multilevel 2PL model I had:
data {
int<lower=1> N; // number of students
int<lower=1> NFam; // number of item families
int<lower=1> NObs; // number of observations
int<lower=1,upper=N> ID_Stu[NObs]; // student id
int<lower=1,upper=NFam> ID_Fam[NObs]; // item family id
int<lower=0,upper=1> Resp[NObs];// resp
int NIC; //number of item clones, fixed in this syntax
int<lower=1,upper=NIC> ID_Clone[NObs];//item clone id
}
parameters {
real theta[N]; // ability
real<lower=0, upper=5> alpha; // discrimination
real mu[NFam]; // difficulty
real<lower=0> sigma[NFam]; // random variation
vector[NIC] beta_z[NFam]; //*beta reparameterization;
}
transformed parameters {
vector[NIC] beta[NFam]; // item clone difficulties
for(i in 1:NFam) {
beta[i]= mu[i] + beta_z[i] * sigma[i];
}
}
model {
row_vector[NObs] alpha_local; // temporary parameters
row_vector[NObs] diff_local;
int fam_n;
theta~normal(0,1); // priors
mu~normal(0,10);
sigma~normal(0,1);
//alpha~uniform(0,5);
for(i in 1:NFam){
beta_z[i] ~ normal(0, 1);
//beta[i] ~normal(mu[i], sigma[i]);
}
for (n in 1:NObs) {
fam_n <- ID_Fam[n];
alpha_local[n] <- alpha;
diff_local[n] <- theta[ID_Stu[n]] - beta[fam_n, ID_Clone[n]];
}
Resp~bernoulli_logit(alpha_local .* diff_local);
}
I did beta reparameterization because I find it runs much faster than the one without reparameterization, thought both model converged. Thank you so much.