fit.FCMIRT: Fit the Forced-Choice Multidimensional IRT (FCMIRT) Model

View source: R/fit.FCMIRT.R

fit.FCMIRTR Documentation

Fit the Forced-Choice Multidimensional IRT (FCMIRT) Model

Description

Fits a forced-choice variant of the multidimensional item response theory model to comparative ranking data. In forced-choice (FC) formats, respondents compare items within blocks rather than rating each item in isolation. The FCMIRT model couples an item-level MIRT endorsement model with a block-level ranking mechanism to recover latent trait estimates from comparative responses.

Usage

fit.FCMIRT(
  data,
  model = "2PL",
  Q.matrix = NULL,
  block.items = NULL,
  D = NULL,
  fc.type = NULL,
  method = c("iStEM", "stan"),
  control.model = NULL,
  control.method = NULL
)

Arguments

data

An N \times B forced-choice data object. Each entry is either a ranking string (e.g., "2>1>3") or a 1-based pattern index into the block's ranking patterns. If pattern indices are used, block.items must be supplied.

model

MIRT model type: "m1pl", "m2pl" (default), "m3pl", or "m4pl".

Q.matrix

An optional I \times D binary (0/1) matrix indicating active item loadings.

block.items

A list of length B where each element is an integer vector of global item indices belonging to that block. If NULL and data contains ranking strings, automatically parsed from the data.

D

Integer; number of latent dimensions. If NULL, inferred from Q.matrix; if both are NULL, an error is raised.

fc.type

Character vector (length 1 or B): "RANK" (full ranking, default), "MOLE" (most-least), or "PICK" (best only). Recycled to all blocks if scalar.

method

Estimation method: "iStEM" (default) or "stan".

control.model

A named list of model-level hyperparameters. Supported entries:

a.mu, a.sigma

Prior location and scale for \log a_{id} (log-normal). Defaults: 0, 1.0. Important: The Stan default for a.sigma is deliberately set to 1.0 (wider than the MIRT default of 0.25) because forced-choice blocks identify relative utilities; tight common slope priors can spuriously shrink within-block slopes toward equality, degrading trait recovery. For iStEM, the prior defaults match the standard MIRT values (a.mu = 0.25, a.sigma = 0.25) unless overridden.

b.mu, b.sigma

Prior mean and SD for b_i (normal). Defaults: 0, 1. Under the block zero-sum constraint \sum_{i \in \text{block } b} b_i = 0, these priors regularize the free difficulty parameters.

c.mu, c.sigma

Uniform support bounds [c_{\min}, c_{\max}] for lower-asymptote parameters c_i. Defaults: 0, 0.35. Only used for 3PL/4PL models.

d.mu, d.sigma

Uniform support bounds [d_{\min}, d_{\max}] for upper-asymptote parameters d_i. Defaults: 0.65, 1. Only used for 4PL models.

theta.mu

Prior mean vector for \boldsymbol{\theta}_j. Default: rep(0, D).

L

Theta grid size per dimension for marginal log-likelihood computation and iStEM block Gibbs sampling. Default adapts to D (e.g., 61 for D = 1, 31 for D = 2, 15 for D = 3).

theta.lower, theta.upper

Bounds for the theta grid used by marginal log-likelihood computation and iStEM block Gibbs sampling. Defaults: -6, 6.

use.prior

Logical (iStEM only). If FALSE, the item-prior penalty term is omitted from the item update, recovering an approximate maximum-likelihood item step. Default is TRUE.

control.method

A named list of method-specific tuning parameters. Common entries (used by both Stan and iStEM):

cores

Number of CPU cores for parallel chains (Stan) or ignored (iStEM). Default: the number of chains.

vis

Logical; if TRUE (default), prints progress information to the console.

seed

Random seed for reproducibility. Default: a random integer.

Stan-specific entries:

chains

Number of MCMC chains (default: 2).

iter

Total iterations per chain (default: 5000).

warmup

Warmup/burn-in iterations per chain (default: iter / 2).

thin

Thinning interval (default: 1).

init

Initial values: "random" (default) for uniform(-2, 2) initialization, or a list of initial values per chain.

algorithm

MCMC algorithm: "HMC" (default), "HMC", or "Fixed_param".

adapt_delta

Target average acceptance probability (NUTS; default: 0.95). Forced-choice models often have challenging posterior geometries; consider increasing to 0.9 or higher if divergent transitions appear.

max_treedepth

Maximum tree depth (NUTS; default: 10). Increase if "max treedepth exceeded" warnings appear.

stepsize

Initial step size for the leapfrog integrator (auto-tuned by Stan if not set).

int_time

Total integration time for HMC trajectories (only when algorithm = "HMC").

metric

Mass matrix type: "unit_e", "diag_e" (default), or "dense_e".

adapt_engaged

Logical; if TRUE (default), warmup adaptation is enabled.

adapt_init_buffer, adapt_term_buffer, adapt_window

Warmup adaptation scheduling parameters (defaults: 25, 50, 25).

iStEM-specific entries:

M

Number of burn-in batches retained for Geweke convergence diagnosis (default: 10; must be \ge 2).

B

Batch size: MCMC iterations per batch (default: 20).

burnin.maxitr

Maximum burn-in batches (default: 100).

maxitr

Maximum total batches (default: 2000).

eps1

Geweke z-score convergence threshold for burn-in (default: 1.5).

eps2

Monte Carlo error tolerance for the final chain (default: 0.4).

frac1, frac2

Fractions for the Geweke diagnostic (defaults: 0.1, 0.5).

corr.optim.maxit

Maximum L-BFGS-B iterations for the constrained unit-diagonal correlation update (default: 50).

optim.maxit

Maximum L-BFGS-B iterations per item (default: 50).

fix.corr

Logical; fix correlations to identity (default: FALSE).

estimate.se

Logical; compute standard errors from final MC chain (default: TRUE).

a.lower, a.upper

Bounds on a_{id} during optimization (defaults: 1e-4, 6).

b.lower, b.upper

Bounds on b_i during optimization (defaults: -6, 6).

c.lower, c.upper

Bounds on c_i for 3PL/4PL models. Defaults from prior support.

d.lower, d.upper

Bounds on d_i for 4PL models. Defaults from prior support.

Value

An object of class "FCMIRT" containing:

npar

Number of free parameters.

method

"stan" or "iStEM".

theta

List with est, se, Rhat (N \times D); person trait estimates.

par

List with est, se, Rhat, free (I \times (D+3)); item parameters a1..aD, b, c, d.

Corr

List with est, se, Rhat (D \times D).

block.items, patterns, patterns.total, response

Block structure and response data.

logLik

Marginal log-likelihood (class "logLik").

Model Specification

Item-level endorsement. Each statement i = 1, \dots, I is governed by a MIRT model (1PL through 4PL). For a person with trait \boldsymbol{\theta}_j, the probability of endorsing statement i in isolation is:

P_i(\boldsymbol{\theta}_j) = c_i + (d_i - c_i) \times \frac{1}{1 + \exp\bigl[-\bigl(\sum_{d=1}^{D} a_{id}\,\theta_{jd} - b_i\bigr)\bigr]}.

Block-level ranking. Let block b = 1, \dots, B consist of items \{i_1, i_2, \dots, i_{K_b}\} and define the implemented statement utility as the logit of the item-level endorsement probability,

u_i(\boldsymbol{\theta}_j) = \log\left[ \frac{P_i(\boldsymbol{\theta}_j)} {1-P_i(\boldsymbol{\theta}_j)} \right].

The probability that an examinee produces the ranking i_{(1)} \succ i_{(2)} \succ \dots \succ i_{(K_b)} (read as "i_{(1)} is preferred over i_{(2)} over ...") is:

P\bigl(i_{(1)} \succ \dots \succ i_{(K_b)} \mid \boldsymbol{\theta}_j\bigr) = \prod_{m=1}^{K_b-1} \frac{ \exp\{u_{i_{(m)}}(\boldsymbol{\theta}_j)\} }{ \sum_{r=m}^{K_b} \exp\{u_{i_{(r)}}(\boldsymbol{\theta}_j)\} }.

The Stan code evaluates the same choice kernel as \log P_i + \sum_{h \ne i}\log(1-P_h) within each remaining set, which is algebraically equivalent to a softmax over \mathrm{logit}(P_i).

Partial rankings (MOLE / PICK). For MOLE (most-least) data, only the best and worst items in each block are identified; for PICK data, only the best item. The probability of a partial ranking is obtained by marginalizing (summing) the full-ranking probabilities over all completions consistent with the partial constraint; the C++ probability helper returns probabilities normalized over the observed RANK/MOLE/PICK patterns for each block.

Identification constraint (2PLM-RANK). Block intercepts b_i are constrained to sum to zero within each block:

\sum_{i \in \text{block } b} b_i = 0, \qquad b = 1, \dots, B,

so that only K_b - 1 difficulties are freely estimated per block.

Estimation Methods

Stan (method = "stan"):

Full Bayesian inference via HMC. The forced-choice likelihood is evaluated over the ranking pattern probabilities. By default, a.sigma is set to 1.0 (wider prior) to avoid spurious shrinkage of within-block slopes toward equality.

iStEM (method = "iStEM"):

Improved Stochastic EM with finite-grid block Gibbs person-sampling and item optimization (L-BFGS-B). Block-level identification constraints are enforced during each item-parameter update.

References

Brown, A., & Maydeu-Olivares, A. (2011). Item response modeling of forced-choice questionnaires. Educational and Psychological Measurement, 71(3), 460–502. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1177/0013164410375112")}

Luce, R. D. (1959). Individual choice behavior: A theoretical analysis. Wiley.

Plackett, R. L. (1975). The analysis of permutations. Journal of the Royal Statistical Society: Series C, 24(2), 193–202.

See Also

sim.data.FCMIRT, get.fit.index.FCMIRT, logLik.FCMIRT, fit.MIRT

Examples

# Simulate forced-choice data
sim <- sim.data.FCMIRT(N.person = 20, N.block = 3, I.block = 2,
                       D = 2, model = "m2pl", fc.type = "RANK")

# Fit via iStEM
fit <- fit.FCMIRT(sim$data, model = "m2pl",
                  Q.matrix = sim$Q.matrix,
                  block.items = sim$block.items,
                  D = 2, fc.type = "RANK",
                  method = "iStEM",
                  control.method = list(
                    vis = FALSE, seed = 123,
                    M = 2, B = 2, burnin.maxitr = 2,
                    maxitr = 3, eps1 = 10, eps2 = 10,
                    estimate.se = FALSE))

# Examine trait recovery
cor(fit$theta$est, sim$theta)

# Fit indices (nominal binary expansion)
gof <- get.fit.index(fit)
summary(gof)


ForceChoice documentation built on Sept. 13, 2026, 1:06 a.m.