| mpt | R Documentation |
Multinomial Processing Tree (MPT) models measure the probabilities of
discrete latent cognitive states from categorical responses. A model is
specified as a set of trees created with mpt_tree(), one per distinct
branch structure, such as one tree for targets and one for lures in a
recognition test. Branch expressions that terminate in the same response
category are summed within each tree, and parameters shared across trees
are equated by giving them the same name. All latent probability
parameters are estimated on an unconstrained latent scale (logit or
probit); predictor formulas supplied via bmmformula() apply on that
latent scale.
mpt(
trees,
tree_id = NULL,
covariates = NULL,
simplex = NULL,
restrictions = NULL,
links = "logit",
...
)
trees |
A single |
tree_id |
Character. Name of the data column whose values name the tree each observation belongs to; the values must match the tree names. Can be omitted for single-tree models. Effects of experimental conditions belong in the parameter formulas, not here; see Details. |
covariates |
Character vector. Names of data columns that appear in
branch expressions but are not latent parameters, for example
design-fixed guessing rates. Covariates pass into the model formulas
unchanged and have no naming restrictions. |
simplex |
A character vector, or a list of character vectors, naming
groups of parameters that are jointly constrained to sum to 1. Each group
is reparameterized via stick-breaking: the last parameter of each group
is derived as 1 minus the sum of the other members, and each other member
|
restrictions |
Parameter restrictions in the string syntax of MPTinR
and TreeBUGS, e.g. |
links |
The link function of the latent probability parameters:
|
... |
used internally for testing, ignore it |
Domain: Categorical decision making, memory, and reasoning
Task: Any task with categorical responses generated by a discrete processing-tree structure
Name: Multinomial Processing Tree (MPT) models
Citation:
Batchelder, W. H., & Riefer, D. M. (1999). Theoretical and empirical review of multinomial process tree modeling. Psychonomic Bulletin & Review, 6(1), 57-86. https://doi.org/10.3758/BF03210812
The data hold aggregated counts: one row per participant and tree (and
per condition, if conditions are crossed with the trees), with one count
column per response category. The count columns must be named exactly
like the branch names given to mpt_tree() (old and new in the
example below); bmm() finds them by these names, so no response
variable is passed. The tree_id column names the tree of each row, and
the counts of a row must come from trials of that tree. Wide tables with
one column per category of an EQN file, as MPTinR and TreeBUGS take them,
are reshaped with mpt_data_reshape().
A separate tree is needed only when the branch expressions differ, that
is, when the trial determines which latent processes apply or which
response categories are reachable (targets versus lures, a response set
with or without distractors, inclusion versus exclusion instructions).
Experimental factors whose effect on the parameters you want to estimate
belong in the parameter formulas, exactly as in every other bmm model:
bmf(D ~ 0 + condition). The two roles are independent, and one data
column can serve both when a factor happens to change the structure as
well. When several levels of a factor share a branch structure, add a
column naming the tree and keep the factor for the formulas.
Equating and fixing parameters. Parameters are equated across trees
by giving them the same name. Beyond that, there are two mechanisms, and
they differ in when the constraint is decided. A restriction
(restrictions = c("Dn = Do", "g = 0.5")) is applied when the model is
built: it is substituted into the branch expressions before the
parameters are identified, so the restricted parameter is not part of
the model, gets no formula and no prior, cannot be a simplex member, and
is listed by print(model) under Restrictions: but not by
parameter_info(). A constant in the formula (bmf(D ~ 1, g = 0.5))
is applied at fit time: the parameter stays part of the model, is listed
by print() under Fixed: and by parameter_info() with its value, and
is freed again by giving it a formula. The value is mapped to the latent
scale when the constant prior is built, so default_prior() shows
constant(0) for a guessing rate of 0.5 under the logit link, and
summary() lists it as g_Intercept 0.00 under "Constant Parameters";
prior_info() and parameter_info() show the probability, 0.5. Members
of a simplex group and their praw components cannot be fixed this
way; fix parameters outside the group instead. As a rule of thumb, a
constant that defines the model goes into restrictions, a constant you
compare against a free version goes into the formula; the section
"Constraining parameters" of the MPT article walks through both.
Default priors. Under the logit link, intercepts and regression
coefficients get a logistic(0, 1) prior and random-effect SDs get
exponential(1). Under the probit link, intercepts and coefficients get
normal(0, 1) and SDs get exponential(2). Group-level correlation
matrices get lkj(2). A parameter switched to the other link after
construction (model$links$D <- "probit") takes that link's priors
unless its default prior was replaced. default_prior() lists the rows
a given formula produces.
The default prior of a simplex group of K members is the uniform
(symmetric Dirichlet(1)) distribution on the simplex: each member has
prior mean 1/K, whatever the listing order. Under stick breaking this is
a Beta(1, K - k) prior on stick k, which default_prior() shows as
logitbeta(1, K - k) (or probitbeta(1, K - k)) on the intercept of
the k-th praw; the last stick keeps logistic(0, 1) (or
normal(0, 1)), which is the same distribution. The result is exact
under both links, and under 0 + cond it holds in every cell. Under
1 + cond it holds in the reference cell only, because the effects keep
their own prior. TreeBUGS instead puts a uniform prior on each branch
parameter, under which the first member has prior mean 0.5 (0.50/0.25/0.25
for three members). To get it for a group gA, gB, gC, gD, pass
prior = brms::set_prior("logistic(0, 1)", nlpar = c("gAraw", "gBraw")),
with "normal(0, 1)" under the probit link; without coef, it covers
every cell of a 0 + cond formula.
A predictor on member p acts on the logit (or probit) of p's share of
the probability left over by the members listed before it. A predictor
on the first member therefore scales all later members by the same
factor, leaving their ratios unchanged. Read such effects on the probability scale with
native_parameters().
Identifiability. Printing the model ends with an identifiability
check for intercept-only formulas. It compares the number of free
parameters with the degrees of freedom (response categories minus 1,
summed over trees) and computes the rank of the Jacobian of the category
probabilities with respect to the free parameters, from exact derivatives
at five interior test values (and five test values of each covariate);
parameters fixed in the formula enter at their values. A rank below the
number of free parameters means that a combination of the named
parameters is not identified by the branch expressions, even when the
count passes. The check is local: it holds at the test values, not at the
boundaries of the parameter space. A test value with a non-finite
derivative is left out, and the printout says how many; if stats::D()
cannot differentiate a branch expression, the rank is not computed and
the count decides. The rank sees the tree parameters only: after a
non-linear formula, the rank line names that formula's parameter as not
analysed.
bmm() warns when the rank is deficient and every formula is
intercept-only. When a formula has a predictor or is non-linear, it only
says that these may identify the parameters and that it did not check.
Example: separate detection parameters Do and Dn in a single old/new
test give three free parameters and rank 2 of 3, so one combination of
Do, Dn and g cannot be estimated; a second condition that varies
the response bias identifies them.
Reading the estimates. summary() reports intercepts and regression
coefficients on the latent (logit or probit) scale. native_parameters()
returns the posterior draws of every parameter on the probability scale
for each observed combination of the predictors, e.g.
native_parameters(fit, re_formula = NA, summary = TRUE); a difference
between conditions is the difference of these draws. With
re_formula = NA these are the probabilities of the median participant
(the quantity TreeBUGS reports as "mean"), not the population mean of
the participants' probabilities; see the section on group-level effects
in native_parameters().
Person effects written as (1 | id) in each parameter's formula are
independent across parameters. A shared label, (1 |p| id) in every
formula, estimates their correlations (prior lkj(2)), which
corresponds to the latent-trait MPT model.
For posterior predictive checks, brms::posterior_predict() returns
simulated counts (draws x rows x categories) and brms::posterior_epred()
the expected counts; ppp() computes the T1 and T2 statistics of Klauer
(2010) and their posterior predictive p-values from them. With newdata,
brms::posterior_predict() needs the columns nTrials, Idx_<tree> and
Poss_<category> that check_data() builds; fit$data contains them.
Non-linear formulas. Parameters that receive a non-linear predictor
formula (a formula whose right-hand side references other formula
parameters, e.g. D ~ Dmax * (1 - exp(-rate * ptime))) are not
transformed by the link function: the user-supplied expression must keep
the parameter within (0, 1). Sub-parameters of such formulas (e.g.,
Dmax and rate) are estimated on the identity scale with
normal(0, 1) default priors on their intercepts and normal(0, 0.5)
on their regression coefficients. Their random-effect SDs keep brms's
default prior, student_t(3, 0, 2.5), because no single rate fits every
scale such a formula can give them.
Order constraints between parameters (Do > Dn) are expressed by
reparameterizing the larger parameter in the model formula, e.g.
bmf(Do ~ Dn + (1 - Dn) * inv_logit(phi), Dn ~ 1, phi ~ 1); the section
"Order constraints" of the MPT article walks through the
recipe.
Names. Parameter and response category names must start with a letter and may contain only letters and digits, because brms does not allow underscores or dots in non-linear parameter names.
All latent parameters are non-linear parameters of the underlying brms
model, and brms has no separate Intercept prior class for those: their
intercept prior is stored as class = "b", coef = "Intercept". A prior
given as class = "b", nlpar = "D" replaces the defaults of all
coefficients of D, the intercept included; add coef = "Intercept" to
set the intercept alone. Call default_prior() to see which rows a given
formula produces.
An object of class bmmodel
## Not run:
# two-high-threshold (2HTM) model of recognition memory
# one tree per probe type: targets (studied items) and lures (new items),
# each ending in the responses "old" and "new"
tree_target <- mpt_tree("target",
old ~ D + (1 - D) * g,
new ~ (1 - D) * (1 - g)
)
tree_lure <- mpt_tree("lure",
old ~ (1 - D) * g,
new ~ D + (1 - D) * (1 - g)
)
model <- mpt(
trees = list(tree_target, tree_lure),
tree_id = "item_type"
)
# simulate data for 20 participants with D = 0.7, g = 0.5:
# one row per participant x tree; count columns named after the branches
data <- data.frame(
id = rep(1:20, each = 2),
item_type = rep(c("target", "lure"), 20)
)
counts <- t(sapply(data$item_type, function(cond) {
rmpt(
n = 1, size = 50, pars = c(D = 0.7, g = 0.5),
mpt_model = model, tree = cond, unpack = TRUE
)
}))
data <- cbind(data, counts)
# predict both parameters by a fixed intercept and correlated random
# intercepts (the shared label |p| estimates the correlation)
formula <- bmf(
D ~ 1 + (1 |p| id),
g ~ 1 + (1 |p| id)
)
fit <- bmm(
formula = formula,
data = data,
model = model,
cores = 4
)
summary(fit)
# population-level D and g on the probability scale
native_parameters(fit, re_formula = NA, summary = TRUE)
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.