Computes the goodness-of-fit statistics \(T_1\) and \(T_2\) of Klauer
(2010) and their posterior predictive p-values (PPP) for models that fit
aggregated response counts: mpt(), m3(), sdt_yn(), sdt_rating(),
sdt_mafc(), sdt_ranking() and sdt_cdp(). TreeBUGS' PPP() reports the
same two statistics; Details says where their values differ.
Arguments
- fit
A
bmmfitobject returned bybmm().- ...
Unused.
- statistic
Character.
"T1","T2", or both (the default). If the participants cannot be identified, the default computes"T1"only.- by
Character vector naming the columns of the model data that define the cells.
NULL(default) uses the cells described in Details;character(0)pools all rows into one cell. Formpt()fits, the tree column can be named even if it is not a predictor.- ndraws
Integer. Number of posterior draws to use.
NULL(default) uses all draws.- level
Character.
"group"(default) for the statistics of the whole data set;"participant"for one \(T_1\) and PPP per participant, as TreeBUGS reports them, to find the participants the model fits poorly.- participant
Character. The column that identifies participants, needed for \(T_2\) and for
level = "participant". It must be a variable of the model formula, because the model data contain only those; a model without random effects has one only if a predictor such as0 + idnames the participants.NULL(default) uses the grouping variable of the random effects; when the model has more than one (e.g. participants and items), name it here.
Value
A data frame of class bmm_ppp with one row per statistic (and per
participant for level = "participant") and the columns statistic,
observed and replicated (the means of the statistic over draws, for the
observed and the simulated counts, as reported by Klauer, 2010, and
TreeBUGS), ppp and ndraws. The draws of the statistics are stored in
the attribute "draws".
Details
Both statistics are computed once per posterior draw, for the observed counts
and for counts simulated from that draw with brms::posterior_predict(),
each against the expected counts of the same draw from
brms::posterior_epred(). The simulated data are new data from the same
participants. The PPP is the proportion of draws in which the simulated
counts deviate more from the expectation than the observed counts do. A PPP
near 0 flags misfit; a PPP away from 0 means that the model reproduces the
aspect of the data the statistic measures.
\(T_1\): mean structure. The rows of the data are summed into cells, and \(T_1\) is Pearson's \(X^2\) over all cells and response categories, $$T_1 = \sum_{c,k} \frac{(n_{ck} - \hat{n}_{ck})^2}{\hat{n}_{ck}},$$ where \(n_{ck}\) is the observed and \(\hat{n}_{ck}\) the expected count of category \(k\) in cell \(c\). Klauer (2010, Eq. 17) and TreeBUGS average the counts over participants instead of summing them. With the same number \(T\) of participants in every cell, the two give the same PPP and \(T_1\) here is \(T\) times theirs; otherwise the mean gives the cells with fewer participants more weight.
\(T_2\): covariance structure. For every participant, the counts are summed per cell, giving one vector per participant over all cells and categories. \(T_2\) compares the covariance matrix \(s\) of these vectors across participants with the covariance matrix \(\sigma\) the model expects (Klauer, 2010, Eq. 18): $$T_2 = \sum_{i,j} \frac{(s_{ij} - \sigma_{ij})^2}{\sqrt{\sigma_{ii}\sigma_{jj}}}.$$ \(\sigma\) is the covariance of the expected counts across participants plus the average multinomial covariance within a participant, which is the expected value of \(s\) given the draw. Both covariances divide by \(T - 1\), where \(T\) is the number of participants. Klauer (2010) multiplies the multinomial part by \((T - 1) / T\), the expected value for covariances that divide by \(T\); that version of \(T_2\) is \((T - 1) / T\) times this one and has the same PPP. TreeBUGS combines the factor with covariances that divide by \(T - 1\), so its \(\sigma\) falls short of the expected \(s\) by \(1 / T\) of the multinomial part. The sum runs over the full matrix, so the covariances between trees or conditions, which carry the correlations between the person parameters, are part of the check. When participants differ in the cells they have, as in a between-participants design, they are grouped by their set of cells, \(T_2\) is computed per group, and the results are summed. A participant who shares the set of cells with nobody else has no covariance and is left out, with a message.
Cells. By default, a cell is a combination of the tree (mpt()), the
stimulus (the SDT models) or the set size (sdt_ranking()), and the
categorical population-level predictors of the model formula. Numeric
predictors are not part of the default, because every distinct value would
form a cell of its own. Rows of a cell are summed, so the trees or stimuli
must be part of by for the statistic to compare each tree's own
categories.
Impossible categories. Categories with an expected count of about 0 in
every draw, such as the impossible categories of an mpt() or m3() model
or the ranks beyond the set size of an sdt_ranking() model, are left out
of both statistics. A cell with a single possible category, such as an
m3() set size without other candidates, is left out of \(T_2\): the
number of trials fixes its count.
References
Klauer, K. C. (2010). Hierarchical multinomial processing tree models: A latent-trait approach. Psychometrika, 75(1), 70–98. https://doi.org/10.1007/s11336-009-9141-0
See also
pp_check.bmmfit() for the graphical check.
Examples
if (FALSE) { # identical(Sys.getenv("BMM_EXAMPLES"), "true")
trees <- list(
mpt_tree("target", list(old = "D + (1 - D) * g", new = "(1 - D) * (1 - g)")),
mpt_tree("lure", list(old = "(1 - D) * g", new = "D + (1 - D) * (1 - g)"))
)
dat <- expand.grid(id = factor(1:20), item_type = c("target", "lure"),
stringsAsFactors = FALSE)
dat$old <- rbinom(nrow(dat), 50, ifelse(dat$item_type == "target", 0.8, 0.2))
dat$new <- 50 - dat$old
fit <- bmm(
bmf(D ~ 1 + (1 | id), g ~ 1 + (1 | id)), dat, mpt(trees, "item_type"),
cores = 4, backend = "cmdstanr"
)
ppp(fit)
ppp(fit, level = "participant")
}
