Tae Hyun Kim (Lowell)

Statistical Power

3분 읽기 #experiments#ab-testing#rct

Definition

**통계적 검정력(Statistical Power)**은 효과가 실제로 존재할 때 그것을 탐지할 확률입니다.

Power=P(효과 탐지효과 존재)=1β\text{Power} = P(\text{효과 탐지} | \text{효과 존재}) = 1 - \beta

여기서:

  • α\alpha: 1종 오류율 (거짓 양성) — 효과 없는데 있다고 판정
  • β\beta: 2종 오류율 (거짓 음성) — 효과 있는데 없다고 판정
  • Power = 1β1 - \beta

일반적으로 80% 검정력을 목표로 합니다.

Intuitive Understanding

검정력은 “실제 효과를 발견할 능력”입니다.

검정력이 낮으면 효과가 있어도 발견하지 못합니다. 예를 들어, 검정력이 50%인 실험에서 효과가 실제로 있어도 동전 던지기 확률로만 발견합니다.

Key Properties

검정력에 영향을 미치는 요인

요인검정력에 미치는 영향
샘플 사이즈 ↑검정력 ↑
효과 크기 ↑검정력 ↑
분산 ↓검정력 ↑
유의수준 α ↑검정력 ↑ (1종 오류 증가)

샘플 사이즈 공식

이항 결과 (전환율): n=2(z1α/2+z1β)2p(1p)δ2n = \frac{2 (z_{1-\alpha/2} + z_{1-\beta})^2 p(1-p)}{\delta^2}

연속 결과: n=2(z1α/2+z1β)2σ2δ2n = \frac{2 (z_{1-\alpha/2} + z_{1-\beta})^2 \sigma^2}{\delta^2}

여기서:

  • z1α/2z_{1-\alpha/2}: 유의수준에 해당하는 z-값 (0.05 → 1.96)
  • z1βz_{1-\beta}: 검정력에 해당하는 z-값 (0.80 → 0.84)
  • δ\delta: 탐지하려는 최소 효과 크기 (MDE)
  • pp: 기준선 비율
  • σ\sigma: 표준편차

MDE (Minimum Detectable Effect)

MDE=(z1α/2+z1β)2σ2nMDE = (z_{1-\alpha/2} + z_{1-\beta}) \cdot \sqrt{\frac{2\sigma^2}{n}}

샘플 사이즈가 주어졌을 때 탐지 가능한 최소 효과 크기.

Example

Python 구현

from scipy import stats
import numpy as np

def sample_size_binary(baseline_rate, mde_relative, alpha=0.05, power=0.80):
    """이항 결과에 대한 샘플 사이즈 계산"""
    p1 = baseline_rate
    p2 = baseline_rate * (1 + mde_relative)
    p_pooled = (p1 + p2) / 2

    z_alpha = stats.norm.ppf(1 - alpha/2)
    z_beta = stats.norm.ppf(power)

    numerator = (z_alpha * np.sqrt(2 * p_pooled * (1 - p_pooled)) +
                 z_beta * np.sqrt(p1*(1-p1) + p2*(1-p2)))**2
    denominator = (p2 - p1)**2

    return int(np.ceil(numerator / denominator))

def sample_size_continuous(std, mde_absolute, alpha=0.05, power=0.80):
    """연속 결과에 대한 샘플 사이즈 계산"""
    z_alpha = stats.norm.ppf(1 - alpha/2)
    z_beta = stats.norm.ppf(power)

    n = 2 * ((z_alpha + z_beta) * std / mde_absolute)**2
    return int(np.ceil(n))

# 예: 기준선 5% 전환율, 10% 상대적 증가 탐지
n_binary = sample_size_binary(baseline_rate=0.05, mde_relative=0.10)
print(f"그룹당 필요 샘플 (이항): {n_binary:,}")  # 약 31,000

# 예: 평균 수익 $100, 표준편차 $50, $5 차이 탐지
n_continuous = sample_size_continuous(std=50, mde_absolute=5)
print(f"그룹당 필요 샘플 (연속): {n_continuous:,}")  # 약 1,570

검정력 곡선

import matplotlib.pyplot as plt

def power_curve(baseline_rate, mde_range, sample_size, alpha=0.05):
    """다양한 효과 크기에 대한 검정력 계산"""
    powers = []

    for mde in mde_range:
        p1 = baseline_rate
        p2 = baseline_rate * (1 + mde)

        se = np.sqrt(p1*(1-p1)/sample_size + p2*(1-p2)/sample_size)
        z = (p2 - p1) / se - stats.norm.ppf(1 - alpha/2)
        power = stats.norm.cdf(z)
        powers.append(power)

    return powers

mde_range = np.linspace(0.01, 0.30, 50)
n = 10000

powers = power_curve(0.05, mde_range, n)

plt.figure(figsize=(8, 5))
plt.plot(mde_range * 100, powers)
plt.axhline(0.8, color='r', linestyle='--', label='80% power')
plt.xlabel('Relative MDE (%)')
plt.ylabel('Power')
plt.title(f'Power Curve (n={n:,} per group)')
plt.legend()
plt.grid(True, alpha=0.3)

가격 실험 예시

# 가격 변경이 전환율에 미치는 영향 테스트
# 기준선: 전환율 3%
# 탐지 목표: 5% 상대적 변화 (3% → 3.15%)

n_required = sample_size_binary(
    baseline_rate=0.03,
    mde_relative=0.05,
    alpha=0.05,
    power=0.80
)
print(f"필요 샘플: 그룹당 {n_required:,}명")

# 하루 방문자 5,000명이면
days_required = n_required * 2 / 5000
print(f"실험 기간: 약 {days_required:.0f}일")
  • A-B Testing - 검정력이 적용되는 맥락
  • CUPED - 분산 감소로 검정력 향상
  • Design Effect - 클러스터 랜덤화의 검정력 영향

References

  • Cohen, J. (1988). Statistical Power Analysis for the Behavioral Sciences.
  • Kohavi, R., Tang, D., & Xu, Y. (2020). Trustworthy Online Controlled Experiments.
  • Comprehensive Personalized Pricing Guide, Part V, §14

연결 그래프