Three-Parameter Mixture Model
Usage
mixture3p(
resp_error,
nt_features,
set_size,
regex = FALSE,
version = c("simple", "slot", "slot_averaging"),
variable_precision = FALSE,
vp_nodes = 81L,
links = NULL,
...
)Arguments
- resp_error
The name of the variable in the dataset containing the response error. The response error should code the response relative to the to-be-recalled target in radians. You can transform the response error in degrees to radians using the
deg2radfunction.- nt_features
A character vector with the names of the non-target feature values. The non_target feature values should be in radians and centered relative to the target. Alternatively, if regex=TRUE, a regular expression can be used to match the non-target feature columns in the dataset.
- set_size
Name of the column containing the set size variable (if set_size varies) or a numeric value for the set_size, if the set_size is fixed. In the
"slot"and"slot_averaging"versions a single set size cannot test the capacity rule:Kis then estimated from the responses at that set size, and only below it.- regex
Logical. If TRUE, the
nt_featuresargument is interpreted as a regular expression to match the non-target feature columns in the dataset.- version
A character string specifying which version of the model to use. Options are:
"simple"(default): the standard three-parameter mixture model. The weights of the target (thetat), the non-targets (thetant) and guessing are normalised across the components a trial actually has, with guessing as the reference."slot": the probability that a response comes from memory follows the fixed-resolution slot model of Zhang and Luck (2008),min(1, K / set_size), andptargetis the probability that a remembered response reports the target rather than a non-target."slot_averaging": as"slot", butKslots are distributed over the items and precision grows with the number of slots an item holds.
Storage and swapping are separate in the capacity versions: the capacity rule says how often a response comes from memory and
ptargetsays which stored item is reported. In"simple"both weights are log odds against guessing,thetatfor the target andthetantfor all non-targets together, so neither is a probability on its own;native_parameters()returns the probabilities.- variable_precision
Logical; if
TRUE, the precision of memory varies from trial to trial (van den Berg et al., 2012). This adds the parametertau, andkappathen describes the average trial: it is the concentration whose Fisher informationJ(kappa)is the mean ofJ. Seemixture2p()for details of the parameterisation. Underversion = "slot_averaging", the precision of an item held injslots is the sum ofjindependent slot draws,gamma(shape = j * J(kappa) / tau, scale = tau), so its variance grows withj.- vp_nodes
Number of quadrature nodes used when
variable_precision = TRUE; must be an odd number of at least 41, and defaults to 81. Seemixture2p()for the accuracy this gives.- links
A named list of link functions for the model parameters. The links of
thetatandthetantcannot be changed, because the softmax over them is part of the likelihood.- ...
used internally for testing, ignore it
Details
Domain: Working memory
Task: Continuous reproduction
Name: Three-Parameter Mixture Model
Citation:
Bays, P. M., Catalao, R. F. G., & Husain, M. (2009). The precision of visual working memory is set by allocation of a shared resource. Journal of Vision, 9(10), Article 7. https://doi.org/10.1167/9.10.7
Zhang, W., & Luck, S. J. (2008). Discrete fixed-resolution representations in visual working memory. Nature, 453(7192), 233-235. https://doi.org/10.1038/nature06860
van den Berg, R., Shin, H., Chou, W.-C., George, R., & Ma, W. J. (2012). Variability in encoding precision accounts for visual short-term memory limitations. Proceedings of the National Academy of Sciences, 109(22), 8780-8785. https://doi.org/10.1073/pnas.1117465109
Requirements:
The response variable should be in radians and represent the angular error relative to the target
The non-target features should be in radians and be centered relative to the target
In the 'slot' and 'slot_averaging' versions, the set size should vary for the capacity rule to be testable
Version: simple
Parameters:
mu: Location of the von Mises distribution of memory responses (in radians). Fixed internally to 0 by default.kappa: Concentration of the von Mises distribution of memory responsesthetat: Mixture weight for target responses. The weights of the target, the non-targets and guessing are normalised across the components present on a trial, with guessing as the reference, so thetat maps to the probability of a target response only jointly with thetant.thetant: Mixture weight for non-target responses, summed over the non-targets, which share it equally. Like thetat, it is weighed against guessing.
Fixed parameters:
mu= 0
Default parameter links:
mu = tan_half; kappa = log; thetat = softmax; thetant = softmax
Default priors:
mu:main: normal(0, 0.5)effects: normal(0, 0.25)sd: exponential(4)
kappa:main: normal(2, 1)effects: normal(0, 1)sd: exponential(1)
thetat:main: logistic(0, 1)effects: normal(0, 2.5)sd: exponential(1)
thetant:main: logistic(0, 1)effects: normal(0, 2.5)sd: exponential(1)
Version: slot
Parameters:
mu: Location of the von Mises distribution of memory responses (in radians). Fixed internally to 0 by default.kappa: Concentration of the von Mises distribution of memory responsesK: Capacity: the number of items that can be held in memory. An item is either held at full precision or not held at all, so the probability that a response comes from memory is min(1, K / set_size).ptarget: Probability that a response reports the target rather than a non-target, given that it comes from memory.
Fixed parameters:
mu= 0
Default parameter links:
mu = tan_half; kappa = log; K = log; ptarget = logit
Default priors:
mu:main: normal(0, 0.5)effects: normal(0, 0.25)sd: exponential(4)
kappa:main: normal(2, 1)effects: normal(0, 1)sd: exponential(1)
K:main: normal(1, 0.5)effects: normal(0, 0.3)sd: exponential(2)
ptarget:main: logistic(1, 1)effects: normal(0, 0.5)sd: exponential(1)
Version: slot_averaging
Parameters:
mu: Location of the von Mises distribution of memory responses (in radians). Fixed internally to 0 by default.kappa: Concentration of the von Mises distribution for an item held in a single slot. An item holding several slots is more precise, because averaging independent samples adds their Fisher information.K: Capacity: the number of memory slots distributed over the items in the array. An item receives floor(K / set_size) or one more slot, and an item that receives none is guessed.ptarget: Probability that a response reports the target rather than a non-target, given that it comes from memory.
Fixed parameters:
mu= 0
Default parameter links:
mu = tan_half; kappa = log; K = log; ptarget = logit
Default priors:
mu:main: normal(0, 0.5)effects: normal(0, 0.25)sd: exponential(4)
kappa:main: normal(2, 1)effects: normal(0, 1)sd: exponential(1)
K:main: normal(1, 0.5)effects: normal(0, 0.3)sd: exponential(2)
ptarget:main: logistic(1, 1)effects: normal(0, 0.5)sd: exponential(1)
Variable precision
With variable_precision = TRUE every version gains tau, and kappa
becomes the precision of the average trial. Shown for "simple":
Parameters:
mu: Location of the von Mises distribution of memory responses (in radians). Fixed internally to 0 by default.kappa: Concentration of the von Mises distribution of memory responses. With variable precision, kappa describes the average trial: it is the concentration whose Fisher information J(kappa) is the mean of J across trials.tau: Scale of the trial-to-trial variability in memory precision. The Fisher information J of a memory representation is drawn from gamma(mean = J(kappa), scale = tau), so tau -> 0 recovers constant precision and larger values spread precision more widely across trials.thetat: Mixture weight for target responses. The weights of the target, the non-targets and guessing are normalised across the components present on a trial, with guessing as the reference, so thetat maps to the probability of a target response only jointly with thetant.thetant: Mixture weight for non-target responses, summed over the non-targets, which share it equally. Like thetat, it is weighed against guessing.
Default parameter links:
mu = tan_half; kappa = log; tau = log; thetat = softmax; thetant = softmax
Default priors:
mu:main: normal(0, 0.5)effects: normal(0, 0.25)sd: exponential(4)
kappa:main: normal(2, 1)effects: normal(0, 1)sd: exponential(1)
thetat:main: logistic(0, 1)effects: normal(0, 2.5)sd: exponential(1)
thetant:main: logistic(0, 1)effects: normal(0, 2.5)sd: exponential(1)
tau:main: normal(0, 1)effects: normal(0, 0.5)sd: exponential(2)
Priors from bmm 1.4
Since bmm 1.5.0, the parameters of this model are distributional parameters
(dpar) of a custom family, and the location mu1 is called mu. Calls
written for bmm 1.4 keep working until bmm 1.6.0 at the earliest: bmm translates their priors,
formulas, links and emmeans(nlpar = ), and warns with the code to use
instead.
# an intercept prior
set_prior("normal(2, 1)", class = "b", coef = "Intercept", nlpar = "kappa") # 1.4
set_prior("normal(2, 1)", class = "Intercept", dpar = "kappa") # 1.5
# a prior on all coefficients
set_prior("normal(0, 0.5)", class = "b", nlpar = "kappa") # 1.4
set_prior("normal(0, 0.5)", class = "Intercept", dpar = "kappa") + # 1.5
set_prior("normal(0, 0.5)", class = "b", dpar = "kappa")
# a prior on the random-effect standard deviations
set_prior("exponential(2)", class = "sd", nlpar = "kappa") # 1.4
set_prior("exponential(2)", class = "sd", dpar = "kappa") # 1.5
# the location, and emmeans()
bmf(mu1 ~ 1 + cond, kappa ~ 1 + cond) # 1.4
bmf(mu ~ 1 + cond, kappa ~ 1 + cond) # 1.5
emmeans(fit, ~ cond, nlpar = "kappa") # 1.4
emmeans(fit, ~ cond, dpar = "kappa") # 1.5In bmm 1.4 a class = "b" prior also covered the intercept, so it now
becomes two priors with the same distribution, unless the intercept has a prior of
its own. One prior changes its meaning.
When a formula has an intercept and predictors, such as kappa ~ 1 + cond,
brms centres the predictors of a distributional parameter, so an intercept
prior applies at the average over the conditions, weighted by their number of
trials, not at the reference condition. The slopes keep their meaning, and so
do intercept-only formulas
and formulas with one coefficient per condition (kappa ~ 0 + cond). If your
intercept prior was meant for the reference condition, give it for the
average instead.
Two things are not translated. The draws of the location are named after
mu (b_Intercept instead of b_mu1_Intercept), and calls that go straight
to brms need dpar =: posterior_linpred(fit, dpar = "kappa"), not
nlpar = "kappa". Fits saved with bmm 1.4 work as before with summary(),
prior_info(), emmeans(), native_parameters() and conditional_effects().
update() samples them again under the custom family, translates their
priors and says so in a message.
References
Bays, P. M., Catalao, R. F. G., & Husain, M. (2009). The precision of visual working memory is set by allocation of a shared resource. Journal of Vision, 9(10), Article 7.
Zhang, W., & Luck, S. J. (2008). Discrete fixed-resolution representations in visual working memory. Nature, 453(7192), 233-235.
van den Berg, R., Shin, H., Chou, W.-C., George, R., & Ma, W. J. (2012). Variability in encoding precision accounts for visual short-term memory limitations. PNAS, 109(22), 8780-8785.
Examples
if (FALSE) { # identical(Sys.getenv("BMM_EXAMPLES"), "true")
# generate artificial data from the Bays et al (2009) 3-parameter mixture model
dat <- data.frame(
y = rmixture3p(n = 2000, mu = c(0, 1, -1.5, 2)),
nt1_loc = 1,
nt2_loc = -1.5,
nt3_loc = 2
)
# define formula
ff <- bmmformula(
kappa ~ 1,
thetat ~ 1,
thetant ~ 1
)
# specify the 3-parameter model with explicit column names for non-target features
model1 <- mixture3p(resp_error = "y", nt_features = paste0("nt", 1:3, "_loc"), set_size = 4)
# fit the model
fit <- bmm(
formula = ff,
data = dat,
model = model1,
cores = 4,
iter = 500,
backend = "cmdstanr"
)
# alternatively specify the 3-parameter model with a regular expression to match non-target features
# this is equivalent to the previous call, but more concise
model2 <- mixture3p(resp_error = "y", nt_features = "nt.*_loc", set_size = 4, regex = TRUE)
# fit the model
fit <- bmm(
formula = ff,
data = dat,
model = model2,
cores = 4,
iter = 500,
backend = "cmdstanr"
)
}
