Problems setting initial value for ndt in Wiener model

Hi,

I’m new to brms and stan, so this might be a trivial question. I have been following Henrik Singmann’s tutorial for running the wiener model in brms. That worked, but I also wanted to run a model with intercepts. So I tried adapting my code based on the example from ‘Bayesian Item Response Modelling in R with brms and Stan’. Then I got an error that the initial values of ndt are set too high (i.e. higher than minimum RT), even though I try to initialize them close to zero ( list(temp_ndt_Intercept = -3) ). To try understand what was going on I ran the code from the paper (https://github.com/paul-buerkner/Bayesian-IRT-paper/blob/master/Bayesian-IRT.R), but that produced the same error:

Excerpt from error message:

Chain 4: Rejecting initial value:
Chain 4: Error evaluating the log probability at the initial value.
Chain 4: Exception: Exception: wiener_lpdf: Random variable = 0.965, but must be greater than nondecision time = 1.04238 (in ‘model7d973fd9c0af_d908d4e2cda6f9128dad49c464cdc6b9’ at line 18)
(in ‘model7d973fd9c0af_d908d4e2cda6f9128dad49c464cdc6b9’ at line 157)

Chain 4:
Chain 4: Initialization between (-0.05, 0.05) failed after 100 attempts.
Chain 4: Try specifying initial values, reducing ranges of constrained values, or reparameterizing the model.
[1] “Error in sampler$call_sampler(args_list[[i]]) : Initialization failed.”
error occurred during calling the sampler; sampling not done
here are whatever error messages were returned
[[1]]
Stan model ‘d908d4e2cda6f9128dad49c464cdc6b9’ does not contain samples.

Code from paper:

library(tidyverse)
library(brms)

set ggplot theme

theme_set(bayesplot::theme_default())

set rstan options

rstan::rstan_options(auto_write = TRUE)
options(mc.cores = min(4, parallel::detectCores()))

data(“rotation”, package = “diffIRT”)
rotation <- rotation %>%
as_tibble() %>%
mutate(person = seq_len(n())) %>%
gather(“key”, “value”, -person) %>%
extract(“key”, into = c(“type”, “item”), regex = “(.)\[(.+)\]”) %>%
spread(“type”, “value”) %>%
rename(time = T, resp = X) %>%
mutate(
rotate = factor(case_when(
item %in% c(2, 5, 8) ~ 50,
item %in% c(3, 6, 10) ~ 100,
item %in% c(1, 4, 7, 9) ~ 150
)),
item = as.numeric(item)
)

get an overview of the data

head(rotation, 10)

bform_drift1 <- bf(
time | dec(resp) ~ rotate + (1 |p| person) + (1 |i| item),
bs ~ rotate + (1 |p| person) + (1 |i| item),
ndt ~ rotate + (1 |p| person) + (1 |i| item),
bias = 0.5
)

specify initial values to help the model start sampling

chains <- 4
inits_drift <- list(temp_ndt_Intercept = -3)
inits_drift <- replicate(chains, inits_drift, simplify = FALSE)

fit the model

fit_drift1 <- brm(
bform_drift1, data = rotation,
family = brmsfamily(“wiener”, “log”, link_bs = “log”, link_ndt = “log”),
chains = chains, cores = chains,
inits = inits_drift, init_r = 0.05,
control = list(adapt_delta = 0.99)
)

summarize the model

summary(fit_drift1)

  • Operating System: macOS Catalina 10.15.2
  • brms Version: 2.10.0
1 Like
Chain 4: Exception: Exception: wiener_lpdf: Random variable = 0.965, but must be greater than nondecision time = 1.04238 (in ‘model7d973fd9c0af_d908d4e2cda6f9128dad49c464cdc6b9’ at line 18)
(in ‘model7d973fd9c0af_d908d4e2cda6f9128dad49c464cdc6b9’ at line 157)

That sorta error means that there is some sort of constraint being violated.

If the original model from @Henrik_Singmann worked, then I’d suspect there’s a mistake somewhere in the changes.

The way to do these things is check what the constraints for each function should be (check in: https://github.com/stan-dev/docs/blob/master/docs/2_21/functions-reference-2_21.pdf, the Wiener docs on the docs page seem to be not showing up properly now) and then see how the changes to the model might mess those up.

Give it a go and if you don’t get anywhere post your reference model and the new one here.

2 Likes

Not sure that this is a problem, but the the link for ndt i log, and the intercept is initialized to -3, which means that any additional effects beyond the intercept must sum up to > 3, to get a valid value for the ndt.

If I remember correctly, brms uses relatively wide priors for regression coefficients. Therefore, one possibility would be to set the intercept for ndt to 0, and to put tighter priors on regression coefficients.

1 Like

I usually run into initialization problems with the wiener log likelihood when the model gets a bit more complex on the non-decision time parameter.

I would first try to specify initial values for the sd terms and covariate effects so the additive effect is close to 0 when initialized, or -3 so it is very small when initialized. Should do the trick to start sampling.

I am not used to brms syntax but I think you can use get_prior() on the model formula to help you out with the object names to which you can specify initial values.

Also, as @Guido_Biele suggests, maybe have a look at the default priors, which usually are very wide (given the likelihood and the log link function) and check the prior predictive distribution for non-decision times. A possible good reference for what is usually reported in the literature is summarized on the last figure the methods section of the HDDM package in python (parameter t).

edit:
What I meant by

is that, besides setting the initial values for the intercept to -3, additionally you should set the effect of the covariates and sd terms to be close to 0, so the initial values for all the non-decision time parameters is very small, exp(-3), and far away from the minimum response time, which is usually the problem for the initialization.

1 Like

Thanks for the input! Looks like this was caused by a simple bug, in that (at least for version 2.10.0 of brms) the model failed when the initial values were specified as (from the example in ‘Bayesian Item Response Modelling in R with brms and Stan’):

inits_drift <- list(temp_ndt_Intercept = -3)

but worked with:

inits_drift <- list(Intercept_ndt = -3)

Using get_prior was very helpful in finding the correct parameter names.

I also agree that for more complicated models it will be important to control the priors and initial values of covariates and sd terms. And deciding on whether to use log or identity and changing the prior and initial values accordingly.

1 Like

In order to find the right names for the initial values you need to look at the stan code itself via make_stancode. In some recent versions I changed the name of the intercept parameter which is invisible to the user unless they specify initial values.

1 Like