---
title: "GLM CMCMC"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{GLM CMCMC}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE, purl=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE,
  purl = FALSE
)
```

## Overview

`glm_cmcmc()` is the formula interface for the built-in CMCMC GLM kernels. It
uses the same model formula style as `stats::glm()`, builds the model frame and
design matrix, checks the response, chooses the correct built-in GLM target
kernel, and then calls `cmcmc()` internally.

The supported family-link combinations are:

| Family | Supported links | Sampled parameters |
|---|---|---|
| Binomial | `logit`, `probit` | regression coefficients |
| Poisson | `log` | regression coefficients |
| Gaussian | `identity`, `log`, `inverse` | regression coefficients and `sigma2` |
| Gamma | `log` | regression coefficients and `alpha` |

All GLM models use independent normal priors on the coefficients,

\[
\beta_j \sim N(0, \sigma_\beta^2),
\]

where `prior_var` is \(\sigma_\beta^2\). Gaussian and Gamma models also sample
one auxiliary scale/shape parameter, controlled by `prior.override`.

`glm_cmcmc()` uses `backend = "auto"` through `cmcmc()`: CUDA is used when it
is available, otherwise the CPU backend is used. Set `verbose = TRUE` to print
which backend was selected.

## Binomial

Use the binomial family for binary responses. Numeric responses must contain
only `0` and `1`; two-level factors and logical responses are also accepted.
The supported links are `logit` and `probit`.

For the logit link,

\[
y_i \mid \beta \sim \operatorname{Bernoulli}(p_i),
\qquad
\operatorname{logit}(p_i) = x_i^\top \beta.
\]

```{r binomial-logit}
library(CMCMC)

set.seed(1)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)

eta <- -0.3 + 0.8 * x1 - 0.5 * x2
p <- 1 / (1 + exp(-eta))
y <- rbinom(n, size = 1, prob = p)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_binomial <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = binomial("logit"),
  k = 128,
  it = 100,
  covit = 10,
  prior_var = 100,
  seed = 1,
  verbose = TRUE
)

fit_binomial
summary(fit_binomial)
coef(fit_binomial)
```

For a probit model, change only the family:

```{r binomial-probit}
fit_binomial_probit <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = binomial("probit"),
  k = 128,
  it = 100,
  covit = 10,
  seed = 1
)
```

## Poisson

Use the Poisson family for non-negative integer counts. The supported link is
`log`.

\[
y_i \mid \beta \sim \operatorname{Poisson}(\mu_i),
\qquad
\log(\mu_i) = x_i^\top \beta.
\]

```{r poisson-log}
library(CMCMC)

set.seed(2)
n <- 120
x1 <- rnorm(n)
x2 <- rnorm(n)

eta <- 0.2 + 0.4 * x1 - 0.3 * x2
mu <- exp(eta)
y <- rpois(n, lambda = mu)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_poisson <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = poisson("log"),
  k = 128,
  it = 100,
  covit = 10,
  prior_var = 100,
  seed = 2,
  verbose = TRUE
)

fit_poisson
summary(fit_poisson)
coef(fit_poisson)
```

## Gaussian

Use the Gaussian family for finite numeric responses. The supported links are
`identity`, `log`, and `inverse`.

For the identity link,

\[
y_i \mid \beta,\sigma \sim N(\mu_i,\sigma^2),
\qquad
\mu_i = x_i^\top \beta.
\]

The sampled auxiliary parameter is `sigma2`. The supported residual-scale
priors are:

| `sigma_prior` | Prior | Main fields |
|---|---|---|
| `"uniform_sigma2"` | bounded uniform prior on \(\sigma^2\) | `sigma2_lower`, `sigma2_upper`, `sigma2_init` |
| `"uniform_sigma"` | bounded uniform prior on \(\sigma\) | `sigma_lower`, `sigma_upper`, `sigma2_init` |
| `"exponential_sigma"` | exponential prior on \(\sigma\), calibrated by \(P(\sigma > U)=q\) | `sigma_upper`, `sigma_tail_prob`, `sigma2_init` |
| `"half_cauchy_sigma"` | half-Cauchy prior on \(\sigma\), calibrated by \(P(\sigma > U)=q\) | `sigma_upper`, `sigma_tail_prob`, `sigma2_init` |

For the tail-calibrated priors, `sigma_upper` is \(U\) and
`sigma_tail_prob` is \(q\). The exponential prior uses
\(\lambda = -\log(q) / U\). The half-Cauchy prior uses scale
\(A = U \tan(\pi q / 2)\).

```{r gaussian-identity}
library(CMCMC)

set.seed(3)
n <- 120
x1 <- rnorm(n)
x2 <- rnorm(n)

mu <- 0.5 + 1.2 * x1 - 0.7 * x2
sigma <- 0.4
y <- mu + rnorm(n, sd = sigma)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_gaussian <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = gaussian("identity"),
  k = 128,
  it = 100,
  covit = 10,
  prior_var = 100,
  prior.override = list(
    sigma_prior = "uniform_sigma",
    sigma_upper = 1
  ),
  seed = 3,
  verbose = TRUE
)

