SeedFinder는 실험 전 편향을 제거하기 위한 방법 중 하나입니다.

SeedFinder는 실험 전 편향을 제거하기 위한 방법 중 하나입니다.
Photo by Silas Köhler / Unsplash

SeedFinder

  • 편향을 최소화하기 위해 "SeedFinder" 방식에서 가장 적은 편향을 가진 SaltKey를 찾는 프로세스
  • 기본적인 아이디어는 여러 SaltKey를 사용해 무작위화된 그룹을 생성하고, A/A 테스트에서 이 그룹들의 성과 지표(예: 전환율 등)가 균등한지 평가하여 편향이 적은 SaltKey를 선택하는 것입니다.

전체 프로세스

  1. 여러 SaltKey를 생성
  2. 각 SaltKey에 대해 고객 ID와 결합하여 무작위화된 Identifier 생성
  3. 각 SaltKey에 대해 A/A 테스트를 수행하고 그룹 간 차이를 비교
  4. 가장 적은 편향을 가진 SaltKey를 선택

코드

import hashlib  
import pandas as pd  
import numpy as np  
from scipy import stats  
import seaborn as sns  
import matplotlib.pyplot as plt  
  
# 예시 데이터: 최근 1-2주 동안의 고객 데이터 (Customer ID 및 성과 지표)  
data = pd.DataFrame({  
    'customer_id': np.random.randint(1, 10000, 1000),  
    'metric': np.random.rand(1000)  # 예: 구매 전환율  
})  
  
# Inf 값을 NaN으로 처리 (이 옵션을 직접 설정하는 방식 대신 수동으로 처리)  
data.replace([np.inf, -np.inf], np.nan, inplace=True)  
  
# SaltKey를 활용한 해시 기반 그룹 무작위화 함수  
def create_randomized_identifier(customer_id, salt_key):  
    hash_input = f"{customer_id}{salt_key}".encode('utf-8')  
    hashed_value = hashlib.sha256(hash_input).hexdigest()  
    # 해시 값을 바탕으로 그룹을 결정 (2개의 그룹으로 나누기 위해 mod 연산)  
    return int(hashed_value, 16) % 2  # 0 또는 1로 그룹화  
  
# 여러 SaltKey 시도 (예: 100개의 서로 다른 SaltKey 생성)  
salt_keys = [f'salt_{i}' for i in range(100)]  
  
# 결과를 저장할 리스트 초기화  
bias_results = []  
  
# 각 SaltKey에 대해 A/A 테스트 수행  
for salt_key in salt_keys:  
    data['group'] = data['customer_id'].apply(lambda x: create_randomized_identifier(x, salt_key))  
  
    # 그룹별 성과 지표의 평균을 계산  
    group_means = data.groupby('group')['metric'].mean()  
  
    # 그룹 간 차이를 t-test로 평가 (A/A 테스트의 경우 p-value가 0.05 이상이 기대됨)  
    group_0 = data[data['group'] == 0]['metric']  
    group_1 = data[data['group'] == 1]['metric']  
    t_stat, p_value = stats.ttest_ind(group_0, group_1)  
  
    # p-value를 기준으로 편향이 적은 SaltKey 평가  
    bias_results.append({'salt_key': salt_key, 'p_value': p_value})  
  
# bias_results 리스트를 DataFrame으로 변환  
bias_results_df = pd.DataFrame(bias_results)  
  
# NaN 값을 제거하고, p_value 컬럼을 float 타입으로 변환  
bias_results_df = bias_results_df.dropna(subset=['p_value'])  # NaN 값 제거  
bias_results_df['p_value'] = bias_results_df['p_value'].astype(float)  # 숫자형으로 변환  
  
# 가장 Bias가 적은 SaltKey는 p-value가 가장 높은 값 (그룹 차이가 가장 적은 경우)  
best_salt_key = bias_results_df.sort_values(by='p_value', ascending=False).iloc[0]  
print(f"가장 적은 편향을 가진 SaltKey: {best_salt_key['salt_key']} (p-value: {best_salt_key['p_value']})")  
  
# Seaborn을 사용한 p-value 분포 시각화  
plt.figure(figsize=(10, 6))  
sns.histplot(bias_results_df['p_value'], bins=30, kde=True)  
plt.title('Distribution of p-values for Different SaltKeys')  
plt.xlabel('p-value')  
plt.ylabel('Frequency')  
plt.axvline(x=0.05, color='red', linestyle='--', label='p=0.05')  
plt.legend()  
plt.show()