math
CHAPTER 44 / 45
읽기 약 2분
FUNCTION
A/B 테스트의 수학: p-value와 유의성
핵심 개념
귀무가설·p-value·유의수준·1·2종 오류·표본 크기 — 랜딩 페이지 A/B 테스트 설계.
본문
A/B 테스트 핵심 개념
H0 (귀무가설): A == B (효과 없음)
H1 (대립가설): A ≠ B (효과 있음)
p-value: H0이 참일 때, 관찰된 결과(또는 더 극단적)가 나올 확률
α (유의수준): 보통 0.05 — H0 기각 임계값
p < α → H0 기각, "통계적으로 유의"
p ≥ α → H0 유지, "유의하지 않음"1종 오류 vs 2종 오류
H0 참 H0 거짓
H0 기각 1종 오류 (α) 정답 (Power = 1-β)
H0 유지 정답 2종 오류 (β)
α 작게 → 1종 오류 적음, but 2종 오류 증가
표본 크게 → α/β 동시 감소Z-test for proportions (비율 비교)
import numpy as np
from scipy import stats
# 변형 A: 1000명 중 50명 전환 (5%)
# 변형 B: 1000명 중 65명 전환 (6.5%)
n_a, x_a = 1000, 50
n_b, x_b = 1000, 65
p_a = x_a / n_a
p_b = x_b / n_b
p_pool = (x_a + x_b) / (n_a + n_b)
# Z-statistic
se = np.sqrt(p_pool * (1 - p_pool) * (1/n_a + 1/n_b))
z = (p_b - p_a) / se
# p-value (양측 검정)
p_value = 2 * (1 - stats.norm.cdf(np.abs(z)))
print(f"변형 A 전환: {p_a*100:.1f}%")
print(f"변형 B 전환: {p_b*100:.1f}%")
print(f"향상률 (lift): {(p_b - p_a) / p_a * 100:+.1f}%")
print(f"Z-score: {z:.3f}")
print(f"p-value: {p_value:.4f}")
if p_value < 0.05:
print("✅ 통계적으로 유의 (p < 0.05) — H0 기각")
else:
print("❌ 유의하지 않음 — 더 많은 데이터 필요")표본 크기 계산
# A 진짜 전환율 5%, B 진짜 전환율 6%일 때
# 1.2%p (즉 1%p) 차이를 95% 신뢰도로 감지하려면 N?
def sample_size_proportions(p1, p2, alpha=0.05, power=0.8):
z_alpha = stats.norm.ppf(1 - alpha/2) # 양측
z_beta = stats.norm.ppf(power)
p_avg = (p1 + p2) / 2
diff = abs(p1 - p2)
n = ((z_alpha * np.sqrt(2 * p_avg * (1 - p_avg))
+ z_beta * np.sqrt(p1*(1-p1) + p2*(1-p2))) / diff) ** 2
return int(np.ceil(n))
# 5% vs 6% 감지
n = sample_size_proportions(0.05, 0.06)
print(f"필요 표본: {n}/변형") # 약 9300
# 5% vs 5.5% (작은 차이) 감지
n = sample_size_proportions(0.05, 0.055)
print(f"필요 표본: {n}/변형") # 약 37000
# → 작은 효과 감지하려면 표본이 폭발적으로 증가실전 — A/B 테스트 시뮬레이션
import numpy as np
np.random.seed(42)
def simulate_ab_test(true_p_a, true_p_b, n_per_variant, n_simulations=1000):
"""N번 시뮬레이션해서 H0 기각률 측정"""
rejections = 0
for _ in range(n_simulations):
# 시뮬레이션
clicks_a = np.random.binomial(n_per_variant, true_p_a)
clicks_b = np.random.binomial(n_per_variant, true_p_b)
# Z-test
p_a = clicks_a / n_per_variant
p_b = clicks_b / n_per_variant
p_pool = (clicks_a + clicks_b) / (n_per_variant * 2)
se = np.sqrt(p_pool * (1 - p_pool) * (2/n_per_variant))
if se == 0:
continue
z = (p_b - p_a) / se
p_value = 2 * (1 - stats.norm.cdf(np.abs(z)))
if p_value < 0.05:
rejections += 1
return rejections / n_simulations
# 같은 분포 (H0 참) — 거짓 양성
false_positive = simulate_ab_test(0.05, 0.05, n_per_variant=1000)
print(f"실제 차이 없음: {false_positive*100:.1f}% 거짓 양성") # 약 5% (α)
# 진짜 1%p 차이 — Power 측정
power = simulate_ab_test(0.05, 0.06, n_per_variant=1000)
print(f"진짜 1%p 차이: {power*100:.1f}% 검출") # 표본 부족 시 낮음
# 표본 늘리면 Power 증가
power = simulate_ab_test(0.05, 0.06, n_per_variant=10000)
print(f"N=10000일 때: {power*100:.1f}% 검출")흔한 함정 — Peeking Problem
# ❌ 매일 결과 확인 + 유의하면 즉시 종료
# → 1종 오류율이 5% 이상으로 폭증
# ✅ 사전 정의된 표본 도달 시 1회만 검정
import numpy as np
from scipy import stats
np.random.seed(42)
# 같은 분포 — 본래 5%만 거짓 양성이어야 함
def peek_simulation(n_simulations=1000, max_n=2000, peek_every=100):
"""매 100명마다 검정 — 잘못된 방법"""
rejections = 0
for _ in range(n_simulations):
rejected = False
for n in range(peek_every, max_n + 1, peek_every):
x_a = np.random.binomial(n, 0.05)
x_b = np.random.binomial(n, 0.05)
p_pool = (x_a + x_b) / (2 * n)
se = np.sqrt(p_pool * (1 - p_pool) * 2/n)
if se == 0:
continue
z = (x_b/n - x_a/n) / se
p = 2 * (1 - stats.norm.cdf(np.abs(z)))
if p < 0.05:
rejected = True
break
if rejected:
rejections += 1
return rejections / n_simulations
false_positive = peek_simulation()
print(f"매번 확인 시 거짓 양성: {false_positive*100:.1f}%")
# 약 30% — 정상 5%의 6배
# → 사전 표본 크기 계산 + 그 시점에만 1회 검정
# 또는 Sequential testing (mSPRT, Always-Valid Inference)다음 챕터
CH.45 "프로그래밍 수학 종합" — 6개 모듈 종합 + 다음 학습 경로.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 A/B 테스트 설계를 검토해서 표본 크기 + 검정 방법 + 함정 방어를 가이드해줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
한국 SaaS 5개의 A/B 테스트 실전 사례 + 의사결정 패턴을 비교해줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 GA4 + 매출 데이터로 자동 A/B 테스트 분석 파이프라인을 구축하는 방법을 알려줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 그로스 팀에서 A/B 테스트 vs 베이지안 의사결정 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
A/B 테스트의 수학: p-value와 유의성은 이 3가지만 확실히 잡으세요
1.p-value < 0.05면 H0 기각 — 단, 효과의 크기(향상률)는 별개
2.표본 크기는 효과 크기의 제곱에 반비례 — 작은 효과 감지하려면 표본 폭발
3.다음 챕터 CH.45에서 프로그래밍 수학 종합 — 6개 모듈과 다음 단계
공유하기
진행도 44 / 45