You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert

523
523
524
-
# Fitting a model with brms
525
524
526
-
##Loading the dataset and data exploration
525
+
# Loading the dataset and data exploration
527
526
528
527
We load a dataset on the number of ant species in New England (USA). Type `?ants` into the console for more info.
529
528
@@ -593,6 +592,9 @@ ants_df %>%
593
592
As an exercise, we will create a model to compare the number of species between both habitats.
594
593
From the data exploration, we already saw that the number of species seems to be higher in forests and that sites with a higher number in bogs often also have a higher number in forests.
595
594
595
+
596
+
# Fitting a model with `brms`
597
+
596
598
## Specification of a linear regression
597
599
598
600
### Model specification
@@ -617,8 +619,8 @@ First of all we decide which MCMC parameters we will use. Type `?brm` to see wha
617
619
```{r simple-model-mcmc-par}
618
620
# Set MCMC parameters
619
621
nchains <- 3 # number of chains
620
-
niter <- 2000 # number of iterations (incl. burn-in, see next)
621
-
burnin <- niter / 4 # number of initial samples to remove (= burn-in)
622
+
niter <- 2000 # number of iterations (incl. warmup, see next)
623
+
warmup <- niter / 4 # number of initial samples to remove (= warmup)
622
624
nparallel <- nchains # number of cores for parallel computing
@@ -630,14 +632,14 @@ The model is fitted using the `brm()` function. The syntax is very similar to fu
630
632
-`file` and `file_refit` to save the model object after it has been fitted. If you run the code again and the model has already been saved, `brm()` will simply load this model instead of refitting it.
family = gaussian(), # we use the Normal distribution
638
640
data = ants_df, # specify data
639
641
chains = nchains, # MCMC parameters
640
-
warmup = burnin,
642
+
warmup = warmup,
641
643
iter = niter,
642
644
cores = nparallel,
643
645
thin = thinning,
@@ -649,7 +651,7 @@ Before we look at the results, we first check whether the model converges well.
649
651
650
652
### MCMC convergence
651
653
652
-
There are several ways to check convergence of the MCMC algorithm for each parameter. The burn-in samples are not taken into account. First and foremost, you have *visual controls*.
654
+
There are several ways to check convergence of the MCMC algorithm for each parameter. The warmup samples are not taken into account. First and foremost, you have *visual controls*.
653
655
654
656
We can obtain the MCMC samples with the `as_draws()` functions or visualise them at once via the [**bayesplot**](https://mc-stan.org/bayesplot/) package that is compatible with brmsfit objects.
655
657
@@ -836,14 +838,14 @@ $$
836
838
837
839
So we need to estimate two parameters: $\beta_0$ and $\beta_1$ We use the same MCMC parameters as before. The only thing we need to adjust is the choice `family = poisson()`.
Based on the PPCs we can already see which model fits the data best. Furthermore, there are some functions that **brms** provides to compare different models. With the function `add_criterion()` you can add model fit criteria to model objects. Type `?add_criterion()` to see which ones are available. See also <https://mc-stan.org/loo/articles/online-only/faq.html>
943
945
944
-
## Leave-one-out cross validation
946
+
###Leave-one-out cross validation
945
947
946
948
Cross-validation (CV) is a family of techniques that attempts to estimate how well a model would predict unknown data through predictions of the model fitted to the known data. You do not necessarily have to collect new data for this. You can split your own data into a test and training dataset. You fit the model to the training dataset and then use that model to estimate how well it can predict the data in the test dataset. With leave-one-out CV (LOOCV) you leave out one observation each time as test dataset and refit the model based on all other observations (= training dataset).
947
949
@@ -977,7 +979,7 @@ comp_loo %>%
977
979
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
978
980
```
979
981
980
-
## K-fold cross-validation
982
+
###K-fold cross-validation
981
983
982
984
With K-fold cross-validation, the data is split into $K$ groups. We will use $K = 10$ groups (= folds) here. So instead of leaving out a single observation each time, as with leave-one-out CV, we will leave out one $10^{th}$ of the data here. Via the arguments `folds = "stratified"` and `group = "habitat"` we ensure that the relative frequencies of habitat are preserved for each group. This technique will therefore be less precise than the previous one, but will be faster to calculate if you work with a lot of data.
983
985
@@ -1023,7 +1025,7 @@ comp_kfold %>%
1023
1025
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
1024
1026
```
1025
1027
1026
-
## WAIC
1028
+
###WAIC
1027
1029
1028
1030
The Widely Applicable Information Criterion (WAIC) does not use cross-validation but is a computational way to estimate the ELPD. How this happens exactly is beyond the purpose of this tutorial. It is yet another measure to apply model selection.
1029
1031
@@ -1055,10 +1057,11 @@ comp_waic %>%
1055
1057
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
1056
1058
```
1057
1059
1058
-
## Conclusion
1060
+
###Conclusion
1059
1061
1060
1062
Both based on the PPC and the comparisons with different model selection criteria, we can conclude that the second Poisson model with random intercepts fits the data best. In principle, we could have expected this based on our own intuition and the design of the study, i.e. the use of the Poisson distribution to model numbers and the use of random intercepts to control for a hierarchical design (habitats nested within sites).
1061
1063
1064
+
1062
1065
# Final model results
1063
1066
1064
1067
When we look at the model fit object, we see results that are similar to results we see when we fit a frequentist model. On the one hand we get an estimate of all parameters with their uncertainty, but on the other hand we see that this is clearly the output of a Bayesian model. We get information about the parameters we used for the MCMC algorithm, we get a 95% credible interval (CI) instead of a confidence interval and we also get the $\hat{R}$ value for each parameter as discussed earlier.
Copy file name to clipboardExpand all lines: content/tutorials/r_brms/brms_nl/workshop_1_mcmc_en_brms.Rmd
+22-19Lines changed: 22 additions & 19 deletions
Original file line number
Diff line number
Diff line change
@@ -293,7 +293,7 @@ confint(lm1, level = 0.9)
293
293
We lezen enkele korte functies in om de (log) likelihood en de prior te berekenen en het MCMC metropolis algoritme uit te voeren.
294
294
295
295
```{r}
296
-
source(file = "./source/mcmc_functions.R")
296
+
source(file = "./mcmc_functions.R")
297
297
```
298
298
299
299
Voor dit eenvoudig model met een kleine dataset kunnen we de posterior voor een groot aantal combinaties voor `beta_0` en `beta_1` uitrekenen en plotten.
@@ -340,7 +340,7 @@ ggplot(df, aes(x = beta_0, y = beta_1, z = post)) +
340
340
theme(legend.position="none")
341
341
```
342
342
343
-
De startwaarde ligt een eind van de maximale likelihood. Het duurt even voor de MCMC stabiliseert in de omgeving van de top van de berg. Daarom wordt het eerste deel van de MCMC nooit gebruikt. Dit is de 'burn-in' (of warmp-up in brms).
343
+
De startwaarde ligt een eind van de maximale likelihood. Het duurt even voor de MCMC stabiliseert in de omgeving van de top van de berg. Daarom wordt het eerste deel van de MCMC nooit gebruikt. Dit is de 'warmup' (engels voor opwarmfase; ook 'burn-in' of 'tuning' in andere bibliotheken).
344
344
345
345
We runnen nu hetzelde model, maar met een veel langere mcmc
346
346
@@ -387,7 +387,7 @@ Voor elke parameter kan de MCMC worden weergegeven in een 'trace plot'.
@@ -509,9 +509,8 @@ Er bestaan ook enkele alternatieven:
509
509

510
510
511
511
512
-
# Een model fitten met brms
513
512
514
-
##Dataset laden en data exploratie
513
+
# Dataset laden en data exploratie
515
514
516
515
We laden een dataset in over het aantal mierensoorten in New England (USA). Typ `?ants` in de console voor meer info.
517
516
@@ -583,6 +582,9 @@ ants_df %>%
583
582
584
583
Als oefening zullen we een model maken om het aantal soorten te vergelijken tussen beide habitats. Uit de data exploratie zagen we al dat het aantal hoger lijkt te liggen in bossen en dat sites met een hoger aantal in moerassen vaak ook een hoger aantal in bossen hebben.
585
584
585
+
586
+
# Een model fitten met `brms`
587
+
586
588
## Specificatie van een lineaire regressie
587
589
588
590
### Model specificatie
@@ -607,8 +609,8 @@ Eerst en vooral besluiten we welke MCMC parameters we zullen gebruiken. Typ `?br
607
609
```{r simpel-model-mcmc-par}
608
610
# Instellen MCMC parameters
609
611
nchains <- 3 # aantal chains
610
-
niter <- 2000 # aantal iteraties (incl. burn-in, zie volgende)
611
-
burnin <- niter / 4 # aantal initiële samples om te verwijderen (= burn-in)
612
+
niter <- 2000 # aantal iteraties (incl. warmup, zie volgende)
613
+
warmup <- niter / 4 # aantal initiële samples om te verwijderen (= warmup)
612
614
nparallel <- nchains # aantal cores voor parallel computing
613
615
thinning <- 1 # verdunningsfactor (hier 1 = geen verdunning)
614
616
```
@@ -620,14 +622,14 @@ Het model wordt gefit a.d.h.v. de `brm()` functie. De syntax is zeer gelijkaardi
620
622
-`file` en `file_refit` om het model object op te slaan nadat het gefit is. Als je de code opnieuw runt en het model is al eens opgeslaan, dan zal `brm()` dit model gewoon inladen in plaats van het opnieuw te fitten.
formula = sp_rich ~ habitat, # beschrijving van het model
627
629
family = gaussian(), # we gebruiken de Normaal verdeling
628
630
data = ants_df, # ingeven data
629
631
chains = nchains, # MCMC parameters
630
-
warmup = burnin,
632
+
warmup = warmup,
631
633
iter = niter,
632
634
cores = nparallel,
633
635
thin = thinning,
@@ -638,7 +640,7 @@ Voor we de resultaten bekijken, controleren we eerst of het model goed convergee
638
640
639
641
### MCMC convergentie
640
642
641
-
Er zijn verschillende manieren om convergentie van het MCMC algoritme voor elke parameter te controleren. Hierbij worden de burn-in samples niet in rekening genomen. Eerst en vooral heb je *visuele controles*.
643
+
Er zijn verschillende manieren om convergentie van het MCMC algoritme voor elke parameter te controleren. Hierbij worden de warmup samples niet in rekening genomen. Eerst en vooral heb je *visuele controles*.
642
644
643
645
We kunnen de MCMC samples met de `as_draws()` functies verkrijgen ofwel ineens visualiseren via de [bayesplot](https://mc-stan.org/bayesplot/) package die compatibel is met brmsfit objecten.
644
646
@@ -825,14 +827,14 @@ $$
825
827
826
828
We moeten dus twee parameters schatten: $\beta_0$ en $\beta_1$ We gebruiken dezelfde MCMC parameters als voordien. Het enige wat we moeten aanpassen is de keuze `family = poisson()`.
# Fit Poisson model met random intercepten per site
893
895
fit_poisson2 <- brm(
894
896
formula = sp_rich ~ habitat + (1|site),
895
897
family = poisson(),
896
898
data = ants_df,
897
899
chains = nchains,
898
-
warmup = burnin,
900
+
warmup = warmup,
899
901
iter = niter,
900
902
cores = nparallel,
901
903
thin = thinning,
@@ -929,11 +931,11 @@ Hoe kunnen we deze modellen nu objectief gaan vergelijken?
929
931
930
932
931
933
932
-
# Vergelijken van modellen
934
+
##Vergelijken van modellen
933
935
934
936
Op basis van de PPCs kunnen we reeds zien welk model het best past bij de data. Verder zijn er nog enkele functies die **brms** voorziet om verschillende modellen te vergelijken. Met de functie `add_criterion()` kan je model fit criteria toevoegen aan model objecten. Typ `?add_criterion()` om te zien welke beschikbaar zijn. Zie ook <https://mc-stan.org/loo/articles/online-only/faq.html>
935
937
936
-
## Leave-one-out cross-validation
938
+
###Leave-one-out cross-validation
937
939
938
940
Cross-validation (CV) is een familie van technieken die probeert in te schatten hoe goed een model onbekende data zou voorspellen via predicties van het model gefit op de bekende data. Hiervoor moet je niet per se nieuwe data gaan inzamelen. Je kan jouw eigen data opsplitsen in een test en training dataset. Je fit het model op de training dataset en je gebruikt dat model dan om te schatten hoe goed het de data in de test dataset kan voorspellen. Bij leave-one-out CV (LOOCV) ga je telkens één observatie weglaten en het model opnieuw fitten o.b.v. alle andere observaties.
939
941
@@ -969,7 +971,7 @@ comp_loo %>%
969
971
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
970
972
```
971
973
972
-
## K-fold cross-validation
974
+
###K-fold cross-validation
973
975
974
976
Bij K-fold cross-validation worden de data in $K$ groepen opgesplitst. Wij zullen hier $K = 10$ groepen (= folds) gebruiken. In plaats van dus telkens één enkele observatie weg te laten zoals bij leave-one-out CV gaan we hier $1/10$e van de data weglaten. Via de argumenten `folds = "stratified"` en `group = "habitat"` zorgen we ervoor dat voor elke groep de relatieve frequenties van habitat bewaard blijven. Deze techniek zal dus minder precies zijn dan de vorige, maar zal sneller zijn om te berekenen indien je met heel veel data werkt.
975
977
@@ -1014,7 +1016,7 @@ comp_kfold %>%
1014
1016
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
1015
1017
```
1016
1018
1017
-
## WAIC
1019
+
###WAIC
1018
1020
1019
1021
Het Widely Applicable Information Criterion (WAIC) maakt geen gebruik van cross-validation maar is een computationele manier om de ELPD te schatten. Hoe dit precies gebeurt valt buiten het doel van deze workshop. Het is nog een andere maat om model selectie toe te passen.
1020
1022
@@ -1046,10 +1048,11 @@ comp_waic %>%
1046
1048
ul_diff = elpd_diff + qnorm(0.95) * se_diff)
1047
1049
```
1048
1050
1049
-
## Conclusie
1051
+
###Conclusie
1050
1052
1051
1053
Zowel o.b.v. de PPC als vergelijkingen met verschillende model selectie criteria, kunnen we besluiten dat het tweede Poisson model met random intercepts het best past bij de data. In principe konden we dit ook verwachten op basis van onze eigen intuïtie en het design van de studie, nl. het gebruik van de Poisson distributie om aantallen te modelleren en het gebruik van random intercepts om te controleren voor een hiërarchisch design (habitats genest in sites).
1052
1054
1055
+
1053
1056
# Resultaten finale model
1054
1057
1055
1058
Als we het model fit object bekijken, zien we resultaten die vergelijkbaar zijn met resultaten zoals we die zien als we een frequentist model gefit hebben. We krijgen enerzijds een schatting van alle parameters met hun onzekerheid maar anderzijds zien we dat dit duidelijk de output is van een Bayesiaans model. Zo krijgen we info over de parameters die we gebruikt hebben voor het MCMC algoritme, we krijgen een 95 % credible interval (CI) in plaats van een confidence interval en we krijgen bij elke parameter ook de $\hat{R}$ waarde die we eerder besproken hebben.
0 commit comments