ทำไมการทดสอบสมมติฐานเกี่ยวกับชุดข้อมูลที่ resampled ปฏิเสธค่า null บ่อยเกินไป?


10

tl; dr: เริ่มต้นด้วยชุดข้อมูลที่สร้างขึ้นภายใต้ null ฉัน resampled กรณีที่มีการเปลี่ยนและดำเนินการทดสอบสมมติฐานในแต่ละชุดข้อมูล resampled การทดสอบสมมติฐานเหล่านี้ปฏิเสธค่าว่างมากกว่า 5% ของเวลา

ในด้านล่างการจำลองที่ง่ายมากฉันสร้างชุดข้อมูลด้วยและฉันพอดีกับ OLS แบบง่าย ๆ จากนั้นสำหรับแต่ละชุดข้อมูลฉันสร้างชุดข้อมูลใหม่ 1,000 ชุดโดยการสุ่มแถวใหม่ของชุดข้อมูลเดิมพร้อมการแทนที่ (อัลกอริทึมที่อธิบายไว้โดยเฉพาะในข้อความคลาสสิกของ Davison & Hinkley ว่าเหมาะสมสำหรับการถดถอยเชิงเส้น) สำหรับแต่ละอันฉันพอดีกับ OLS รุ่นเดียวกัน ในที่สุดประมาณ 16% ของการทดสอบสมมติฐานในตัวอย่าง bootstrap ปฏิเสธ nullในขณะที่เราควรได้รับ 5% (ตามที่เราทำในชุดข้อมูลดั้งเดิม)XN(0,1)⨿YN(0,1)

ฉันสงสัยว่ามันมีบางอย่างเกี่ยวกับการสังเกตซ้ำ ๆ ทำให้เกิดความสัมพันธ์ที่สูงเกินจริงดังนั้นในการเปรียบเทียบฉันลองวิธีอื่นสองวิธีในรหัสด้านล่าง (แสดงความคิดเห็น) ในวิธีที่ 2 ฉันแก้ไขจากนั้นแทนที่ด้วยส่วนที่เหลือ resampled จากโมเดล OLS ในชุดข้อมูลดั้งเดิม ในวิธีที่ 3 ฉันวาดตัวอย่างย่อยแบบสุ่มโดยไม่มีการแทนที่ ทั้งสองตัวเลือกเหล่านี้ทำงานกล่าวคือการทดสอบสมมติฐานของพวกเขาปฏิเสธโมฆะ 5% ของเวลาXY

คำถามของฉัน: ฉันถูกไหมที่การสังเกตซ้ำ ๆ เป็นผู้ร้าย? ถ้าเป็นเช่นนั้นนี่เป็นวิธีมาตรฐานในการบูตสแตรปเราจะละเมิดทฤษฎีบูตสแตรปมาตรฐานได้อย่างไร

อัปเดต # 1: จำลองเพิ่มเติม

ฉันพยายามสถานการณ์ได้ง่ายแบบจำลองการถดถอยตัดเท่านั้นสำหรับYปัญหาเดียวกันเกิดขึ้นY

# 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 ถูกต้องว่าปัญหาอยู่ที่เราต้องการไปยังศูนย์สถิติบูตโดยประมาณการข้อมูลเดิมในการสั่งซื้อที่จะได้รับการกระจายการสุ่มตัวอย่างที่ถูกต้องภายใต้H_0อย่างไรก็ตามฉันคิดว่าความคิดเห็นของ whuber เกี่ยวกับการฝ่าฝืนสมมติฐานการทดสอบพารามิเตอร์นั้นถูกต้องเช่นกัน แต่ในกรณีนี้เราได้รับผลบวกเล็กน้อยจริง ๆ เมื่อเราแก้ไขปัญหาของ JWalkerH0


