Data Processing 와 Computation — Cooking · Cleaning · Enriching · Materialization

Raw Log 에서 Trustworthy Scorecard 까지의 Pipeline 메커니즘

Kohavi (2020) Ch.16.1~16.2 를 깊게 다룬다. Data cooking 의 3 단계 (sort+group, clean, enrich), bot detection 의 heuristic, materialization vs virtual join 의 trade-off, per-user stats architecture vs integrated computation, terabyte 단위의 scaling, common metric definition 과 change management 의 governance 를 코드와 사례로 풀이한다.

Experimentation
A/B Test
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: Data Processing + Computation Pipeline

Raw instrumented log 를 분석 가능한 trustworthy scorecard 로 변환하는 두 단계 (Kohavi, Tang, Xu, 2020, Ch.16.1~16.2).

1.0.0.1 Stage 1 — Data Processing (Cooking)
Sub-step 작업 출력
Sort + Group User ID·timestamp 별 정렬, multi-source join User-session 단위 chronological event
Clean Bot/fraud 제거, instrumentation issue 수정 Trustworthy data
Enrich Browser, day-of-week, business logic annotation 분석 가능한 dimensional data
1.0.0.2 Stage 2 — Data Computation
입력: Processed data
계산: Per-user metrics, segments, statistical tests
출력: Scorecard (effect estimate + significance)

원문 (Ch.16.1): “To get the raw instrumented data into a state suitable for computation, we need to cook the data.”

핵심 통찰: “Cooking” 비유가 본질. Raw ingredient (log) 만으로는 못 먹음. 정렬·세척·향신료 (sort· clean·enrich) 후에야 dish (analysis) 가능. 각 step 의 quality 가 final dish 의 quality 결정.

2 개념 및 원리

2.1 Stage 1.1 — Sort and Group

2.1.1 Multi-source Join 의 메커니즘

저자 명시 (Ch.16.1): “As information about a user request may be logged by multiple systems, including both client- and server-side logs, we start by sorting and joining multiple logs.”

Multi-source 의 typical 구성:

Client logs:
  - Browser JavaScript (web)
  - Mobile app (iOS, Android)
  - Desktop client (Office, Adobe)

Server logs:
  - Web server (Nginx, Apache)
  - Application server (Java, Python)
  - API gateway

External logs:
  - Email service (SendGrid)
  - Push provider (Firebase)
  - Payment gateway (Stripe)

Internal state:
  - User profile (sign-in info)
  - Subscription status
  - Preference settings

2.1.2 Sort 차원

Primary sort: user_id
  - 같은 user 의 event 묶음
  - User-level metric 계산 가능

Secondary sort: timestamp (server time)
  - 시간 순서대로 event
  - Session 식별 (30 분 inactivity)
  - Causal analysis ("이 event 가 다음 event 야기?")

Tertiary sort: source priority
  - 같은 timestamp 시 어느 source 먼저
  - Server log 우선 (timestamp 정확)
  - Client log 후행 (clock 신뢰성 약함)

2.1.3 Materialization Trade-off

저자 강조: “You may not need to materialize this join, as a virtual join as a step during processing and computation may suffice.”

2.1.3.1 Materialize 의 use case
Materialize join 결과:

Use case 1 — 다목적 사용:
  - Experiment analysis
  - Debugging (특정 user 의 실제 행동 추적)
  - Hypothesis generation (새 metric 발견)
  - Compliance audit (특정 user 의 모든 행동)

Use case 2 — 빠른 query:
  - 한 번 join → 여러 query
  - Query latency 감소

Cost:
  - Storage 추가 (joined data 의 size)
  - Update 시 재 join 필요
2.1.3.2 Virtual join 의 use case
Virtual join (computation 시점에만):

Use case:
  - 한 use case (experiment analysis) 만 필요
  - Storage 절약 우선
  - Source data 가 자주 변경

Trade-off:
  - 매 query 마다 join 비용
  - Query latency ↑
  - 단 storage cost ↓
2.1.3.3 산업 trend
Initial stage:
  - Materialize 만 (단순)
  - Storage 의 cost 가 작아도 OK

