Kohavi Ch.21 개관 — SRM (Sample Ratio Mismatch) 과 Trust Guardrails

실험 trust 의 핵심 검증 · 5 가지 cause · 6 가지 debug 단계 · 4 가지 추가 guardrail

Kohavi (2020) Ch.21 의 흐름을 한 편으로 압축한다. SRM 의 정의 (sample ratio 의 design 과 mismatch), Bing 의 실제 scorecard 사례, 5 가지 SRM cause (buggy randomization, pipeline, residual, bad trigger, Treatment-affected attribute), 6 가지 debugging 절차, 4 가지 추가 trust guardrail (telemetry fidelity, cache hit, cookie clobbering, quick queries) 의 지도를 정리한다.

Experimentation
A/B Test
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: SRM (Sample Ratio Mismatch)

Treatment 와 Control 의 sample 비율이 design (예: 50/50) 과 statistically significant 차이. 실험 의 internal validity 위협 신호 (Kohavi, Tang, Xu, 2020, Ch.21).

1.0.0.1 검증 mechanism
Design ratio: 50/50 (Treatment : Control)
Observed ratio: 49.7 / 50.3

Test:
  Chi-square test:
    Expected: equal split
    Observed: actual count
    p-value: 의 distribution

Threshold:
  p < 0.001 또는 0.01 → SRM detected
  → 모든 다른 metric 의 trust 의심
1.0.0.2 통계적 근거
Law of Large Numbers:
  Sample size 증가 시 ratio 가 design 비율로 수렴
  변동의 standard error: 1/√N

50/50 design 의 100K user:
  표준 변동: ±0.5 percentage points
  ±2 percentage points 시 SRM (p < 0.001)

원문 인용 (Douglas Adams): “The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly go wrong goes wrong it usually turns out to be impossible to get at or repair.”

핵심 통찰: SRM 발생 시 거의 모든 metric 분석이 unreliable. 6% 의 Microsoft 실험에서 SRM 발견 (Kohavi 2017). SRM 이 platform 의 가장 중요한 trust check. Pass 시만 metric 분석 valid.

2 개념 및 원리

2.1 Why SRM Matters

저자 도입 강조: “Multiple companies have reported seeing SRMs and have highlighted the value of this test as a guardrail.”

2.1.1 Internal Validity 의 위협

실험 의 internal validity:
  Treatment 만이 변수 차이
  Random assignment 가 다른 confound 제거
  Treatment effect 의 정확한 측정

SRM 시:
  Random assignment 가 깨짐
  - Sample 의 unequal
  - Treatment·Control 의 다른 user composition
  - Confound 가능

영향:
  Metric 의 차이 가 Treatment effect 가 아닌 user composition 의 차이
  Conclusion 무효

2.1.2 Industry 의 SRM 발생률

저자 인용: “at Microsoft about 6% of experiments exhibited an SRM.”

6% 의 의미:
  100 실험 중 6 개 가 SRM
  대부분 platform bug 의 detection
  Continuous SRM monitoring 의 가치

2.1.3 인용된 사례

저자 인용: Kohavi and Longbotham 2017, Zhao et al. 2016, Chen, Liu and Xu 2019, Fabijan et al. 2019.

산업 사례 의 documentation:
  - Microsoft Bing
  - LinkedIn
  - Netflix
  - 일반적으로 발생

이 universal occurrence 가 SRM check 의 의무.

2.2 Scenario 1 — Simple SRM Detection

저자 명시 (Ch.21.2).

2.2.1 시나리오

Setup:
  Design: 50/50
  Control: 821,588 users
  Treatment: 815,482 users

  Ratio: 815,482 / 821,588 = 0.9926
  → 0.74 percentage points difference

Statistical test:
  Chi-square 또는 t-test
  Expected: 0.50 split
  Observed: 0.4981 split

  p-value: 1.8 × 10^-6
  Less than 1 in 500,000

→ Extremely unlikely event
→ SRM detected

2.2.2 해석

저자 강조: “It is therefore more likely that there is a bug in the implementation of the experiment, and you should not trust any of the other metrics.”

Probability 의미:
  Random chance 으로 발생할 확률 < 0.0001%
  → 거의 confirmed bug

