Come funziona il bootstrap in R?


22

Ho esaminato il pacchetto di avvio in R e mentre ho trovato una serie di buoni primer su come usarlo, devo ancora trovare qualcosa che descriva esattamente cosa sta succedendo "dietro le quinte". Ad esempio, in questo esempio , la guida mostra come utilizzare i coefficienti di regressione standard come punto di partenza per una regressione bootstrap ma non spiega cosa sta effettivamente facendo la procedura bootstrap per derivare i coefficienti di regressione bootstrap. Sembra che stia accadendo una sorta di processo iterativo, ma non riesco a capire esattamente cosa stia succedendo.


3
È passato molto tempo dall'ultima volta che l'ho aperto, quindi non so se risponderà alla tua domanda, ma il pacchetto di avvio si basa in particolare sui metodi dettagliati in Davison, AC e Hinkley, DV (1997). Metodi Bootstrap e loro applicazione. Cambridge: Cambridge University Press. (Il riferimento è anche citato nel file della guida per il pacchetto di avvio .)
Gala

Risposte:


34

Esistono diversi "sapori" o forme del bootstrap (ad es. Non parametrico, parametrico, ricampionamento residuo e molti altri). Il bootstrap nell'esempio è chiamato bootstrap non parametrico o ricampionamento dei casi (vedere qui , qui , qui e qui per le applicazioni in regressione). L'idea di base è che tratti il ​​tuo campione come popolazione e ne prelevi ripetutamente nuovi campioni con la sostituzione . Tutte le osservazioni originali hanno la stessa probabilità di essere disegnate nel nuovo campione. Quindi calcoli e memorizzi le statistiche di interesse, questa potrebbe essere la media, la mediana o i coefficienti di regressione usando il campione appena disegnato. Questo è ripetuto volte. In ogni iterazione, alcune osservazioni del campione originale vengono disegnate più volte mentre alcune osservazioni potrebbero non essere affatto disegnate. Dopo iterazioni, avete memorizzate le stime bootstrap della statistica (s) di interesse (ad esempio, se e la statistica di interesse è la media, si dispone di 1000 le stime bootstrap della media). Infine, vengono calcolate statistiche riassuntive come la media, la mediana e la deviazione standard delle stime bootstrap.nnnn=1000n

Il bootstrap viene spesso utilizzato per:

  1. Calcolo degli intervalli di confidenza (e stima degli errori standard)
  2. Stima della distorsione delle stime puntuali

Esistono diversi metodi per calcolare gli intervalli di confidenza in base ai campioni bootstrap ( questo documento fornisce spiegazioni e indicazioni). Un metodo molto semplice per calcolare un intervallo di confidenza del 95% è solo il calcolo dei 2,5 e 97,5 percentili empirici dei campioni bootstrap (questo intervallo è chiamato intervallo percentile bootstrap; vedere il codice sotto). Il metodo dell'intervallo percentile semplice viene raramente utilizzato in pratica poiché esistono metodi migliori, come il bootstrap con correzione di polarizzazione e accelerazione (BCa). Gli intervalli BCa si adattano sia al bias che all'asimmetria nella distribuzione bootstrap.

Il bias viene semplicemente stimato come la differenza tra la media degli campioni bootstrap memorizzati e le stime originali.n

Repliciamo l'esempio dal sito Web ma utilizzando il nostro loop incorporando le idee che ho delineato sopra (disegnando ripetutamente con la sostituzione):

#-----------------------------------------------------------------------------
# Load packages
#-----------------------------------------------------------------------------

require(ggplot2)
require(pscl)
require(MASS)
require(boot)

#-----------------------------------------------------------------------------
# Load data
#-----------------------------------------------------------------------------

zinb <- read.csv("http://www.ats.ucla.edu/stat/data/fish.csv")
zinb <- within(zinb, {
  nofish <- factor(nofish)
  livebait <- factor(livebait)
  camper <- factor(camper)
})

#-----------------------------------------------------------------------------
# Calculate zero-inflated regression
#-----------------------------------------------------------------------------

m1 <- zeroinfl(count ~ child + camper | persons, data = zinb,
               dist = "negbin", EM = TRUE)

#-----------------------------------------------------------------------------
# Store the original regression coefficients
#-----------------------------------------------------------------------------

original.estimates <- as.vector(t(do.call(rbind, coef(summary(m1)))[, 1:2]))

#-----------------------------------------------------------------------------
# Set the number of replications
#-----------------------------------------------------------------------------

n.sim <- 2000

#-----------------------------------------------------------------------------
# Set up a matrix to store the results
#-----------------------------------------------------------------------------

