Part2
MarathonData.RDatakm4week and sp4weekon MarathonTimeMplot() function∼ AIC or BIC in Frequentist statistics
^elpd: “expected log predictive density” (higher ^elpd implies better model fit without being sensitive for overfitting!)
elpd_diff se_diff elpd_loo se_elpd_loo p_loo se_p_loo
MarathonTimes_Mod2 0.0 0.0 -356.3 12.0 7.2 4.4
MarathonTimes_Mod1 -39.9 12.6 -396.2 5.3 1.7 0.3
looic se_looic
MarathonTimes_Mod2 712.6 24.0
MarathonTimes_Mod1 792.3 10.6
by Laurent Smeets and Rens van der Schoot
Before estimating the model:
After estimation before inspecting results:
Understanding the exact influence of the priors
File called WAMBS_workflow_MarathonData.qmd (quarto document)
Click here for the Quarto version
Create your own project and project folder
Copy the template and rename it
We will go through the different parts in the slide show
You can apply/adapt the code in the template
To render the document properly with references, you also need the references.bib file
here packageIf you do not know how to use Projects in RStudio or the here package, these two sources might be helpfull:
Projects: https://youtu.be/MdTtTN8PUqU?si=mmQGlU063EMt86B2
here package: https://youtu.be/oh3b3k5uM7E?si=0-heLJXfFVLtTohh
Packages needed:
Load the dataset and the model:
Uninformative/Weakly informative
When objectivity is crucial and you want let the data speak for itself…
Informative
When including significant information is crucial
brms defaultsWeakly informative priors
If dataset is big, impact of priors is minimal
But, always better to know what you are doing!
Complex models might run into convergence issues → specifying more informative priors might help!
So, how to deviate from the defaults?
brmsFunction: get_prior( )
Remember our model 2 for Marathon Times:
MarathonTimeMi∼N(μ,σe)μ=β0+β1∗km4weeki+β2∗sp4weeki
brmsprior: type of prior distributionclass: parameter class (with b being population-effects)coef: name of the coefficient within parameter classgroup: grouping factor for group-level parameters (when using mixed effects models)resp : name of the response variable when using multivariate modelslb & ub: lower and upper bound for parameter restrictionThe best way to make sense of the priors used is visualizing them!
Many options:
See WAMBS template!
There we demonstrate the use of ggplot2, metRology, ggtext and patchwork to visualize the priors.
library(metRology)
library(ggplot2)
library(ggtext)
library(patchwork)
# Setting a plotting theme
theme_set(theme_linedraw() +
theme(text = element_text(family = "Times", size = 8),
panel.grid = element_blank(),
plot.title = element_markdown())
)
# Generate the plot for the prior of the Intercept (mu)
Prior_mu <- ggplot( ) +
stat_function(
fun = dt.scaled, # We use the dt.scaled function of metRology
args = list(df = 3, mean = 199.2, sd = 24.9), #
xlim = c(120,300)
) +
scale_y_continuous(name = "density") +
labs(title = "Prior for the intercept",
subtitle = "student_t(3,199.2,24.9)")
# Generate the plot for the prior of the error variance (sigma)
Prior_sigma <- ggplot( ) +
stat_function(
fun = dt.scaled, # We use the dt.scaled function of metRology
args = list(df = 3, mean = 0, sd = 24.9), #
xlim = c(0,6)
) +
scale_y_continuous(name = "density") +
labs(title = "Prior for the residual variance",
subtitle = "student_t(3,0,24.9)")
# Generate the plot for the prior of the effects of independent variables
Prior_betas <- ggplot( ) +
stat_function(
fun = dnorm, # We use the normal distribution
args = list(mean = 0, sd = 10), #
xlim = c(-20,20)
) +
scale_y_continuous(name = "density") +
labs(title = "Prior for the effects of independent variables",
subtitle = "N(0,10)")
Prior_mu + Prior_sigma + Prior_betas +
plot_layout(ncol = 3)brms?DO NOT HESITATE TO ASK FOR GUIDANCE HERE
Tip
Consider re-scaling your (in)dependent variables if it is hard to make sense of parameters a priori. E.g., standardizing variables enables you to think in effect sizes.
brmsSetting our custom priors can be done with set_prior( ) command
E.g., change the priors for the beta’s (effects of km4week and sp4week):
Did you set sensible priors?
brmsStep 1: Fit the model with custom priors with option sample_prior="only"
Fit_Model_priors <- brm( MarathonTimeM ~ 1 + km4week + sp4week, data = MarathonData, prior = Custom_priors, backend = "cmdstanr", cores = 4, sample_prior = "only" )Fit_Model_priors <- brm( MarathonTimeM ~ 1 + km4week + sp4week, data = MarathonData, prior = Custom_priors, backend = "cmdstanr", cores = 4, sample_prior = "only" )
brmsStep 2: visualize the data with the pp_check( ) function
brmsHow are summary statistics of simulated datasets (e.g., median, min, max, …) distributed over the datasets?
How does that compare to our real data?
Use type = "stat" argument within pp_check()
Your data and model
Perform a prior predictive check
If necessary re-think your priors and check again
Create custom trace-plots (aka caterpillar plots) with ggs( ) function from ggmcmc package
Model_chains <- ggs(MarathonTimes_Mod2)
Model_chains %>%
filter(Parameter %in% c(
"b_Intercept",
"b_km4week",
"b_sp4week",
"sigma"
)
) %>%
ggplot(aes(
x = Iteration,
y = value,
col = as.factor(Chain)))+
geom_line() +
facet_grid(Parameter ~ .,
scale = 'free_y',
switch = 'y') +
labs(title = "Caterpillar Plots for the parameters",
col = "Chains")Re-fit the model with more iterations
Check trace-plots again
Warning
First consider the need to do this! If you have a complex model that already took a long time to run, this check will take at least twice as much time…
Sampling of parameters done by:
If variance between chains is big → NO CONVERGENCE
R-hat (ˆR) : compares the between- and within-chain estimates for model parameters
ˆR < 1.05 for each parameter estimate
at least 4 chains are recommended
Effective Sample Size (ESS) > 400 to rely on ˆR
brmsmcmc_rhat() function from the bayesplot package
brmsYour data and model
Check the R-hat statistics
Sampling of parameter values are not independent!
So there is autocorrelation
But you don’t want too much impact of autocorrelation
2 approaches to check this:
Should be higher than 0.1 (Gelman et al., 2013)
Visualize making use of the mcmc_neff( ) function from bayesplot
mcmc_acf( ) functionYour data and model
Check the autocorrelation
additional way to assess the convergence of MCMC
if the algorithm converged, plots of all chains look similar
Your data and model
Check the rank order plots
Histogram of posterior for each parameter
Have clear peak and sliding slopes
Step 1: create a new object with ‘draws’ based on the final model
Step 2: create histogram making use of that object
post_intercept <-
posterior_PD %>%
select(b_Intercept) %>%
ggplot(aes(x = b_Intercept)) +
geom_histogram() +
ggtitle("Intercept")
post_km4week <-
posterior_PD %>%
select(b_km4week) %>%
ggplot(aes(x = b_km4week)) +
geom_histogram() +
ggtitle("Beta km4week")
post_sp4week <-
posterior_PD %>%
select(b_sp4week) %>%
ggplot(aes(x = b_sp4week)) +
geom_histogram() +
ggtitle("Beta sp4week") Step 3: print the plot making use of patchwork ’s workflow to combine plots
Generate data based on the posterior probability distribution
Create plot of distribution of y-values in these simulated datasets
Overlay with distribution of observed data
using pp_check() again, now with our model
Your data and model
Focus on the posterior and do some checks!
Often we rely on ‘arbitrary’ chosen (default) weakly informative priors
What is the influence of the prior (and the likelihood) on our results?
You could ad hoc set new priors and re-run the analyses and compare (a lot of work, without strict sytematical guidelines)
Semi-automated checks can be done with priorsense package
priorsense packageRecently a package dedicated to prior sensibility analyses is launched
Key-idea: power-scaling (both prior and likelihood)
background reading:
YouTube talk:
First check is done by using the powerscale_sensitivity( ) function
column prior contains info on sensibility for prior (should be lower than 0.05)
column likelihood contains info on sensibility for likelihood (that we want to be high, ‘let our data speak’)
column diagnosis is a verbalization of potential problem (- if none)
Sensitivity based on cjs_dist:
# A tibble: 4 × 4
variable prior likelihood diagnosis
<chr> <dbl> <dbl> <chr>
1 b_Intercept 0.000858 0.0856 -
2 b_km4week 0.000515 0.0807 -
3 b_sp4week 0.000372 0.0837 -
4 sigma 0.00574 0.152 -
Your data and model
Check the prior sensibility of your results