1
ใน bootstrap มาตรฐานคุณจะพิจารณาเฉพาะการกระจาย bootstrap ของสัมประสิทธิ์ของ X1 ไม่ใช่ค่า p ที่เกี่ยวข้อง ดังนั้นจึงไม่ใช่ปัญหาของ bootstrap อย่างไรก็ตามการสังเกตของคุณน่าสนใจและใช้งานง่าย
Michael M

1
@MichaelM มันเป็นเรื่องจริง แต่เนื่องจาก CDF ร่วมของข้อมูลใน resamples ควรมาบรรจบกันใน n และจำนวนของ bootstrap iterates กับ CDF จริงที่สร้างข้อมูลต้นฉบับฉันไม่คาดหวังว่าค่า p จะแตกต่างกัน
ครึ่ง

ขวา. ฉันค่อนข้างมั่นใจว่าผลกระทบมาจากการสังเกตที่ไม่เป็นอิสระ (ดังที่คุณพูด) ทำให้เกิดข้อผิดพลาดมาตรฐานในแง่ดีเกินไป ในการจำลองของคุณดูเหมือนว่าจะเป็นเพียงข้อสันนิษฐานที่ละเมิดของโมเดลเชิงเส้นปกติเท่านั้น บางทีเราอาจได้รับปัจจัยความแปรปรวนที่สอดคล้องกัน
Michael M

2
สิ่งหนึ่งที่ชัดเจนในวิธีที่ 1 คือการละเมิดสมมติฐานข้อผิดพลาดของ iid: เมื่อ resampling ด้วยการแทนที่ค่าส่วนที่เหลือสำหรับค่าใดก็ตามที่มีความสัมพันธ์กันอย่างสมบูรณ์แทนที่จะเป็นอิสระ! ดังนั้นคุณจึงไม่สามารถบูตได้อย่างถูกต้องนั่นคือทั้งหมด เป็นการสาธิตหลังจากคำนวณแทนที่ด้วยแต่ดำเนินการเหมือนเดิม ที่จัดการรายการที่ซ้ำกันได้อย่างถูกต้อง (แม้ว่าจะสร้างตัวอย่างที่เล็กกว่า) คุณจะได้รับการแจกแจงค่า p แบบสม่ำเสมอ xidsids <- unique(ids)
whuber

2
@whuber ฉันเห็น. และนั่นจะอธิบายว่าทำไม resampling เศษเหลือใช้ด้วยงานทดแทนแม้ว่าจะมีการสังเกตซ้ำ ๆ ซ้ำ ๆ ซากของแบบจำลองนั้นไม่ขึ้นกับ X อีกครั้งหากคุณต้องการทำให้เป็นคำตอบฉันยินดีที่จะยอมรับ
ครึ่ง

คำตอบ:


5

เมื่อคุณลองโมฆะค่าที่คาดหวังของสัมประสิทธิ์การถดถอยเป็นศูนย์ เมื่อคุณลองชุดข้อมูลที่สังเกตอีกครั้งค่าที่คาดไว้คือค่าสัมประสิทธิ์ที่สังเกตได้สำหรับข้อมูลนั้น ไม่ใช่ข้อผิดพลาดประเภท I หาก P <= 0.05 เมื่อคุณสุ่มข้อมูลที่สังเกตใหม่ ที่จริงแล้วมันเป็นข้อผิดพลาด type II หากคุณมี P> 0.05

คุณสามารถรับปรีชาได้โดยการคำนวณความสัมพันธ์ระหว่าง abs (b) และค่าเฉลี่ย (P) นี่คือรหัสที่ง่ายกว่าในการทำซ้ำสิ่งที่คุณทำพร้อมคำนวณความสัมพันธ์ระหว่าง b และข้อผิดพลาด "type I" เหนือชุดการจำลอง

