View source: R/core_estimate.R
| estimate_dm | R Documentation |
estimate_dm() is the main function to fit a drift diffusion model (DDM)
in dRiftDM. Several ways of fitting a model are supported: fitting a single
participant, fitting multiple participants separately or aggregated, and
fitting a (hierarchical) Bayesian model. The particular way is controlled
via the approach argument.
estimate_dm(
drift_dm_obj,
obs_data = NULL,
approach = NULL,
optimizer = NULL,
control = list(),
n_cores = 1,
parallelization_strategy = NULL,
lower = NULL,
upper = NULL,
start_vals = NULL,
means = NULL,
sds = NULL,
shapes = NULL,
rates = NULL,
n_chains = 40,
burn_in = 500,
samples = 1000,
prob_migration = 0.1,
prob_re_eval = 1,
messaging = TRUE,
seed = NULL,
...
)
## S3 method for class 'fits_agg_dm'
print(x, ...)
## S3 method for class 'fits_ids_dm'
print(x, ...)
## S3 method for class 'mcmc_dm'
print(x, ..., round_digits = drift_dm_default_rounding())
drift_dm_obj |
a drift_dm object containing the model to be fitted. |
obs_data |
an optional data.frame (see also obs_data).
If no |
approach |
an optional character string, specifying the approach to
fitting the model. Options are |
optimizer |
a character string. For classical optimization, one of
|
control |
a list of control parameters passed to the optimizer
(for Nelder-Mead, BFGS, and L-BFGS-B, see stats::optim; for nmkb, see
dfoptim::nmkb; for DEoptim, see DEoptim::DEoptim).
Per default, we set the |
n_cores |
an integer > 0, indicating the number of CPU cores/threads to use (at the moment, this doesn't have an effect when fitting a single individual within the Bayesian framework). |
parallelization_strategy |
an integer, controlling how parallelization
is performed when fitting multiple individuals with the classical approach.
If |
lower, upper |
numeric vectors or lists, specifying the lower and upper bounds on each parameter to be optimized (see Details). |
start_vals |
optional starting values for classical single-subject fits
and when using an optimizer that requires a starting value. Can be
a numeric vector of model parameters when fitting a single individual, or
a |
means, sds, shapes, rates |
optional numeric vectors for prior specification (when using the Bayesian framework, see Details). |
n_chains |
an integer, providing the number of MCMC chains (Bayesian framework). |
burn_in |
an integer, number of burn-in iterations (Bayesian framework). |
samples |
an integer, number of post-burn-in samples per chain ( Bayesian framework). |
prob_migration |
a numeric in |
prob_re_eval |
a numeric in |
messaging |
a logical, if |
seed |
an optional integer to set the RNG seed for reproducibility. |
... |
additional arguments forwarded to lower-level routines. Options
are: |
x |
an object of type |
round_digits |
integer, specifying the number of decimal places for rounding in the printed summary. Default is 3. |
The function supports different "approaches" to fitting data.
"sep_c": This means that data is always considered separately for
each participant (if there are multiple participants) and that a
classical approach to parameter optimization is used. This means that
a standard cost_function is minimized (e.g., the negative
log-likelihood). If users provide only a single participant or a data set
without an ID column, then the model is fitted just once to that data
set.
"agg_c": This fits the model to aggregated data. For each individual in
a data set, summary statistics (e.g., quantiles, accuracies) are
calculated, and the model is fitted once to the average of these summary
statistics.
"sep_b": Similar to sep_b", although a Bayesian approach is used to
sample from the posterior distribution.
"hier_b": A hierarchical approach to parameter estimation. In this case
all participants are considered simultaneously and samples are drawn both
at the individual-level and group-level.
The optimizers "nmkb", "L-BFGS-B", and "DEoptim" (for classical
parameter optimization) require the specification of the lower/upper
arguments.
For aggregated fits, aggregated statistics are set to the model and the cost
function is switched to "rmse". If incompatible settings are requested,
the function switches to a compatible configuration and informs the user
with messages (these messages can be suppressed via the messaging argument).
lower/upper for Classical optimizationthe function estimate_model_dm() provides a flexible way of specifying the
optimization space; this is identical to specifying the parameter simulation
space in simulate_data.drift_dm().
Users have three options to specify the search space (see also the examples below):
Plain numeric vectors (not very much recommended). In this case,
lower/upper must be sorted in accordance with the parameters in the
underlying flex_prms object of drift_dm_obj that vary for at
least one condition (call print(drift_dm_obj) and have a look at the
columns of the Parameter Settings output; for each column that has a
number > 0, specify an entry in lower/upper).
Named numeric vectors. In this case lower/upper have to provide labels
in accordance with the parameters that are considered "free" at least once
across conditions (call coef(drift_dm_obj) and provide one named entry for
each parameter; dRiftDM will try to recycle parameter values across
conditions).
The most precise way is when lower/upper are lists. In this case, the
list requires an entry called "default_values" which specifies the named or
plain numeric vectors as above. If the list only contains this entry, then
the behavior is as if lower/upper were already numeric vectors. However,
the lower/upper lists can also provide entries labeled as specific
conditions, which contain named (!) numeric vectors with parameter labels.
This will modify the value for the upper/lower parameter space with respect
to the specified parameters in the respective condition.
(Default) Prior settings in the non-hierarchical case:
Let \theta^{(j)} indicate parameter j of a model (e.g., the
drift rate).
The prior on \theta^{(j)} is a truncated normal distribution:
\theta^{(j)} \sim NT(\mu^{(j)}, \sigma^{(j)}, l^{(j)}, u^{(j)})
With \mu^{(j)} and \sigma^{(j)} representing the mean and standard
deviation of parameter j. l^{(j)} and u^{(j)} represent the
lower and upper boundary. \mu^{(j)} is taken from the mean
argument or the currently set model parameters (i.e., from
coef(drift_dm_obj)) when calling the function. \sigma^{(j)} is, per
default, equal to \mu^{(j)}. This can be changed by passing
the sd argument. The lower and upper boundaries of the truncated normal
are -Inf and Inf per default. This can be altered by passing the
arguments lower and upper (see the examples below).
(Default) Prior settings in the hierarchical case:
Let \theta_i^{(j)} indicate parameter j for participant i
(e.g., the drift rate estimated for individual i). The prior on
\theta_i^{(j)} is a truncated normal distribution:
\theta_i^{(j)} \sim NT(\mu^{(j)}, \sigma^{(j)}, l^{(j)}, u^{(j)})
With \mu^{(j)} and \sigma^{(j)} representing the mean and
standard deviation of parameter j at the group level. l^{(j)} and
u^{(j)} represent the lower and upper boundary. The lower and upper
boundaries of the truncated normal are -Inf and Inf per default.
This can be altered by passing the arguments lower and upper.
For a group-level mean parameter, \mu^{(j)}, the prior is also a
truncated normal distributions:
\mu^{(j)} \sim NT(M^{(j)}, SD^{(j)}, l^{(j)}, u^{(j)})
With M^{(j)} specified by the mean argument or the currently
set model parameters. SD^{(j)} is, per default, equal to M^{(j)}.
This can be changed by passing the sd argument.
For a group-level standard deviation parameter, \sigma^{(j)}, the prior
is a gamma distribution:
\sigma^{(j)} \sim \Gamma(shape^{(j)},rate^{(j)})
With shape^{(j)} and rate^{(j)} being 1 by default. This
can be changed by passing the arguments shape and rate.
Specifying Prior Settings/Arguments
Argument specification for mean, sd, lower, upper, shape and
rate is conceptually identical to specifying lower/upper for the
classical optimization approach (see the subsection above and the examples
below).
If fitting a single individual: either a drift_dm object with
fitted parameters and additional fit information (for the classical
optimization framework) or an object of type mcmc_dm (for the Bayesian
framework)
If fitting multiple individuals separately: a fits_ids_dm object
or a list of mcmc_dm objects, containing all the individual model fits.
If fitting aggregated data: a fits_agg_dm object containing the model
itself and the raw data.
If fitting multiple individuals hierarchically: an object of type
mcmc_dm.
estimate_dm dispatches to underlying estimation routines that are not
exported:
Classical optimization of one individual via
estimate_classical()
Classical optimization of multiple individuals via
estimate_classical_wrapper()
Bayesian estimation via estimate_bayesian().
Aggregated fitting is handled within estimate_dm() in combination with
estimate_classical()
When fitting a model with optimizer = "DEoptim", the corresponding
minimization routine always runs for 200 iterations by default, irrespective
of whether a minimum has already been reached (see
DEoptim::DEoptim.control). Therefore, with default optimization settings,
estimate_dm() returns the convergence flag NA for
optimizer = "DEoptim", because the termination of the routine does not
necessarily indicate convergence. However, this is typically not an issue, as
200 iterations are generally sufficient for the algorithm to find the global
minimum. If users explicitly define convergence criteria via the control
argument of estimate_dm() (which is passed on to
DEoptim::DEoptim.control), valid convergence messages and flags are
returned.
estimate_classical(), estimate_bayesian(),
estimate_classical_wrapper(), get_parameters_smart()
##########
# Note: The following examples were trimmed for speed to ensure they run
# within seconds. They do not always provide realistic settings.
##########
####
# Setup
# get a model for the examples (DMC with just two free parameters)
model <- dmc_dm(
instr = "
b <!>
non_dec <!>
sd_non_dec <!>
tau <!>
alpha <!>
"
)
# get some data (the first two participants in the data set of Ulrich et al.)
data <- ulrich_flanker_data[ulrich_flanker_data$ID %in% 1:2, ]
####
# Fit a single individual (using unbounded Nelder-Mead)
fit <- estimate_dm(
drift_dm_obj = model,
obs_data = data[data$ID == 1, ],
optimizer = "Nelder-Mead"
)
print(fit)
####
# Fit a single individual (using DEoptim)
l_u <- get_lower_upper(model)
set.seed(2)
fit <- estimate_dm(
drift_dm_obj = model,
obs_data = data[data$ID == 1, ],
optimizer = "DEoptim",
lower = l_u$lower, upper = l_u$upper,
control = list(itermax = 5) # use default itermax in practice!
)
print(fit)
####
# Fit multiple individuals (separately; using bounded Nelder-Mead)
l_u <- get_lower_upper(model)
fit <- estimate_dm(
drift_dm_obj = model,
obs_data = data, # contains the data for two individuals
optimizer = "nmkb",
lower = l_u$lower, upper = l_u$upper,
)
print(fit)
coef(fit)
###
# Fit to aggregated data (using unbounded Nelder-Mead)
fit <- estimate_dm(
drift_dm_obj = model,
obs_data = data, # contains data for two individuals
optimizer = "Nelder-Mead",
approach = "agg_c"
)
print(fit)
coef(fit)
###
# EXPERIMENTAL
# Fit a single individual (using DE-MCMC; Bayesian; custom priors)
fit <- estimate_dm(
drift_dm_obj = model,
obs_data = data[data$ID == 1, ],
approach = "sep_b",
burn_in = 1, # higher in practice (e.g., 500)
samples = 1, # higher in practice (e.g., 1000)
n_chains = 5, # higher in practice (e.g., 40)
mean = c(muc = 3, A = 0.9),
sd = c(muc = 2, A = 0.8),
)
print(fit)
coef(fit)
###
# EXPERIMENTAL
# Fit multiple individuals (using DE-MCMC; hierarchical Bayesian)
fit <- estimate_dm(
drift_dm_obj = model,
approach = "hier_b",
obs_data = data, # contains data for two individuals
burn_in = 1, # higher in practice (e.g., 500)
samples = 1, # higher in practice (e.g., 1000)
n_chains = 5, # higher in practice (e.g., 40)
n_cores = 1, # higher in practice (depending on your machine and data set)
)
print(fit)
coef(fit)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.