tl;dr:从在 null 下生成的数据集开始,我对带有替换的案例进行了重新采样,并对每个重新采样的数据集进行了假设检验。这些假设检验在超过 5% 的时间内拒绝零。
在下面非常简单的模拟中,我使用生成数据集,并为每个数据集拟合一个简单的 OLS 模型。然后,对于每个数据集,我通过使用替换对原始数据集的行进行重新采样来生成 1000 个新数据集(Davison & Hinkley 的经典文本中专门描述的适用于线性回归的算法)。对于其中的每一个,我都适合相同的 OLS 模型。最终,bootstrap 样本中大约 16% 的假设检验拒绝了 null,而我们应该得到 5%(就像我们在原始数据集中所做的那样)。
我怀疑这与重复观察导致关联膨胀有关,因此为了比较,我在下面的代码中尝试了其他两种方法(已注释掉)。在方法 2 中,我修复 ,然后将替换为原始数据集上 OLS 模型的重采样残差。在方法 3 中,我绘制了一个没有放回的随机子样本。这两种选择都有效,即他们的假设检验在 5% 的时间里拒绝了零。
我的问题:重复观察是罪魁祸首,我说得对吗?如果是这样,鉴于这是一种标准的自举方法,我们究竟在哪里违反了标准的自举理论?
更新 #1:更多模拟
的仅截距回归模型。出现同样的问题。
# note: simulation takes 5-10 min on my laptop; can reduce boot.reps
# and n.sims.run if wanted
# set the number of cores: can change this to match your machine
library(doParallel)
registerDoParallel(cores=8)
boot.reps = 1000
n.sims.run = 1000
for ( j in 1:n.sims.run ) {
# make initial dataset from which to bootstrap
# generate under null
d = data.frame( X1 = rnorm( n = 1000 ), Y1 = rnorm( n = 1000 ) )
# fit OLS to original data
mod.orig = lm( Y1 ~ X1, data = d )
bhat = coef( mod.orig )[["X1"]]
se = coef(summary(mod.orig))["X1",2]
rej = coef(summary(mod.orig))["X1",4] < 0.05
# run all bootstrap iterates
parallel.time = system.time( {
r = foreach( icount( boot.reps ), .combine=rbind ) %dopar% {
# Algorithm 6.2: Resample entire cases - FAILS
# residuals of this model are repeated, so not normal?
ids = sample( 1:nrow(d), replace=TRUE )
b = d[ ids, ]
# # Method 2: Resample just the residuals themselves - WORKS
# b = data.frame( X1 = d$X1, Y1 = sample(mod.orig$residuals, replace = TRUE) )
# # Method 3: Subsampling without replacement - WORKS
# ids = sample( 1:nrow(d), size = 500, replace=FALSE )
# b = d[ ids, ]
# save stats from bootstrap sample
mod = lm( Y1 ~ X1, data = b )
data.frame( bhat = coef( mod )[["X1"]],
se = coef(summary(mod))["X1",2],
rej = coef(summary(mod))["X1",4] < 0.05 )
}
} )[3]
###### Results for This Simulation Rep #####
r = data.frame(r)
names(r) = c( "bhat.bt", "se.bt", "rej.bt" )
# return results of each bootstrap iterate
new.rows = data.frame( bt.iterate = 1:boot.reps,
bhat.bt = r$bhat.bt,
se.bt = r$se.bt,
rej.bt = r$rej.bt )
# along with results from original sample
new.rows$bhat = bhat
new.rows$se = se
new.rows$rej = rej
# add row to output file
if ( j == 1 ) res = new.rows
else res = rbind( res, new.rows )
# res should have boot.reps rows per "j" in the for-loop
# simulation rep counter
d$sim.rep = j
} # end loop over j simulation reps
##### Analyze results #####
# dataset with only one row per simulation
s = res[ res$bt.iterate == 1, ]
# prob of rejecting within each resample
# should be 0.05
mean(res$rej.bt); mean(s$rej)
更新#2:答案
评论和答案中提出了几种可能性,我做了更多的模拟来经验性地测试它们。事实证明,JWalker 是正确的,问题在于我们需要通过原始数据的估计来集中引导统计数据,以便在下获得正确的抽样分布。但是,我也认为 whuber 关于违反参数测试假设的评论也是正确的,尽管在这种情况下,当我们解决 JWalker 的问题时,我们实际上确实得到了名义上的误报。