boot.reps = 1000
n.sims.run = 10
n <- 1000
b <- matrix(NA, nrow=boot.reps, ncol=n.sims.run)
p <- matrix(NA, nrow=boot.reps, ncol=n.sims.run)
for(sim_j in 1:n.sims.run){
  x <- rnorm(n)
  y <- rnorm(n)
  inc <- 1:n
  for(boot_i in 1:boot.reps){
    fit <- lm(y[inc] ~ x[inc])
    b[boot_i, sim_j] <- abs(coefficients(summary(fit))['x[inc]', 'Estimate'])
    p[boot_i, sim_j] <- coefficients(summary(fit))['x[inc]', 'Pr(>|t|)']
    inc <- sample(1:n, replace=TRUE)
  }
}
# note this is not really a type I error but whatever
type1 <- apply(p, 2, function(x) sum(x <= 0.05))/boot.reps
# correlation between b and "type I"
cor(b[1, ], type1)

อัปเดตคำตอบโดย grand_chat ไม่ใช่เหตุผลที่ความถี่ของ P <= 0.05 คือ> 0.05 คำตอบนั้นง่ายมากและสิ่งที่ฉันได้กล่าวไว้ข้างต้น - ค่าที่คาดหวังของค่าเฉลี่ยของตัวอย่างแต่ละค่าเป็นค่าดั้งเดิมที่สังเกตได้ นี่คือพื้นฐานทั้งหมดของ bootstrap ซึ่งได้รับการพัฒนาเพื่อสร้างข้อผิดพลาดมาตรฐาน / ข้อ จำกัด ความเชื่อมั่นในค่าเฉลี่ยที่สังเกตได้และไม่เป็นการทดสอบสมมติฐาน เนื่องจากความคาดหวังไม่เป็นศูนย์แน่นอน "ข้อผิดพลาดประเภทที่ 1" จะมากกว่า alpha และนี่คือสาเหตุที่จะมีความสัมพันธ์ระหว่างขนาดของสัมประสิทธิ์ (ไกลจากศูนย์) และขนาดของการเบี่ยงเบนของ "ความผิดพลาดประเภทที่ 1" จากอัลฟ่า


H0:β=β^H0:β=0

H0:β=βˆทดสอบเพื่อความเท่าเทียมและต้องการแนวทางการออกแบบการศึกษาที่แตกต่างกัน ใช้เมื่อสิ่งที่สำคัญคือเพื่อให้แน่ใจว่าความแตกต่างที่คุณสังเกตเห็นไม่ได้เป็นความบังเอิญหรือเทียบเท่าเมื่อคุณต้องการให้แน่ใจว่าการทำนายของคุณถูกต้อง น่าเสียดายที่มักพบว่าขนาดเดียวเหมาะกับทุกคน แต่ขึ้นอยู่กับความเสี่ยงในสถานการณ์ของคุณ เป็นเรื่องปกติที่จะใช้ในการวิจัยขั้นต้นเพื่อกรอง flukes เมื่อคุณไม่รู้จักการกำหนดสมมติฐานทางเลือกที่มากพอแล้วเมื่อเป็นที่รู้จักมากขึ้นมันอาจเปลี่ยนการทดสอบความถูกต้องของความรู้ของคุณ H0:β=0H0:β=0
ReneBt

2

หากคุณได้ลิ้มลองกับการเปลี่ยนจากกลุ่มตัวอย่างปกติเดิมของคุณตัวอย่างบูตส่งผลให้ไม่ปกติ การกระจายแบบร่วมของตัวอย่าง bootstrap จะตามด้วยการกระจายแบบผสม gnarly ซึ่งมีแนวโน้มมากที่จะมีระเบียนที่ซ้ำกันในขณะที่ค่าที่ซ้ำกันมีความน่าจะเป็นศูนย์เมื่อคุณนำตัวอย่าง iid จากการแจกแจงแบบปกติ

