Σ
SDCalc
ขั้นสูงขั้นสูง·15 min

วิธีบูตสแตรปสำหรับส่วนเบี่ยงเบนมาตรฐาน

เชี่ยวชาญการสุ่มตัวอย่างซ้ำแบบบูตสแตรปสำหรับการประมาณส่วนเบี่ยงเบนมาตรฐาน เรียนรู้วิธีเปอร์เซ็นไทล์ BCa และบูตสแตรปแบบพารามิเตอร์ พร้อมการนำไปใช้ด้วย Python และตัวอย่างพร้อมวิธีทำ

บูตสแตรป: การปฏิวัติทางสถิติยุคคอมพิวเตอร์

การสุ่มตัวอย่างซ้ำแบบบูตสแตรป เป็นเทคนิคทางสถิติที่ทรงพลังในการประมาณการแจกแจงการสุ่มตัวอย่างของสถิติใดๆ โดยการสุ่มตัวอย่างซ้ำจากข้อมูลที่สังเกตได้ เปิดตัวโดย Bradley Efron ในปี 1979 มันปฏิวัติการอนุมานทางสถิติโดยทำให้การวิเคราะห์สถิติซับซ้อนเป็นไปได้โดยไม่ต้องอาศัยสูตรทางคณิตศาสตร์หรือข้อสมมติเกี่ยวกับการแจกแจง

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

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

ทำไมต้องบูตสแตรปสำหรับส่วนเบี่ยงเบนมาตรฐาน?

ช่วงความเชื่อมั่นแบบดั้งเดิมสำหรับส่วนเบี่ยงเบนมาตรฐานสมมติว่าข้อมูลมาจากการแจกแจงปกติ เมื่อข้อสมมตินี้ล้มเหลว (ซึ่งเกิดขึ้นบ่อย) ช่วงเหล่านี้อาจไม่แม่นยำอย่างมาก บูตสแตรปให้ทางเลือกที่ไม่ขึ้นกับการแจกแจง

เมื่อวิธีดั้งเดิมล้มเหลว

CI ที่อิงไคสแควร์สำหรับส่วนเบี่ยงเบนมาตรฐานสมมติความเป็นปกติ กับข้อมูลที่เบ้ (รายได้ เวลาตอบสนอง ข้อมูลการอยู่รอด) สิ่งนี้อาจสร้างช่วงที่พลาดพารามิเตอร์จริง 20-30% ของเวลา ไม่ใช่ 5% ที่คาดหวัง

ข้อได้เปรียบสำคัญของบูตสแตรปสำหรับส่วนเบี่ยงเบนมาตรฐาน:

  • ไม่มีข้อสมมติเกี่ยวกับการแจกแจง: ทำงานได้ดีเท่ากันกับข้อมูลปกติ เบ้ หรือหางหนัก
  • ประสิทธิภาพกับตัวอย่างเล็ก: มักแม่นยำกว่าวิธีแบบพารามิเตอร์เมื่อ n < 30
  • จัดการสถิติซับซ้อน: วิธีเดียวกันใช้ได้กับ SD ที่ตัดแต่ง MAD หรือตัววัดความแปรผันที่กำหนดเอง
  • ข้อมูลเชิงลึกเชิงภาพ: การแจกแจงบูตสแตรปแสดงให้คุณเห็นว่าเกิดอะไรขึ้น ไม่ใช่แค่ตัวเลขสุดท้าย

ขั้นตอนบูตสแตรป

อัลกอริทึมบูตสแตรปตรงไปตรงมาอย่างน่าทึ่ง จากตัวอย่างเดิมที่มี n ข้อสังเกต:

1

สุ่มตัวอย่างบูตสแตรป

สุ่มเลือก n ข้อสังเกตแบบใส่คืนจากข้อมูลเดิม บางค่าจะปรากฏหลายครั้ง บางค่าไม่ปรากฏเลย
2

คำนวณสถิติ

คำนวณส่วนเบี่ยงเบนมาตรฐานของตัวอย่างบูตสแตรปนี้ นี่คือหนึ่งค่าบูตสแตรป
3

ทำซ้ำหลายครั้ง

ทำซ้ำขั้นตอน 1-2 หลายพันครั้ง (โดยทั่วไป B = 10,000) แต่ละครั้งให้ SD บูตสแตรปหนึ่งค่า
4

วิเคราะห์การแจกแจง

ชุดของ B SD บูตสแตรปประมาณการแจกแจงการสุ่มตัวอย่าง ใช้สำหรับ CI และการทดสอบสมมติฐาน

ทำไมต้องแบบใส่คืน?

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

ต้องการตัวอย่างบูตสแตรปกี่ตัว? B = 1,000 มักเพียงพอสำหรับค่าประมาณคร่าวๆ และการทดสอบสมมติฐาน สำหรับช่วงความเชื่อมั่น B = 10,000 ให้เปอร์เซ็นไทล์ที่เสถียร สำหรับช่วง BCa คุณภาพสิ่งพิมพ์ แนะนำ B = 15,000+

วิธีช่วงความเชื่อมั่นแบบบูตสแตรป

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

1. วิธีเปอร์เซ็นไทล์ (ง่ายที่สุด)

วิธีที่เข้าใจง่ายที่สุด: ใช้เปอร์เซ็นไทล์ของการแจกแจงบูตสแตรปโดยตรง

CI แบบเปอร์เซ็นไทล์

95% CI = [θ*₂.₅, θ*₉₇.₅]