Mature stage:
  - Hybrid:
    - Common queries: materialized
    - Ad-hoc queries: virtual
  - Storage tier 분리:
    - Hot: materialized (frequent access)
    - Cold: source 만 (rare access)

이 evolution 이 storage·compute trade-off 의 운영적 답.

2.2 Stage 1.2 — Cleaning

저자 명시 5 가지 cleaning task.

2.2.1 Task 1 — Bot/Fraud Detection

저자 강조: “We can use heuristics to remove sessions that are unlikely to be real users.”

2.2.1.1 5 가지 heuristic
1. Activity 양:
   - Too much: 1 시간에 10,000 events (정상 user 100~1000)
   - Too little: 0 click + 100 page view (bot scraping)

2. Event 사이 간격:
   - Too short: 10ms 이내 (정상 user 의 click 의 limits 미만)
   - Too consistent: 100% 정확히 5 초 간격 (script)

3. Activity 패턴:
   - 10K clicks on a page (impossible)
   - 모든 click 의 같은 (x, y) coordinate (bot)

4. Geographical anomaly:
   - 10 분 내 NY → London → Tokyo (impossible)
   - VPN 또는 fraud

5. Device fingerprint:
   - 100 user 가 같은 fingerprint (bot farm)
   - User-agent 의 unusual combination
2.2.1.2 “Laws of Physics” Violation

저자 격언: “users who engage with the site in ways that defy the laws of physics.”

물리 법칙 위반 사례:

1. Time travel:
   - Event timestamp 가 미래
   - Sequential event 의 time decrease (timestamp 거꾸로)

2. Multi-location simultaneity:
   - 같은 user 가 동시에 두 IP (다른 country)
   - Session ID 의 conflict

3. Speed limits:
   - 10 차원의 form 을 1 초 내 완성 (인간 불가)
   - 50 page 를 5 초 내 view (인간 불가)

4. Causality 위반:
   - "Confirm" 클릭 전에 "Confirmed" event
   - "Login" 전에 logged-in action

이 violation 들이 detection 의 hard signal.

2.2.2 Task 2 — Instrumentation Issue 수정

저자 명시: “We can also fix instrumentation issues, such as duplicate event detection or incorrect timestamp handling.”

Instrumentation issue 의 종류:

1. Duplicate event:
   원인:
     - Network retry (같은 event 재전송)
     - Browser back/forward (같은 page 재 trigger)
     - Mobile app 의 reconnect

   Detection:
     - Same user_id + same event_id + same timestamp
     - Deduplication

2. Timestamp 오류:
   원인:
     - Client clock 신뢰 불가 (Ch.13)
     - Server clock skew
     - Daylight saving 전환

   Fix:
     - Server timestamp 우선 사용
     - Local time → UTC 변환
     - Outlier filter (1900 년 또는 미래 timestamp 제거)

3. Encoding 오류:
   원인:
     - UTF-8 vs ASCII
     - 일부 character escape 실패

   Fix:
     - Standard encoding
     - Bad character 제거 또는 escape

2.2.3 Task 3 — Missing Event 의 한계

저자 강조: “Data cleansing cannot fix missing events, which may be a result of lossiness in the underlying data collection.”

Missing 의 원인:
  - Web beacon 손실 (Ch.13.1)
  - Network timeout
  - Server overload (rate limit)
  - Client crash (event 발생했지만 전송 안 됨)

Cleaning 의 limit:
  - "Event 가 발생했지만 데이터 없음" 인지 불가
  - Inferred 만 가능 (hypothesized)
  - 정확한 회복 불가능
2.2.3.1 Lossiness 의 inherent trade-off

저자 인용 (Kohavi, Longbotham, Walker 2010): “Click logging, for example, is inherently a tradeoff between fidelity and speed.”

Sync click logging:
  + Fidelity 높음 (loss rate 낮음)
  - Latency ↑ (사용자 click 후 대기)

Async click logging:
  + Latency 0 (사용자 즉시 navigate)
  - Loss rate ~10~30%

