Part2
MarathonData.RData
km4week
and sp4week
on MarathonTimeM
plot()
function\(\sim\) AIC or BIC in Frequentist statistics
\(\widehat{elpd}\): “expected log predictive density” (higher \(\widehat{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
Dropbox
File called WAMBS_workflow_MarathonData.qmd (quarto document)
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
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 \(\rightarrow\) specifying more informative priors might help!
So, how to deviate from the defaults?
brms
Function: get_prior( )
Remember our model 2 for Marathon Times:
\[\begin{aligned} & \text{MarathonTimeM}_i \sim N(\mu,\sigma_e)\\ & \mu = \beta_0 + \beta_1*\text{km4week}_i + \beta_2*\text{sp4week}_i \end{aligned}\]
brms
prior
: 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:
Over to the WAMBS template (see Dropbox)!
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.
brms
Setting 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?
brms
Step 1: Fit the model with custom priors with option sample_prior="only"
brms
Step 2: visualize the data with the pp_check( )
function
brms
How 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 \(\rightarrow\) NO CONVERGENCE
R-hat (\(\widehat{R}\)) : compares the between- and within-chain estimates for model parameters
\(\widehat{R}\) < 1.015 for each parameter estimate
at least 4 chains are recommended
Effective Sample Size (ESS) > 400 to rely on \(\widehat{R}\)
brms
mcmc_rhat()
function from the bayesplot
package
brms
Your 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: – ratio of the effective sample size to the total sample size – plot degree of autocorrelation
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