Wiecki 2013 - Hierarchical Bayesian Estimation Regression and Model Checking in HDDM

Summary

HDDM places group-level priors on subject DDM parameters, shrinking sparse subjects toward the group, and samples the joint posterior by MCMC. It supplies depends_on (condition-wise parameters), HDDMRegressor (trial-wise covariates on any parameter), Gelman-Rubin convergence checks, DIC model comparison and direct posterior probability statements such as .

Overview

Two classical extremes are rejected: fitting each subject independently (ignores shared structure) and fitting an “average subject” (cannot fit any individual). The hierarchical model lets the group variance be estimated per parameter, so a parameter that is similar across subjects (e.g. non-decision time) is strongly pooled while a variable one (threshold) is not.

Main Content

The HDDM hierarchical model (Figure 2, p. 3)

For subject with trials and group means/SDs :

and , the full-DDM likelihood of Navarro and Fuss (2009). is parameterized by mean and SD, is half-normal (SD), by mean and rate, by . Inter-trial variabilities are group-only: they have too small an influence on the likelihood to be estimable per subject. A non-informative-prior variant also exists, but informative priors are recommended because they keep estimates in the literature’s plausible range, reduce parameter collinearity and improve recovery with few trials.

Workflow (Results, pp. 4-7). Data are a CSV with required columns subj_idx, rt, response plus experiment columns (here theta EEG power, dbs, stim, conf). The reward-learning task (Cavanagh et al. 2011) has win-win (WW), lose-lose (LL) and win-lose (WL) trials; WW and LL are high conflict (HC), WL low conflict (LC). The hypothesis: conflict raises the decision threshold, with frontal theta tracking trial-wise threshold and subthalamic stimulation (DBS) interrupting that link.

  1. m = hddm.HDDM(data); m.find_starting_values() (MAP by gradient ascent); m.sample(2000, burn=20). Recommended 2,000-10,000 samples, thinning only if memory matters.
  2. Convergence: trace, autocorrelation and marginal posterior plots (plot_posteriors), and Gelman-Rubin across five models; values should be near 1 and not above 1.02 (example output a: 1.000, a_std: 1.001, t: 1.000).
  3. Summary: print_stats() gives mean, SD and quantiles; example threshold posterior mean (SD , 95% interval ), group SD .
  4. Condition effects: depends_on={'v':'stim'} builds separate group distributions per level; also usable between groups (e.g. drug vs placebo on ).
  5. Posterior inference: compare traces directly, and , so WL drift is clearly higher.
  6. Model comparison by DIC: lumped model 10960.57 vs stimulus-specific drift 10775.62 (lower is better). The paper warns DIC favours complexity and suggests simulating data from the alternatives to calibrate DIC differences; Bayes factors (Savage-Dickey; Wagenmakers et al. 2010) are an alternative.

HDDMRegressor (trial-wise covariates)

A parameter (here ) is replaced by a linear predictor given as a Patsy formula, e.g. "a ~ theta:C(conf, Treatment('LC'))", with depends_on={'v':'stim'}. This fits an intercept and one slope of theta on threshold per conflict level, relative to the LC treatment level, instead of one static threshold per subject: with hierarchical priors on the coefficients.

Finding. In DBS-off participants theta power has a positive effect on threshold in HC trials; with DBS on, the coefficient reverses (Figure 5), supporting the hypothesised role of the subthalamic nucleus. The supplement (not captured) covers within-subject effects and the outlier mixture.

Examples

Interpreting the DIC and posterior contrast

DIC drops by 185 when drift is allowed to vary by stimulus (10960.6 to 10775.6) and : all posterior mass of LL drift is below WL drift. WW vs LL is unresolved (). A reader should therefore claim “WL is easier” but not an ordering of WW and LL.

PyMC-style sketch of the regression (untested pseudocode).

with pm.Model() as hddm_reg:
    mu_b = pm.Normal("mu_b", 2, 1, shape=2)           # intercept, theta slope
    sd_b = pm.HalfNormal("sd_b", 1, shape=2)
    b = pm.Normal("b", mu_b, sd_b, shape=(n_subj, 2))  # partial pooling
    a_trial = pm.math.exp(b[subj, 0] + b[subj, 1] * theta)   # positive threshold
    pm.CustomDist("y", v[subj], a_trial, z[subj], t[subj], logp=wfpt_logp, observed=Y)

Connections

See Also

Wiecki 2013 - Drift-Diffusion Model and Wiener First-Passage Likelihood, Wiecki 2013 - Parameter Recovery Simulations and Detection Power