Metric 의 trustworthy:
  분석 결과 의심
  Bug fix 전까지 launch decision 안 함

Action:
  Investigation
  Bug fix
  Re-run experiment
2.2.2.1 통계적 detail
Chi-square test 의 statistic:
  χ² = Σ (Observed - Expected)² / Expected

For binary outcome (T or C):
  N_total = 821,588 + 815,482 = 1,637,070
  Expected_each = 818,535

  χ² = (821,588 - 818,535)² / 818,535
     + (815,482 - 818,535)² / 818,535
     = (3053)² / 818,535 × 2
     ≈ 22.79

  df = 1
  p-value = P(χ² > 22.79 | df=1) ≈ 1.8E-6

이 매우 작은 p-value 가 SRM 의 indicator.

2.3 Scenario 2 — Subtle SRM with Browser Bug

저자 명시 (Ch.21.2).

2.3.1 시나리오

Setup:
  Design: 50/50
  Treatment: 959,716 users
  Control: 965,679 users
  Ratio: 959,716 / 965,679 = 0.9938
  p-value: 2 × 10^-5

  매우 strong SRM

2.3.2 Bing 의 Real Scorecard (저자 Figure 21.1)

Overall scorecard (모든 사용자):
  Sessions/UU: +0.54%, p=0.0094
  Metric 2: +0.20%, p=7e-11
  Metric 3: +0.49%, p=2e-10
  Metric 4: -0.46%, p=4e-5
  Metric 5: +0.24%, p=0.0001

  → 5 metric 모두 statistically significant
  → "Treatment 가 좋아 보임"

  But: SRM 도 있음

2.3.3 Investigation

저자 강조: “the excluded users were those that used an old version of the Chrome browser, which was the cause of the SRM.”

Investigation:
  Browser segment 별 분석:
    - 일부 Chrome version 의 user 가 Treatment 에 포함 안 됨
    - Old Chrome browser 의 bug

Root cause:
  Bot 의 일부 가 Treatment 의 변경으로 다르게 분류
  → Treatment 의 bot count ↓
  → Sample mismatch

2.3.4 After SRM Fix

After excluding affected users:
  Treatment: 924,240
  Control: 924,842
  Ratio: 0.9993
  p-value: 0.658
  → SRM passes

Metric 의 재분석:
  Sessions/UU: +0.19%, p=0.3754 (NOT significant)
  Metric 2: +0.04%, p=0.1671 (NOT significant)
  Metric 3: +0.13%, p=0.0727 (marginal)
  Metric 4: -0.12%, p=0.2877 (NOT significant)
  Metric 5: +0.01%, p=0.8275 (NOT significant)

→ 5 metric 의 statistical significance 사라짐
→ "Treatment 의 강한 효과" 가 SRM 의 부산물
2.3.4.1 Lesson
SRM 의 dramatic 영향:
  6% 사용자 의 unequal exposure
  → 5 metric 모두 의 significant lift 의 false 결론
  → 잘못된 launch decision 위험

해결:
  SRM check 의 의무
  Pass 시만 metric 분석
  Fail 시 investigation + fix

Trust foundation:
  SRM 가 실험 의 first check
  나머지 metric 의 prerequisite

저자 인용 (Bing actual data) 가 SRM 의 critical 성의 evidence.

가정 — SRM 무시 시

가정: 분석가 가 metric 만 보고 SRM check 무시.

2.3.4.2 시나리오 (저자 Bing 사례 기반)
Standard scorecard:
  5 metric 모두 statistically significant
  All positive 또는 critical
  Decision: Launch

Without SRM check:
  Bug 가 invisible
  False positive launch
  Production 의 실측 시 lift absent
  ROI 실망
  Engineer reputation 위기
2.3.4.3 해결
SRM check 의 enforcement:
  - 모든 scorecard 의 first row
  - Fail 시 다른 metric hide
  - Investigation 의 의무