เป็นตัวอย่างง่ายๆหากตัวอย่างดั้งเดิมของคุณคือการสังเกตสองครั้งจากการแจกแจงแบบปกติแบบไม่เปลี่ยนแปลงดังนั้นตัวอย่างบูตสแตรปที่มีการแทนที่จะครึ่งเวลาประกอบด้วยตัวอย่างดั้งเดิมและครึ่งเวลาจะประกอบด้วยหนึ่งในค่าดั้งเดิมที่ซ้ำกัน เป็นที่ชัดเจนว่าค่าความแปรปรวนตัวอย่างของตัวอย่างบู๊ตสแตรปโดยเฉลี่ยจะน้อยกว่าของเดิม - อันที่จริงแล้วมันจะเป็นครึ่งหนึ่งของเดิม

พีเสื้อ


แต่ถ้าเป็นเช่นนั้นเราจะไม่พบปัญหาเดียวกันอีกครั้งเมื่อเปลี่ยนค่าของเหลือให้เป็นค่าทดแทนหรือไม่ แต่ในความเป็นจริงวิธีการนั้นปฏิเสธด้วยความน่าจะเป็นเล็กน้อย
ครึ่ง

นอกจากนี้การทดสอบด้วย n = 1,000 ไม่ควรมีปัญหากับข้อมูลที่ไม่ปกติ
ครึ่ง

0

ฉันเห็นด้วยอย่างยิ่งกับคำตอบของ @ JWalker

มีปัญหาอีกด้านหนึ่งของปัญหานี้ ที่อยู่ในกระบวนการสุ่มตัวอย่างของคุณ คุณคาดว่าสัมประสิทธิ์การถดถอยจะอยู่กึ่งกลางรอบศูนย์เพราะคุณถือว่าXและYเป็นอิสระ อย่างไรก็ตามในการ resampling ของคุณคุณทำ

ids = sample( 1:nrow(d), replace=TRUE )
  b = d[ ids, ]

ซึ่งสร้างความสัมพันธ์เพราะคุณเป็นตัวอย่างXและYร่วมกัน ตัวอย่างเช่นสมมติว่าแถวแรกของชุดข้อมูลdคือ(x1, y1)ในชุดข้อมูลที่ resampled P(Y = y1|X = x1) = 1ในขณะที่ถ้าXและYเป็นอิสระP(Y|X = x1)ต่อไปนี้การกระจายตามปกติ

อีกวิธีหนึ่งในการแก้ไขปัญหานี้คือการใช้

b = data.frame( X1 = rnorm( n = 1000 ), Y1 = rnorm( n = 1000 ) )

รหัสเดียวกันกับที่คุณใช้ในการสร้างdเพื่อทำให้ X และ Y เป็นอิสระจากกัน

เหตุผลเดียวกันอธิบายว่าทำไมทำงานกับ resampling เหลือ (เพราะXเป็นอิสระจากใหม่Y)


ในขณะที่ฉันยังคิดว่าการสังเกต resampled อาจไม่อิสระ แต่เมื่อคิดเกี่ยวกับมันมากขึ้นจริงฉันไม่คิดว่าเป็นกรณีนี้: stats.stackexchange.com/questions/339237/…
ครึ่ง -pass

ปัญหาที่ฉันอธิบายด้านบนแตกต่างจากโพสต์ของคุณ x'sสิ่งที่คุณเรียกว่าเป็นอิสระของ สิ่งที่ฉันพูดถึงคือความสัมพันธ์ระหว่างXs กับYs
Tianxia Zhou

-1

ปัญหาที่ใหญ่ที่สุดในที่นี้คือผลลัพธ์ของโมเดลปลอมและไม่เสถียรอย่างมากเนื่องจากโมเดลเป็นเพียงสัญญาณรบกวนที่เหมาะสม ในความหมายที่แท้จริงมาก Y1 ไม่ใช่ตัวแปรตามเนื่องจากวิธีสร้างข้อมูลตัวอย่าง


แก้ไขเพื่อตอบความคิดเห็นขอให้ฉันลองอธิบายความคิดของฉันดู

