3.3 El problema de la dependencia
En el caso de dependencia, bajo condiciones muy generales se verifica la ley débil de los grandes números. Sin embargo, la estimación de la precisión se complica: \[Var\left( \overline{X}\right) =\frac{1}{n^{2}}\left( \sum_{i=1}^{n}Var\left( X_{i} \right) + 2\sum_{i<j}Cov\left( X_{i},X_{j}\right) \right).\]
Ejemplo 3.3 (aproximación de una proporción bajo dependencia cadena de Markov)
Supongamos que en A Coruña llueve de media uno de cada tres días al año, y que la probabilidad de que un día llueva solo depende de lo que ocurrió el día anterior, siendo 0.94 si el día anterior llovió y 0.03 si no.
Podemos generar valores de la variable indicadora de día lluvioso con el siguiente código:
# Variable dicotómica 0/1 (FALSE/TRUE)
set.seed(1)
<- 10000
nsim <- 0.03 # prob de cambio si seco
alpha <- 0.06 # prob de cambio si lluvia
beta <- logical(nsim) # x == "llueve"
rx 1] <- FALSE # El primer día no llueve
rx[for (i in 2:nsim)
<- if (rx[i-1]) runif(1) > beta else runif(1) < alpha rx[i]
Si generamos el gráfico de convergencia asumiendo independencia:
<- 1:nsim
n <- cumsum(rx)/n
est <- sqrt(est*(1-est)/(n-1)) # OJO! Supone independencia
esterr plot(est, type="l", lwd=2, ylab="Probabilidad",
xlab="Número de simulaciones", ylim=c(0,0.6))
abline(h = est[nsim], lty=2)
lines(est + 2*esterr, lty=2)
lines(est - 2*esterr, lty=2)
abline(h = 1/3, col="darkgray") # Probabilidad teórica
La probabilidad teórica, obtenida empleando resultados de cadenas de Markov, es \(p = 1/3\) y la aproximación de la proporción sería correcta (es consistente):
est[nsim]
## [1] 0.3038
Sin embargo, al ser datos dependientes, la aproximación anterior del error estándar no es adecuada:
esterr[nsim]
## [1] 0.004599203
En este caso al haber dependencia positiva se produce una subestimación del verdadero error estándar. Podemos generar el gráfico de autocorrelaciones:
acf(as.numeric(rx))
El gráfico anterior sugiere que si solo tomamos 1 de cada 25 valores podría ser razonable asumir independencia.
<- 24
lag <- c(rep(FALSE, lag), TRUE)
xlag <- rx[xlag]
rxi acf(as.numeric(rxi))
<- length(rxi)
nrxi <- 1:nrxi
n <- cumsum(rxi)/n
est <- sqrt(est*(1-est)/(n-1))
esterr plot(est, type="l", lwd=2, ylab="Probabilidad",
xlab=paste("Número de simulaciones /", lag + 1), ylim=c(0,0.6))
abline(h = est[length(rxi)], lty=2)
lines(est + 2*esterr, lty=2) # Supone independencia
lines(est - 2*esterr, lty=2)
abline(h = 1/3, col="darkgray") # Prob. teor. cadenas Markov
Esta forma de proceder podría ser adecuada para tratar de aproximar la precisión:
esterr[nrxi]
## [1] 0.02277402
pero no sería la más eficiente para aproximar la media. Siempre es preferible emplear todas las observaciones.
Por ejemplo, se podría pensar en considerar las medias de grupos de 25 valores consecutivos y suponer que hay independencia entre ellas:
<- rowMeans(matrix(rx, ncol = lag + 1, byrow = TRUE))
rxm <- length(rxm)
nrxm <- 1:nrxm
n <- cumsum(rxm)/n
est <- sqrt((cumsum(rxm^2)/n - est^2)/(n-1)) # Errores estándar
esterr plot(est, type="l", lwd=2, ylab="Probabilidad",
xlab=paste("Número de simulaciones /", lag + 1), ylim=c(0,0.6))
abline(h = est[length(rxm)], lty=2)
lines(est + 2*esterr, lty=2) # OJO! Supone independencia
lines(est - 2*esterr, lty=2)
abline(h = 1/3, col="darkgray") # Prob. teor. cadenas Markov
Esta es la idea del método de medias por lotes (batch means; macro-micro replicaciones) para la estimación de la precisión. Supongamos que la correlación entre \(X_i\) y \(X_{i+k}\) es aproximadamente nula, y consideramos las subsecuencias (lotes) \((X_{t+1},X_{t+2},\ldots,X_{t+k})\) con \(t=(j-1)k\), \(j=1,\ldots,m\) y \(n = mk\). Entonces:
\[\begin{aligned} Var \left(\bar X \right) &= Var \left(\frac{1}{n} \sum_{i=1}^n X_i\right) = Var \left( \frac{1}{m}\sum_{j=1}^m \left(\frac{1}{k} \sum_{t=(i-1)k + 1}^{ik} X_t\right) \right) \\ &\approx \frac{1}{m^2} \sum_{j=1}^m Var \left(\frac{1}{k} \sum_{t=(i-1)k + 1}^{ik} X_t\right) = \frac{1}{m} Var \left(\bar{X}_k \right) \end{aligned}\] donde \(\bar{X}_k\) es la media de una subsecuencia de longitud \(k\).
Alternativamente se podría recurrir a la generación de múltiples secuencias independientes entre sí:
# Variable dicotómica 0/1 (FALSE/TRUE)
set.seed(1)
<- 1000
nsim <- 10
nsec <- 0.03 # prob de cambio si seco
alpha <- 0.06 # prob de cambio si lluvia
beta <- matrix(FALSE, nrow = nsec, ncol= nsim)
rxm for (i in 1:nsec) {
# rxm[i, 1] <- FALSE # El primer día no llueve
# rxm[i, 1] <- runif(1) < 1/2 # El primer día llueve con probabilidad 1/2
1] <- runif(1) < 1/3 # El primer día llueve con probabilidad 1/3 (ideal)
rxm[i, for (j in 2:nsim)
<- if (rxm[i, j-1]) runif(1) > beta else runif(1) < alpha
rxm[i, j] }
La idea sería considerar las medias de las series como una muestra independiente de una nueva variable y estimar su varianza de la forma habitual:
# Media de cada secuencia
<- 1:nsim
n <- apply(rxm, 1, function(x) cumsum(x)/n)
est matplot(n, est, type = 'l', lty = 3, col = "lightgray",
ylab="Probabilidad", xlab="Número de simulaciones")
# Aproximación
<- apply(est, 1, mean)
mest lines(mest, lwd = 2)
abline(h = mest[nsim], lty = 2)
# Precisión
<- apply(est, 1, sd)/sqrt(nsec)
mesterr lines(mest + 2*mesterr, lty = 2)
lines(mest - 2*mesterr, lty = 2)
# Prob. teor. cadenas Markov
abline(h = 1/3, col="darkgray")
# Aproximación final
# mean(rxm) mest[nsim]
## [1] 0.3089
# Error estándar
mesterr[nsim]
## [1] 0.02403491
Trataremos este tipo de problemas en la diagnosis de algoritmos Monte Carlo de Cadenas de Markov (MCMC, Capítulo 10). Aparecen también en la simulación dinámica (por eventos o cuantos).
3.3.1 Periodo de calentamiento
En el caso de simulación de datos dependientes (simulación dinámica) pueden aparecer problemas de estabilización. Puede ocurrir que el sistema evolucione lentamente en el tiempo hasta alcanzar su distribución estacionaria, siendo muy sensible a las condiciones iniciales con las que se comienzó la simulación. En tal caso resulta conveniente ignorar los resultados obtenidos durante un cierto período inicial de tiempo (denominado período de calentamiento o estabilización), cuyo único objeto es conseguir que se estabilice la distribución de probabilidad.
Como ejemplo comparamos la simulación del Ejemplo 3.3 con la obtenida considerando como punto de partida un día lluvioso (con una semilla distinta para evitar dependencia).
set.seed(2)
<- 10000
nsim <- logical(nsim)
rx2 1] <- TRUE # El primer día llueve
rx2[for (i in 2:nsim)
<- if (rx2[i-1]) runif(1) > beta else runif(1) < alpha
rx2[i] <- 1:nsim
n <- cumsum(rx)/n
est <- cumsum(rx2)/n
est2 plot(est, type="l", ylab="Probabilidad",
xlab="Número de simulaciones", ylim=c(0,0.6))
lines(est2, lty = 2)
# Ejemplo periodo calentamiento nburn = 2000
abline(v = 2000, lty = 3)
# Prob. teor. cadenas Markov
abline(h = 1/3, col="darkgray")
En estos casos puede ser recomendable ignorar los primeros valores generados (por ejemplo los primeros 2000) y recalcular los estadísticos deseados.
También trataremos este tipo de problemas en la diagnosis de algoritmos MCMC.
Ejemplo 3.4 (simulación de un proceso autorregresivo serie de tiempo)
\[X_t = \mu + \rho * (X_{t-1} - \mu) + \varepsilon_t\] Podemos tener en cuenta que en este caso la varianza es: \[\textrm{var}(X_t)=\operatorname{E}(X_t^2)-\mu^2=\frac{\sigma_\varepsilon^2}{1-\rho^2}.\]
Establecemos los parámetros:
<- 200 # Numero de simulaciones
nsim <- 0 # Media
xmed <- 0.5 # Coeficiente AR
rho <- 10 # Periodo de calentamiento (burn-in) nburn
Se podría fijar la varianza del error:
<- 1
evar # Varianza de la respuesta
<- evar / (1 - rho^2) xvar
pero la recomendación sería fijar la varianza de la respuesta:
<- 1
xvar # Varianza del error
<- xvar*(1 - rho^2) evar
Para simular la serie, al ser un \(AR(1)\), normalmente simularíamos el primer valor
1] <- rnorm(1, mean = xmed, sd = sqrt(xvar)) x[
o lo fijamos a la media. Después generamos los siguientes valores de forma recursiva.
Como ejemplo nos alejamos un poco de la distribución estacionaria, para que el “periodo de calentamiento” sea mayor:
set.seed(1)
<- numeric(nsim + nburn)
x # Establecer el primer valor
1] <- -10
x[# Simular el resto de la secuencia
for (i in 2:length(x))
<- xmed + rho*(x[i-1] - xmed) + rnorm(1, sd=sqrt(evar))
x[i] <- as.ts(x)
x plot(x)
abline(v = nburn, lty = 2)
y eliminamos el periodo de calentamiento:
<- x[-seq_len(nburn)] rx
Para simular una serie de tiempo en R se puede emplear la función arima.sim
del paquete base stats
.
En este caso el periodo de calentamiento se establece mediante el parámetro n.start
(que se fija automáticamente a un valor adecuado).
Por ejemplo, podemos generar este serie autoregresiva con:
<- arima.sim(list(order = c(1,0,0), ar = rho), n = nsim,
rx2 n.start = nburn, sd = sqrt(evar))
La recomendación es fijar la varianza de las series simuladas si se quieren comparar resultados considerando distintos parámetros de dependencia.