Bootstrap 신뢰 구간 — Percentile 과 BCa

Buisson Ch.7 — 4 가지 부트스트랩 CI 의 도출과 비교

Buisson Ch.7 의 부트스트랩 신뢰 구간 구성 방법을 정리한다. Percentile, BCa (Bias-Corrected accelerated), Normal, Bootstrap-t 의 도출, 편향과 비대칭 보정의 의미, 각 방법의 적합한 사용 시점을 다룬다.

Experimentation
Fundamentals
저자

Kwangmin Kim

공개

2026년 05월 08일

1 도입 — 부트스트랩 CI 의 4 가지 형태

부트스트랩으로 CI 를 구성하는 4 가지 표준 방법 이 있다.

  1. Normal Bootstrap — 평균 ± 1.96 × 부트스트랩 SE
  2. Percentile — 부트스트랩 분포의 2.5 %, 97.5 % 분위수
  3. BCa — Bias-Corrected accelerated (편향·비대칭 보정)
  4. Bootstrap-t — 부트스트랩 t 통계량 분포 사용

이 글은 각 방법의 도출, 특성, 사용 시점을 정리한다.

2 Method 1 — Normal Bootstrap

2.1 절차

Normal Bootstrap CI

부트스트랩 분포의 표준 편차 (= 부트스트랩 SE) 를 사용해 정규 CI 구성.

\[ \text{CI} = \hat{\theta} \pm z_{1-\alpha/2} \cdot \text{SE}_{\text{boot}} \]

여기서 \(\text{SE}_{\text{boot}}\)\(B\) 개 부트스트랩 통계량 \(\hat{\theta}^*\) 의 표준 편차.

2.2 특징

  • 가장 단순
  • 통계량의 분포가 정규 인 경우만 정확
  • 비대칭 분포에서 부정확

2.3 사용 시점

거의 사용되지 않음. Percentile 또는 BCa 가 일반적으로 더 정확.

3 Method 2 — Percentile Bootstrap

3.1 절차

Percentile Bootstrap CI

\(B\) 개 부트스트랩 통계량의 경험적 분위수 를 직접 사용:

\[ \text{CI}_{95\%} = (\hat{\theta}^*_{(0.025 B)}, \hat{\theta}^*_{(0.975 B)}) \]

\(B\) 개 통계량을 정렬하고, \(2.5 \%\)\(97.5 \%\) 위치의 값을 CI 끝으로 사용.

3.2 특징

  • 단순, 직관적
  • 분포 가정 X
  • 비대칭 자료에 자연스럽게 적응

3.3 Buisson 의 사례 결과

베이커 자료 (이상치 포함, \(n = 10\)):

  • 표본 평균: 56 분
  • Percentile 95 % CI: (26, 110) 분 (대략)

전통 CI \((-23, 135)\) 와 달리 음수 X. 임상적으로 의미 있음.

직관 — Percentile 이 정직한 이유

Percentile CI 의 해석:

“1000 개 가상 표본의 평균 분포에서, 가장 작은 2.5 % 값과 가장 큰 2.5 % 값을 제외한 95 % 영역이 CI.”

이는 원 자료가 보여줄 수 있는 평균의 범위 에 자연스럽게 대응. 자료가 음수를 만들 수 없으면 CI 도 음수가 안 나옴.

전통 CI 는 모집단이 정규 라는 가정 위에서 공식적으로 음수를 만들 수 있음. 자료의 본질을 무시.

A/B 테스트의 매출 자료처럼 비음수만 가능 한 경우 percentile CI 가 자연스러움.

3.4 Percentile 의 한계

편향 자료에서 부정확. 통계량 추정에 체계적 편향 이 있으면 percentile 도 편향됨. 이를 보정한 것이 BCa.

4 Method 3 — BCa (Bias-Corrected accelerated)

4.1 동기

부트스트랩 통계량 분포가 편향 또는 비대칭 일 때 percentile 부정확. BCa 는 두 보정 적용.

