Brms: Prior setting for IRT 2PL ordinal models

Hello all,

I am new to Brms and IRT, and I am trying to understand the theory and modeling of IRT by reading and replicating @paul.buerkner 's great piece https://arxiv.org/pdf/1905.09501.pdf line by line. And, I plan to utilize the instructions for modeling in the paper in my own IRT 2PL ordinal modeling.

What I am confusing is about the prior setting in IRT 2PL ordinal models in the paper. In the model formula of 2PL Graded Response Model (on page 37),

R> formula_va_ord_2pl <- bf(
R+ resp ~ 1 + (1 |i| item) + (1 | id),
R+ disc ~ 1 + (1 |i| item)
R+ )

the paper sets the “weakly informative priors on hierarchical standard deviations” as below.

R> prior_va_ord_2pl <-
R+ prior("constant(1)", class = "sd", group = "id") +
R+ prior("normal(0, 3)", class = "sd", group = "item") +
R+ prior("normal(0, 1)", class = "sd", group = "item", dpar = "disc")

As far as I understand, the partial pooling for item and person parameters, the normal prior on those parameters is automatically set and cannot be changed via the prior option, but may change the hyperparameters defining the covariance matrix of the person or item parameters that is on the standard deviations and correlation matrices (as the author explains on page 17).

Question 1. In the above 2PL GRM model, what are the default (or hidden?) normal priors on item and person? Is “normal (0,5)” or “normal (0,3)” set to item and person?
If I look at the manual of Brms (https://cran.r-project.org/web/packages/brms/brms.pdf), the manual says the corresponding standard deviation parameters are restricted
to be non-negative and, by default, have a half student-t prior with 3 degrees of freedom on page 194. If my understanding is correct, in the above model, priors on hyperparameters (standard deviations) are changed into “constant (1)”, “normal (0,3)”, and “normal (0,1)” from “default half student-t prior with 3 degrees of freedom”. Still, I am uncertain what are default normal priors on item and person.

Comparing 2PL GRM, if I look into the prior setting for the 2PL binary model on page 27 in the paper, the model formula of 2PL binary as follows

R> formula_va_2pl <- bf(
R+ r2 ~ exp(logalpha) * eta,
R+ eta ~ 1 + (1 |i| item) + (1 | id),
R+ logalpha ~ 1 + (1 |i| item),
R+ nl = TRUE
R+ )

with prior setting,

R> prior_va_2pl <-
R+ prior("normal(0, 5)", class = "b", nlpar = "eta") +
R+ prior("normal(0, 1)", class = "b", nlpar = "logalpha") +
R+ prior("constant(1)", class = "sd", group = "id", nlpar = "eta") +
R+ prior("normal(0, 3)", class = "sd", group = "item", nlpar = "eta") +
R+ prior("normal(0, 1)", class = "sd", group = "item", nlpar = "logalpha")

Ok, it seems like priors for priors on hyperparameters (standard deviations) are the same with 2PL GRM except for setting “normal (0,5)” and “normal (0,1)” to two parameters “eta” and “logalpha”.

Question 2. The author says, “The parameter eta represents the sum of person parameter and item easiness, whereas logalpha represents the log discrimination.” If so, is it a correct understanding that “normal (0, 3)” is set to “person parameter” and “item easiness parameter”, whereas “normal (0,1)” is set to “item discrimination parameter”?
And, I am wondering whether I can utilize this 2PL binary formula and prior setting into the modeling of my own 2PL ordinary model. This is because I want to adjust priors for item and person with more flexibility, and I want item discrimination function to be positive for all items using “logalpha” as the author did.

Thank you for reading my long questions. If anyone who is familiar with this paper and 2PL IRT ordinal modeling can help me, it would be really appreciated.

Hi,

For Question 1:
One way to check on how the priors have been set is to pass your model to prior_summary(), this will show you a summary of the priors for each of the parameters in the model.

It’s possible you want to change the prior for the Intercept parameter to something other than the default student_t prior. In and ordinal model with brms the Intercept parameter(s) refer to the thresholds/cutpoints on the latent variable.

For Question 2:
The nonlinear syntax of brms cannot handle the ordinal thresholds in the way that is required when
adding discrimination parameters. So the way you have specified the model is correct as far as I know.

1 Like

Hi JLC,

Thank you for your answer. I have a little clarification question.

As you suggested, I used prior_summary(formula_va_ord_2pl, all=FALSE) to figure out the parameters in the model and got the result below,

                prior class    coef  group resp dpar nlpar bound  source
 student_t(3, 0, 2.5) Intercept                                  default
         normal(0, 1) Intercept                 disc             default
 lkj_corr_cholesky(1)         L                                  default
 student_t(3, 0, 2.5)        sd                                  default
 student_t(3, 0, 2.5)        sd                 disc             default
          constant(1)        sd         id                          user
         normal(0, 3)        sd       item                          user
         normal(0, 1)        sd       item      disc                user 

Since I set constant(1), normal(0,3), and normal (0,1) to each hyperparameter (standard deviation) of ID and Item, I can see them in the result.

@paul.buerkner writes in the paper : "the normal prior on item and person parameters is automatically set and cannot be changed via the prior option if we use partial pooling for item and person parameter.’’

In the above, I can see that student_t (3, 0, 2.5) is set to class Intercept , and normal (0, 1) is set to class Intercept along with dpar (distributional parameter) as default. Given this, is it a correct understanding that "the normal prior normal (0, 1) on item and student_t (3, 0, 2.5) on person parameters is automatically set’’?

Yes, they are set automatically, but I’ve been able to change all of the available priors.

If you try something like:

prior("normal(0,3)", class = "Intercept") +
        prior("normal(0,3)", class = "sd", group = "id") +
        prior("normal(0,3)", class = "sd", group = "item") +
        prior("normal(0,3)", class = "Intercept", dpar = "disc") +
        prior("normal(0,3)", class = "sd", dpar = "disc") +
        prior("normal(0,3)", class = "sd")

Then you can fit an empty model by passing empty = TRUE to your brm call, so it will fit immediately. If you then call prior_summary() you should see all the Intercept and sd priors set to “normal(0,3)”.

1 Like

Great, it works now! Thank you so much.