การใช้ bootstrap ภายใต้ H0 เพื่อทำการทดสอบความแตกต่างของสองวิธี: การเปลี่ยนภายในกลุ่มหรือภายในกลุ่มตัวอย่าง


18

สมมติว่าฉันมีข้อมูลที่มีสองกลุ่มอิสระ:

g1.lengths <- c (112.64, 97.10, 84.18, 106.96, 98.42, 101.66)

g2.lengths <- c (84.44, 82.10, 83.26, 81.02, 81.86, 86.80, 
                     85.84, 97.08, 79.64, 83.32, 91.04, 85.92,
                     73.52, 85.58, 97.70, 89.72, 88.92, 103.72,
                     105.02, 99.48, 89.50, 81.74)

group = rep (c ("g1", "g2"), c (length (g1.lengths), length (g2.lengths)))

lengths = data.frame( lengths = c(g1.lengths, g2.lengths), group)

จะเห็นว่าขนาดของกลุ่มตัวอย่างต่อกลุ่มจะลำเอียงที่G1 มี 6สังเกตและG2 มี 22 ANOVA ดั้งเดิมชี้ให้เห็นว่ากลุ่มมีวิธีการที่แตกต่างกันเมื่อค่าวิกฤตถูกตั้งค่าเป็น 0.05 (ค่า p คือ0.0044 )

summary (aov (lengths~group, data = lengths))  

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

การทดสอบ PERMUTATION

สมมติฐาน Null (H0) ระบุว่าค่าเฉลี่ยของกลุ่มเหมือนกัน ข้อสันนิษฐานในการทดสอบการเปลี่ยนแปลงนี้มีการพิสูจน์ด้วยการรวมกลุ่มเป็นตัวอย่างเดียว สิ่งนี้ทำให้มั่นใจได้ว่าตัวอย่างสำหรับสองกลุ่มนั้นมาจากการแจกแจงที่เหมือนกัน โดยการสุ่มตัวอย่างซ้ำ ๆ (หรือแม่นยำยิ่งขึ้น - reshuffling) จากข้อมูล pooled การสังเกตจะถูกจัดสรรใหม่ (สับ) กับตัวอย่างในวิธีการใหม่และคำนวณสถิติการทดสอบ การดำเนินการ n ครั้งนี้จะให้การกระจายตัวอย่างของสถิติการทดสอบภายใต้สมมติฐานที่ H0 คือ TRUE ในตอนท้ายภายใต้ H0 ค่า p คือความน่าจะเป็นที่สถิติทดสอบเท่ากับหรือสูงกว่าค่าที่สังเกตได้

s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)

pool <- lengths$lengths
obs.diff.p <- mean (g1.lengths) - mean (g2.lengths)
iterations <- 10000
sampl.dist.p <- NULL

set.seed (5)
for (i in 1 : iterations) {
        resample <- sample (c(1:length (pool)), length(pool))

        g1.perm = pool[resample][1 : s.size.g1]
        g2.perm = pool[resample][(s.size.g1+1) : length(pool)]
        sampl.dist.p[i] = mean (g1.perm) - mean (g2.perm) 
}
p.permute <- (sum (abs (sampl.dist.p) >= abs(obs.diff.p)) + 1)/ (iterations+1)

p-value รายงานของการทดสอบการเปลี่ยนแปลงเป็น0.0053 ตกลงถ้าฉันทำอย่างถูกต้องการเรียงสับเปลี่ยนและพารามิเตอร์ ANOVA ให้ผลลัพธ์เกือบเหมือนกัน

บูต

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

ให้ฉันแนะนำวิธี bootstrap ที่พบบ่อยที่สุดก่อน (Bootstrap1: resampling ภายในกลุ่ม pooled ตัวอย่าง ):

s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)

pool <- lengths$lengths
obs.diff.b1 <- mean (g1.lengths) - mean (g2.lengths)
iterations <- 10000
sampl.dist.b1 <- NULL

