---
title: "Gamma"
format:
html:
toc: true
number-depth: 3
toc-location: left
embed-resources: true
---
## 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
```{r}
#| label: setup
#| message: false
#| warning: false
library(tidyverse)
library(brms)
library(posterior)
library(bayesplot)
library(ggdist)
library(patchwork)
color_scheme_set(scheme = "red")
theme_set(theme_ggdist())
prior_pred_lines <- function(post) {
map(.x = seq_len(nrow(post)),
.f = function(ii, post){
p_Intercept <- post$b_Intercept[ii]
p_shape <- post$shape[ii]
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 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}$$
where $\Gamma$ is the Gamma function
Inverse scale parameter = rate:
$$\beta = \frac{1}{\theta} = \frac{1}{\alpha}$$
Mean:
$$\bar{x} = \mu = \frac{\alpha}{\beta}$$
## Data
```{r}
set.seed(3475934)
x_mean <- 4
alpha <- 12
(beta <- alpha / x_mean)
n <- 1e4
GD <- tibble(x = rgamma(n, shape = alpha, rate = beta))
```
```{r}
#| echo: false
ggplot(GD, aes(x)) +
stat_dotsinterval() +
ggplot(GD, aes(log(x))) +
stat_dotsinterval()
```
```{r}
alpha / beta
mean(GD$x)
```
$$Var(x) = \frac{\alpha}{\beta^2}$$
```{r}
alpha / (beta^2)
var(GD$x)
```
$$Var(x) = \phi~\mu^2$$
where $\phi$ is a *dispersion* parameter
```{r}
(alpha / (beta^2)) / ((alpha / beta)^2)
```
## GLM
```{r}
fm_glm <- glm(x ~ 1, data = GD, family = Gamma(link = log))
summary(fm_glm)
```
## Mean
$$\mu = \exp(\alpha + \beta~x)$$
```{r}
(fm_beta <- coef(fm_glm))
exp(fm_beta)
alpha / beta
# alpha
1 / MASS::gamma.dispersion(fm_glm)
```
## Priors
```{r}
get_prior(x ~ 1,
family = Gamma(link = log),
data = GD)
```
## Prior prediction - default
```{r}
#| message: false
priors <- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
prior(gamma(0.01, 0.01), class = "shape"))
PP <- brm(x ~ 1,
family = Gamma(link = log),
prior = priors,
data = GD,
sample_prior = "only",
backend = "cmdstanr",
refresh = 0)
(post <- as_draws_df(PP) |>
slice_sample(n = 200))
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
```{r}
(pr_mean <- log(mean(GD$x))) |> round(2)
priors <- c(prior(student_t(3, 1.4, 2.5), class = "Intercept"),
prior(gamma(1.4, 1/1.4), class = "shape"))
PP <- brm(x ~ 1,
family = Gamma(link = log),
prior = priors,
data = GD,
backend = "cmdstanr",
sample_prior = "only",
refresh = 0)
(post <- as_draws_df(PP) |>
slice_sample(n = 200))
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
```{r}
fm <- brm(x ~ 1,
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)
```
```{r}
prior_summary(fm)
```
```{r}
mcmc_combo(fm, pars = c("b_Intercept", "shape"),
combo = c("dens_overlay", "rank_overlay"))
pp_check(fm, ndraws = 100)
```
```{r}
ps <- posterior_summary(fm)
```
```{r}
(mean_est <- exp(ps[1, 1]))
mean(GD$x)
```