A continuación se describe la estructura básica de un modelo de Regresión Poisson como un modelo lineal generalizado (GLM, Generalized Linear Model).
Distribución muestral:
\[ y_i \mid \theta_i \stackrel{\text{iid}}{\sim} \textsf{Poisson}(\theta_i), \qquad i = 1, \ldots, n, \] donde la media \(\theta_i\) está relacionada con una combinación lineal de predictores a través de una transformación logarítmica: \[ \log(\theta_i) = \boldsymbol{\beta}^{\textsf{T}} \boldsymbol{x}_i = \sum_{j=1}^p \beta_j x_{i,j}, \] donde \(\boldsymbol{\beta} = (\beta_1, \ldots, \beta_p)\) y \(\boldsymbol{x}i = (x{i1}, \ldots, x_{ip})\) denotan, respectivamente, el vector de coeficientes desconocidos y el vector de predictores observados correspondientes a la \(i\)-ésima observación.
La función de enlace (link function) utilizada es la logarítmica, \(\log\), la cual asegura que \(\theta_i > 0\), en concordancia con las propiedades de la distribución Poisson.
Distribución previa:
No existen distribuciones previas conjugadas para los modelos lineales generalizados, excepto en el caso de la regresión normal. Por ello, se emplea una distribución previa normal como aproximación: \[ \boldsymbol{\beta} \sim \textsf{N}_p(\boldsymbol{\beta}_0, \Sigma_0)\,, \] donde \(\boldsymbol{\beta}_0\) es la media previa de los coeficientes y \(\Sigma_0\) esl la matriz de covarianza previa.
Los parámetros del modelo son \((\beta_1, \ldots, \beta_p)\).
Los hiperparámetros del modelo son \((\boldsymbol{\beta}_0, \Sigma_0)\).
(Ejercicio.) La distribución posterior del modelo es de la forma: \[ p(\boldsymbol{\beta}\mid\boldsymbol{y}) \propto \prod_{i=1}^n e^{-\theta_i}\,\theta_i^{y_i} \times \exp\left\{ -\tfrac{1}{2} \left[ \boldsymbol{\beta}^{\textsf{T}}\Sigma_0^{-1}\boldsymbol{\beta} - 2\boldsymbol{\beta}^{\textsf{T}}\Sigma_0^{-1}\boldsymbol{\beta}_0 \right] \right\}\,, \] donde \(\log(\theta_i) = \boldsymbol{\beta}^{\textsf{T}}\boldsymbol{x}_i\).
Observe que \(p(\boldsymbol{\beta}\mid\boldsymbol{y})\) no corresponde a ninguna familia paramétrica de distribuciones conocida.
(Ejercicio.) En escala logarítmica, se tiene que \[ \log p(\boldsymbol{\beta}\mid\boldsymbol{y}) = \sum_{i=1}^n(y_i\log(\theta_i) - \theta_i) -\tfrac{1}{2} \left[ \boldsymbol{\beta}^{\textsf{T}}\Sigma_0^{-1}\boldsymbol{\beta} - 2\boldsymbol{\beta}^{\textsf{T}}\Sigma_0^{-1}\boldsymbol{\beta}_0 \right] + \text{C} \] donde \(\text{C}\) es una constante (términos que no dependen de \(\boldsymbol{\beta}\)).
(Ejercicio.) El gradiente correspondiente está dado por \[ \frac{\partial}{\partial \boldsymbol{\beta}}\log p(\boldsymbol{\beta} \mid \boldsymbol{y}) = \sum_{i=1}^n \left( y_i - \exp{\left(\boldsymbol{\beta}^{\textsf{T}}\boldsymbol{x}_i\right)} \right)\boldsymbol{x}_i\,. \]
El algoritmo de Metropolis-Hastings es un método general para aproximar distribuciones probabilísticas, incluso cuando no se dispone de una solución analítica exacta.
El principal desafío aparece cuando \(p(\boldsymbol{\theta} \mid \boldsymbol{y})\) no corresponde a una distribución estándar conocida, lo que impide generar muestras directamente de la misma.
El algoritmo de Metropolis es un caso particular del algoritmo de Metropolis-Hastings.
Este algoritmo produce una cadena de Markov que converge a la distribución posterior objetivo \(p(\theta \mid \boldsymbol{y})\), bajo el supuesto de que la distribución de propuestas es simétrica.
Dado el estado actual \(\theta^{(b)}\) del parámetro \(\theta\), el siguiente estado \(\theta^{(b+1)}\) se genera de la siguiente manera:
Generación de la propuesta:
Simular un valor propuesto \(\theta^* \sim
J(\theta \mid \theta^{(b)})\), donde \(J\) es una distribución
simétrica tal que \(J(\theta_1 \mid \theta_2) = J(\theta_2 \mid
\theta_1)\).
Esta distribución, conocida como distribución de
propuestas (proposal distribution), suele
especificarse como:
\[
J(\theta \mid \theta^{(b)}) = \textsf{N}(\theta \mid \theta^{(b)},
\delta^2)
\quad \text{o} \quad
J(\theta \mid \theta^{(b)}) = \textsf{U}(\theta \mid \theta^{(b)} -
\delta, \theta^{(b)} + \delta),
\] donde \(\delta\) es el
parámetro de ajuste, elegido para garantizar un
rendimiento adecuado del algoritmo.
Cálculo de la probabilidad de aceptación:
Calcular la probabilidad de aceptación \(r\), definida como:
\[
r = \frac{p(\theta^* \mid \boldsymbol{y})}{p(\theta^{(b)} \mid
\boldsymbol{y})}.
\]
Para mejorar la estabilidad numérica, este cálculo suele realizarse en
la escala logarítmica:
\[
r = \exp\left[ \log p(\theta^* \mid \boldsymbol{y}) - \log
p(\theta^{(b)} \mid \boldsymbol{y}) \right].
\]
Actualización del estado:
Actualizar el estado \(\theta^{(b+1)}\)
según la probabilidad de aceptación:
\[
\theta^{(b+1)} =
\begin{cases}
\theta^*, & \text{con probabilidad } \min(1, r), \\
\theta^{(b)}, & \text{con probabilidad } 1 - \min(1, r).
\end{cases}
\]
Este algoritmo produce una secuencia de valores \(\theta^{(1)}, \ldots, \theta^{(B)}\), donde \(\theta^{(b+1)}\) depende únicamente del estado anterior \(\theta^{(b)}\). Esto hace que la secuencia sea una cadena de Markov, lo que garantiza su convergencia a la distribución objetivo bajo condiciones apropiadas.
Es común calibrar \(\delta\) para lograr una tasa de aceptación entre el 30% y el 50% (0.234 para cadenas de alta dimensión o 0.44 para dimensión 1), lo que suele optimizar el rendimiento del algoritmo. Para facilitar esta calibración, pueden emplearse algoritmos adaptativos que ajusten automáticamente el valor de \(\delta\) durante las iteraciones iniciales.
El parámetro de ajuste \(\delta\) controla el tamaño de los pasos propuestos y tiene un impacto directo en la eficiencia del algoritmo. Valores de \(\delta\) demasiado pequeños generan una exploración lenta del espacio de parámetros, mientras que valores grandes pueden conducir a bajas tasas de aceptación.
La correlación de la cadena entre estados consecutivos depende del valor de \(\delta\) en la distribución de propuestas. Una correlación alta indica una exploración menos eficiente del espacio de parámetros.
Algoritmo de Metropolis en un modelo Normal con varianza conocida.
Los datos \(y_i\) se suponen independientes e idénticamente distribuidos (i.i.d.) según una distribución Normal con media \(\theta = 10\) y varianza \(1\).
El modelo es de la forma: \[ y_i \mid \theta \overset{\text{i.i.d.}}{\sim} \textsf{N}(\theta, 1), \qquad i = 1, \ldots, n. \]
Se especifica una distribución previa conjugada para el parámetro
\(\theta\):
\[
\theta \sim \textsf{N}(\mu, \tau^2).
\]
# Reproducibilidad
set.seed(123)
# Simular datos
n <- 5
s2 <- 1
y <- rnorm(n = n, mean = 10, sd = 1)
# Previa
t2 <- 10
mu <- 5
# Algoritmo de Metropolis
theta <- 0 # valor inicial
delta <- 1.75 # parámetro de ajuste
acr <- 0 # tasa de aceptación
B <- 10000 # número de muestras
THETA <- matrix(NA, nrow = B, ncol = 1) # almacenamiento
# cadena
for (b in 1:B) {
# 1. propuesta
theta_star <- rnorm(n = 1, mean = theta, sd = sqrt(delta))
# 2. probabilidad de aceptación (en escala log)
log_post_star <- sum(dnorm(x = y, mean = theta_star, sd = sqrt(s2), log = TRUE)) +
dnorm(x = theta_star, mean = mu, sd = sqrt(t2), log = TRUE)
log_post_curr <- sum(dnorm(x = y, mean = theta, sd = sqrt(s2), log = TRUE)) +
dnorm(x = theta, mean = mu, sd = sqrt(t2), log = TRUE)
log_r <- log_post_star - log_post_curr
# 3. actualizar
if (runif(1) < exp(log_r)) {
theta <- theta_star
acr <- acr + 1/B
}
# 4. almacenar
THETA[b] <- theta
}
# Tasa de aceptación
round(100 * acr, 1)
## [1] 38
# Gráfico
par(mfrow = c(1, 2), mar = c(3, 3, 1, 1), mgp = c(1.75, 0.75, 0))
# Cadena
plot(x = seq_along(THETA), y = THETA, type = "p", pch = 20, cex = 0.3,
xlab = "Iteración", ylab = expression(theta))
# Histograma (sin periodo de calentamiento)
hist(x = THETA[-(1:10)], freq = FALSE, col = "gray", border = "gray",
main = "", xlab = expression(theta), ylab = "Densidad")
# Posterior analítica
th <- seq(min(THETA), max(THETA), length.out = 1000)
mu_n <- (mu / t2 + n * mean(y) / s2) / (1 / t2 + n / s2)
t2_n <- 1 / (1 / t2 + n / s2)
lines(x = th, y = dnorm(th, mean = mu_n, sd = sqrt(t2_n)),
col = 2, lty = 1, lwd = 2)
# Reproducibilidad
set.seed(123)
ACR <- NULL # tasa de aceptaciones
ACF <- NULL # autocorrelaciones
SAM <- NULL # muestras
for (delta2 in 2^c(-5, -1, 1, 5, 7)) {
# parámetros iniciales
theta <- 0 # valor inicial
acr <- 0 # tasa de aceptación
B <- 10000 # número de muestras
THETA <- matrix(NA, nrow = B, ncol = 1) # almacenamiento
# cadena
for (b in 1:B) {
# 1. propuesta
theta_star <- rnorm(n = 1, mean = theta, sd = sqrt(delta2))
# 2. probabilidad de aceptación (escala log)
log_post_star <- sum(dnorm(x = y, mean = theta_star, sd = sqrt(s2), log = TRUE)) +
dnorm(x = theta_star, mean = mu, sd = sqrt(t2), log = TRUE)
log_post_curr <- sum(dnorm(x = y, mean = theta, sd = sqrt(s2), log = TRUE)) +
dnorm(x = theta, mean = mu, sd = sqrt(t2), log = TRUE)
log_r <- log_post_star - log_post_curr
# 3. actualizar
if (runif(1) < exp(log_r)) {
theta <- theta_star
acr <- acr + 1/B
}
# 4. almacenar
THETA[b] <- theta
}
# almacenar valores para todos los valores de delta2
ACR <- c(ACR, acr)
ACF <- c(ACF, acf(THETA, plot = FALSE)$acf[2])
SAM <- cbind(SAM, THETA)
}
## [1] 0.031 0.500 2.000 32.000 128.000
## [1] 86.4 56.3 35.4 8.8 4.8
## [1] 0.975 0.845 0.743 0.891 0.915
## var1 var2 var3 var4 var5
## 120 347 1027 611 399
Emplear la varianza posterior en la distribución de propuestas suele ser la opción más eficiente.
Aunque la varianza posterior exacta no se conoce antes de ejecutar el algoritmo de Metropolis, una aproximación suele ser suficiente para lograr un buen desempeño.
Si la tasa de aceptación obtenida es demasiado baja o demasiado alta, puede ajustarse la variabilidad de la propuesta de forma adaptativa con el fin de optimizar el rendimiento del algoritmo.
Una forma común de adaptar el parámetro de ajuste (tuning parameter) \(\delta\) en el algoritmo de Metropolis es usar una regla de actualización estocástica basada en la tasa de aceptación observada: \[ \log \delta_{t+1} \;=\; \log \delta_t \;+\; \gamma_t \,(\alpha_t - \alpha^\ast) \qquad\Longleftrightarrow\qquad \delta_{t+1} \;=\; \delta_t \; \exp\!\big(\,\gamma_t \,(\alpha_t - \alpha^\ast)\,\big), \] donde:
¡Cuidado! La adaptación se realiza solo durante el periodo de calentamiento (burn-in).
El algoritmo Metropolis-Hastings es una generalización del algoritmo de Metropolis, que permite utilizar una distribución de propuestas arbitraria, lo que lo hace más flexible para aplicaciones donde estas variantes más simples son inadecuadas.
Dado el estado actual \(\theta^{(b)}\) del parámetro \(\theta\), el siguiente estado \(\theta^{(b+1)}\) se obtiene mediante el siguiente procedimiento:
Generación de la propuesta:
Simular un valor propuesto \(\theta^* \sim
J(\theta \mid \theta^{(b)})\), donde \(J\) es una distribución de propuestas
arbitraria.
Cálculo de la tasa de aceptación:
Evaluar la tasa de aceptación \(r\)
como
\[
r = \frac{p(\theta^* \mid y)}{p(\theta^{(b)} \mid y)} \cdot
\frac{J(\theta^{(b)} \mid \theta^*)}{J(\theta^* \mid \theta^{(b)})}.
\]
Este ajuste incorpora el cociente de las probabilidades de la
distribución de propuestas para corregir posibles asimetrías en \(J\).
Actualización del estado:
Definir \(\theta^{(b+1)}\) de acuerdo
con la probabilidad de aceptación:
\[
\theta^{(b+1)} =
\begin{cases}
\theta^*, & \text{con probabilidad } \min(1, r), \\
\theta^{(b)}, & \text{con probabilidad } 1 - \min(1, r).
\end{cases}
\]
El algoritmo de Metropolis es un caso particular del método de Metropolis–Hastings en el que la distribución de propuestas \(J(\theta \mid \theta^{(b)})\) es simétrica, es decir, \(J(\theta_1 \mid \theta_2) = J(\theta_2 \mid \theta_1)\).
La simetría de \(J(\theta \mid \theta^{(b)})\) simplifica el cálculo de la probabilidad de aceptación, pues elimina la necesidad de incluir el cociente de probabilidades de la distribución de propuestas, reduciendo así la complejidad computacional.
Investigar las actividades de reproducción de gorriones en función de la edad.
El estudio analiza la relación entre la edad de los gorriones y el número de crías que producen, con el objetivo de caracterizar cómo la edad influye en su éxito reproductivo.
Referencias:
Las variables del modelo son:
# Actividades de reproducción de gorriones (hembras) en función de la edad
# "age" : edad.
# "fledged" : número de crías.
dat <- structure(
c(
3, 1, 1, 2, 0, 0, 6, 3, 4, 2, 1, 6, 2, 3, 3, 4, 7, 2, 2, 1,
1, 3, 5, 5, 0, 2, 1, 2, 6, 6, 2, 2, 0, 2, 4, 1, 2, 5, 1, 2,
1, 0, 0, 2, 4, 2, 2, 2, 2, 0, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4,
4, 4, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 6, 1, 1, 9, 9, 1, 1,
1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 25, 25, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 25, 16, 16, 16, 16,
25, 25, 25, 25, 9, 9, 9, 9, 9, 9, 9, 36, 1, 1
),
.Dim = c(52L, 4L),
.Dimnames = list(NULL, c("fledged", "intercept", "age", "age2"))
)
dat <- as.data.frame(dat)
y <- dat$fledged # y = variable dependiente (respuesta)
age <- dat$age # x1 = variable independiente 1
age2 <- age^2 # x2 = variable independiente 2
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 1.000 2.000 2.404 3.000 7.000
## [1] 3.265
# Visualización
par(mar = c(3, 3, 1, 1), mgp = c(1.75, 0.75, 0))
# Boxplots
plot(y ~ as.factor(age), boxwex = 0.4, range = 0,
xlab = "Edad (años)", ylab = "No. Crias", col = 0, border = "darkgray")
# Añadir observaciones con jitter
points(jitter(as.numeric(as.factor(age)), amount = 0.15), y,
pch = 20, col = adjustcolor(4, 0.5), cex = 1.2)
##
## Call:
## glm(formula = y ~ age + age2, family = "poisson")
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.27662 0.44219 0.626 0.5316
## age 0.68174 0.33850 2.014 0.0440 *
## age2 -0.13451 0.05786 -2.325 0.0201 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 76.081 on 51 degrees of freedom
## Residual deviance: 67.837 on 49 degrees of freedom
## AIC: 198.78
##
## Number of Fisher Scoring iterations: 5
# Variable respuesta
y <- dat$fledged
# Matriz de diseño (incluye intercepto, edad y edad^2)
X <- cbind(1, age, age^2)
# Tamaño de la muestra y número de predictores
(n <- nrow(X))
## [1] 52
## [1] 3
# Reproducibilidad
set.seed(123)
# Algoritmo de Metropolis
beta <- rep(0, p) # valor inicial
acr <- 0 # tasa de aceptación
B <- 100000 # número de muestras
BETA <- matrix(NA, nrow = B, ncol = p) # almacenamiento
# Progreso
ncat <- floor(B / 10)
# Cadena
for (b in 1:B) {
# 1. Propuesta
beta_p <- c(mvtnorm::rmvnorm(n = 1, mean = beta, sigma = Delta))
# 2. Tasa de aceptación (escala log)
eta_p <- as.numeric(X %*% beta_p) # predictor lineal propuesto
eta <- as.numeric(X %*% beta) # predictor lineal actual
log_post_star <- sum(dpois(x = y, lambda = exp(eta_p), log = TRUE)) +
sum(dnorm(x = beta_p, mean = beta0, sd = Sigma0, log = TRUE))
log_post_curr <- sum(dpois(x = y, lambda = exp(eta), log = TRUE)) +
sum(dnorm(x = beta, mean = beta0, sd = Sigma0, log = TRUE))
log_r <- log_post_star - log_post_curr
# 3) Actualizar
if (runif(1) < exp(log_r)) {
beta <- beta_p
acr <- acr + 1/B
}
# 4. Almacenar
BETA[b, ] <- beta
# 5. Progreso
if (b %% ncat == 0) {
cat(round(100 * b / B, 1), "% completado ...\n", sep = "")
}
}
## 10% completado ...
## 20% completado ...
## 30% completado ...
## 40% completado ...
## 50% completado ...
## 60% completado ...
## 70% completado ...
## 80% completado ...
## 90% completado ...
## 100% completado ...
## [1] 53
## [1] 6379 6008 5524
## 2.5% 97.5%
## 0.073 1.408
## 2.5% 97.5%
## -0.259 -0.032
## [1] 0.986
## [1] 0.005
La inferencia sobre \(\beta_2\) indica que el número de crías aumenta con la edad en las primeras etapas de vida, mientras que la estimación de \(\beta_3\) revela un efecto cuadrático negativo, lo que implica que el éxito reproductivo declina en edades avanzadas.
El algoritmo de Monte Carlo Hamiltoniano (HMC, Hamiltonian Monte Carlo) es una alternativa de alta eficiencia al algoritmo de Metropolis–Hastings.
El HMC incorpora una variable auxiliar denominada impulso (\(\boldsymbol{\varphi}\)), que permite recorrer la distribución objetivo mediante trayectorias dinámicas, superando las limitaciones del movimiento local propio de una caminata aleatoria.
La variable \(\boldsymbol{\varphi}\) incrementa la eficiencia del algoritmo al permitir desplazamientos más amplios y efectivos en el espacio de parámetros.
En HMC, las simulaciones se realizan sobre la distribución conjunta
dada por \[
p(\boldsymbol{\theta}, \boldsymbol{\varphi} \mid \boldsymbol{y})
= p(\boldsymbol{\theta} \mid \boldsymbol{y}) \, p(\boldsymbol{\varphi}
\mid \boldsymbol{y})
= p(\boldsymbol{\theta} \mid \boldsymbol{y}) \, p(\boldsymbol{\varphi}),
\]
donde \(p(\boldsymbol{\varphi})\) suele
ser una distribución Normal centrada. Aunque se simulan tanto \(\boldsymbol{\theta}\) como \(\boldsymbol{\varphi}\), el interés
principal se centra en \(\boldsymbol{\theta}\).
Inicialización del impulso:
Generar \(\boldsymbol{\varphi} \sim
\mathsf{N}(\boldsymbol{0}, \mathbf{M})\), donde \(\mathbf{M}\) es la matriz de covarianza
asociada a la función de impulso \(p(\boldsymbol{\varphi})\).
Integración Hamiltoniana:
Aplicar \(L\) pasos de integración con
tamaño de paso \(\epsilon\), siguiendo
el esquema leapfrog:
Primer medio paso en \(\boldsymbol{\varphi}\):
\[
\boldsymbol{\varphi} \leftarrow \boldsymbol{\varphi} +
\frac{\epsilon}{2} \, \frac{\partial}{\partial \boldsymbol{\theta}} \log
p(\boldsymbol{\theta} \mid \boldsymbol{y}).
\]
Paso completo en \(\boldsymbol{\theta}\)
\[
\boldsymbol{\theta} \leftarrow \boldsymbol{\theta} + \epsilon \,
\mathbf{M} \, \boldsymbol{\varphi}.
\]
Pasos intermedios:
Repetir la secuencia de actualización para \(\boldsymbol{\varphi}\) y \(\boldsymbol{\theta}\) durante \(L-1\) iteraciones. En cada paso
intermedio:
\[
\boldsymbol{\varphi} \leftarrow \boldsymbol{\varphi} + \epsilon \,
\frac{\partial}{\partial \boldsymbol{\theta}} \log p(\boldsymbol{\theta}
\mid \boldsymbol{y}),
\]
seguido de la actualización en \(\boldsymbol{\theta}\) como en (b).
Último medio paso en \(\boldsymbol{\varphi}\):
\[
\boldsymbol{\varphi} \leftarrow \boldsymbol{\varphi} +
\frac{\epsilon}{2} \, \frac{\partial}{\partial \boldsymbol{\theta}} \log
p(\boldsymbol{\theta} \mid \boldsymbol{y}).
\]
Cálculo de la probabilidad de aceptación:
Sean \((\boldsymbol{\theta}^{(b-1)},
\boldsymbol{\varphi}^{(b-1)})\) los valores iniciales y \((\boldsymbol{\theta}^*,
\boldsymbol{\varphi}^*)\) los valores obtenidos tras \(L\) pasos. La razón de aceptación es:
\[
r = \frac{p(\boldsymbol{\theta}^* \mid \boldsymbol{y}) \,
p(\boldsymbol{\varphi}^*)}{p(\boldsymbol{\theta}^{(b-1)} \mid
\boldsymbol{y}) \, p(\boldsymbol{\varphi}^{(b-1)})}.
\]
Aceptación o rechazo:
Actualizar:
\[
\boldsymbol{\theta}^{(b)} =
\begin{cases}
\boldsymbol{\theta}^*, & \text{con probabilidad } \min(1, r), \\
\boldsymbol{\theta}^{(b-1)}, & \text{en caso contrario}.
\end{cases}
\] Referencias:
MCMC using Hamiltonian dynamics: Disponible en arXiv. Este documento presenta los fundamentos teóricos del método y su aplicación en contextos de inferencia bayesiana.
Learning Hamiltonian Monte Carlo in R: Disponible en arXiv. Proporciona una introducción práctica al uso de HMC en R, con un enfoque en ejemplos y casos reales.
STAN Reference Manual: Disponible en STAN Documentation. Este manual describe en detalle la implementación de HMC en STAN, incluyendo configuraciones recomendadas y optimización de parámetros.
Se recomienda seleccionar los valores de \(\mathbf{M}\), \(\epsilon\) y \(L\) de forma que la tasa de aceptación se sitúe entre el 60 % y el 70 %.
Una configuración habitual es \(\mathbf{M} = \mathbf{I}\), \(\epsilon = 1 / L\) y \(L\) como un entero positivo (e.g., \(L = 10\)).
No es necesario almacenar los valores de \(\boldsymbol{\varphi}\), ya que su función es únicamente facilitar un desplazamiento eficiente en el espacio de parámetros.
# Reproducibilidad
set.seed(123)
# Algoritmo de Metropolis
beta <- rep(0, p) # valor inicial
acr <- 0 # tasa de aceptación
B <- 2100 # número de muestras
BETA <- matrix(NA, nrow = B, ncol = p) # almacenamiento
# Progreso
ncat <- floor(B / 10)
# Cadena
tictoc::tic()
for (b in 1:B) {
# 1. Propuesta
beta_p <- c(mvtnorm::rmvnorm(n = 1, mean = beta, sigma = Delta))
# 2. Tasa de aceptación (escala log)
eta_p <- as.numeric(X %*% beta_p) # predictor lineal propuesto
eta <- as.numeric(X %*% beta) # predictor lineal actual
log_post_star <- sum(dpois(x = y, lambda = exp(eta_p), log = TRUE)) +
sum(dnorm(x = beta_p, mean = beta0, sd = Sigma0, log = TRUE))
log_post_curr <- sum(dpois(x = y, lambda = exp(eta), log = TRUE)) +
sum(dnorm(x = beta, mean = beta0, sd = Sigma0, log = TRUE))
log_r <- log_post_star - log_post_curr
# 3) Actualizar
if (runif(1) < exp(log_r)) {
beta <- beta_p
acr <- acr + 1/B
}
# 4. Almacenar
BETA[b, ] <- beta
# 5. Progreso
if (b %% ncat == 0) {
cat(round(100 * b / B, 1), "% completado ...\n", sep = "")
}
}
## 10% completado ...
## 20% completado ...
## 30% completado ...
## 40% completado ...
## 50% completado ...
## 60% completado ...
## 70% completado ...
## 80% completado ...
## 90% completado ...
## 100% completado ...
## 0.151 sec elapsed
## [1] 52.6
# Gradiente
grad <- function(beta, y, X) {
out <- 0
for (i in 1:length(y)) {
eta <- sum(beta * X[i, ])
out <- out + (y[i] - exp(eta)) * X[i, ]
}
return(out)
}
# Reproducibilidad
set.seed(123)
# Algoritmo de Metropolis
beta <- rep(0, p) # valor inicial
acr <- 0 # tasa de aceptación
B <- 2100 # número de muestras
BETA2 <- matrix(NA, nrow = B, ncol = p) # almacenamiento
# Cadena
tictoc::tic()
for (b in 1:B) {
# 1. Inicialización del impulso
phi <- c(mvtnorm::rmvnorm(1, mean = rep(0, p), sigma = diag(p)))
beta_p <- beta
phi_p <- phi
# 2. Integración Hamiltoniana
# Primer medio paso en phi
phi_p <- phi_p + 0.5 * eps * grad(beta_p, y, X)
# L pasos leapfrog
for (l in 1:L) {
# Paso completo en beta
beta_p <- beta_p + eps * phi_p
# Paso completo en phi (excepto al final)
if (l < L) {
phi_p <- phi_p + eps * grad(beta_p, y, X)
}
}
# Último medio paso en phi
phi_p <- phi_p + 0.5 * eps * grad(beta_p, y, X)
# 3. Cálculo de la tasa de aceptación (log-scale)
logr <- sum(dpois(y, lambda = exp(X %*% beta_p), log = TRUE)) -
sum(dpois(y, lambda = exp(X %*% beta), log = TRUE)) +
mvtnorm::dmvnorm(beta_p, mean = beta0, sigma = Sigma0, log = TRUE) -
mvtnorm::dmvnorm(beta, mean = beta0, sigma = Sigma0, log = TRUE) +
mvtnorm::dmvnorm(phi_p, log = TRUE) -
mvtnorm::dmvnorm(phi, log = TRUE)
# 3. Aceptación o rechazo
if (runif(1) < exp(logr)) {
beta <- beta_p
acr <- acr + 1/B
}
# 4. Almacenamiento
BETA2[b, ] <- beta
# 5. Progreso
if (b %% floor(B / 10) == 0) {
cat(100 * round(b / B, 1), "% completado ...\n", sep = "")
}
}
## 10% completado ...
## 20% completado ...
## 30% completado ...
## 40% completado ...
## 50% completado ...
## 60% completado ...
## 70% completado ...
## 80% completado ...
## 90% completado ...
## 100% completado ...
## 9.704 sec elapsed
## [1] 65
# Remover burn-in
burn <- 100
BETA <- BETA[-seq_len(burn), , drop = FALSE]
BETA2 <- BETA2[-seq_len(burn), , drop = FALSE]
# Parámetros de gráfico
par(mfrow = c(3, 2), mar = c(2.75, 2.75, 1.5, 0.5), mgp = c(1.7, 0.7, 0))
for (j in seq_len(p)) {
rango <- range(BETA[, j], BETA2[, j], na.rm = TRUE)
# Metropolis
plot(x = seq_len(nrow(BETA)), y = BETA[, j],
col = 2, type = "p", pch = 16, cex = 0.6,
ylim = rango, cex.axis = 0.9,
main = "Metropolis", xlab = "Iteración",
ylab = bquote(beta[.(j)]))
# HMC
plot(x = seq_len(nrow(BETA2)), y = BETA2[, j],
col = 4, type = "p", pch = 16, cex = 0.6,
ylim = rango, cex.axis = 0.9,
main = "Hamiltoniano", xlab = "Iteración",
ylab = bquote(beta[.(j)]))
}
# Tamaños efectivos (neff) y tabla comparativa
neff_metro <- round(coda::effectiveSize(BETA), 1) # vector por parámetro
neff_hmc <- round(coda::effectiveSize(BETA2), 1)
# Armar tabla
tab <- cbind("neff Metro" = neff_metro, "neff HMC" = neff_hmc)
# Nombres de las filas
rownames(tab) <- paste0("beta", seq_len(p))
# Mostrar
round(tab, 3)
## neff Metro neff HMC
## beta1 118.5 1176.3
## beta2 110.9 1154.9
## beta3 103.9 1137.9
Hoff, P. D. (2009). A First Course in Bayesian Statistical Methods. Springer New York.
Gelman, A., Carlin, J. B., Stern, H. S., Dunson, D. B., Vehtari, A., & Rubin, D. B. (2013). Bayesian Data Analysis (3rd ed.). Chapman & Hall/CRC.