Item banks and adaptive testing
What this is for
A collection of calibrated items is an item bank, and its most demanding use is computerized adaptive testing (CAT): each item is chosen after the last answer, to suit the respondent. Information, precision, and short forms picked the most informative items for one point on the scale; a CAT does that again after every response, at the respondent’s current estimate. This lesson builds the loop from information and the EAP, asks what stopping rules buy and what choosing by information costs, and runs adaptive tests after the fact on a medical examination and the PROMIS depression items. A CAT is only as good as the bank is where the respondent sits.
Goals
By the end of this lesson you should be able to:
- say what an item bank holds and what keeping one up involves;
- run the adaptive loop: start, choose by information, score by EAP, stop;
- compare fixed-length, standard-error and classification stopping rules;
- explain what maximum information does to item exposure, and what the fixes cost;
- run a post-hoc CAT on real responses and read it as a statement about the bank.
Core ideas
An item bank
What does a bank store? At the least, each item and its calibrated parameters, fixed, so that a respondent’s \(\theta\) can be estimated from any subset of the items and lands on the bank’s scale (Wainer et al., 2000; van der Linden & Glas, 2010). A working bank also records each item’s content codes, dates, how often it has been given, and the checks it has passed.
If you’ve done Model fit and out-of-sample prediction, outfit’s spread under a true model shrinks with sample size, so the screening rule should depend on the calibration sample. If you’ve done Differential item functioning, each item also gets a DIF screen, which needs group memberships in the calibration data. If you’ve done Linking and equating, new items join the bank’s scale by calibration alongside old ones acting as anchors. A bank is maintained, not finished: overused items are retired, old items checked for drift, new ones added.
The adaptive loop
How do we choose items for someone whose \(\theta\) we don’t yet know? One at a time (Lord, 1980, ch. 10; Weiss, 1982):
- Start at the population mean.
- Choose the unused item most informative at the current estimate, and give it.
- Update the estimate from every response so far.
- Stop when a rule says so; otherwise go back to 2.
Step 3 has a problem at the start.
After one item every pattern is all-right or all-wrong, so there is no MLE until the respondent has one of each; the EAP exists throughout, and adaptive testing and Bayesian scoring grew up together (Owen, 1975; Bock & Mislevy, 1982). Adapting is older than computers: Binet and Simon (1904) graded their tasks by the age at which children pass them, and individually given tests still start at a basal level and stop at a ceiling.
Try it: one CAT, step by step
A 100-item 2PL bank and one simulated respondent. Choose their true \(\theta\) and step through the test. In the top panel each dot is one bank item, placed at its difficulty \(b\), at a height equal to its information at the EAP before this step; the orange dot is the item the CAT gives at this step (the most informative one still available). The bottom panel is the posterior after the response.
At the defaults the first four answers are right, and there is no MLE until the fifth, a wrong answer; the EAP climbs meanwhile (0.56, 1.06, 1.41, 1.74) and ends at 1.59, posterior SD 0.34. The first four items have slopes from 2.2 to 2.4, and from step 10 on the slopes are 1.2 to 1.6: maximum information spends the steepest items first, because \(a^2\) multiplies everything else.
Stopping rules
When should a CAT stop? Three answers are standard (Weiss & Kingsbury, 1984).
- Fixed length. Everyone gets, say, 20 items: predictable time, easy content balance, precision that varies along the scale.
- Target standard error. Stop when the posterior SD reaches, say, 0.3, with a cap on length: equal precision wherever the bank can deliver it, and varying length.
- Classification. For a pass/fail decision, stop once the responses favour one side of the cut clearly enough (callout below). If you’ve done What does a score mean?, this spends the items near the cut, where classification is uncertain.
A standard-error rule stops on the posterior SD, and the posterior includes the prior: where the bank is thin, part of the precision it counts is the prior’s, and the estimate that stops has been pulled toward the mean. (Between fixed forms and a CAT sit multistage tests, which adapt between short preassembled modules; Luecht & Nungester, 1998.)
Try it: stopping rules and the shape of the bank
A 150-item bank whose difficulties you place; 25 simulated respondents at each true \(\theta\) from −3 to 3 (target-SE tests stop at 60 items at most).
With 20 items for everyone the RMSE is 0.19 at \(\theta = 0\) and 0.67 at \(-3\): equal length, unequal precision. With a target of 0.3, respondents near the middle stop after about 13 items and those at \(\pm 3\) run to about 57, with an RMSE still 0.52 at \(-3\): the bank has few items out there. Narrow the bank to an SD of 0.3 and the middle gets cheaper (11 items) while respondents at \(\pm 2\) need 53 to 58. The stopping rule decides how the bank’s shape is spent; it can’t change the shape.
What maximum information costs
Choosing the most informative item is efficient, with side effects (Kingsbury & Zara, 1989). Everyone sees the same first item and respondents who answer alike see the same next ones, so a few steep items go to almost everyone; where a test has stakes, such items become known. And information knows nothing about content: a CAT on a medical examination could spend every item on one specialty unless told otherwise.
The fixes trade precision for control (Revuelta & Ponsoda, 1998, compare eight). Randomesque selection picks at random among the few most informative items (Kingsbury & Zara, 1989). Sympson–Hetter gives each selected item a probability of being administered, tuned by simulation to cap its exposure (Hetter & Sympson, 1997; van der Linden, 2003). a-stratification splits the bank by slope and moves from the flattest stratum to the steepest, matching \(b\) to the estimate within each (Chang & Ying, 1999; Chang, 2015).
Try it: who sees which items
Five hundred simulated respondents take a 20-item CAT from a 100-item bank. Each dot is an item, at its difficulty and the share of respondents who saw it.
Under maximum information one item goes to everyone, 17 go to more than half, and 38 of the 100 are never used; the most exposed are steep items near the middle. Randomesque selection among the top five brings the most-seen item down only to 87%, with 30 unused and no loss of precision. a-stratification spreads the load much further (3 items seen by more than half, 9 unused) at a cost: the RMSE rises from 0.28 to 0.34, because the steep items wait.
Everything rests on the bank’s parameters
A CAT puts every respondent’s different test on one scale, which works only if the bank’s parameters, estimated from particular respondents taking a particular form, hold for other respondents and other combinations of items. If you’ve done Parameter invariance, that lesson tested this property. The ROAR-CAT project checked it before going live (Ma et al., 2025): it calibrated a reading bank in four groups of students, removed six items that functioned differently across them, and then randomly assigned students to random or CAT order. To reach a reliability of 0.9, 75 CAT items did the work of 125 random ones.
A cheaper check uses data already in hand: a post-hoc CAT. Calibrate on some respondents who answered every item, and let a CAT choose items for the others, revealing only the responses it asks for; then compare its estimate with the whole bank’s, respondent by respondent. The unchosen items are missing by design, which is ignorable given the model (Mislevy & Wu, 1996). What it can’t show is whether respondents answer an item the same way inside a CAT as inside the fixed form.
Simulate
The code below gives 200 simulated respondents a CAT from a 200-item 2PL bank (EAP, maximum information, stop at a posterior SD of 0.3 or 60 items), and compares it with a fixed form of the 20 items most informative at \(\theta = 0\). It is base R and runs in a second or two.
With the seed as written, the CAT uses 13.65 items on average against the form’s 20, with RMSEs of 0.29 and 0.31. The averages hide a trade: in the middle (\(-0.5\) to \(0.5\)) the fixed form is more precise (0.22 against 0.29), since the CAT stops at 0.3 after about 10 items; above 1.5 the CAT is (0.30 against 0.47), using 26 items. The form spends its items where most respondents are; the CAT spends them where each respondent is. Try se_stop <- 0.2, or b <- rnorm(n_items, 1.5, 0.5), a bank built for a high cut.
Download this code to run it in your own R session.
With real data
A medical examination as a bank
Our main example is choi_2026_cmsce_2020_1: a 2020 sitting of Korea’s Clinical Medical Science Comprehensive Examination (CMSCE) for medical students (Choi et al., 2026, data). Its job is to be a real bank for a post-hoc CAT. The items are five-option multiple choice across seven clinical domains, scored 1 for correct, and Choi et al. (2025) built a self-assessment CAT from six such sittings. Download the code; it needs mirt (Chalmers, 2012), and the CAT engine is a few dozen lines of base R.
Code
library(mirt)
# Each IRW table has a landing page (itemresponsewarehouse.org/tables/<name>/) with a
# CSV download. This link is pinned to one version of the data.
cm_url <- "https://redivis.com/api/v1/tables/datapages.item_response_warehouse_4:v8_0.choi_2026_cmsce_2020_1/rows?format=csv"
df <- read.csv(cm_url)
# resp is 1 for a correct answer and 0 otherwise. One sitting per respondent: no waves.
cm <- tapply(df$resp, list(df$id, df$item), function(x) x[1])
c(respondents = nrow(cm), items = ncol(cm), missing = sum(is.na(cm)),
mean_correct = round(mean(cm), 2)) respondents items missing mean_correct
5388.00 304.00 0.00 0.68
Every student answered every item. We calibrate a 2PL on a random half and keep the other half to be tested.
Code
# Calibrate on a random half; the other half is kept back to take the adaptive test.
# mirt writes the 2PL as a*theta + d; our difficulty is b = -d/a (IRTpars = TRUE).
set.seed(2020)
cal <- sort(sample(nrow(cm), nrow(cm) %/% 2))
m_cm <- mirt(as.data.frame(cm[cal, ]), 1, itemtype = "2PL", verbose = FALSE)
pars <- coef(m_cm, IRTpars = TRUE, simplify = TRUE)$items[, c("a", "b")]
# Items with slopes below 0.3 say little about theta anywhere (information a^2/4 at
# most 0.02); they stay out of the bank.
bank_items <- rownames(pars)[pars[, "a"] >= 0.3]
c(calibration = length(cal), items = nrow(pars), low_slope = sum(pars[, "a"] < 0.3),
of_which_negative = sum(pars[, "a"] < 0), bank = length(bank_items)) calibration items low_slope of_which_negative
2694 304 33 11
bank
271
Code
round(quantile(pars[bank_items, "b"], c(0, 0.1, 0.5, 0.9, 1)), 2) # bank difficulties 0% 10% 50% 90% 100%
-7.15 -2.73 -1.25 0.20 4.21
Code
round(quantile(pars[bank_items, "a"], c(0, 0.5, 1)), 2) # bank slopes 0% 50% 100%
0.30 1.05 2.59
Thirty-three items with slopes below 0.3 stay out, leaving 271. Eleven of the 33 have negative slopes, which in a working bank would send them to content review; the scored responses alone can’t say why. The bank’s median difficulty is −1.25, and only a tenth of its items are harder than 0.20: most are easy for these students.
Code
# A CAT in base R, for any unidimensional model mirt fits. Every quantity lives on a
# grid of nodes: the prior, each item's response probabilities and its information.
nodes <- seq(-6, 6, length.out = 121)
prior <- dnorm(nodes) # mirt's calibration fixes the mean at 0 and the SD at 1
make_bank <- function(model, items) {
it <- lapply(items, function(i) extract.item(model, i))
list(items = items,
logp = lapply(it, function(e) log(probtrace(e, nodes))), # nodes x categories
info = sapply(it, function(e) iteminfo(e, nodes))) # nodes x items
}
# EAP and posterior SD from the log likelihood on the nodes
eap <- function(ll) {
w <- exp(ll - max(ll)) * prior
w <- w / sum(w)
th <- sum(nodes * w)
c(theta = th, se = sqrt(sum((nodes - th)^2 * w)))
}
# Each available item's information at theta, interpolated between nodes
info_at <- function(bank, th, avail) {
k <- findInterval(th, nodes, all.inside = TRUE)
f <- (th - nodes[k]) / (nodes[k + 1] - nodes[k])
(1 - f) * bank$info[k, avail] + f * bank$info[k + 1, avail]
}
# One respondent. x holds their responses (0, 1, ...) to the bank items, in bank order.
# Start at the prior mean; give the most informative item at the current EAP (or pick
# at random among the `top` most informative, or at random from the whole bank); update;
# stop at max_items or when the posterior SD reaches se_stop.
run_cat <- function(x, bank, max_items = 20, se_stop = 0, select = "info", top = 1) {
ll <- numeric(length(nodes))
used <- integer(0)
est <- eap(ll)
while (length(used) < max_items && est[["se"]] > se_stop) {
avail <- setdiff(seq_along(bank$items), used)
if (select == "random") {
j <- avail[sample.int(length(avail), 1)]
} else {
best <- avail[order(info_at(bank, est[["theta"]], avail), decreasing = TRUE)]
best <- best[seq_len(min(top, length(best)))]
j <- best[sample.int(length(best), 1)]
}
ll <- ll + bank$logp[[j]][, x[j] + 1]
used <- c(used, j)
est <- eap(ll)
}
list(theta = est[["theta"]], se = est[["se"]], n = length(used), used = used)
}
bank_cm <- make_bank(m_cm, bank_items)The next chunk draws 600 held-out students and computes each one’s full-bank EAP, the answer a CAT tries to reach with fewer items.
Code
# The respondents who take the CAT: 600 drawn from the held-out half (the precomputed
# run uses all 600; the page runs the first 50 live).
held <- setdiff(seq_len(nrow(cm)), cal)
set.seed(2021)
cat_ids <- sample(held, 600)
X_cm <- cm[cat_ids, bank_items]
# Everyone's full-bank EAP: the target a CAT is trying to reach with fewer items
full_cm <- t(apply(X_cm, 1, function(x) unlist(run_cat(x, bank_cm, max_items = length(bank_items))[1:3])))Code
# Where is the bank informative? Test information and CSEM along the scale.
th <- seq(-4, 4, by = 0.01)
I_bank <- rowSums(sapply(bank_items, function(i) iteminfo(extract.item(m_cm, i), th)))
c(peak_at = th[which.max(I_bank)], peak_info = round(max(I_bank), 1),
csem_at_peak = round(1 / sqrt(max(I_bank)), 2)) peak_at peak_info csem_at_peak
-1.41 72.20 0.12
Code
round(sapply(c(-3, -2, -1, 0, 1, 2, 3), function(t) 1 / sqrt(I_bank[abs(th - t) < 1e-9])), 2)[1] 0.16 0.12 0.12 0.15 0.21 0.31 0.44
Code
c(items_above_2 = sum(pars[bank_items, "b"] > 2), items_below_minus2 = sum(pars[bank_items, "b"] < -2)) items_above_2 items_below_minus2
8 74
The bank’s information peaks at \(\theta = -1.41\) (CSEM 0.12); the CSEM is 0.31 at \(\theta = 2\) and 0.44 at 3. Only 8 items have \(b\) above 2, against 74 below −2, so even the whole bank can’t give a student at \(\theta = 2\) a standard error of 0.3. First, a known answer: a “CAT” allowed the whole bank must reproduce mirt’s full-bank EAP.
Code
# A known answer first: a "CAT" that gives the whole bank must reproduce mirt's own
# full-test EAP for every respondent (same nodes, same prior). Non-bank items are NA.
pat <- cm[cat_ids, colnames(cm)]
pat[, setdiff(colnames(cm), bank_items)] <- NA
mirt_eap <- fscores(m_cm, method = "EAP", response.pattern = pat, quadpts = 121,
theta_lim = c(-6, 6))
c(largest_difference = signif(max(abs(mirt_eap[, "F1"] - full_cm[, "theta"])), 2))largest_difference
1.3e-14
It does, to rounding error. The first items for one student:
Code
# The first few steps for one respondent: after one or two right answers there is no
# maximum-likelihood estimate, but the EAP moves up and its SD falls.
one <- run_cat(X_cm[1, ], bank_cm, max_items = 6)
steps <- t(sapply(1:6, function(s) {
ll <- Reduce(`+`, lapply(one$used[1:s], function(j) bank_cm$logp[[j]][, X_cm[1, j] + 1]))
e <- eap(ll)
c(item = s, a = round(pars[bank_items[one$used[s]], "a"], 2),
b = round(pars[bank_items[one$used[s]], "b"], 2), x = X_cm[1, one$used[s]],
eap = round(e[["theta"]], 2), post_sd = round(e[["se"]], 2))
}))
steps item a b x eap post_sd
[1,] 1 2.03 -0.01 0 -0.61 0.79
[2,] 2 2.21 -0.54 0 -1.04 0.68
[3,] 3 2.09 -1.12 0 -1.42 0.62
[4,] 4 2.59 -1.72 1 -1.16 0.50
[5,] 5 2.13 -1.27 0 -1.40 0.45
[6,] 6 2.21 -1.50 0 -1.60 0.42
Three wrong answers, a pattern with no MLE, yet the EAP moves from −0.61 to −1.42; every item chosen has a slope of 2 or more.
Code
# The first 50 CAT respondents, three rules: 20 items chosen by information, 20 chosen
# at random, and information until the posterior SD reaches 0.3 (at most 100 items).
set.seed(50)
live <- 1:50
rules <- list(info20 = list(max_items = 20), random20 = list(max_items = 20, select = "random"),
se0.3 = list(max_items = 100, se_stop = 0.3))
live_res <- lapply(rules, function(r) t(sapply(live, function(k)
unlist(do.call(run_cat, c(list(x = X_cm[k, ], bank = bank_cm), r))[1:3]))))
t(sapply(live_res, function(z) c(
mean_items = mean(z[, "n"]), r_full = round(cor(z[, "theta"], full_cm[live, "theta"]), 3),
rmse = round(sqrt(mean((z[, "theta"] - full_cm[live, "theta"])^2)), 2)))) mean_items r_full rmse
info20 20.0 0.956 0.28
random20 20.0 0.854 0.49
se0.3 30.4 0.967 0.26
For 50 students, 20 items chosen by information correlate 0.96 with the full-bank EAP (RMSE 0.28); 20 at random, 0.85 (0.49). A target SE of 0.3 takes 30 items on average.
Six hundred students, five rules
All 600 students under five rules are precomputed by compute.R, which reuses this page’s code for the data, calibration and engine; its first 50 students are those above.
Code
res_path <- file.path("..", "deepdives", "item-banks-cat", "results.rds")
cat600 <- if (file.exists(res_path)) readRDS(res_path) else NULL
if (!is.null(cat600)) {
s <- cat600$summary
print(data.frame(rule = s$rule, mean_items = round(s$mean_items, 1), median_items = s$median_items,
r_full = round(s$r_full, 3), rmse = round(s$rmse, 2),
reached_0.3 = round(s$share_reached_0.3, 2),
max_exposure = round(s$max_exposure, 2), never_used = s$items_never_used),
row.names = FALSE)
} rule mean_items median_items r_full rmse reached_0.3 max_exposure
random20 20.0 20 0.869 0.50 0.00 0.10
info20 20.0 20 0.957 0.29 0.50 1.00
info40 40.0 40 0.975 0.23 0.74 1.00
se0.3 33.5 21 0.967 0.26 0.93 1.00
se0.3_top5 33.6 21 0.965 0.27 0.93 0.86
never_used
0
205
144
121
114
Run on 25 September 2026 for 600 respondents, in 1.3 minutes.
Twenty items by information correlate 0.957 with the full bank (RMSE 0.29), against 0.869 (0.50) at random; forty reach 0.975. Under a target SE of 0.3, 93% reach it, in a mean of 33.5 items but a median of 21. The last two columns show the cost: twenty items by information use only 66 of the 271, and one goes to every student (86% under randomesque selection).
Code
if (!is.null(cat600)) {
b <- cat600$by_band
print(data.frame(full_bank_theta = b$band, students = b$respondents, mean_items = round(b$mean_items, 1),
share_at_cap = round(b$share_at_cap, 2), mean_post_sd = round(b$mean_se, 2)), row.names = FALSE)
} full_bank_theta students mean_items share_at_cap mean_post_sd
(-Inf,-1] 90 12.6 0.00 0.29
(-1,0] 211 16.0 0.00 0.30
(0,1] 180 33.7 0.00 0.30
(1,2] 99 75.8 0.22 0.30
(2, Inf] 20 100.0 1.00 0.37
Students below \(\theta = -1\) need 12.6 items on average; between 1 and 2 they need 75.8, with 22% at the cap, and all 20 above 2 stop at 100 items with a posterior SD of 0.37. Choi et al. (2025) saw the same in their live CAT, where students at the extremes reached its 50-item maximum, and they call for more hard items. The post-hoc CAT finds this before anyone is tested. (Their bank pooled six sittings whose IRW tables share no items; how those were put on one scale is a question for Linking and equating.)
What does the choice of stopping rule rest on? Two assumptions: whether scores must be compared at equal precision, and whether everyone must get the same testing time. A target standard error with a cap takes the first and gives up the second; a fixed length does the reverse. A post-hoc CAT on real responses, as here, shows what each rule costs for a given bank, and where the bank runs out before any respondent does. For this bank, the students above \(\theta = 2\) reach the 100-item cap with a posterior SD of 0.37, which says that new hard items would buy more than a higher cap.
PROMIS depression: a bank built for symptoms
For contrast, promis1wave1_depression: the 56 candidate depression items from the first wave of PROMIS testing, given to US adults (Cella et al., 2010; data at https://doi.org/10.7910/DVN/0NGAKG). Its job is to show a bank whose information sits where its purpose puts it. The items ask how often, in the past seven days, the respondent had a depressive feeling or thought, from never to always; PROMIS kept 28 in its bank (Pilkonis et al., 2011). HealthMeasures, which distributes PROMIS, doesn’t permit republishing the items, so we don’t quote them. Higher means more frequent symptoms; we recode the categories 0–4.
Code
# PROMIS wave 1 depression: 56 candidate items, each on five frequency categories, 1
# (never) to 5 (always), so higher means more symptoms; none needs reversing. Recoded 0-4.
dep_url <- "https://redivis.com/api/v1/tables/datapages.item_response_warehouse:v60_0.promis1wave1_depression/rows?format=csv"
dd <- read.csv(dep_url)
dep <- tapply(dd$resp - 1, list(dd$id, dd$item), function(x) x[1])
dep <- dep[, order(colnames(dep))]
n_answered <- rowSums(!is.na(dep))
c(respondents = nrow(dep), items = ncol(dep), answered_7 = sum(n_answered == 7),
answered_all_56 = sum(n_answered == 56)) respondents items answered_7 answered_all_56
14909 56 13975 781
Code
round(mean(dep == 0, na.rm = TRUE), 2) # share of responses that are "never"[1] 0.52
Most respondents answered 7 items; 781 answered all 56. We keep 300 of those for a post-hoc CAT and calibrate the graded response model on everyone else; the engine works unchanged.
Code
# 300 of the respondents who answered all 56 items take the CAT; the graded response
# model (PROMIS's own choice) is calibrated on everyone else, with the missing blocks
# left missing.
set.seed(56)
dep_cat <- sample(which(n_answered == 56), 300)
m_dep <- mirt(as.data.frame(dep[-dep_cat, ]), 1, itemtype = "graded", verbose = FALSE)
bank_dep <- make_bank(m_dep, colnames(dep))
X_dep <- dep[dep_cat, ]
I_dep <- rowSums(sapply(colnames(dep), function(i) iteminfo(extract.item(m_dep, i), th)))
c(peak_at = th[which.max(I_dep)], peak_info = round(max(I_dep), 1)) peak_at peak_info
1.53 129.80
Code
round(sapply(c(-2, -1, -0.5, 0, 1, 2, 3), function(t) 1 / sqrt(I_dep[abs(th - t) < 1e-9])), 2)[1] 0.49 0.19 0.13 0.10 0.09 0.09 0.13
Code
b_dep <- coef(m_dep, IRTpars = TRUE, simplify = TRUE)$items
round(quantile(b_dep[, "b1"], c(0, 0.5, 1)), 2) # the lowest boundary, never vs. rarely 0% 50% 100%
-1.20 -0.04 2.70
Information peaks at \(\theta = 1.53\) (CSEM 0.09), and the CSEM stays below 0.2 from \(-1\) to 3; at \(-2\), all 56 items together give 0.49. The median item’s lowest boundary, between never and rarely, is at −0.04: most items start to be informative only where symptoms start. Pilkonis et al. (2011) describe the calibrated banks as more informative than older measures from about \(-1\) to \(+3\) SDs.
Code
# Post-hoc CAT to a posterior SD of 0.3 (no cap beyond the 56 items), against each
# respondent's full-bank EAP.
full_dep <- t(apply(X_dep, 1, function(x) unlist(run_cat(x, bank_dep, max_items = 56)[1:3])))
set.seed(57)
cat_dep <- t(apply(X_dep, 1, function(x) unlist(run_cat(x, bank_dep, max_items = 56, se_stop = 0.3)[1:3])))
c(median_items = median(cat_dep[, "n"]), mean_items = round(mean(cat_dep[, "n"]), 1),
r_full = round(cor(cat_dep[, "theta"], full_dep[, "theta"]), 3),
reached_0.3 = round(mean(cat_dep[, "se"] <= 0.3), 2))median_items mean_items r_full reached_0.3
5.000 10.000 0.954 0.910
Code
band <- cut(full_dep[, "theta"], c(-Inf, -0.5, 0.5, 1.5, Inf))
data.frame(respondents = as.vector(table(band)),
mean_items = round(tapply(cat_dep[, "n"], band, mean), 1),
mean_post_sd = round(tapply(cat_dep[, "se"], band, mean), 2))| respondents | mean_items | mean_post_sd | |
|---|---|---|---|
| (-Inf,-0.5] | 120 | 19.6 | 0.31 |
| (-0.5,0.5] | 111 | 3.7 | 0.28 |
| (0.5,1.5] | 49 | 2.6 | 0.28 |
| (1.5, Inf] | 20 | 5.8 | 0.29 |
Code
c(at_floor = sum(rowSums(X_dep) == 0), floor_eap = round(unique(full_dep[rowSums(X_dep) == 0, "theta"]), 2)) at_floor floor_eap
7.00 -2.22
The CAT needs a median of 5 items and a mean of 10.0, and correlates 0.95 with the full bank (Choi et al., 2010, found CAT and full-bank scores highly correlated on the 28-item bank). By band the lengths run the other way from the CMSCE’s: 2.6 to 3.7 items between \(-0.5\) and 1.5, and 19.6 below \(-0.5\), where the average posterior SD at the stop is still 0.31. The seven respondents who chose “never” on all 56 items share an EAP of −2.2. None of this is a fault in the respondents or the items: a depression bank is built to tell mild from moderate from severe, which it does in three or four items, and telling “none” from “very few” isn’t its job. The examination is thin at the top, the depression bank at the bottom, and in both a post-hoc CAT finds the thin end.
Problems
- Which item next? (a) Under the Rasch model, show that the most informative item at \(\hat\theta\) has \(b\) closest to \(\hat\theta\). (b) Under the 2PL, which of \(a = 2, b = 1\) and \(a = 1, b = 0\) is more informative at \(\hat\theta = 0\), and where does the answer change? Why does maximum information give steep items early?
- A stricter bank. Apply Choi et al.’s (2025) screen (slopes above 0.6, \(|b| < 5\)) to the CMSCE calibration and rerun the target-SE CAT on the 50 live respondents. How much bank is left, and what happens at the top?
- You work at the state agency. You have last year’s summative test data for one grade: every student’s scored responses to a fixed form, and nothing else about the students. Build an item bank from it: which fields does each item’s record need, how would you calibrate, and how would next year’s new items join? Then say what you can’t do with these data, and what you would ask for. (There are no data for this problem.)
- The low end. A general-population survey expects most respondents to report few depressive symptoms. Would you use the PROMIS CAT, a fixed short form, or new low-end items first, and how would you calibrate new items onto the bank’s scale?
- Pass or fail. Put a pass mark at the 10th percentile of the 600 CMSCE students’ full-bank \(\theta\) and stop with an SPRT (\(\delta = 0.2\), error rates of 5%), choosing items by information at the cut. How many items does a decision take, by band, against the target-SE rule, and how many students are classified differently from their full-bank \(\theta\)?
- Challenge (open): post-hoc and live. A post-hoc CAT reuses responses given in a fixed form and order. How might responses in a live CAT differ (item position, fatigue, a test that feels hard to strong respondents, stakes)? Design a study that would show whether post-hoc results carry over. I don’t think one study settles it for every bank.
Going further
- Wainer, H., Dorans, N. J., Flaugher, R., Green, B. F., & Mislevy, R. J. (2000). Computerized adaptive testing: A primer (2nd ed.). Erlbaum. https://doi.org/10.4324/9781410605931. The standard introduction, from item banks to scoring.
- van der Linden, W. J., & Glas, C. A. W. (Eds.). (2010). Elements of adaptive testing. Springer. https://doi.org/10.1007/978-0-387-85461-8. Item selection, exposure control, stopping and item pools, chapter by chapter.
- Weiss, D. J. (1982). Improving measurement quality and efficiency with adaptive testing. Applied Psychological Measurement, 6(4), 473–492. https://doi.org/10.1177/014662168200600408. Adaptive tests designed for equal precision along the scale.
- Weiss, D. J., & Kingsbury, G. G. (1984). Application of computerized adaptive testing to educational problems. Journal of Educational Measurement, 21(4), 361–375. https://doi.org/10.1111/j.1745-3984.1984.tb01040.x. Stopping rules for measurement and for classification.
- Owen, R. J. (1975). A Bayesian sequential procedure for quantal response in the context of adaptive mental testing. Journal of the American Statistical Association, 70(350). https://doi.org/10.2307/2285821. An early Bayesian procedure for choosing items.
- Bock, R. D., & Mislevy, R. J. (1982). Adaptive EAP estimation of ability in a microcomputer environment. Applied Psychological Measurement, 6(4), 431–444. https://doi.org/10.1177/014662168200600405. EAP scoring for adaptive tests.
- van der Linden, W. J. (1998). Bayesian item selection criteria for adaptive testing. Psychometrika, 63(2), 201–216. https://doi.org/10.1007/BF02294775. Selection criteria built on the full posterior (the Go deeper callout).
- Chang, H.-H., & Ying, Z. (1996). A global information approach to computerized adaptive testing. Applied Psychological Measurement, 20(3), 213–229. https://doi.org/10.1177/014662169602000303. Why Fisher information at the estimate suits the start of a test least.
- Kingsbury, G. G., & Zara, A. R. (1989). Procedures for selecting items for computerized adaptive tests. Applied Measurement in Education, 2(4), 359–375. https://doi.org/10.1207/s15324818ame0204_6. Content balancing and exposure in item selection.
- Chang, H.-H., & Ying, Z. (1999). a-Stratified multistage computerized adaptive testing. Applied Psychological Measurement, 23(3), 211–222. https://doi.org/10.1177/01466219922031338. Holding steep items back.
- Chang, H.-H. (2015). Psychometrics behind computerized adaptive testing. Psychometrika, 80(1), 1–20. https://doi.org/10.1007/s11336-014-9401-5. A survey of the theory, and of problems met in large-scale use.
- Hetter, R. D., & Sympson, J. B. (1997). Item exposure control in CAT-ASVAB. In W. A. Sands, B. K. Waters, & J. R. McBride (Eds.), Computerized adaptive testing: From inquiry to operation (pp. 141–144). American Psychological Association. https://doi.org/10.1037/10244-014. The Sympson–Hetter method in an operational test.
- van der Linden, W. J. (2003). Some alternatives to Sympson-Hetter item-exposure control in computerized adaptive testing. Journal of Educational and Behavioral Statistics, 28(3), 249–265. https://doi.org/10.3102/10769986028003249. What the Sympson–Hetter method does, and alternatives to it.
- Revuelta, J., & Ponsoda, V. (1998). A comparison of item exposure control methods in computerized adaptive testing. Journal of Educational Measurement, 35(4), 311–327. https://doi.org/10.1111/j.1745-3984.1998.tb00541.x. Eight selection methods compared for exposure and precision.
- Wald, A. (1945). Sequential tests of statistical hypotheses. The Annals of Mathematical Statistics, 16(2), 117–186. https://doi.org/10.1214/aoms/1177731118. The sequential probability ratio test.
- Spray, J. A., & Reckase, M. D. (1996). Comparison of SPRT and sequential Bayes procedures for classifying examinees into two categories using a computerized test. Journal of Educational and Behavioral Statistics, 21(4), 405–414. https://doi.org/10.3102/10769986021004405. The SPRT as a CAT stopping rule.
- Eggen, T. J. H. M. (1999). Item selection in adaptive testing with the sequential probability ratio test. Applied Psychological Measurement, 23(3), 249–261. https://doi.org/10.1177/01466219922031365. Choosing items for a classification CAT.
- Luecht, R. M., & Nungester, R. J. (1998). Some practical examples of computer-adaptive sequential testing. Journal of Educational Measurement, 35(3), 229–249. https://doi.org/10.1111/j.1745-3984.1998.tb00537.x. Multistage testing with preassembled modules.
- Mislevy, R. J., & Wu, P.-K. (1996). Missing responses and IRT ability estimation: Omits, choice, time limits, and adaptive testing. ETS Research Report Series, 1996(2). https://doi.org/10.1002/j.2333-8504.1996.tb01708.x. Why the items a CAT didn’t give can be ignored.
- Binet, A., & Simon, T. (1904). Méthodes nouvelles pour le diagnostic du niveau intellectuel des anormaux. L’Année psychologique, 11, 191–244. https://doi.org/10.3406/psy.1904.3675. Tasks graded by age, a paper ancestor of adaptive testing.
- Ma, W. A., Richie-Halford, A., Burkhardt, A. K., Kanopka, K., Chou, C., Domingue, B. W., & Yeatman, J. D. (2025). ROAR-CAT: Rapid Online Assessment of Reading ability with Computerized Adaptive Testing. Behavior Research Methods, 57(1), 56. https://doi.org/10.3758/s13428-024-02578-y. Checking a bank’s parameters across groups, and a randomized test of CAT against random order.
- Choi, J., Jung, S.-S., Choi, E. K., Kim, K. S., & Seo, D. G. (2025). Feasibility of applying computerized adaptive testing to the Clinical Medical Science Comprehensive Examination in Korea: A psychometric study. Journal of Educational Evaluation for Health Professions, 22, 29. https://doi.org/10.3352/jeehp.2025.22.29. The live CAT built from the CMSCE.
- Pilkonis, P. A., Choi, S. W., Reise, S. P., Stover, A. M., Riley, W. T., Cella, D., & PROMIS Cooperative Group. (2011). Item banks for measuring emotional distress from the Patient-Reported Outcomes Measurement Information System (PROMIS®): Depression, anxiety, and anger. Assessment, 18(3), 263–283. https://doi.org/10.1177/1073191111411667. How the depression bank was built and calibrated.
- Choi, S. W., Reise, S. P., Pilkonis, P. A., Hays, R. D., & Cella, D. (2010). Efficiency of static and computer adaptive short forms compared to full-length measures of depressive symptoms. Quality of Life Research, 19(1), 125–136. https://doi.org/10.1007/s11136-009-9560-5. Post-hoc CATs and short forms on the PROMIS depression bank.
- Cella, D., Riley, W., Stone, A., Rothrock, N., Reeve, B., Yount, S., et al. (2010). The Patient-Reported Outcomes Measurement Information System (PROMIS) developed and tested its first wave of adult self-reported health outcome item banks: 2005–2008. Journal of Clinical Epidemiology, 63(11), 1179–1194. https://doi.org/10.1016/j.jclinepi.2010.04.011. The source of the depression data.
- Magis, D., & Raîche, G. (2012). Random generation of response patterns under computerized adaptive testing with the R package catR. Journal of Statistical Software, 48(8). https://doi.org/10.18637/jss.v048.i08. A package for simulating CATs, with many selection and stopping rules.
- Chalmers, R. P. (2016). Generating adaptive and non-adaptive test interfaces for multidimensional item response theory applications. Journal of Statistical Software, 71(5). https://doi.org/10.18637/jss.v071.i05.
mirtCAT, for running CATs, live or post hoc, frommirtmodels. - Chalmers, R. P. (2012). mirt: A multidimensional item response theory package for the R environment. Journal of Statistical Software, 48(6). https://doi.org/10.18637/jss.v048.i06. The calibrations, and the item probabilities and information the engine uses.
- Lord, F. M. (1980). Applications of item response theory to practical testing problems. Erlbaum. https://doi.org/10.4324/9780203056615. Chapter 10 is on tailored testing.
- van der Linden, W. J. (2017). Adaptive testing. In W. J. van der Linden (Ed.), Handbook of item response theory: Vol. 3. Applications (pp. 197–228). Chapman and Hall/CRC. https://doi.org/10.1201/9781315117430. A handbook chapter on adaptive testing.
- Gershon, R. C., Hays, R. D., & Kallen, M. A. (2017). Health measurement. In W. J. van der Linden (Ed.), Handbook of item response theory: Vol. 3. Applications (pp. 349–364). Chapman and Hall/CRC. https://doi.org/10.1201/9781315117430. A handbook chapter on item response theory in health measurement.
Data sources
Data from the Item Response Warehouse (each table name links to its IRW page); references from IRW biblio.
choi_2026_cmsce_2020_1: Choi, J., Jung, S.-S., Choi, E. K., Kim, K. S., & Seo, D. G. (2026). Feasibility of applying computerized adaptive testing to the Clinical Medical Science Comprehensive Examination in Korea: a psychometric study [Data set]. Harvard Dataverse. https://doi.org/10.7910/DVN/TQZQ6L. Licence: CC0 1.0.promis1wave1_depression: Cella, D., Riley, W., Stone, A., Rothrock, N., Reeve, B., Yount, S., … & Hays, R. (2010). Initial adult health item banks and first wave testing of the patient-reported outcomes measurement information system (PROMIS™) network: 2005–2008. Journal of clinical epidemiology, 63(11), 1179. Cella, David, 2015, “PROMIS 1 Wave 1”, https://doi.org/10.7910/DVN/0NGAKG, Harvard Dataverse, V3, UNF:6:sXYqKDzGWfX7QuTXNGpjGQ== [fileUNF]. Licence: CC0 1.0.
For instructors
- Source: EDUC 252 class 6 (slides c6, 22–31: item banks, the adaptive loop, ROAR-CAT) and class 10 (slides c10, 44–45 and 49: item banks in practice, and the state-agency exercise). There was no 252 code or problem set for this lesson; the CAT engine, the widgets, the simulation and the post-hoc CATs are new.
- Timing: the core ideas and widgets take about 50 minutes; the two real-data analyses work as a 30-minute lab. The page’s code takes about two and a half minutes in local R, most of it the two calibrations;
compute.Rtakes under two minutes. - Precomputed results: the 600-respondent CAT under five rules is in
deepdives/item-banks-cat/results.rds, written bycompute.R(digest E12); the page runs the first 50 respondents itself.compute.Rruns this page’s own code for the data, the calibration and the engine, so the two can’t drift apart. - Changed from 252: the slides walk through a CAT on a figure; here the reader steps through one in a widget and then runs one on real responses. The state-agency exercise (c10, slide 45) pointed to anonymized state data that isn’t in the IRW, so it is problem 3, a design problem without data (digest F21). A paper basal-and-ceiling widget in the outline was dropped for length; basal and ceiling rules get a sentence.
- Held back: writing and pre-calibrating new items, and predicting their difficulty from the text (AI and psychometrics); multidimensional CAT (Dimensionality and multidimensional IRT); response times in adaptive tests (Response time and the speed-accuracy tradeoff). Item drift over time, multistage testing and content-balancing algorithms are named but not taught.
- Item text: PROMIS items are summarized, not quoted (HealthMeasures’ terms of use bar redistribution). The CMSCE deposit holds scored responses only, with no item text.
- Solutions: held back in
solutions/item-banks-cat.qmd(not published).