선택 ipsum trade-off:
  - 광고 click (compliance critical): sync
  - 일반 user behavior: async

2.2.4 Task 4 — Filter Bias 점검

저자 강조: “Some filtering may unintentionally remove more events from one variant than another, potentially causing a sample ratio mismatch (SRM).”

2.2.4.1 Filter bias 의 메커니즘
시나리오:
  Treatment 가 새 ML model
  Bot detection heuristic: "특이 행동 패턴 = bot"

Treatment 의 특이성:
  - 새 model 이 일부 사용자 에 unusual UI 노출
  - 사용자 가 unusual 행동 (모든 button 시도)
  - "Unusual pattern" → bot 판정 → filter

결과:
  - Treatment 의 사용자 가 Control 보다 많이 filter
  - Sample ratio mismatch (50/50 → 48/52)
  - SRM 의 cause 가 Treatment 자체

Detection:
  - SRM check (Ch.21)
  - Filter rate by variant 비교
  - 차이 detect 시 alert

이것이 cleaning 의 silent danger. 보호 의도의 cleaning 이 자체로 bias 를 만든다.

2.2.5 Task 5 — Edge Case Handling

일반 edge case:

1. Daylight saving:
   - Spring forward: 2~3am 사이 1 시간 사라짐
   - Fall back: 1~2am 두 번
   - Timestamp 분석 시 보정

2. Timezone shift:
   - 사용자가 여행 중
   - Same user 의 timezone 변경
   - Day-of-week 분석 시 사용자 의 local timezone

3. Year boundary:
   - 12/31 → 1/1
   - Year-over-year 분석 시 보정

4. Holiday effect:
   - Christmas, New Year, Black Friday
   - 평소 baseline 과 다름
   - Holiday 별 segment 분석

2.3 Stage 1.3 — Enrich

저자 명시.

2.3.1 Enrichment Levels

Per-event level:
  Event 자체에 dimension 추가
  - Browser family/version (user-agent parsing)
  - OS, device type
  - IP 의 country/region
  - Page category

Per-session level:
  Session 단위 aggregation
  - Total events
  - Total duration
  - Unique pages
  - Conversion 발생 여부
  - Bounce 여부

Per-user level:
  User 단위 aggregation
  - Total sessions
  - Total time on site
  - Last visit
  - User segment (new/return/power)

2.3.2 Experiment-specific Annotation

저자 강조: “Specific to experiments, you may want to annotate whether to include this session in the computation of the experiment results.”

2.3.2.1 포함·제외 결정
Annotation 의 logic:

이 session 을 실험에 포함?
  - Variant 가 결정된 시점 이후?
  - 사용자가 실험 영역 visit 했는가? (triggered)
  - 사용자가 bot 으로 분류 안 됐는가?
  - Variant 가 일관된가? (mid-session 변경 안 됨)

True 시 → 포함
False 시 → 제외 (분석에서 빼기)
2.3.2.2 Experiment Transition 정보

저자 강조: “experiment transitions information (e.g., starting an experiment, ramping up an experiment, changing the version number) to help determine whether to include this session.”

Transition 의 사례:

Day 1: 실험 시작
Day 2 noon: ramp 5% → 25%
Day 3: ramp 25% → 50%
Day 4 morning: variant code update (bug fix)
Day 5: ramp 50% → 100%

Session 의 timestamp 별 처리:
  Day 1 morning session: 실험 진행 중
  Day 2 11am session: 5% ramp (1/20 사용자)
  Day 2 1pm session: 25% ramp (1/4)
  Day 4 9am session: variant v1 (old)
  Day 4 11am session: variant v2 (new) ← 다른 처치 효과

분석 시:
  - 어떤 ramp 단계의 session 만 포함?
  - 어떤 variant version?
  - Transition 시점의 session 은 어떻게?

이 annotation 이 분석의 정확성 보장. Without it: confused mix of different states.

2.4 Stage 2 — Data Computation

저자 명시 (Ch.16.2).

2.4.1 2 가지 Architecture 비교

2.4.1.1 Architecture 1 — Materialize Per-User Stats
Pipeline:

