library(tidyverse)
library(brms)
library(posterior)
library(bayesplot)
library(ggdist)
library(patchwork)
color_scheme_set(scheme = "red")
theme_set(theme_ggdist())
<- function(post) {
prior_pred_lines map(.x = seq_len(nrow(post)),
.f = function(ii, post){
<- post$b_Intercept[ii]
p_Intercept <- post$shape[ii]
p_shape tibble(ii = ii,
x = seq(0, 30, length.out = 100),
y = dgamma(x, shape = exp(p_Intercept), rate = 1 / p_shape))
post = post) |>
}, list_rbind()
}
Gamma
Resources
- https://discourse.mc-stan.org/t/output-for-family-in-brms/9379
- https://discourse.mc-stan.org/t/decoding-smooth-fits-in-brms/34473
- https://stats.stackexchange.com/questions/96972/how-to-interpret-parameters-in-glm-with-family-gamma
Gamma distribution
Shape (\(\theta\)) and Scale (\(k\))
\[PDF(x)=\frac{1}{\Gamma(k)~\theta^k} x^{k - 1}~e^{-x/\theta}\]
Shape (\(\alpha = \theta\)) and Rate (\(\beta\))
\[PDF(x) = \frac{\beta^\alpha}{\Gamma(\alpha)} x^{\alpha - 1}~e^{-\beta x}\]
Inverse scale parameter = rate
\[\beta = \frac{1}{\theta} = \frac{1}{\alpha}\]
\[\bar{x} = \mu = \frac{\alpha}{\beta}\]
Data
set.seed(3475934)
<- 4
x_mean <- 12
alpha <- alpha / x_mean) (beta
[1] 3
<- 1e4
n
<- tibble(x = rgamma(n, shape = alpha, rate = beta)) GD
/ beta alpha
[1] 4
mean(GD$x)
[1] 4.010262
\[Var(x) = \frac{\alpha}{\beta^2}\]
/ (beta^2) alpha
[1] 1.333333
var(GD$x)
[1] 1.327161
\[Var(x) = \phi~\mu^2\]
where \(\phi\) is a dispersion parameter
/ (beta^2)) / ((alpha / beta)^2) (alpha
[1] 0.08333333
GLM
<- glm(x ~ 1, data = GD, family = Gamma(link = log))
fm_glm summary(fm_glm)
Call:
glm(formula = x ~ 1, family = Gamma(link = log), data = GD)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.388857 0.002873 483.5 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for Gamma family taken to be 0.08252358)
Null deviance: 842.49 on 9999 degrees of freedom
Residual deviance: 842.49 on 9999 degrees of freedom
AIC: 30718
Number of Fisher Scoring iterations: 4
Mean
\[\mu = \exp(\alpha + \beta~x)\]
<- coef(fm_glm)) (fm_beta
(Intercept)
1.388857
exp(fm_beta)
(Intercept)
4.010262
/ beta alpha
[1] 4
# alpha
1 / MASS::gamma.dispersion(fm_glm)
[1] 12.03391
Priors
get_prior(x ~ 1,
family = Gamma(link = log),
data = GD)
prior class coef group resp dpar nlpar lb ub source
student_t(3, 1.4, 2.5) Intercept default
gamma(0.01, 0.01) shape 0 default
Prior prediction - default
<- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
priors prior(gamma(0.01, 0.01), class = "shape"))
<- brm(x ~ 1,
PP family = Gamma(link = log),
prior = priors,
data = GD,
sample_prior = "only",
backend = "cmdstanr",
refresh = 0)
Running MCMC with 4 sequential chains...
Chain 1 finished in 0.0 seconds.
Chain 2 finished in 0.0 seconds.
Chain 3 finished in 0.0 seconds.
Chain 4 finished in 0.1 seconds.
All 4 chains finished successfully.
Mean chain execution time: 0.0 seconds.
Total execution time: 0.8 seconds.
<- as_draws_df(PP) |>
(post slice_sample(n = 200))
# A draws_df: 180 iterations, 4 chains, and 5 variables
b_Intercept shape Intercept lprior lp__
1 1.87 6.1e+00 1.87 -8.4 -6.6
2 4.32 2.0e-207 4.32 463.9 -12.1
3 0.81 1.8e-72 0.81 156.9 -8.3
4 5.61 2.9e-08 5.61 9.3 -8.1
5 18.50 2.1e-21 18.50 34.9 -12.7
6 2.33 6.2e-251 2.33 563.7 -12.4
7 5.45 9.1e-105 5.45 229.4 -10.2
8 7.34 1.8e-44 7.34 91.1 -9.7
9 -2.43 1.9e-19 -2.43 35.0 -8.1
10 6.93 2.0e-16 6.93 27.3 -8.9
# ... with 190 more draws
# ... hidden reserved variables {'.chain', '.iteration', '.draw'}
ggplot() +
geom_line(data = prior_pred_lines(post), aes(x, y, group = ii),
color = "firebrick4", alpha = 0.5) +
geom_dotsinterval(data = GD, aes(x))
Prior prediction - improved
<- log(mean(GD$x))) |> round(2) (pr_mean
[1] 1.39
<- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
priors prior(gamma(1.4, 1/1.4), class = "shape"))
<- brm(x ~ 1,
PP family = Gamma(link = log),
prior = priors,
data = GD,
backend = "cmdstanr",
sample_prior = "only",
refresh = 0)
Start sampling
Running MCMC with 4 sequential chains...
Chain 1 finished in 0.0 seconds.
Chain 2 finished in 0.0 seconds.
Chain 3 finished in 0.0 seconds.
Chain 4 finished in 0.0 seconds.
All 4 chains finished successfully.
Mean chain execution time: 0.0 seconds.
Total execution time: 0.6 seconds.
<- as_draws_df(PP) |>
(post slice_sample(n = 200))
# A draws_df: 188 iterations, 4 chains, and 5 variables
b_Intercept shape Intercept lprior lp__
1 17.42 1.71 17.42 -8.6 -8.1
2 2.63 1.17 2.63 -3.2 -3.0
3 0.50 6.27 0.50 -6.1 -4.3
4 6.25 0.71 6.25 -4.5 -4.9
5 -5.96 1.20 -5.96 -5.8 -5.6
6 0.44 4.31 0.44 -4.9 -3.4
7 3.91 0.94 3.91 -3.5 -3.6
8 10.46 3.19 10.46 -7.4 -6.3
9 2.83 1.23 2.83 -3.3 -3.1
10 -2.25 4.07 -2.25 -5.7 -4.3
# ... with 190 more draws
# ... hidden reserved variables {'.chain', '.iteration', '.draw'}
ggplot() +
geom_line(data = prior_pred_lines(post), aes(x, y, group = ii),
color = "firebrick4", alpha = 0.5) +
geom_dotsinterval(data = GD, aes(x))
brms model
<- brm(x ~ 1,
fm family = Gamma(link = log),
data = GD,
prior = priors,
backend = "cmdstanr",
cores = 4,
init = list(list(Intercept = 1, shape = 2),
list(Intercept = 1, shape = 2),
list(Intercept = 1, shape = 2),
list(Intercept = 1, shape = 2)),
control = list(step_size = 0.01),
refresh = 0)
Start sampling
Running MCMC with 4 parallel chains...
Chain 3 finished in 6.7 seconds.
Chain 4 finished in 6.8 seconds.
Chain 1 finished in 7.0 seconds.
Chain 2 finished in 7.1 seconds.
All 4 chains finished successfully.
Mean chain execution time: 6.9 seconds.
Total execution time: 7.2 seconds.
prior_summary(fm)
prior class coef group resp dpar nlpar lb ub source
student_t(3, 1.4, 2.5) Intercept user
gamma(1.4, 1/1.4) shape 0 user
mcmc_combo(fm, pars = c("b_Intercept", "shape"),
combo = c("dens_overlay", "rank_overlay"))
pp_check(fm, ndraws = 100)
<- posterior_summary(fm) ps
<- exp(ps[1, 1])) (mean_est
[1] 4.01048
mean(GD$x)
[1] 4.010262