store.matrix <- matrix(NA, nrow=n.sim, ncol=12)

#-----------------------------------------------------------------------------
# The loop
#-----------------------------------------------------------------------------

set.seed(123)

for(i in 1:n.sim) {

  #-----------------------------------------------------------------------------
  # Draw the observations WITH replacement
  #-----------------------------------------------------------------------------

  data.new <- zinb[sample(1:dim(zinb)[1], dim(zinb)[1], replace=TRUE),]

  #-----------------------------------------------------------------------------
  # Calculate the model with this "new" data
  #-----------------------------------------------------------------------------

  m <- zeroinfl(count ~ child + camper | persons,
                data = data.new, dist = "negbin",
                start = list(count = c(1.3711, -1.5152, 0.879),
                             zero = c(1.6028, -1.6663)))

  #-----------------------------------------------------------------------------
  # Store the results
  #-----------------------------------------------------------------------------

  store.matrix[i, ] <- as.vector(t(do.call(rbind, coef(summary(m)))[, 1:2]))

}


#-----------------------------------------------------------------------------
# Save the means, medians and SDs of the bootstrapped statistics
#-----------------------------------------------------------------------------

boot.means <- colMeans(store.matrix, na.rm=T)

boot.medians <- apply(store.matrix,2,median, na.rm=T)

boot.sds <- apply(store.matrix,2,sd, na.rm=T)

#-----------------------------------------------------------------------------
# The bootstrap bias is the difference between the mean bootstrap estimates
# and the original estimates
#-----------------------------------------------------------------------------

boot.bias <- colMeans(store.matrix, na.rm=T) - original.estimates

#-----------------------------------------------------------------------------
# Basic bootstrap CIs based on the empirical quantiles
#-----------------------------------------------------------------------------

conf.mat <- matrix(apply(store.matrix, 2 ,quantile, c(0.025, 0.975), na.rm=T),
ncol=2, byrow=TRUE)
colnames(conf.mat) <- c("95%-CI Lower", "95%-CI Upper")

Ed ecco la nostra tabella riassuntiva:

#-----------------------------------------------------------------------------
# Set up summary data frame
#-----------------------------------------------------------------------------

summary.frame <- data.frame(mean=boot.means, median=boot.medians,
sd=boot.sds, bias=boot.bias, "CI_lower"=conf.mat[,1], "CI_upper"=conf.mat[,2])

summary.frame

      mean  median       sd       bias CI_lower CI_upper
1   1.2998  1.3013  0.39674 -0.0712912  0.51960   2.0605
2   0.2527  0.2486  0.03208 -0.0034461  0.19898   0.3229
3  -1.5662 -1.5572  0.26220 -0.0509239 -2.12900  -1.0920
4   0.2005  0.1986  0.01949  0.0049019  0.16744   0.2418
5   0.9544  0.9252  0.48915  0.0753405  0.03493   1.9025
6   0.2702  0.2688  0.02043  0.0009583  0.23272   0.3137
7  -0.8997 -0.9082  0.22174  0.0856793 -1.30664  -0.4380
8   0.1789  0.1781  0.01667  0.0029513  0.14494   0.2140
9   2.0683  1.7719  1.59102  0.4654898  0.44150   8.0471
10  4.0209  0.8270 13.23434  3.1845710  0.58114  57.6417
11 -2.0969 -1.6717  1.56311 -0.4306844 -8.43440  -1.1156
12  3.8660  0.6435 13.27525  3.1870642  0.33631  57.6062

Alcune spiegazioni

  • La differenza tra la media delle stime bootstrap e le stime originali è ciò che viene chiamato "bias" nell'output di boot
  • Qual è l'output delle bootchiamate "std. Error" è la deviazione standard delle stime avviate

Confrontalo con l'output di boot:

#-----------------------------------------------------------------------------
# Compare with boot output and confidence intervals
#-----------------------------------------------------------------------------

set.seed(10)
res <- boot(zinb, f, R = 2000, parallel = "snow", ncpus = 4)

res

Bootstrap Statistics :
       original       bias    std. error
t1*   1.3710504 -0.076735010  0.39842905
t2*   0.2561136 -0.003127401  0.03172301
t3*  -1.5152609 -0.064110745  0.26554358
t4*   0.1955916  0.005819378  0.01933571
t5*   0.8790522  0.083866901  0.49476780
t6*   0.2692734  0.001475496  0.01957823
t7*  -0.9853566  0.083186595  0.22384444
t8*   0.1759504  0.002507872  0.01648298
t9*   1.6031354  0.482973831  1.58603356
t10*  0.8365225  3.240981223 13.86307093
t11* -1.6665917 -0.453059768  1.55143344
t12*  0.6793077  3.247826469 13.90167954