Step 1: Per-user statistics 사전 계산
  for each user:
    - pageviews count
    - clicks count
    - impressions count
    - sessions count
    - total time
    - 기타 metric
  → Per-user table (materialized)

Step 2: User → Experiment mapping
  - 각 user 의 모든 active 실험
  - Variant assignment
  → Mapping table

Step 3: Per-experiment join
  for each experiment:
    SELECT user_stats.metric, mapping.variant
    FROM user_stats
    JOIN mapping ON user_id
    WHERE experiment_id = X
  - Variant 별 metric mean
  - Statistical test
2.4.1.2 장점·단점
장점:
  1. Per-user stats 가 다른 use case 에도 사용:
     - Overall business reporting
     - User segmentation analysis
     - LTV calculation
  2. Storage efficiency:
     - 한 번 계산 → 여러 use case
  3. Compute efficiency:
     - 일별 update 만
     - 실험 분석 시 빠른 lookup

단점:
  1. Storage cost:
     - Per-user table 의 size
     - 모든 metric × 모든 user
  2. Flexibility 제한:
     - 새 metric 추가 시 backfill 필요
     - 일부 segment 는 user-level 이 아닌 finer
2.4.1.3 Architecture 2 — Integrated Per-Experiment
Pipeline:

for each experiment:
  Step 1: Get raw data of users in this experiment
  Step 2: Compute per-user metric on-the-fly
  Step 3: Aggregate by variant
  Step 4: Statistical test
  Step 5: Output scorecard

별도 materialize 안 함 (memory 또는 streaming)
2.4.1.4 장점·단점
장점:
  1. Flexibility:
     - 실험별 다른 metric 정의 가능
     - 새 metric 즉시 추가
  2. Storage 절약:
     - Materialize 안 함
     - Source 만 저장
  3. 일관성:
     - 매번 같은 source 에서 계산
     - Stale data 위험 없음

단점:
  1. Compute cost:
     - 매 실험마다 raw 처리
     - Same metric 의 중복 계산

  2. 일관성 challenge:
     - 같은 metric 의 다른 pipeline 결과가 다를 가능성
     - Definition 공유 mechanism 필요

  3. 복잡성:
     - Pipeline orchestration
     - Distributed compute
2.4.1.5 산업 trend
Common pattern:
  Initial: Architecture 1 (materialize, 단순)
  Growth: Hybrid
    - Common metric: materialized
    - Rare metric: integrated
    - Storage tier 분리

Mature: Architecture 2 + strong governance
  - Definition 의 single source of truth
  - 자동 검증 (consistency check)
  - 빠른 metric 추가

2.4.2 Speed 와 Efficiency 의 dual

저자 인용: “Bing, LinkedIn, and Google all process terabytes of experiment data daily.”

2.4.2.1 Terabyte/day scale
규모 추정:
  사용자: 1 billion (10^9)
  일별 평균 events: 1000/user
  Total daily events: 10^12 (1 trillion)
  Event size: ~1 KB (after compression)
  Total daily data: ~10^15 byte = 1 PB (petabyte)

Bing/Google/LinkedIn:
  실험 specific data: ~1~10 TB/day
  전체 platform data: 1+ PB/day

Compute requirement:
  - Distributed processing (Spark, Dremel)
  - Petabyte-scale storage (BigQuery, Cosmos)
  - Fast read (column store, indexed)

이 scale 이 modern A/B platform 의 reality. 단일 server 로는 불가.

2.4.2.2 Initial vs Modern

저자 명시: “In the early days of the experimentation platform, Bing, Google, and LinkedIn generated experiment scorecards daily with a ~24-hour delay (e.g., Monday’s data shows up by end-of-day Wednesday). Today, we all have near real-time (NRT) paths.”

Evolution:

Initial (2010s):
  - Daily batch
  - 24~48 시간 lag
  - Decision speed 느림

Modern (2020s):
  - NRT (분 단위) + Batch (시간 단위)
  - Decision speed 가속
  - Innovation cycle 단축

2.4.3 Platform 의 3 가지 Recommendation