이 enforcement 가 platform 의 표준.
2.3.4.4 Microsoft ExP 의 운영
ExP 의 SRM 처리:
  Scorecard 첫 row: SRM check
  Status: pass / warning / fail

  Pass: scorecard 표시 (모든 metric)
  Warning: scorecard 표시 + warning banner
  Fail: scorecard hide
    - 분석가가 reason 확인 후 force-show 가능
    - 일반 사용자 (PM, exec) 는 hide

이 progressive disclosure 가 trust 의 운영.

2.4 5 가지 SRM Causes

저자 명시 (Ch.21.3) — F-KOH21-2 에서 상세.

2.4.1 Cause 1 — Buggy Randomization

Standard randomization:
  hash(user_id) % 2 → 0 (T) 또는 1 (C)
  Random uniform

Common bugs:
  - Hash function 의 non-uniform
  - Ramp-up 의 implementation 잘못
  - Concurrent experiment 의 isolation issue
  - Hash seed 의 잘못된 selection
2.4.1.1 사례 — Microsoft Office Internal Users

저자 명시.

시나리오:
  Microsoft Office 의 internal employee 가 Treatment 에 100% 노출
  External user 가 10/10 split

Issue:
  Treatment 에 internal heavy user 포함
  Control 에 internal user 없음
  → Treatment 의 user composition 다름
  → 강한 lift (heavy user 의 자연스러운 effect)

SRM detect:
  Treatment count > Control count
  Internal user 만큼

After fix (internal user 제외):
  Treatment effect 가 사라짐
  Internal user 의 영향이 dominate

이 사례 가 randomization bug 의 typical pattern.

2.4.2 Cause 2 — Data Pipeline Issues

Pipeline 의 bot filtering 의 bias:
  Bot detection heuristic 의 적용
  Treatment 와 Control 의 다른 비율 filter
  → Sample mismatch
2.4.2.1 Scenario 2 의 mechanism
저자 Bing 사례:
  Treatment 의 변경으로 bot 분류 다름
  Old Chrome browser 의 일부 user 가 bot 분류 변화
  → Treatment 의 bot count > Control 의 bot count
  → After filtering, Treatment user 적음
  → SRM

2.4.3 Cause 3 — Residual Effects

실험 restart 의 함정:
  Day 1~7: 실험 진행 중 bug 발견
  Day 8: Bug fix + restart
  Day 8~ 분석 (분석 시작 = bug fix 시점)

Issue:
  Day 1~7 의 bug 가 user 의 일부 abandonment
  Day 8 의 sample 이 bug 영향 받은 user 의 subset
  Treatment 의 affected user 가 Control 보다 많이 abandoned
  → Sample mismatch

2.4.4 Cause 4 — Bad Trigger Condition

Trigger condition 의 mistake:
  redirect 시나리오:
    Site A → Site A' (Treatment redirect)
    Trigger condition: "user reached A'"

Issue:
  Redirect 의 일부 loss (browser, network)
  Treatment 의 일부 user 가 A' 도달 못 함
  → Triggered T 가 Triggered C 보다 작음
  → SRM in triggered analysis

2.4.5 Cause 5 — Treatment-Affected Attribute Trigger

Trigger 가 Treatment 영향 받는 attribute:
  예: dormant user 에 promotion
  Trigger: dormant attribute (last seen > 30d)

Issue:
  Treatment 의 effective:
    Dormant user 가 active
    "Dormant" attribute 변경
  Trigger condition 의 evaluation:
    실험 끝 시점 의 dormant
    → Treatment 의 일부 dormant user 가 active 화
    → Trigger 에 포함 안 됨

Solution:
  Pre-experiment 의 dormant attribute 사용
  Trigger condition 의 timing 의 critical

이 5 cause 가 산업 표준 의 root cause.

2.5 6 가지 Debugging 단계

저자 명시 (Ch.21.4) — F-KOH21-2 에서 상세.

Step 1: Upstream check
  Randomization point 의 upstream 의 차이?
  Trigger 시점 의 upstream 의 변경?

Step 2: Variant assignment validation
  Hash function 의 정확성
  Concurrent experiment 의 isolation

Step 3: Pipeline stage 의 SRM check
  Each stage 의 SRM:
    Raw data
    After bot filter
    After cleaning
    After enrichment
  → Stage 별 mismatch detect

Step 4: Initial period exclude
  실험 시작 의 일부 시간 (1 일~) 제외
  Caches, ramp-up, etc.

Step 5: Segment 분석
  Day 별 SRM
  Browser segment
  New vs returning user
  Other dimensions

Step 6: Other experiment 의 intersection
  Treatment 와 Control 의 다른 실험 variants 비율
  Should be similar

이 6 step 이 SRM debug 의 표준 절차.

2.6 4 가지 추가 Trust Guardrails

저자 명시 (Ch.21.5) — F-KOH21-3 에서 상세.

2.6.1 Guardrail 1 — Telemetry Fidelity

Click tracking 의 lossiness (Kohavi, Messner et al. 2010):
  Web beacon 이 일부 손실
  Treatment 가 loss rate 영향:
    예: Treatment 의 page 가 더 빠른 navigate
    → Beacon 손실 ↑
    → Apparent click rate ↓

Detection:
  Internal referrer 또는 dual logging
  Loss rate 의 variant 별 비교

2.6.2 Guardrail 2 — Cache Hit Rates

Shared cache 의 SUTVA violation (F-KOH19 의 Example 4):
  Treatment 와 Control 의 cache pressure 다름
  Hit rate 가 다름 → latency 다름

Detection:
  Cache hit rate 의 variant 별 비교
  Significant 차이 시 alert

2.6.4 Guardrail 4 — Quick Queries

Quick queries (Google·Bing):
  같은 user 의 1초 내 multiple search query
  Cause 알 수 없음 (open question)

Treatment 의 quick query 비율 변화 시:
  Result 의 untrustworthy
  → Untrustworthy guardrail

이 4 guardrail 이 SRM 외 의 추가 trust check.

직관 — Multi-layer Trust 의 mental model
2.6.4.1 4 layer
Layer 1 — SRM:
  Sample composition 의 검증
  가장 중요한 single check
  Pass 시 다른 metric 의 prerequisite

Layer 2 — A/A test (Ch.19):
  Variance 의 검증
  Distribution 의 정상

Layer 3 — Telemetry/Cache/Cookie:
  Implementation 의 hidden bug
  Specific 분야의 robustness

Layer 4 — Domain-specific (Quick queries 등):
  특정 metric 의 anomaly
  Awareness 만 (cause 모름)
2.6.4.2 Layered defense
모든 4 layer pass:
  → Strong trust
  → Decision quality 보장

Single layer fail:
  → Specific issue 의 detection
  → Layer 별 fix

Multi-layer fail:
  → Major issue
  → Comprehensive investigation
2.6.4.3 산업 표준
Modern platform:
  - SRM check: 의무
  - A/A: 자동
  - Telemetry/Cache/Cookie: 일부 platform
  - Domain-specific: mature platform 만

이 evolution 이 maturity 의 한 차원.

3 왜 필요한가

SRM check 부재 시.

  • Spurious significance: 잘못된 launch (Bing scorecard 의 평행)
  • Hidden bug: Implementation issue 가 invisible
  • Decision quality: 잘못된 결정의 누적

활성 시.

  • Trustworthy 통계
  • Hidden bug detection
  • Decision quality 보장

이 check 가 production trust 의 foundation.

4 응용 사례 — Microsoft ExP 의 SRM 운영

ExP 의 SRM 운영:

Continuous monitoring:
  매 실험의 SRM check (자동)
  Threshold: p < 0.001

Fail 시 procedure:
  1. Scorecard 의 SRM 첫 row
  2. Status: fail
  3. Other metric hide (default)
  4. Engineer 의 investigation 의무

Investigation tools:
  - Pipeline stage 별 SRM
  - Segment 별 SRM (browser, country, day)
  - Concurrent experiment 의 intersection

Documentation:
  - Common SRM cause 의 cheat sheet
  - Past 사례 의 case studies
  - Resolution patterns

이 운영이 ExP 의 trust 의 enforcement.

5 Ch.21 시리즈 다음 글

주제
F21-1 SRM 정의 + Scenarios 1, 2
F21-2 SRM Causes + Debugging
F21-3 Other Trust-Related Guardrail Metrics

6 코드 예시 — SRM Detection

자동 chi-square test 의 implementation.

import numpy as np
from scipy import stats

def check_srm(n_treatment, n_control, expected_ratio=0.5, alpha=0.001):
    """
    Sample Ratio Mismatch check via chi-square test.

    Returns:
        dict with statistic, p_value, passed
    """
    n_total = n_treatment + n_control
    expected_t = n_total * expected_ratio
    expected_c = n_total * (1 - expected_ratio)

    chi_squared = ((n_treatment - expected_t)**2 / expected_t
                   + (n_control - expected_c)**2 / expected_c)
    p_value = 1 - stats.chi2.cdf(chi_squared, df=1)

    return {
        "n_treatment": n_treatment,
        "n_control": n_control,
        "ratio": n_treatment / max(n_control, 1),
        "chi_squared": chi_squared,
        "p_value": p_value,
        "passed": p_value > alpha,
    }

# === Scenario 1: 저자 example ===
print("=== Scenario 1 ===")
result = check_srm(815_482, 821_588)
print(f"T: {result['n_treatment']:,}, C: {result['n_control']:,}")
print(f"Ratio: {result['ratio']:.4f}")
print(f"Chi-squared: {result['chi_squared']:.2f}")
print(f"P-value: {result['p_value']:.2e}")
print(f"Passed (p > 0.001): {result['passed']}")

# === Scenario 2: 저자 Bing example ===
print("\n=== Scenario 2 (Bing actual) ===")
result = check_srm(959_716, 965_679)
print(f"T: {result['n_treatment']:,}, C: {result['n_control']:,}")
print(f"Ratio: {result['ratio']:.4f}")
print(f"P-value: {result['p_value']:.2e}")
print(f"Passed: {result['passed']}")

# After fix (excluded buggy browser users)
print("\n=== After fix (excluded buggy browser users) ===")
result = check_srm(924_240, 924_842)
print(f"T: {result['n_treatment']:,}, C: {result['n_control']:,}")
print(f"Ratio: {result['ratio']:.4f}")
print(f"P-value: {result['p_value']:.4f}")
print(f"Passed: {result['passed']}")

# === Edge cases ===
print("\n=== Edge cases ===")

# Small sample
print("Small sample (1000/990):")
result = check_srm(1000, 990)
print(f"P-value: {result['p_value']:.4f}, Passed: {result['passed']}")

# Large sample with small ratio difference
print("\nLarge sample (1M/999K, ratio 1.001):")
result = check_srm(1_000_000, 999_000)
print(f"P-value: {result['p_value']:.4e}, Passed: {result['passed']}")

# 90/10 split (unequal design)
print("\n90/10 split (900K/100K):")
result = check_srm(905_000, 95_000, expected_ratio=0.9)
print(f"P-value: {result['p_value']:.4f}, Passed: {result['passed']}")
직관 — SRM Check 의 sensitivity
6.0.0.1 Power vs sample size
Same ratio (0.99):
  Sample 1K (T=995, C=1005):
    p-value: 0.82 (not detected)

  Sample 10K (T=9950, C=10050):
    p-value: 0.48

  Sample 100K (T=99,500, C=100,500):
    p-value: 0.024

  Sample 1M (T=995,000, C=1,005,000):
    p-value: 1E-12 (detected)

→ Same ratio, different detection
→ Larger sample = more sensitive
6.0.0.2 Implication
작은 sample:
  - 큰 ratio difference 만 detect
  - Sensitivity 부족

큰 sample:
  - 미세 ratio difference 도 detect
  - Hidden bug 의 vocal 화

산업 표준:
  Production 실험 의 sample 충분 (~수십만)
  → SRM check 가 sensitive
  → Bug 의 빠른 detection
6.0.0.3 Threshold 의 결정
Standard alpha:
  0.05: too lenient (5% false alarm)
  0.01: standard
  0.001: stringent (Microsoft ExP 의 default)

Why 0.001:
  100 실험 의 0.1 false alarm 만
  False alarm 의 cost: investigation 시간
  Bug 의 cost: incorrect decision
  → Stringent threshold 가 합리적

7 관련 주제

선행

다음 글

관련 챕터

다른 카테고리 연결

Subscribe

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