ด้วย OLS ความตั้งใจทั่วไปคือการค้นหาและกำหนดปริมาณความสัมพันธ์พื้นฐานในข้อมูล ด้วยข้อมูลในโลกแห่งความเป็นจริงเรามักจะไม่ทราบอย่างแน่นอน

แต่นี่เป็นสถานการณ์การทดสอบประดิษฐ์ เรารู้กลไกการสร้างข้อมูลที่แน่นอนมันอยู่ที่นั่นในรหัสที่โพสต์โดย OP It's

X1 = rnorm (n = 1,000), Y1 = rnorm (n = 1,000)

หากเราแสดงว่าในรูปแบบที่คุ้นเคยของการถดถอย OLS คือ

Y1 = การสกัดกั้น + Beta1 * X1 + ข้อผิดพลาด
ที่กลายเป็น
Y1 = หมายถึง (X1) + 0 (X1) + ข้อผิดพลาด

ในใจของฉันนี่คือแบบจำลองที่แสดงในรูปแบบเชิงเส้น แต่จริงๆแล้วมันไม่ใช่ความสัมพันธ์เชิงเส้น / แบบจำลองเนื่องจากไม่มีความชัน Beta1 = 0.000000

เมื่อเราสร้างจุดข้อมูลแบบสุ่ม 1,000 จุดสแคตชอตจะดูเหมือนสเปรย์ปืนลูกซองแบบวงกลม อาจมีความสัมพันธ์ระหว่าง X1 และ Y1 ในตัวอย่างเฉพาะของจุดสุ่ม 1,000 จุดที่สร้างขึ้น แต่ถ้าเป็นเช่นนั้นจะเกิดขึ้นแบบสุ่ม หาก OLS พบความสัมพันธ์คือปฏิเสธสมมติฐานว่าง ๆ ว่าไม่มีความชันเนื่องจากเรารู้อย่างชัดเจนว่าไม่มีความสัมพันธ์ใด ๆ ระหว่างตัวแปรทั้งสองนี้ดังนั้น OLS จึงพบรูปแบบในองค์ประกอบของข้อผิดพลาด ฉันโดดเด่นว่า "กระชับเสียง" และ "ปลอม"

นอกจากนี้หนึ่งในสมมติฐาน / ข้อกำหนดของมาตรฐานของ OLS คือ (+/-) "โมเดลการถดถอยเชิงเส้นคือ" พารามิเตอร์เชิงเส้น " จากข้อมูลที่ฉันได้รับก็คือเราไม่พอใจกับข้อสันนิษฐานนั้นดังนั้นสถิติการทดสอบพื้นฐานที่มีนัยสำคัญนั้นไม่ถูกต้องความเชื่อของฉันคือการละเมิดสมมติฐานเชิงเส้นตรงเป็นสาเหตุโดยตรงของผลลัพธ์บูตสแตรป

เมื่อฉันอ่านปัญหานี้เป็นครั้งแรกมันไม่ได้จมลงในการที่ OP ตั้งใจจะทดสอบภายใต้ null [สมมติฐาน]

แต่ผลลัพธ์เดียวกันที่ไม่ได้เกิดขึ้นเองจะเกิดขึ้นหากมีการสร้างชุดข้อมูลเป็น

X1 = rnorm (n = 1,000), Y1 = X1 * .4 + rnorm (n = 1,000)?


4
Y1Y1

(-1) ด้วยเหตุผลเดียวกันกับที่ @whuber ให้
ครึ่ง

1
ตอบคำถามสุดท้ายในการแก้ไขของคุณ: ใช่แน่นอน ลองด้วยตัวเองด้วยการจำลอง (แต่ต้องระวังเกี่ยวกับการตีความเพราะคุณต้องพิจารณาสิ่งที่เป็นโมฆะและสถานะที่แท้จริงของกิจการ)
whuber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.