저자 명시 (Ch.16.2).

2.4.3.1 Recommendation 1 — Common Definitions
Common metric definition 의 가치:

문제 (no common definition):
  Team A 의 "engagement" = sessions per day
  Team B 의 "engagement" = clicks per session
  Team C 의 "engagement" = time on site

같은 단어, 다른 metric.

Reporting 시:
  "Engagement +5%" 의 의미 unclear
  - Sessions ↑?
  - Clicks ↑?
  - Time ↑?

해결 (common definition):
  Single source of truth
  "engagement" 가 명시 정의됨
  모든 분석이 same definition 사용
  Discussion 의 시작이 "왜" 가 아닌 "다음 어디로"

저자 강조: “you can discuss the interesting product questions rather than re-litigating definitions and investigating surprising deltas between similar-looking metrics produced by different systems.”

2.4.3.2 Recommendation 2 — Implementation Consistency
Common implementation:
  - Single code base
  - 모든 pipeline 이 same implementation 호출

또는 testing-based consistency:
  - 다른 implementations
  - 정기 testing 으로 일치 확인
  - Discrepancy 시 alert

이유:
  - 같은 metric 이 다른 pipeline 에서 다른 값 → 신뢰 위기
  - Decision 의 quality ↓
2.4.3.3 Recommendation 3 — Change Management

저자 강조: “Changing the definition of an existing metric is often more challenging than additions or deletions.”

Metric 변경의 challenge:

1. Backfill 결정:
   - 새 정의로 historical 데이터 재계산?
   - 어디까지? (1 년? 5 년?)
   - Storage·compute cost
   - 결과 변경의 영향

2. Comparison confusion:
   - Old definition vs new definition
   - 기존 결과 reference 의 모호성
   - Stakeholder 혼란

3. Stakeholder 알림:
   - Metric owner
   - Decision maker
   - Backfill 의 announcement
2.4.3.4 Change Management 의 운영
산업 표준:
  1. RFC (Request for Comments):
     - Metric 변경 제안
     - Stakeholder review
     - Comment + iterate

  2. Dual reporting period:
     - Old + new 동시 reporting
     - 1~3 개월 transition

  3. Backfill decision:
     - Cost-benefit 분석
     - 대부분: forward 만 변경, no backfill
     - 단 critical metric: backfill

  4. Deprecation announcement:
     - Old metric 의 usage 중단 시점 명시
     - Migration deadline
     - Final removal
가정 — Common Definition 부재 시

가정: 회사 가 metric definition 통합 안 됨. 각 team 자기 정의.

2.4.3.5 1 년 후 시나리오
같은 회사 의 분석:

Team A (Marketing): "engagement = clicks per session"
Team B (Product): "engagement = sessions per day"
Team C (Analytics): "engagement = time on site"

Cross-team 회의:
  PM: "이번 quarter engagement +10%"
  Analyst: "어느 engagement?"
  PM: "음... 모든 engagement?"

Confusion:
  - 다른 metric 이 다른 방향
  - "+10%" 의 진정 의미 모호
  - Discussion 의 30 분 이 definition 토론
  - 30 분 후 metric 일치 시 다음 토론
2.4.3.6 의사결정 의 영향
Launch 결정:
  Team A 의 engagement +10% 보고
  → Launch 추천

Team C 의 분석:
  - "이 launch 가 time-on-site 영향?"
  - 별도 분석 필요 (다른 definition 으로)
  - 시간 추가
  - Inconsistency 발견 시 confusion

결과:
  - Decision speed ↓
  - 분석 quality 의문
  - Cross-team trust 위기
2.4.3.7 해결
1. Metric registry:
   - 회사 단위 single source
   - 모든 metric 의 명시 정의
   - Owner, version, history

2. Tooling enforcement:
   - 분석 도구가 registry 의 metric 만 사용
   - Custom metric 정의 시 registry 등록 필수

3. Cultural norm:
   - "engagement" 같은 용어의 명시 metric 매핑
   - Slack message 에도 metric ID 첨부
   - 회의 시 metric 명확화

이 governance 가 modern platform 의 silent foundation. Visible 하지 않지만 모든 결정의 quality 의 기초.

3 왜 필요한가

Data Processing + Computation 부재 시.

  • Bot noise — Treatment effect 가 bot 행동 의 부산물
  • Filter bias — Variant 별 다른 cleaning → SRM
  • Stale materialization — Old data 로 결정
  • Inconsistent metric — 같은 metric 의 다른 결과
  • Slow decision — Daily lag 으로 innovation 느림

활성 시.

  • Trustworthy data — Bot, anomaly 정리
  • Fast decision — NRT path
  • Consistent metric — Common definition
  • Flexible analysis — Architecture 적합 선택
  • Scalable — Terabyte 단위 처리

이 격차가 platform maturity 의 핵심 차원. Run·Fly 단계의 prerequisite.

4 응용 사례 — Bing 의 Daily Pipeline

Bing 의 매일 운영 (가상 reconstruction):

00:00 UTC: 새 day 시작

Stage 1 — NRT Path (분 단위):
  - Real-time event stream
  - SRM 체크 (5 min)
  - Crash rate alert (1 min)
  - Auto shut-off

Stage 2 — Batch Path (3 hour cycle):
  03:00: Yesterday data 의 final commit
  03:30~04:00: Sort + group
  04:00~05:00: Bot detection + cleaning
  05:00~06:00: Enrichment
  06:00~07:00: Per-user stats computation
  07:00~08:00: Per-experiment metric + segment
  08:00~09:00: Statistical test (multiple correction)
  09:00: Daily scorecard published

Stage 3 — Visualization:
  09:00: Dashboard updated
  All experimenters can access

이 pipeline 이 daily innovation cycle 의 backbone. Engineer 가 매일 09:00 에 어제 결과 review → 새 실험 시작.

5 코드 예시 — Bot Detection Heuristic

저자 명시 5 가지 heuristic 의 구현.

import pandas as pd
import numpy as np
from datetime import timedelta

rng = np.random.default_rng(42)

# 가상 event log
n_events = 10_000
n_users = 500
events = []
for i in range(n_events):
    is_bot = rng.uniform(0, 1) < 0.05  # 5% bot

    if is_bot:
        # Bot 행동 패턴
        user_id = f"bot_{rng.integers(0, 5):03d}"  # 5 bot accounts
        timestamp = pd.Timestamp("2026-05-08 10:00") + timedelta(seconds=int(i * 0.1))
        click_x = 0  # 항상 같은 x (bot)
        click_y = 0
    else:
        # 정상 user
        user_id = f"user_{rng.integers(0, n_users):04d}"
        timestamp = pd.Timestamp("2026-05-08 10:00") + timedelta(seconds=int(rng.uniform(0, 3600)))
        click_x = rng.uniform(0, 1000)
        click_y = rng.uniform(0, 1000)

    events.append({
        "event_id": f"evt_{i:05d}",
        "user_id": user_id,
        "timestamp": timestamp,
        "click_x": click_x,
        "click_y": click_y,
        "is_bot_truth": is_bot,
    })

df = pd.DataFrame(events).sort_values(["user_id", "timestamp"])

# Heuristic 1 — Activity 양
print("=== Heuristic 1: Activity 양 ===")
activity_per_user = df.groupby("user_id").size()
print(f"Median activity: {activity_per_user.median():.0f}")
print(f"P99 activity: {activity_per_user.quantile(0.99):.0f}")
high_activity_users = activity_per_user[activity_per_user > activity_per_user.quantile(0.99)].index
print(f"Suspect users (top 1% activity): {len(high_activity_users)}")
print(f"Of which actually bots: {sum(df[df['user_id'].isin(high_activity_users)]['is_bot_truth'])}")

# Heuristic 2 — Event 사이 간격
print("\n=== Heuristic 2: Event 사이 간격 ===")
df["time_diff"] = df.groupby("user_id")["timestamp"].diff().dt.total_seconds()
suspect_intervals = df[df["time_diff"] < 0.5]
suspect_users_interval = suspect_intervals["user_id"].value_counts()
suspect_users_interval = suspect_users_interval[suspect_users_interval > 10].index
print(f"Suspect users (too short intervals): {len(suspect_users_interval)}")
print(f"Of which actually bots: {sum(df[df['user_id'].isin(suspect_users_interval)]['is_bot_truth'])}")

# Heuristic 3 — Click coordinate 패턴
print("\n=== Heuristic 3: Click coordinate ===")
click_variability = df.groupby("user_id").agg({"click_x": "std", "click_y": "std"})
zero_variability_users = click_variability[
    (click_variability["click_x"] < 1) & (click_variability["click_y"] < 1)
].index
print(f"Suspect users (zero click variability): {len(zero_variability_users)}")
print(f"Of which actually bots: {sum(df[df['user_id'].isin(zero_variability_users)]['is_bot_truth'])}")

# 종합 detection
print("\n=== 종합 Bot Detection ===")
detected_bots = set(high_activity_users) | set(suspect_users_interval) | set(zero_variability_users)
actual_bots = set(df[df["is_bot_truth"]]["user_id"])
true_positives = detected_bots & actual_bots
false_positives = detected_bots - actual_bots
false_negatives = actual_bots - detected_bots

print(f"Detected: {len(detected_bots)}")
print(f"Actual bots: {len(actual_bots)}")
print(f"True positives: {len(true_positives)}")
print(f"False positives: {len(false_positives)}")
print(f"False negatives: {len(false_negatives)}")
print(f"Precision: {len(true_positives)/len(detected_bots)*100:.1f}%")
print(f"Recall: {len(true_positives)/len(actual_bots)*100:.1f}%")

# Filter 의 SRM bias 점검 (가상 variant 추가)
print("\n=== Filter 의 SRM Bias 점검 ===")
df["variant"] = rng.choice(["T", "C"], size=len(df), p=[0.5, 0.5])
filter_rate_T = df[df["user_id"].isin(detected_bots) & (df["variant"] == "T")].shape[0] / df[df["variant"] == "T"].shape[0]
filter_rate_C = df[df["user_id"].isin(detected_bots) & (df["variant"] == "C")].shape[0] / df[df["variant"] == "C"].shape[0]
print(f"Filter rate T: {filter_rate_T*100:.2f}%")
print(f"Filter rate C: {filter_rate_C*100:.2f}%")
print(f"Difference: {abs(filter_rate_T - filter_rate_C)*100:.3f}%")
if abs(filter_rate_T - filter_rate_C) > 0.005:
    print("*** ALERT: Filter rate difference > 0.5%, possible SRM ***")
else:
    print("OK: No significant filter bias")
직관 — Bot Detection 의 trade-off

이 코드의 메시지.

1. 단일 heuristic 의 한계

각 heuristic 별 detection rate 가 일정. 단일 사용 시 bot 의 일부만 catch.

2. 종합 detection 의 효과

여러 heuristic 의 union → recall ↑. 단 precision 약간 ↓ (false positive ↑).

3. Filter 의 SRM bias 점검 자체가 critical

Bot detection 적용 후 SRM check:
  - Treatment·Control 의 filter rate 차이?
  - 차이가 0.5% 이상 시 alert

Why critical:
  - Cleaning 자체가 bias 만들 수 있음
  - Detect 되는 bot 패턴이 variant 별 다른 빈도
  - Filter 후 SRM → 분석 무력화

4. Precision vs Recall trade-off

Strict heuristic (precision ↑, recall ↓):
  - 명백한 bot 만 catch
  - 일부 bot 잔존 → noise 일부

Loose heuristic (precision ↓, recall ↑):
  - 많은 user 제거
  - 정상 user 도 일부 제거 → bias risk

선택:
  - SRM check + filter bias 점검 통과 시 → loose 가능
  - 통과 안 하면 strict

이 trade-off 가 bot detection 의 본질. 100% 정확 detection 은 impossible. 적절한 균형 + 검증.

6 관련 주제

선행

다음 글

관련 챕터

다른 카테고리 연결

Subscribe

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