fit_gaussian
summary(fit_gaussian)
coef(fit_gaussian)
```

For a Gaussian log-link model, generate positive means and use
`family = gaussian("log")`:

```{r gaussian-log}
set.seed(4)
n <- 120
x1 <- rnorm(n)
x2 <- rnorm(n)

eta <- 0.2 + 0.15 * x1 - 0.1 * x2
mu <- exp(eta)
y <- mu + rnorm(n, sd = 0.2)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_gaussian_log <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = gaussian("log"),
  k = 128,
  it = 100,
  covit = 10,
  prior.override = list(
    sigma_prior = "exponential_sigma",
    sigma_upper = 1,
    sigma_tail_prob = 0.05
  ),
  seed = 4
)
```

For the inverse link, the linear predictor must stay away from zero because
\(\mu_i = 1 / \eta_i\):

```{r gaussian-inverse}
set.seed(5)
n <- 120
x1 <- runif(n, -0.5, 0.5)
x2 <- runif(n, -0.5, 0.5)

eta <- 1.4 + 0.2 * x1 - 0.1 * x2
mu <- 1 / eta
y <- mu + rnorm(n, sd = 0.05)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_gaussian_inverse <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = gaussian("inverse"),
  k = 128,
  it = 100,
  covit = 10,
  prior.override = list(
    sigma_prior = "uniform_sigma",
    sigma_upper = 0.3
  ),
  seed = 5
)
```

## Gamma

Use the Gamma family for positive continuous responses. The supported link is
`log`.

CMCMC uses the Gamma GLM parameterisation

\[
y_i \mid \beta,\alpha
\sim
\operatorname{Gamma}\left(
\operatorname{shape}=\alpha,
\operatorname{rate}=\frac{\alpha}{\mu_i}
\right),
\qquad
\log(\mu_i) = x_i^\top \beta.
\]

This gives

\[
E(y_i) = \mu_i,
\qquad
\operatorname{Var}(y_i) = \frac{\mu_i^2}{\alpha},
\qquad
CV = \frac{1}{\sqrt{\alpha}}.
\]

The sampled auxiliary parameter is `alpha`, but the prior is specified on
\(CV\). The supported CV priors are:

| `cv_prior` | Prior | Main fields |
|---|---|---|
| `"uniform_cv"` | bounded uniform prior on \(CV\) | `cv_lower`, `cv_upper`, `alpha_init` |
| `"exponential_cv"` | exponential prior on \(CV\), calibrated by \(P(CV > U)=q\) | `cv_upper`, `cv_tail_prob`, `alpha_init` |
| `"half_cauchy_cv"` | half-Cauchy prior on \(CV\), calibrated by \(P(CV > U)=q\) | `cv_upper`, `cv_tail_prob`, `alpha_init` |

For the tail-calibrated CV priors, `cv_upper` is \(U\) and
`cv_tail_prob` is \(q\). The exponential prior uses
\(\lambda = -\log(q) / U\). The half-Cauchy prior uses scale
\(A = U \tan(\pi q / 2)\).

```{r gamma-log}
library(CMCMC)

set.seed(6)
n <- 120
x1 <- rnorm(n)
x2 <- rnorm(n)

eta <- 0.3 + 0.4 * x1 - 0.2 * x2
mu <- exp(eta)
alpha <- 8
y <- rgamma(n, shape = alpha, rate = alpha / mu)

dat <- data.frame(y = y, x1 = x1, x2 = x2)

fit_gamma <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = Gamma("log"),
  k = 128,
  it = 100,
  covit = 10,
  prior_var = 100,
  prior.override = list(
    cv_prior = "uniform_cv",
    cv_upper = 1
  ),
  seed = 6,
  verbose = TRUE
)

fit_gamma
summary(fit_gamma)
coef(fit_gamma)
```

For example:

```{r gamma-tail-priors}
fit_gamma_pc <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = Gamma("log"),
  k = 128,
  it = 100,
  covit = 10,
  prior.override = list(
    cv_prior = "exponential_cv",
    cv_upper = 0.75,
    cv_tail_prob = 0.05
  ),
  seed = 6
)

fit_gamma_half_cauchy <- CMCMC::glm_cmcmc(
  y ~ x1 + x2,
  data = dat,
  family = Gamma("log"),
  k = 128,
  it = 100,
  covit = 10,
  prior.override = list(
    cv_prior = "half_cauchy_cv",
    cv_upper = 0.75,
    cv_tail_prob = 0.05
  ),
  seed = 6
)
```

## Output

`glm_cmcmc()` returns a data frame with class `"glm_cmcmc"`. The first two
columns are `iter` and `particle`; the remaining columns are posterior draws.
`coef()` returns posterior means for regression coefficients only, while
`summary()` reports marginal summaries for all sampled parameters.

```{r output-methods}
coef(fit_binomial)
summary(fit_gaussian)
```