perc.cis <- matrix(NA, nrow=dim(res$t)[2], ncol=2)
    for( i in 1:dim(res$t)[2] ) {
  perc.cis[i,] <- boot.ci(res, conf=0.95, type="perc", index=i)$percent[4:5] 
}
colnames(perc.cis) <- c("95%-CI Lower", "95%-CI Upper")

perc.cis 

      95%-CI Lower 95%-CI Upper
 [1,]      0.52240       2.1035
 [2,]      0.19984       0.3220
 [3,]     -2.12820      -1.1012
 [4,]      0.16754       0.2430
 [5,]      0.04817       1.9084
 [6,]      0.23401       0.3124
 [7,]     -1.29964      -0.4314
 [8,]      0.14517       0.2149
 [9,]      0.29993       8.0463
[10,]      0.57248      56.6710
[11,]     -8.64798      -1.1088
[12,]      0.33048      56.6702

#-----------------------------------------------------------------------------
# Our summary table
#-----------------------------------------------------------------------------

summary.frame

      mean  median       sd       bias CI_lower CI_upper
1   1.2998  1.3013  0.39674 -0.0712912  0.51960   2.0605
2   0.2527  0.2486  0.03208 -0.0034461  0.19898   0.3229
3  -1.5662 -1.5572  0.26220 -0.0509239 -2.12900  -1.0920
4   0.2005  0.1986  0.01949  0.0049019  0.16744   0.2418
5   0.9544  0.9252  0.48915  0.0753405  0.03493   1.9025
6   0.2702  0.2688  0.02043  0.0009583  0.23272   0.3137
7  -0.8997 -0.9082  0.22174  0.0856793 -1.30664  -0.4380
8   0.1789  0.1781  0.01667  0.0029513  0.14494   0.2140
9   2.0683  1.7719  1.59102  0.4654898  0.44150   8.0471
10  4.0209  0.8270 13.23434  3.1845710  0.58114  57.6417
11 -2.0969 -1.6717  1.56311 -0.4306844 -8.43440  -1.1156
12  3.8660  0.6435 13.27525  3.1870642  0.33631  57.6062

Confronta le colonne "bias" e "std. Error" con la colonna "sd" della nostra tabella di riepilogo. I nostri intervalli di confidenza al 95% sono molto simili agli intervalli di confidenza calcolati boot.ciusando il metodo percentile (non tutti però: guarda il limite inferiore del parametro con indice 9).


Grazie per la risposta dettagliata. In pratica stai dicendo che i coefficienti sono la media dei 2000 set di coefficienti che sono stati generati?
zgall1,

4
t

"L'idea di base è che tratti il ​​tuo campione come popolazione e ne prelevi ripetutamente nuovi campioni con la sostituzione" - come determinare quale è la dimensione dei nuovi campioni?
Sinusx,

1
@Sinusx Normalmente, si disegnano campioni della stessa dimensione del campione originale. L'idea cruciale è di disegnare il campione con la sostituzione. Quindi alcuni valori dell'esempio originale verranno disegnati più volte e alcuni valori per niente.
COOLSerdash

6

Dovresti concentrarti sulla funzione che viene passata bootcome parametro "statistico" e notare come è costruita.

f <- function(data, i) {
  require(pscl)
  m <- zeroinfl(count ~ child + camper | persons,
    data = data[i, ], dist = "negbin",
    start = list(count = c(1.3711, -1.5152, 0.879), zero = c(1.6028, -1.6663)))
  as.vector(t(do.call(rbind, coef(summary(m)))[, 1:2]))
}

L'argomento "data" riceverà un intero frame di dati, ma l'argomento "i" riceverà un campione di indici di riga generati dal "boot" e presi da 1: NROW (data). Come puoi vedere da quel codice, "i" viene quindi usato per creare un neo-campione che viene passato zeroinle quindi vengono restituite solo parti selezionate dei suoi risultati.

Immaginiamo che "i" sia {1,2,3,3,3,6,7,7,10}. La funzione "[" restituirà solo quelle righe con 3 copie della riga 3 e 2 copie della riga 7. Questa sarebbe la base per un singolo zeroinl()calcolo e quindi i coefficienti verranno restituiti bootcome risultato da quella replica del processo. Il numero di tali replicati è controllato dal parametro "R".

Poiché statisticin questo caso vengono restituiti solo i coefficienti di regressione , la bootfunzione restituirà questi coefficienti accumulati come valore di "t". Ulteriori confronti possono essere eseguiti da altre funzioni del pacchetto di avvio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.