4.2 절차

BCa 보정

두 모수 추정:

  1. 편향 보정 \(\hat{z}_0\):

\[ \hat{z}_0 = \Phi^{-1}\left(\frac{\#\{\hat{\theta}^* < \hat{\theta}\}}{B}\right) \]

(부트스트랩 분포에서 원 추정값보다 작은 비율의 정규 분위수)

  1. 가속도 \(\hat{a}\) (jackknife 기반):

\[ \hat{a} = \frac{\sum_{i=1}^{n} (\bar{\theta}_{(\cdot)} - \hat{\theta}_{(i)})^3}{6 \left(\sum_{i=1}^{n} (\bar{\theta}_{(\cdot)} - \hat{\theta}_{(i)})^2\right)^{3/2}} \]

(분포 비대칭 측정)

조정된 분위수:

\[ \alpha_1 = \Phi\left(\hat{z}_0 + \frac{\hat{z}_0 + z_{\alpha/2}}{1 - \hat{a}(\hat{z}_0 + z_{\alpha/2})}\right) \]

\[ \alpha_2 = \Phi\left(\hat{z}_0 + \frac{\hat{z}_0 + z_{1-\alpha/2}}{1 - \hat{a}(\hat{z}_0 + z_{1-\alpha/2})}\right) \]

CI: \((\hat{\theta}^*_{(\alpha_1 B)}, \hat{\theta}^*_{(\alpha_2 B)})\).

4.3 특징

  • 대부분의 경우에서 가장 정확
  • 편향 + 비대칭 모두 보정
  • 계산이 percentile 보다 약간 복잡

4.4 권장

R 의 boot.ci(type="bca") 또는 Python 의 scipy.stats.bootstrap(method='BCa') 가 자동 계산.

5 Method 4 — Bootstrap-t

5.1 절차

부트스트랩으로 t 통계량의 분포 를 시뮬레이션하고 분위수 사용.

\[ t^* = \frac{\hat{\theta}^* - \hat{\theta}}{\text{SE}^*} \]

\(B\)\(t^*\) 의 분포에서 분위수로 CI:

\[ \text{CI} = \hat{\theta} - t^*_{1-\alpha/2} \cdot \text{SE}, \; \hat{\theta} - t^*_{\alpha/2} \cdot \text{SE} \]

5.2 특징

  • 정확성: BCa 와 비슷하거나 더 좋음
  • 단점: 각 부트스트랩 표본에서 SE 추정 필요. 계산 비용 두 배.

5.3 사용 시점

큰 표본에서 매우 정확한 CI 필요한 경우.

6 4 가지 방법 비교 표

방법 정확성 계산 비용 사용 시점
Normal 낮음 낮음 거의 사용 X
Percentile 중간 낮음 빠른 추정
BCa 높음 중간 표준 권장
Bootstrap-t 매우 높음 높음 정밀 추정 필요

7 사용 시점 결정 트리

빠른 추정 (탐색)
   ↓
   Percentile

표준 분석 (대부분의 경우)
   ↓
   BCa

매우 정밀 (논문 등)
   ↓
   Bootstrap-t 또는 BCa

8 Buisson 의 권장

“대부분의 경우 BCa 사용. Percentile 은 시각화직관 을 위해 보조적으로.”

8.1 Robustness Check

여러 방법 동시 보고가 robustness 를 확인:

부트스트랩 95 % CI:
  Percentile: (26, 110)
  BCa:        (28, 112)
  Bootstrap-t: (27, 111)

→ 세 방법 결과 일관 → 강건

방법 간 큰 차이 시 자료의 특이성 (강한 비대칭, 작은 표본) 의심.

9 코드 예시 — 4 가지 CI 비교

import numpy as np
from scipy.stats import bootstrap, norm

np.random.seed(42)

# Buisson 사례
times = np.array([300, 12, 18, 25, 30, 35, 22, 28, 31, 19])
n = len(times)
B = 10000

# 1. Percentile
boot_means = np.array([
    np.random.choice(times, size=n, replace=True).mean()
    for _ in range(B)
])
ci_perc = np.percentile(boot_means, [2.5, 97.5])

# 2. Normal Bootstrap
mean = times.mean()
se_boot = boot_means.std(ddof=1)
ci_normal = (mean - 1.96 * se_boot, mean + 1.96 * se_boot)

# 3. BCa (scipy)
res = bootstrap((times,), np.mean, n_resamples=B, method='BCa', random_state=42)
ci_bca = res.confidence_interval

# 4. Bootstrap-t (자체 구현)
t_stars = []
for _ in range(B):
    sample = np.random.choice(times, size=n, replace=True)
    if sample.std(ddof=1) > 0:
        t_stars.append((sample.mean() - mean) / (sample.std(ddof=1) / np.sqrt(n)))
t_stars = np.array(t_stars)
t_lower, t_upper = np.percentile(t_stars, [2.5, 97.5])
se_orig = times.std(ddof=1) / np.sqrt(n)
ci_t = (mean - t_upper * se_orig, mean - t_lower * se_orig)

# 비교
print(f"표본 평균: {mean:.2f}\n")
print(f"전통 95 % CI:        ({mean - 1.96*se_orig:.2f}, {mean + 1.96*se_orig:.2f})")
print(f"Bootstrap Percentile: ({ci_perc[0]:.2f}, {ci_perc[1]:.2f})")
print(f"Bootstrap Normal:     ({ci_normal[0]:.2f}, {ci_normal[1]:.2f})")
print(f"Bootstrap BCa:        ({ci_bca.low:.2f}, {ci_bca.high:.2f})")
print(f"Bootstrap-t:          ({ci_t[0]:.2f}, {ci_t[1]:.2f})")

10 A/B 테스트의 적용

10.1 매출 분석

A/B 테스트 매출 자료가 우편향. 부트스트랩 BCa 로 그룹 평균과 차이의 CI 직접 계산.

10.2 Median 분석

매출 중앙값 비교 (이상치 robust). 전통 공식 X. 부트스트랩이 표준.

10.3 Lift 분석

상대 효과 (\(p_T / p_C - 1\)) 의 CI. 비율의 비율이라 분포 복잡. 부트스트랩이 일반.

11 4 방법의 시뮬레이션 비교

부트스트랩 CI 4 방법의 성능을 시뮬레이션 으로 비교.

11.1 시뮬레이션 설정

import numpy as np
from scipy.stats import bootstrap

np.random.seed(42)

# 진짜 모집단 (대수정규)
true_dist = lambda n: np.random.lognormal(mean=2, sigma=1, size=n)
true_mean = np.exp(2 + 0.5)  # 진짜 모집단 평균

# 1000 회 반복으로 coverage 측정
n_simulations = 1000
n_sample = 30

coverage = {'normal': 0, 'percentile': 0, 'bca': 0}
ci_widths = {'normal': [], 'percentile': [], 'bca': []}

for _ in range(n_simulations):
    sample = true_dist(n_sample)
    B = 2000

    # Bootstrap 통계량
    boot_means = np.array([
        np.random.choice(sample, n_sample, replace=True).mean()
        for _ in range(B)
    ])

    # Normal
    se = boot_means.std(ddof=1)
    ci_n = (sample.mean() - 1.96*se, sample.mean() + 1.96*se)

    # Percentile
    ci_p = np.percentile(boot_means, [2.5, 97.5])

    # BCa (scipy)
    res = bootstrap((sample,), np.mean, n_resamples=B, method='BCa', random_state=0)
    ci_b = (res.confidence_interval.low, res.confidence_interval.high)

    # Coverage
    if ci_n[0] < true_mean < ci_n[1]:
        coverage['normal'] += 1
    if ci_p[0] < true_mean < ci_p[1]:
        coverage['percentile'] += 1
    if ci_b[0] < true_mean < ci_b[1]:
        coverage['bca'] += 1

    ci_widths['normal'].append(ci_n[1] - ci_n[0])
    ci_widths['percentile'].append(ci_p[1] - ci_p[0])
    ci_widths['bca'].append(ci_b[1] - ci_b[0])

# 결과
for method in ['normal', 'percentile', 'bca']:
    print(f"{method}: coverage = {coverage[method]/n_simulations:.3f}, "
          f"평균 폭 = {np.mean(ci_widths[method]):.3f}")

11.2 예상 결과

방법 Coverage (목표 95 %) 평균 폭
Normal 0.88 좁음
Percentile 0.91 보통
BCa 0.94 보통

비대칭 자료에서 BCa 가 목표에 가장 가까움.

12 Bootstrap CI 의 함정

12.1 함정 1 — 작은 \(B\) 의 변동

\(B\) 가 너무 작으면 부트스트랩 분포가 불안정. 같은 자료의 두 부트스트랩 실행이 다른 CI.

해법: \(B \geq 5000\) (CI 용), \(B \geq 10000\) (정밀 분석).

12.2 함정 2 — 극단 통계량

최댓값, 최솟값, 극단 분위수에서 부트스트랩 부정확.

이유: 부트스트랩 표본의 max 가 항상 원 자료의 max (그 이하). 표집 분포 왜곡.

해법: m-out-of-n bootstrap 또는 극단값 이론.

12.3 함정 3 — 의존성 자료

시계열, 클러스터에서 단순 부트스트랩 부정확.

해법: Block bootstrap, Cluster bootstrap (다음 글들).

12.4 함정 4 — 큰 표본의 조심

매우 큰 자료에서 부트스트랩이 느림. BLB 또는 분산 컴퓨팅.

13 CI 보고 시 권장 형식

효과 점추정: 5.30 (단위)
95 % BCa CI: (3.20, 7.80)
Bootstrap 표본 수: B = 5000
방법: BCa (Bias-Corrected accelerated)

이 형식이 재현 가능 + 정확성 정보 모두.

14 다른 Bootstrap CI 방법

14.1 Bootstrap Hypothesis Testing CI

검정 통계량의 부트스트랩 분포 → CI 도출.

14.2 Studentized Bootstrap (Bootstrap-t)

각 부트스트랩 표본에서 t 통계량 계산. 분포의 분위수 사용.

def studentized_bootstrap(data, B=5000):
    n = len(data)
    obs_mean = data.mean()
    obs_se = data.std(ddof=1) / np.sqrt(n)

    t_stars = []
    for _ in range(B):
        sample = np.random.choice(data, n, replace=True)
        t = (sample.mean() - obs_mean) / (sample.std(ddof=1) / np.sqrt(n))
        t_stars.append(t)

    t_stars = np.array(t_stars)
    t_low, t_high = np.percentile(t_stars, [2.5, 97.5])

    return (obs_mean - t_high * obs_se, obs_mean - t_low * obs_se)

가장 정확하지만 각 부트스트랩 표본에서 SE 계산 필요. 비싸지만 2 차 정확.

14.3 ABC (Approximate Bootstrap Confidence)

분석적 근사 — 부트스트랩 시뮬레이션 대신 분석 공식.

# 단순화 (실제 ABC 는 더 복잡)
def abc_ci(data, alpha=0.05):
    n = len(data)
    mean = data.mean()
    se = data.std(ddof=1) / np.sqrt(n)
    z = norm.ppf(1 - alpha/2)
    return (mean - z*se, mean + z*se)

빠르지만 분포 가정 일부 사용.

15 후속 — Sample Size 와 임의 통계량

다음 글 A-BUI7-2 는 부트스트랩 표본 수 권고와 임의 통계량 (회귀, ROC AUC 등) 적용을 다룬다.

16 관련 주제

선행 지식

후속 주제 (Phase A)

  • A-BUI7-2 Sample Size + 임의 통계량
  • A-WOO14-2 Bootstrap CI 4 유형 (Woodward 시각)

다른 카테고리 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: