본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] A/B Testing vs Multi-Armed Bandit: 모델 업데이트 시 2가지 트래픽 전환 전략 해결 방법

by Papa Martino V 2026. 4. 20.
728x90

A/B Testing vs Multi-Armed Bandit
A/B Testing vs Multi-Armed Bandit

 

1. 모델 배포의 딜레마: 탐색(Exploration)과 수확(Exploitation)

새로운 머신러닝 모델을 개발한 후, 이를 실제 서비스에 적용할 때 우리는 큰 고민에 빠집니다. "새 모델이 정말 기존 모델보다 나은가?"라는 의문을 해결하기 위해 트래픽을 나누어 테스트해야 합니다. 이때 가장 대중적인 A/B Testing과 동적인 최적화 방식인 Multi-Armed Bandit (MAB) 알고리즘은 각각 뚜렷한 차이점과 활용 사례를 가집니다.

2. A/B Testing과 Multi-Armed Bandit 핵심 차이 해결 및 비교

두 전략의 기회비용과 통계적 유의성 확보 방식을 상세히 비교합니다.

항목 A/B Testing (고정 할당) Multi-Armed Bandit (동적 할당)
트래픽 배분 방식 50:50 또는 고정된 비율로 유지 성능에 따라 실시간으로 비율 조정
최적화 시점 실험 종료 후 분석 단계에서 결정 실험 진행 중 실시간 최적화
기회비용(Regret) 높음 (성능 낮은 모델에도 트래픽 유지) 낮음 (우수한 모델에 트래픽 집중)
통계적 엄밀함 매우 높음 (P-value 계산 용이) 낮음 (결과에 편향 발생 가능)
주요 용도 새로운 기능의 인과관계 증명 광고 클릭률, 추천 시스템 수익 최적화

3. 실무자를 위한 7가지 Python 기반 트래픽 제어 예제

개발자가 실무 서버 시스템에 즉시 도입할 수 있는 다양한 알고리즘과 해결 코드를 제공합니다.

Example 1: 해시 함수를 이용한 고정 A/B 테스팅 트래픽 분할

사용자 ID를 기반으로 항상 동일한 모델을 경험하게 하는 세션 유지 방식입니다.

import hashlib

def get_model_assignment(user_id, salt="experiment_v1"):
    # 사용자 ID와 소금을 결합하여 해시 생성
    hash_val = hashlib.md5(f"{user_id}{salt}".encode()).hexdigest()
    # 해시값을 숫자로 변환 후 100으로 나눈 나머지 계산
    score = int(hash_val, 16) % 100
    
    if score < 50:
        return "Model_A (Champion)"
    else:
        return "Model_B (Challenger)"

# 사용 예시
print(get_model_assignment("user_123"))

Example 2: Epsilon-Greedy 알고리즘 기반 MAB 구현

가장 간단하면서도 강력한 MAB 방식으로, 일정 비율(epsilon)로 탐색을 수행합니다.

import numpy as np

class EpsilonGreedy:
    def __init__(self, epsilon=0.1, n_models=2):
        self.epsilon = epsilon
        self.counts = np.zeros(n_models)
        self.values = np.zeros(n_models)

    def select_model(self):
        if np.random.random() < self.epsilon:
            return np.random.randint(len(self.values)) # 탐색(Exploration)
        return np.argmax(self.values) # 수확(Exploitation)

    def update(self, model_idx, reward):
        self.counts[model_idx] += 1
        n = self.counts[model_idx]
        # 점진적 평균 업데이트 식
        self.values[model_idx] = ((n - 1) / n) * self.values[model_idx] + (1 / n) * reward

# 0번 모델 성능이 더 좋은 환경 시뮬레이션
mab = EpsilonGreedy()
mab.update(0, 1) # 모델 0 성공
mab.update(1, 0) # 모델 1 실패

Example 3: 톰슨 샘플링(Thompson Sampling)을 이용한 고차원 최적화

베이지안 사후 확률을 이용하여 더 지능적으로 트래픽을 전환하는 해결 방법입니다.

import random

class ThompsonSampling:
    def __init__(self, n_models=2):
        self.alphas = [1] * n_models # 성공 횟수 초기화
        self.betas = [1] * n_models  # 실패 횟수 초기화

    def select_model(self):
        # 베타 분포에서 샘플링하여 가장 높은 값 선택
        samples = [random.betavariate(self.alphas[i], self.betas[i]) for i in range(len(self.alphas))]
        return samples.index(max(samples))

    def update(self, model_idx, success):
        if success:
            self.alphas[model_idx] += 1
        else:
            self.betas[model_idx] += 1

Example 4: 시간에 따른 가중치 감쇠(Time Decay) 전략

과거의 데이터보다 최신 데이터의 성능 지표에 가중치를 두어 모델을 전환합니다.

def calculate_decayed_score(history, decay_factor=0.9):
    """
    history: [1, 0, 1, 1, 0] (최신이 마지막)
    """
    score = 0
    weight = 1
    for outcome in reversed(history):
        score += outcome * weight
        weight *= decay_factor
    return score

Example 5: 카나리 배포(Canary Deployment) 트래픽 전환기

특정 비율만큼 조금씩 트래픽을 늘려가며 모델의 에러율을 모니터링합니다.

def canary_router(traffic_pct):
    import random
    if random.uniform(0, 100) < traffic_pct:
        return "v2_new_model"
    return "v1_stable_model"

# 실무 예시: 에러가 없으면 10분마다 traffic_pct를 10씩 증가

Example 6: 상한 신뢰 구간(UCB) 기반 모델 선택

불확실성이 높은 모델에게 기회를 주어 탐색 손실을 최소화하는 알고리즘입니다.

import math

def ucb_score(value, count, total_trials):
    if count == 0: return float('inf')
    # 보상 평균 + 탐색 보너스
    return value + math.sqrt(2 * math.log(total_trials) / count)

Example 7: FastAPI와 결합한 실시간 모델 서빙 라우터

실제 API 엔드포인트에서 모델 선택 로직을 통합하는 구조입니다.

from fastapi import FastAPI

app = FastAPI()
mab_strategy = ThompsonSampling(n_models=2)

@app.get("/predict")
async def predict(user_id: str):
    idx = mab_strategy.select_model()
    model = [model_a, model_b][idx]
    
    result = model.predict(user_id)
    # 실제 비즈니스 결과(클릭 여부 등)를 비동기로 피드백 받아 업데이트 수행
    return {"prediction": result, "model_version": idx}

4. 결론: 어떤 전략을 선택해야 하는가?

단순히 어떤 모델이 '왜' 좋은지 학술적으로 증명해야 한다면 A/B Testing이 정답입니다. 하지만 전자상거래 추천이나 광고와 같이 실험 중 발생하는 수익 손실을 최소화해야 한다면 Multi-Armed Bandit이 훨씬 경제적인 해결 방법이 됩니다. 최근 MLOps 트렌드는 두 방식을 혼합하여, 초기에는 A/B 테스트로 안전성을 검증하고 이후 MAB로 전환하여 수익을 극대화하는 하이브리드 전략을 취하고 있습니다.


내용 출처 및 참조:

  • Google Cloud Architecture Framework: MLOps Deployment Strategies
  • Multi-Armed Bandit Algorithms for Website Optimization (O'Reilly Media)
  • Statistical Significance in A/B Testing: A Practitioner's Guide
  • 파이썬을 활용한 실무 강화학습 및 최적화 전략 세미나 (2025)
728x90