set.seed (5)
for (i in 1 : iterations) {
        resample <- sample (c(1:length (pool)), length(pool), replace = TRUE) 
        # "replace = TRUE" is the only difference between bootstrap and permutations

        g1.perm = pool[resample][1 : s.size.g1]
        g2.perm = pool[resample][(s.size.g1+1) : length(pool)]
        sampl.dist.b1[i] = mean (g1.perm) - mean (g2.perm) 
}
p.boot1 <- (sum (abs (sampl.dist.b1) >= obs.diff.b1) + 1)/ (iterations+1)

ค่า P ของบูตดำเนินการในลักษณะนี้เป็น0.005 แม้ว่ามันจะฟังดูสมเหตุสมผลและเกือบจะเหมือนกับการทดสอบความแปรปรวนแบบ Parametric และการเปลี่ยนแปลงการเปลี่ยนแปลงมันเหมาะสมหรือไม่ที่จะแสดงให้เห็นว่า H0 ใน bootstrap นี้บนพื้นฐานที่เราเพิ่งรวบรวมตัวอย่างจากที่เราวาดตัวอย่างต่อมา?

แนวทางที่แตกต่างฉันพบในเอกสารทางวิทยาศาสตร์หลายฉบับ โดยเฉพาะฉันเห็นว่านักวิจัยแก้ไขข้อมูลเพื่อให้ตรงกับ H0 ก่อน bootstrap เมื่อค้นหารอบ ๆ ฉันพบโพสต์ที่น่าสนใจมากใน CVโดยที่@ jan.sอธิบายผลลัพธ์ที่ผิดปกติของ bootstrap ในคำถามโพสต์ที่มีจุดประสงค์เพื่อเปรียบเทียบสองวิธี อย่างไรก็ตามในการโพสต์นั้นจะไม่ครอบคลุมถึงวิธีการ bootstrap เมื่อมีการแก้ไขข้อมูลก่อน bootstrap วิธีการที่ข้อมูลถูกแก้ไขก่อนบูตสแตรปมีลักษณะดังนี้:

  1. H0 ระบุว่าค่าเฉลี่ยของสองกลุ่มเหมือนกัน
  2. H0 ถือเป็นจริงถ้าเราลบการสังเกตแต่ละรายการจากค่าเฉลี่ยของกลุ่มตัวอย่าง

ในกรณีนี้การปรับเปลี่ยนข้อมูลควรมีผลต่อความหมายของกลุ่มและดังนั้นจึงแตกต่างกัน แต่ไม่เปลี่ยนแปลงในกลุ่ม (และระหว่าง)

  1. แก้ไขข้อมูลจะเป็นพื้นฐานสำหรับการบูตต่อไปด้วยประการที่สุ่มตัวอย่างจะดำเนินการในแต่ละกลุ่มแยกต่างหาก
  2. ความแตกต่างระหว่างค่าเฉลี่ย bootstrapped ของ g1 และ g2 นั้นถูกคำนวณและเปรียบเทียบกับความแตกต่างระหว่างกลุ่ม
  3. สัดส่วนของค่าที่เท่ากันหรือมากเกินกว่าที่สังเกตได้หนึ่งหารด้วยจำนวนการทำซ้ำจะให้ค่า p

นี่คือรหัส (Bootstrap2: การสุ่มตัวอย่างใหม่ภายในกลุ่มหลังจากการปรับเปลี่ยนที่ H0 คือ TRUE ):

s.size.g1 <- length (g1.lengths)
s.size.g2 <- length (g2.lengths)

pool <- lengths$lengths
obs.diff.b2 <- mean (g1.lengths) - mean (g2.lengths)

# make H0 to be true (no difference between means of two groups)
H0 <- pool - mean (pool)

# g1 from H0 
g1.H0 <- H0[1:s.size.g1] 

# g2 from H0
g2.H0 <- H0[(s.size.g1+1):length(pool)]