สำหรับ 10,000 ตัวอย่างบูตสแตรป นี่คือค่าที่เรียงลำดับตำแหน่งที่ 250 และ 9,750 ง่ายแต่อาจมีความเอนเอียงเมื่อการแจกแจงบูตสแตรปเบ้

2. บูตสแตรปพื้นฐาน (แบบจุดหมุน)

ใช้ความสัมพันธ์ระหว่างสถิติตัวอย่างและสถิติบูตสแตรป:

CI บูตสแตรปพื้นฐาน

95% CI = [2θ̂ - θ*₉₇.₅, 2θ̂ - θ*₂.₅]

โดยที่ θ̂ คือ SD ตัวอย่างเดิม สิ่งนี้ “สะท้อน” ช่วงเปอร์เซ็นไทล์รอบค่าประมาณตัวอย่าง

3. BCa (แก้ไขความเอนเอียงและเร่ง)

มาตรฐานทองคำสำหรับความแม่นยำ BCa ปรับแก้ทั้งความเอนเอียงในการแจกแจงบูตสแตรปและการเร่ง (ความคลาดเคลื่อนมาตรฐานเปลี่ยนไปอย่างไรตามค่าพารามิเตอร์) ซับซ้อนกว่าในการคำนวณแต่ให้ช่วงที่แม่นยำในระดับที่สอง

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

ตัวอย่างพร้อมวิธีทำ: ข้อมูลที่ไม่เป็นปกติ

พิจารณา 15 การวัดเวลาตอบสนอง (เป็น ms): 245, 312, 287, 456, 234, 298, 267, 523, 289, 301, 278, 645, 256, 289, 312 ข้อมูลนี้เบ้ขวา (บางค่าตอบสนองช้ามาก)

1

คำนวณ SD ตัวอย่าง

ตัวอย่างเดิม: n=15, SD = 109.8 ms
2

สร้างตัวอย่างบูตสแตรป

สุ่ม 10,000 ตัวอย่างขนาด 15 แบบใส่คืน แต่ละตัวอย่างมีองค์ประกอบแตกต่างกัน
3

คำนวณ SD บูตสแตรป

คำนวณ SD สำหรับแต่ละตัวอย่างบูตสแตรป ได้ 10,000 ค่าตั้งแต่ ~60 ถึง ~180
4

หาเปอร์เซ็นไทล์

เปอร์เซ็นไทล์ที่ 2.5: 72.3 ms, เปอร์เซ็นไทล์ที่ 97.5: 156.8 ms
5

สร้าง 95% CI

95% CI: [72.3, 156.8] ms เปรียบเทียบกับ CI ไคสแควร์: [79.4, 175.2] ซึ่งสมมติความเป็นปกติ

CI บูตสแตรปไม่สมมาตร (กว้างกว่าด้านสูง) สะท้อนลักษณะเบ้ขวาของข้อมูล CI ไคสแควร์ไม่จับความไม่สมมาตรนี้

การนำไปใช้ด้วย Python

การนำบูตสแตรปไปใช้อย่างสมบูรณ์พร้อมหลายวิธี CI:

python
import numpy as np
from scipy import stats

def bootstrap_sd_ci(data, n_bootstrap=10000, ci=0.95, method='percentile'):
    """
    Bootstrap confidence interval for standard deviation.

    Parameters:
    -----------
    data : array-like - Original sample
    n_bootstrap : int - Number of bootstrap samples
    ci : float - Confidence level (e.g., 0.95)
    method : str - 'percentile', 'basic', or 'bca'

    Returns:
    --------
    tuple : (lower_bound, upper_bound, bootstrap_sds)
    """
    data = np.array(data)
    n = len(data)
    original_sd = np.std(data, ddof=1)

    # Generate bootstrap samples and calculate SDs
    bootstrap_sds = np.array([
        np.std(np.random.choice(data, size=n, replace=True), ddof=1)
        for _ in range(n_bootstrap)
    ])

    alpha = 1 - ci

    if method == 'percentile':
        lower = np.percentile(bootstrap_sds, 100 * alpha/2)
        upper = np.percentile(bootstrap_sds, 100 * (1 - alpha/2))

    elif method == 'basic':
        lower = 2*original_sd - np.percentile(bootstrap_sds, 100*(1-alpha/2))
        upper = 2*original_sd - np.percentile(bootstrap_sds, 100*alpha/2)

    elif method == 'bca':
        # Bias correction
        prop_less = np.mean(bootstrap_sds < original_sd)
        z0 = stats.norm.ppf(prop_less)

        # Acceleration (jackknife estimate)
        jackknife_sds = np.array([
            np.std(np.delete(data, i), ddof=1) for i in range(n)
        ])
        jack_mean = jackknife_sds.mean()
        a = np.sum((jack_mean - jackknife_sds)**3) / \
            (6 * np.sum((jack_mean - jackknife_sds)**2)**1.5)

        # Adjusted percentiles
        z_alpha = stats.norm.ppf([alpha/2, 1-alpha/2])
        adj_percentiles = stats.norm.cdf(
            z0 + (z0 + z_alpha) / (1 - a*(z0 + z_alpha))
        ) * 100
        lower = np.percentile(bootstrap_sds, adj_percentiles[0])
        upper = np.percentile(bootstrap_sds, adj_percentiles[1])

    return lower, upper, bootstrap_sds

# Example usage
response_times = [245, 312, 287, 456, 234, 298, 267, 523, 289, 301, 278, 645, 256, 289, 312]

for method in ['percentile', 'basic', 'bca']:
    lower, upper, _ = bootstrap_sd_ci(response_times, method=method)
    print(f"{method.upper():12s} 95% CI: [{lower:.1f}, {upper:.1f}]")