::opts_chunk$set(warning = FALSE, message = FALSE)
knitrlibrary(bistablehistory)
#> Lade nötiges Paket: loo
#> This is loo version 2.4.1
#> - Online documentation and vignettes at mc-stan.org/loo
#> - As of v2.0.0 loo defaults to 1 core but we recommend using as many as possible. Use the 'cores' argument or set options(mc.cores = NUM_CORES) for an entire session.
#> - Windows 10 users: loo may be very slow if 'mc.cores' is set in your .Rprofile file (see https://github.com/stan-dev/loo/issues/94).
#> Lade nötiges Paket: rlang
#> Lade nötiges Paket: rstantools
#> This is rstantools version 2.1.1
#>
#> Attache Paket: 'bistablehistory'
#> Das folgende Objekt ist maskiert 'package:loo':
#>
#> loo
The main function is fit_cumhist()
that takes a data frame with time-series as a first argument. In addition, you need to specify the name of the column that codes the perceptual state (state
argument) and a column that holds either dominance phase duration (duration
) or its onset (onset
). The code below fits data using Gamma distribution (default family) for a single run of a single participant. By default, the function fits cumulative history time constant but uses default fixed mixed state value (mixed_state = 0.5
), history mixing proportion (history_mix = 0.2
), and initial history values (history_init = 0
).
data(br_singleblock)
<- fit_cumhist(br_singleblock,
gamma_fit state="State",
duration="Duration",
refresh=0)
Alternatively, you specify onset of individual dominance phases that will be used to compute their duration.
<- fit_cumhist(br_singleblock,
gamma_fit state="State",
onset="Time")
Now you can look at the fitted value for history time constant using history_tau()
history_tau(gamma_fit)
#> # A tibble: 1 x 3
#> Estimate `5.5%` `94.5%`
#> <dbl> <dbl> <dbl>
#> 1 0.775 0.485 1.17
and main effect of history for both parameters of gamma distribution
historyef(gamma_fit)
#> # A tibble: 2 x 4
#> DistributionParameter Estimate `5.5%` `94.5%`
#> <fct> <dbl> <dbl> <dbl>
#> 1 shape 1.76 0.625 2.95
#> 2 scale -1.44 -2.67 -0.244
The following model is fitted for the example above, see also companion vignette for details on cumulative history computation. \[Duration[i] \sim Gamma(shape[i], rate[i]) \\ log(shape[i]) = \alpha^{shape} + \beta^{shape}_H \cdot H_{mix}[i] \\ log(rate[i]) = \alpha^{rate} + \beta^{rate}_H \cdot H_{mix}[i] \\ H_{mix}[i] = \text{cumulative_history}(\tau,\text{history_mixture}, \text{history_init})\\ \alpha^{shape}, \alpha^{rate} \sim Normal(log(3), 5) \\ \beta^{shape}_H, \beta^{rate}_H \sim Normal(0, 1) \\ \tau \sim Normal(log(1), 0.75)\]
By default, fit_cumhist()
function assumes that the time-series represent a single run with the consequence that history states are initialized only once at the very beginning. You can use run
argument to pass the name of a column that specifies individual runs. In this case, history is initialize at the beginning of every run to avoid spill-over effects.
<- fit_cumhist(br_single_subject,
gamma_fit state="State",
onset="Time",
run="Block")
Experimental session specifies which time-series were measured together and is used to compute an average dominance phase duration that, in turn, is used when computing cumulative history: \(\tau_H = \tau <D>\), where \(\tau\) is normalized time constant and \(<D>\) is the mean dominance phase duration. This can be used to account for changes in overall alternation rate between different sessions (days), as, for example, participants new to the stimuli tend to “speed up” over the course of days Suzuki & Grabowecky (2007). If you do not specify session
parameter then a single mean dominance phase duration is computed for all runs of a single subject.
The random_effect
argument allows you to specify a name of the column that codes for a random effect, e.g., participant identity, bistable display (if different displays were used for a single participant), etc. If specified, it is used to fit a hierarchical model with random slopes for the history effect (\(\beta_H\)). Note that we if random independent intercepts are used as prior research suggest large differences in overall alternation rate between participants Brascamp et al. (2019).
Here, is the R code that specifies participants as random effect
<- fit_cumhist(kde_two_observers,
gamma_fit state="State",
duration="Duration",
random_effect="Observer",
run="Block")
And here is the corresponding model, specified for the shape parameter only as identical formulas are used for the rate parameter as well. Here, \(R_i\) codes for a random effect level (participant identity) and a non-centered parametrization is used for the pooled random slopes.
\[Duration[i] \sim Gamma(shape[i], rate[i]) \\ log(shape[i]) = \alpha[R_i] + \beta_H[R_i] \cdot H_{mix}[i] \\ H_{mix}[i] = \text{cumulative_history}(\tau,\text{history_mixture}, \text{history_init})\\ \alpha[R_i] \sim Normal(log(3), 5) \\ \beta_H[R_i] = \beta^{pop}_H + \beta^{z}_H[R_i] \cdot \sigma^{pop}_H\\ \beta^{pop}_H \sim Normal(0, 1) \\ \beta^{z}_H[R_i] \sim Normal(0, 1) \\ \sigma^{pop}_H \sim Exponential(1) \\ \tau \sim Normal(log(1), 0.75)\]
Identical approach is take for \(\tau\), if tau=' "1|random"'
was specified (same holds for mixed_state=' "1|random"'
and history_mix=' "1|random"'
arguments, see below).
fit_cumhist()
functions allows you to specify multiple fixed effect terms as a vector of strings. The implementation is restricted to:
Although this limits usability of the fixed effects, these restrictions allowed for both a simpler model specification and a simpler underlying code. If you do require more complex models, please refer to companion vignette that provides several examples on writing model using Stan directly.
Once fitted, you can use fixef()
function to extract a posterior distribution or its summary for each effect.
fit_cumhist()
function takes four parameters for cumulative history computation (see also companion vignette):
tau
: a normalized time constant in units of mean dominance phase duration.mixed_state
: value used for mixed/transition state phases, defaults to 0.5
.history_mix
: weight used to compute a weighted cumulative history, see Cumulative History vignette. Defaults to 0.2
.history_init
: an initial value for cumulative history at the onset of each run. Defaults to 0
.Note that although history_init
accepts only fixed values either a single value used for both states or a vector of two. In contrast, both fixed and fitted values can be used for the other three parameters. Here are possible function argument values
tau
or single number within [0, 1] range for mixed_state
and history_mix
. In this case, the value is used directly for the cumulative history computation. Default option for mixed_state
and history_mix
.NULL
: a single value is fitted and used for all participants and runs. This is a default for tau
.'random'
: an independent tau is fitted for each random cluster (participant, displays, etc.). random_effect
argument must be specified.'1|random'
: values for individual random cluster are sampled from a fitted population distribution (pooled values). random_effect
argument must be specified.Once fitted, you can use history_tau()
, history_mixed_state()
, and history_mix()
functions to obtain a posterior distribution or its summary for each parameter.
fit_cumhist
currenly supports three distributions: 'gamma'
, 'lognormal'
, and 'normal'
.
\[Duration[i] \sim Gamma(shape[i], rate[i])\] For Gamma distribution independent linear models with a log link function are fitted for both shape and rate parameter. Priors for intercepts for both parameters are \(\alpha ~ Normal(log(3), 5)\).
\[Duration[i] \sim LogNormal(\mu[i], \sigma)\] The \(\mu\) parameter is computed via a linear model with a log link function. Priors for the intercept are \(\alpha ~ Normal(log(3), 5)\). Prior for \(\sigma\) was \(\sigma \sim Exponential(1)\).
\[Duration[i] \sim Normal(\mu[i], \sigma)\] The \(\mu\) parameter is computed via a linear model. Priors for the intercept are \(\alpha ~ Normal(3, 5)\). Prior for \(\sigma\) was \(\sigma \sim Exponential(1)\).
If you are interested in the cumulative history itself, you can extract from the fitted object via extract_history()
function
<- extract_history(gam_fit) H
Alternatively, you can skip fittiong and compute history directly using predefined values via compute_history()
.
<- compute_history(br_singleblock,
df state="State",
duration="Duration",
tau=1,
mixed_state=0.5,
history_init=0)