iterations <- 10000
sampl.dist.b2 <- NULL

set.seed (5)
for (i in 1 : iterations) {
        # Sample with replacement in g1
        g1.boot = sample (g1.H0, replace = T)

        # Sample with replacement in g2
        g2.boot = sample (g2.H0, replace = T)

        # bootstrapped difference
        sampl.dist.b2[i] <- mean (g1.boot) - mean (g2.boot)  
}
p.boot2 <- (sum (abs (sampl.dist.b2) >= obs.diff.b2) + 1)/ (iterations+1)

bootstrap ที่ทำเช่นนี้จะให้ค่า p 0.514ซึ่งแตกต่างอย่างมากเมื่อเทียบกับการทดสอบก่อนหน้านี้ ฉันเชื่อว่าสิ่งนี้จะต้องจัดการกับคำอธิบายของ @jan.sแต่ฉันไม่สามารถหาได้ว่ากุญแจอยู่ที่ไหน ...


1
ปัญหาที่น่าสนใจและนำเสนออย่างดี bootstrap มีปัญหาเมื่อขนาดตัวอย่างเล็กมากเท่านั้นเนื่องจากตัวอย่างดั้งเดิมมีแนวโน้มที่จะไม่ได้เป็นตัวแทนของประชากรได้ดี ขนาดตัวอย่างไม่จำเป็นต้องมีขนาดใหญ่มากสำหรับ bootstrap ในการทำงาน ขนาดตัวอย่างที่ 6 และ 22 ของคุณอาจไม่แย่ขนาดนั้น ในกระดาษโดย Efron (1983) bootstrap ถูกเปรียบเทียบกับรูปแบบของ CV สำหรับการประเมินอัตราความผิดพลาดสำหรับฟังก์ชัน discriminant เชิงเส้นในปัญหาการจำแนกประเภทที่มี 2 คลาสที่แต่ละขนาดตัวอย่างการฝึกอบรมน้อยกว่า 10 ฉันครอบคลุมสิ่งนี้ในหนังสือ Bootstrap 2007)
Michael R. Chernick

2
หนังสือของฉันยังมีบทที่เมื่อ bootstrap ล้มเหลวและรวมถึงการอภิปรายของปัญหาขนาดตัวอย่างเล็ก ๆ
Michael R. Chernick

เดียวบรรทัดที่คุณจำเป็นต้องแก้ไขในบูตของคุณ # 2 H0 <- pool - mean (pool)วิธีที่จะทำให้มันเป็นหนึ่งในการทำงานนี้: H0 <- c(g1.lengths - mean(g1.lengths), g2.lengths - mean(g2.lengths))มันต้องถูกแทนที่ด้วย จากนั้นคุณจะได้รับค่า p-0.0023 (นี่คือสิ่งเดียวกับที่เซนิตอธิบายไว้ในคำตอบของเขา) นี่คือทั้งหมดที่มีให้มันเป็นเพียงข้อบกพร่องง่ายๆในโค้ด CC ถึง @MichaelChernick
อะมีบาพูดว่า Reinstate Monica

วิธีการเหล่านี้สามารถเอาชนะได้หรือไม่? ฉันหมายถึงว่าพวกเขาสามารถตรวจจับความแตกต่างใด ๆ ว่าเป็นสิ่งสำคัญหรือไม่เมื่อกลุ่มใหญ่มาก: พูล> 43k
Alex Alvarez Pérez

คำตอบ:


17

นี่คือสิ่งที่ฉันใช้ตามบทที่ 16 ของ Efron และ Tibshirani's An Introduction to bootstrap (หน้า 220-224) สั้น ๆ ก็คืออัลกอริทึมการบูตที่สองของคุณถูกนำไปใช้อย่างไม่ถูกต้อง แต่แนวคิดทั่วไปนั้นถูกต้อง

