Como o bootstrapping no R realmente funciona?

22

Eu estive pesquisando o pacote de inicialização no R e, embora tenha encontrado uma série de boas instruções sobre como usá-lo, ainda não encontrei nada que descreva exatamente o que está acontecendo "nos bastidores". Por exemplo, neste exemplo , o guia mostra como usar os coeficientes de regressão padrão como ponto de partida para uma regressão de inicialização, mas não explica o que o procedimento de inicialização está realmente fazendo para derivar os coeficientes de regressão de inicialização. Parece que está acontecendo algum tipo de processo iterativo, mas não consigo descobrir exatamente o que está acontecendo.

zgall1
fonte
3
Faz muito tempo que eu o abri pela última vez, então não sei se ele responderá à sua pergunta, mas o pacote de inicialização é baseado principalmente nos métodos detalhados em Davison, AC e Hinkley, DV (1997). Métodos de inicialização e sua aplicação. Cambridge: Cambridge University Press. (A referência também é citado no arquivo de ajuda para o arranque pacote.)
Gala

Respostas:

34

Existem vários "sabores" ou formas do bootstrap (por exemplo, reamostragem não paramétrica, paramétrica, residual e muito mais). O bootstrap no exemplo é chamado de bootstrap não paramétrico ou reamostragem de caso (veja aqui , aqui , aqui e aqui para aplicativos em regressão). A idéia básica é que você trate sua amostra como população e extraia repetidamente novas amostras com substituição . Todas as observações originais têm igual probabilidade de serem incluídas na nova amostra. Depois, você calcula e armazena as estatísticas de interesse, que podem ser a média, a mediana ou os coeficientes de regressão usando a amostra recém-desenhada. Isso é repetido vezes. Em cada iteração, algumas observações da amostra original são desenhadas várias vezes, enquanto outras podem não ser desenhadas. Após n iterações, você n armazenou estimativas de inicialização das estatísticas de interesse (por exemplo, se n = 1000 e a estatística de interesse for a média, você terá 1000 estimativas de média de inicialização). Por fim, são calculadas estatísticas resumidas, como média, mediana e desvio padrão das n estimativas de autoinicialização.nnnn=1000n

O bootstrapping é frequentemente usado para:

  1. Cálculo dos intervalos de confiança (e estimativa dos erros padrão)
  2. Estimação do viés das estimativas pontuais

Existem vários métodos para calcular intervalos de confiança com base nas amostras de bootstrap ( este artigo fornece explicações e orientações). Um método muito simples para calcular um intervalo de confiança de 95% é apenas o cálculo dos percentis empírico 2,5 e 97,5º das amostras de bootstrap (esse intervalo é chamado de intervalo de percentil de bootstrap; consulte o código abaixo). O método simples de intervalo percentil é raramente usado na prática, pois existem métodos melhores, como o bootstrap com correção de bias e aceleração (BCa). Os intervalos BCa se ajustam tanto ao viés quanto à assimetria na distribuição do bootstrap.

n amostras de bootstrap armazenadas e as estimativas originais.

Vamos replicar o exemplo do site, mas usando nosso próprio loop incorporando as idéias que descrevi acima (desenhando repetidamente com a substituição):

#-----------------------------------------------------------------------------
# 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")

E aqui está a nossa tabela de resumo:

#-----------------------------------------------------------------------------
# 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

Algumas explicações

  • A diferença entre a média das estimativas de autoinicialização e as estimativas originais é o que é chamado de "viés" na saída de boot
  • Qual é o resultado das bootchamadas "erro padrão" é o desvio padrão das estimativas inicializadas

Compare-o com a saída de 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

Compare as colunas "viés" e o "erro padrão" com a coluna "sd" da nossa própria tabela de resumo. Nossos intervalos de confiança de 95% são muito semelhantes aos intervalos de confiança calculados boot.ciusando o método de percentil (embora nem todos: observe o limite inferior do parâmetro com o índice 9).

COOLSerdash
fonte
Obrigado pela resposta detalhada. Você está basicamente dizendo que os coeficientes são a média dos 2000 conjuntos de coeficientes gerados?
precisa saber é o seguinte
4
t
'A idéia básica é que você trate sua amostra como população e extraia repetidamente novas amostras com reposição' - como determinar qual é o tamanho das novas amostras?
Sinusx
1
@ Sinusx Normalmente, você desenha amostras do mesmo tamanho da amostra original. A idéia crucial é desenhar a amostra com substituição. Portanto, alguns valores da amostra original serão desenhados várias vezes e outros nem um pouco.
precisa saber é o seguinte
6

Você deve se concentrar na função que é passada bootcomo o parâmetro "estatística" e observe como ela é construída.

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]))
}

O argumento "dados" receberá um quadro de dados inteiro, mas o argumento "i" receberá uma amostra dos índices de linha gerados pela "inicialização" e extraídos de 1: NROW (dados). Como você pode ver nesse código, "i" é usado para criar uma neo-amostra que é passada parazeroinl e, em seguida, somente partes selecionadas dos resultados são retornadas.

Vamos imaginar que "i" seja {1,2,3,3,3,6,7,7,10}. A função "[" retornará apenas as linhas com 3 cópias da linha 3 e 2 cópias da linha 7. Essa seria a base para um único zeroinl()cálculo e, em seguida, os coeficientes serão retornados paraboot como resultado dessa replicação do processo. O número de tais réplicas é controlado pelo parâmetro "R".

Como somente os coeficientes de regressão são retornados statisticnesse caso, a bootfunção retornará esses coeficientes acumulados como o valor de "t". Comparações adicionais podem ser realizadas por outras funções do pacote de inicialização.

DWin
fonte