9.3 Bootstrap suavizado
Cuando la distribución poblacional, \(F\), es continua es lógico incorporar dicha información al bootstrap. Eso significa que la función de distribución tiene una función de densidad asociada, relacionadas mediante la expresión: \(f(x) =F^{\prime}(x)\). Una forma de remuestrear de un universo bootstrap continuo es emplear un estimador de la función de densidad, como por ejemplo el estimador no paramétrico tipo núcleo, y remuestrear de él.
Si \(\left( X_1, X_2, \ldots, X_n \right)\) es una muestra aleatoria simple (m.a.s.), de una población con función de distribución \(F\), absolutamente continua, y función de densidad \(f\), el estimador tipo núcleo propuesto por Parzen (1962) y Rosenblatt (1956) viene dado por \[\hat{f}_{h}\left( x \right) =\frac{1}{nh}\sum_{i=1}^{n}K\left( \frac{x-X_i}{h} \right) =\frac{1}{n}\sum_{i=1}^{n}K_{h}\left( x-X_i \right),\] donde \(K_{h}\left( u \right) =\frac{1}{h}K\left( \frac{u}{h} \right)\), \(K\) es una función núcleo (normalmente una densidad simétrica en torno al cero) y \(h>0\) es una parámetro de suavizado, llamado ventana, que regula el tamaño del entorno que se usa para llevar a cabo la estimación.
Es habitual seleccionar una función núcleo \(K\) no negativa y con integral uno: \[K\left( u \right) \geq 0,~\forall u,~\int_{-\infty }^{\infty } K\left( u \right) du=1\] (i.e. una función de densidad). Además, frecuentemente \(K\) es una función simétrica (\(K\left( -u \right) =K\left( u \right)\)). Aunque la elección de esta función no tiene gran impacto en las propiedades del estimador (salvo sus condiciones de regularidad: continuidad, diferenciabilidad, etc.) la elección del parámetro de suavizado sí es muy importante para una correcta estimación. En otras palabras, el tamaño del entorno usado para la estimación no paramétrica debe ser adecuado (ni demasiado grande ni demasiado pequeño).
En R
podemos emplear la función density()
del paquete base para obtener
una estimación tipo núcleo de la densidad.
Los principales parámetros (con los valores por defecto) son los siguientes:
density(x, bw = "nrd0", adjust = 1, kernel = "gaussian", n = 512, from, to)
bw
: ventana, puede ser un valor numérico o una cadena de texto que la determine (en ese caso llamará internamente a la funciónbw.xxx()
dondexxx
se corresponde con la cadena de texto). Las opciones son:"nrd0"
,"nrd"
: Reglas del pulgar de Silverman (1986, page 48, eqn (3.31)) y Scott (1992), respectivamente. Como es de esperar que la densidad objetivo no sea tan suave como la normal, estos criterios tenderán a seleccionar ventanas que producen un sobresuavizado de las observaciones."ucv"
,"bcv"
: Métodos de validación cruzada insesgada y sesgada, respectivamente."sj"
,"sj-ste"
,"sj-dpi"
: Métodos de Sheather y Jones (1991), “solve-the-equation” y “direct plug-in,” respectivamente.
adjust
: parameto para reescalado de la ventana, las estimaciones se calculan con la ventanaadjust*bw
.kernel
: cadena de texto que determina la función núcleo, las opciones son:"gaussian"
,"epanechnikov"
,"rectangular"
,"triangular"
,"biweight"
,"cosine"
y"optcosine"
.n
,from
,to
: permiten establecer la rejilla en la que se obtendrán las estimaciones (si \(n>512\) se empleafft()
por lo que se recomienda establecern
a un múltiplo de 2; por defectofrom
yto
se establecen comocut = 3
veces la ventana desde los extremos de las observaciones).
Como ejemplo consideraremos el conjunto de datos precip
, que contiene el promedio de precipitación,
en pulgadas de lluvia, de 70 ciudades de Estados Unidos.
<- precip
x <- bw.SJ(x)
h <- density(x, bw = h)
npden # npden <- density(x, bw = "SJ")
# h <- npden$bw
# plot(npden)
hist(x, freq = FALSE, breaks = "FD", main = "Kernel density estimation",
xlab = paste("Bandwidth =", formatC(h)), border = "darkgray",
xlim = c(0, 80), ylim = c(0, 0.04))
lines(npden, lwd = 2)
rug(x, col = "darkgray")
Alternativamente podríamos emplear implementaciones en otros paquetes de R
.
Uno de los más empleados es ks
(Duong, 2019), que admite estimación incondicional y condicional multidimensional.
También se podrían emplear los paquetes KernSmooth
(Wand y Ripley, 2019), sm
(Bowman y Azzalini, 2019), np
(Tristen y Jeffrey, 2019), kedd
(Guidoum, 2019), features
(Duong y Matt, 2019) y npsp
(Fernández-Casal, 2019), entre otros.
La función de distribución asociada al estimador tipo núcleo de la función de densidad viene dada por \[\begin{aligned} \hat{F}_{h}\left( x \right) &= \int_{-\infty }^{x}\hat{f}_{h}\left( y \right) dy =\int_{-\infty }^{x}\frac{1}{n}\sum_{i=1}^{n}\frac{1}{h} K\left( \frac{y-X_i}{h} \right) dy \\ &= \frac{1}{nh}\sum_{i=1}^{n}\int_{-\infty }^{x} K\left( \frac{y-X_i}{h} \right) dy \\ &= \frac{1}{n}\sum_{i=1}^{n}\int_{-\infty }^{\frac{x-X_i}{h}}K\left( u \right) du =\frac{1}{n}\sum_{i=1}^{n}\mathbb{K}\left( \frac{x-X_i}{h} \right) \end{aligned}\] donde \(\mathbb{K}\) es la función de distribución asociada al núcleo \(K\), es decir \[\mathbb{K}\left( t \right) =\int_{-\infty }^{t}K\left(u \right) du.\]
Por ejemplo, en el caso de del conjunto de datos de precipitaciones, el siguiente código compara la estimación tipo núcleo de la distribución con la empírica:
<- ecdf(precip)
Fn curve(Fn, xlim = c(0, 75), ylab = "F(x)", type = "s")
<- function(x) sapply(x, function(y) mean(pnorm(y, precip, h)))
Fnp curve(Fnp, lty = 2, add = TRUE)
legend("bottomright", legend = c("Empírica", "Tipo núcleo"), lty = 1:2)
Tendiendo en cuenta que el estimador \(\hat{f}_{h}\left( x \right)\) es una combinación lineal convexa de funciones de densidad, \(K_{h}\left(x-X_i \right)\), con pesos \(\frac{1}{n}\), podemos simular valores \(X^{\ast}\), procedentes de esta distribución empleando el método de composición descrito en la Sección 4.4. El primer paso consistiría en elegir (aleatoriamente y con equiprobabilidad) un índice \(i\in \left\{ 1,\ldots ,n\right\}\), y posteriormente simular \(X^{\ast}\) a partir de la densidad \(K_{h}\left(\cdot -X_i \right)\). Este último paso puede realizarse simulando un valor \(V\) con densidad \(K\) y haciendo \(X_i+hV\). Por tanto, podemos pensar que el bootstrap suavizado parte del bootstrap uniforme (\(X_i^{\ast}=X_{\left\lfloor nU_i\right\rfloor +1}\)) y añade una perturbación (\(hV_i\)), cuya magnitud viene dada por el parámetro de suavizado (\(h\)) y cuya forma imita a la de una variable aleatoria (\(V_i\)) con densidad \(K\).
Por ejemplo, la función density()
emplea por defecto un núcleo gaussiano, y como se muestra en la ayuda de esta función, podemos emplear un código como el siguiente para obtener nsim
simulaciones(ver Figura 9.6):
## simulation from a density() fit:
# a kernel density fit is an equally-weighted mixture.
<- 1e6
nsim set.seed(1)
# x_boot <- sample(x, nsim, replace = TRUE)
# x_boot <- x_boot + bandwidth * rnorm(nsim)
<- rnorm(nsim, sample(x, nsim, replace = TRUE), h)
x_boot # Representar
plot(npden, main = "")
lines(density(x_boot), col = "blue", lwd = 2, lty = 2)
En el boostrap suavizado, la distribución de una observación \(X_i^{\ast}\) de la remuestra bootstrap es continua (puede tomar infinitos valores), mientras que en el bootstrap uniforme es discreta. De esta forma se pueden evitar algunos de los problemas del bootstrap uniforme, como los descritos en la Sección 9.1. Un problema importante es la elección del parámetro de suavizado, \(h\), en este procedimiento de remuestreo. En la práctica es razonable elegir \(h\) como un valor bastante pequeño, en relación con la desviación típica de la muestra. Es fácil observar que en el caso extremo \(h=0\) este método de remuestreo se reduce al bootstrap uniforme.
Ejemplo 9.4 (Inferencia sobre la media, continuación)
Continuando con el Ejemplo 8.2 del tiempo de vida de microorganismos, podríamos pensar en emplear bootstrap suavizado para calcular un intervalo de confianza para la media poblacional.
<- simres::lifetimes
muestra <- length(muestra)
n <- 0.05
alfa # Estimaciones muestrales
<- mean(muestra)
x_barra <- sd(muestra)
cuasi_dt # Remuestreo
set.seed(1)
<- 1000
B # h <- 1e-08
# h <- 0.05*cuasi_dt
<- bw.SJ(muestra)/2
h <- numeric(B)
estadistico_boot for (k in 1:B) {
# remuestra <- sample(muestra, n, replace = TRUE)
# remuestra <- rexp(n, 1/x_barra)
<- rnorm(n, sample(muestra, n, replace = TRUE), h)
remuestra <- mean(remuestra)
x_barra_boot <- sd(remuestra)
cuasi_dt_boot <- sqrt(n) * (x_barra_boot - x_barra)/cuasi_dt_boot
estadistico_boot[k]
}# Aproximación Monte Carlo de los ptos críticos:
<- quantile(estadistico_boot, c(alfa/2, 1 - alfa/2))
pto_crit # Construcción del IC
<- x_barra - pto_crit[2] * cuasi_dt/sqrt(n)
ic_inf_boot <- x_barra - pto_crit[1] * cuasi_dt/sqrt(n)
ic_sup_boot <- c(ic_inf_boot, ic_sup_boot)
IC_boot names(IC_boot) <- paste0(100*c(alfa/2, 1-alfa/2), "%")
IC_boot
## 2.5% 97.5%
## 0.4960975 1.1880279
Con el paquete boot
, la recomendación es implementarlo como
un bootstrap paramétrico:
library(boot)
<- function(data, mle) {
ran.gen.smooth # Función para generar muestras aleatorias mediante
# bootstrap suavizado con función núcleo gaussiana,
# mle contendrá la ventana.
<- length(data)
n <- mle
h <- rnorm(n, sample(data, n, replace = TRUE), h)
out
out
}
<- function(data){
statistic c(mean(data), var(data)/length(data))
}
set.seed(1)
<- boot(muestra, statistic, R = B, sim = "parametric",
res.boot ran.gen = ran.gen.smooth, mle = h)
boot.ci(res.boot, type = "stud")
## BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
## Based on 1000 bootstrap replicates
##
## CALL :
## boot.ci(boot.out = res.boot, type = "stud")
##
## Intervals :
## Level Studentized
## 95% ( 0.4960, 1.1927 )
## Calculations and Intervals on Original Scale
En el Capítulo 6 de Cao y Fernández-Casal (2022) se describen métodos bootstrap diseñados específicamente para hacer inferencia sobre la densidad empleando el estimador no paramétrico tipo núcleo (i.e. empleando bootstrap suavizado), como la construcción de intervalos de confianza o la selección del parámetro de suavizado.