เมื่อทำการทดสอบ bootstrap เราต้องแน่ใจว่าวิธีการสุ่มตัวอย่างใหม่สร้างข้อมูลที่สอดคล้องกับสมมติฐานว่าง ฉันจะใช้ข้อมูลการนอนหลับใน R เพื่อแสดงโพสต์นี้ โปรดทราบว่าฉันใช้สถิติแบบทดสอบมากกว่าแค่ความแตกต่างของค่าเฉลี่ยซึ่งตำราเรียนแนะนำ

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

x <- sleep$extra[sleep$group==1] y <- sleep$extra[sleep$group==2]
t.test(x,y)
t = -1.8608, df = 17.776, p-value = 0.07939

n1n2

# pooled sample, assumes equal variance
pooled <- c(x,y)
for (i in 1:10000){
  sample.index <- sample(c(1:length(pooled)),replace=TRUE)
  sample.x <- pooled[sample.index][1:length(x)]
  sample.y <- pooled[sample.index][-c(1:length(y))]
  boot.t[i] <- t.test(sample.x,sample.y)$statistic
}
p.pooled <-  (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1) 
p.pooled
[1] 0.07929207

H0H0H0Z¯

x~ผม=xผม-x¯+Z¯
Y~ผม=Yผม-Y¯+Z¯

x~/Y~Z¯H0

# sample from H0 separately, no assumption about equal variance
xt <- x - mean(x) + mean(sleep$extra) #
yt <- y - mean(y) + mean(sleep$extra)

boot.t <- c(1:10000)
for (i in 1:10000){
  sample.x <- sample(xt,replace=TRUE)
  sample.y <- sample(yt,replace=TRUE)
  boot.t[i] <- t.test(sample.x,sample.y)$statistic
}
p.h0 <-  (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1)  # 
p.h0
[1] 0.08049195

คราวนี้เราสิ้นสุดด้วยค่า p ที่คล้ายกันสำหรับสามวิธี หวังว่านี่จะช่วยได้!


1
คุณจะกรุณาและอธิบายว่าทำไมเพิ่ม '1' ลงในสิ่งต่อไปนี้: (1 + sum(abs(boot.t) > abs(t.test(x,y)$statistic))) / (10000+1)แทนที่จะเป็นอย่างนี้: mean(abs(boot.t) > abs(t.test(x,y)$statistic))ขอบคุณสำหรับเวลา
TG_Montana

+1 bootstrap-on-modified-data-to-sample-from-H0 มีชื่อเฉพาะหรือไม่?
อะมีบาพูดว่า Reinstate Monica

3
H0พี-โวลต์aล.ยูอี=จำนวนครั้ง {เสื้อ* * * *>เสื้อโอs}BB

@amoeba: ฉันไม่แน่ใจว่าขั้นตอนนี้มีความเป็นทางการหรือตามที่ตกลงชื่อ แต่ผมคิดว่ามันสามารถอธิบายได้ว่าการทดสอบบูตเพื่อความเท่าเทียมกันของวิธีการมากกว่าการกระจาย หน้าแสดงขั้นตอนแบบเต็มจะหายไปในGoogle หนังสือแต่แรงจูงใจของมันจะปรากฏในหน้า 223 รายละเอียดของมันสามารถพบได้ในบันทึกเหล่านี้ในหน้า 13 ( galton.uchicago.edu/~eichler/stat24600/Handouts/bootstrap pdf )
เซนิต

(+1) คำตอบที่ยอดเยี่ยม คุณช่วยอธิบายได้ไหมว่าทำไม "อัลกอริทึมนี้ [การสุ่มตัวอย่างข้อมูลเองโดยไม่อยู่ตรงกลาง] กำลังทดสอบว่าการแจกแจงของ x และ y เหมือนกันหรือไม่" ฉันเข้าใจว่ากลยุทธ์การสุ่มตัวอย่างใหม่นี้ช่วยให้มั่นใจได้ว่าการกระจายตัวเหมือนกัน แต่ทำไมมันถึงทดสอบว่าเหมือนกัน
ครึ่ง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.