A/B TEST는 어떤 처리(treatment)를 했을 때 발생하는 결과를 통계적으로 검증하는 테스트이다. 이를 통해 더 효율이 높은 방법을 알 수 있다. 웹사이트나 게임 등에서 어떤 방법이 더 효율적인지 판단할 때 많이 사용된다.
A/B 테스트는 보통 2개의 그룹을 대상으로 테스트가 진행된다. 하나는 처리를 한 treatment 그룹과 하지 않은 control 그룹이다. 우리나라 말로 처리군, 대조군이라고 하는데 영어가 더 이해하기 쉬운 듯 하다. 대상은 랜덤하게 추출하는 것이 중요하다. 그렇지 않은 경우, 다른 요인의 작용으로 두 그룹이 차이가 날 수도 있기 때문이다.
A/B 테스트보다 진보(?)한 방법으로 멀티암드 밴딧 알고리즘이 있다. A/B테스트로 처리를 한 것이 결과가 더 좋으면, 이후에는 모든 대상을 처리한다. 이보다는 더 빠르게 최적화할 수 있는 알고리즘이 멀티암드 밴딧 알고리즘이라고 한다. 이 방법은 A가 더 우수하더라도 모든 결과에 A를 적용하지 않는다. 0부터 1사이의 난수를 생성해서, 이 값이 미리 정해둔 값보다 작으면 랜덤하게 결과를 선택한다. 반대의 경우에는 지금까지 결과중에 가장 좋은 결과를 표시한다. 3가지 이상의 처리를 한 경우 전통적인 통계방식의 A/B 테스트는 결정 과정이 훨씩 복잡해지므로, 이 경우에는 밴딧 알고리즘의 장점이 훨씰 커진다고 한다.
A/B 테스트에 관련된 내용을 찾다보니 아래의 포스팅에서 구체적인 내용을 더 찾아볼 수 있었다. 하지만 코드가 R로 되어 있어, 파이썬으로 테스트를 해 보았다.
데이터셋을 별도로 가지고 있는 것은 아니라, 임의로 만들어보았다. 먼저 control그룹을 만들어 보았다.
import pandas as pd
import numpy as np
import random
date_index=pd.date_range('2020-01-01', periods=100)
temp2=pd.date_range('2020-01-01', periods=100)
for i in range(0,9):
date_index = date_index.append(temp2)
df_control = pd.DataFrame({"testing":"control", "r":np.random.rand(1000)})
df_control["like"] = df_control["r"].apply(lambda x: 1 if x>0.5 else 0)
df_control.index = date_index
df_control["like"].value_counts()
다음으로 test그룹을 만들어 보았다.
df_test = pd.DataFrame({"testing":"test", "r":np.random.rand(1000)})
df_test["like"] = df_test["r"].apply(lambda x: 1 if x>0.2 else 0)
df_test.index = date_index
df_test["like"].value_counts()
이제 두 데이터셋을 합쳤다.
df = pd.concat([df_control, df_test], 0)
df["testing"].value_counts()
control 1000
test 1000
Name: testing, dtype: int64
각각 1000개 씩의 샘플을 보유한 그룹을 만들었다. 이제 날짜별로 '좋아요'한 비율을 구하고 비교해보았다.
df_gr = df.groupby(["index", "testing"]).agg({"like":"sum", "r":"count"}).reset_index(drop=False)
df_gr["ratio"]=df_gr["like"]/df_gr["r"]
import seaborn as sns
sns.lineplot(data=df_gr, x="index", y="ratio", hue="testing")
다음으로 statsmodels 함수를 이용해 t테스트를 수행했다. 동일집단의 경우 paired t검정을 하거나, 범주형 변수의 경우 카이스퀘어 검증을 하기도 한다고 한다. 실험은 2개 이상 진행한 경우는 분산분석 모형이 되기도 한다. 위의 포스팅에서는 많은 경우에 일반화 선형모형을 동일하게 사용할 수 있다고 하여, 일반화 선형모형도 적용해 보았다.
import statsmodels.stats.weightstats as ws
df_control_ratio = df_gr[df_gr["testing"]=="control"]["ratio"]
df_test_ratio = df_gr[df_gr["testing"]=="test"]["ratio"]
ws.ttest_ind(df_test_ratio, df_control_ratio, alternative="larger", usevar="pooled", value=0)
(12.594134227461538, 2.126753298486975e-27, 198.0)
순서대로 t통계량, pvalue, 자유도이다. p-value가 굉장히 낮은 것을 알 수 있다. 0.3이 더 크다고 볼 수 있는지 검증해 보았다.
ws.ttest_ind(df_test_ratio, df_control_ratio, alternative="larger", usevar="pooled", value=0.3)
(-0.803880908135841, 0.7887850899570643, 198.0)
다음으로 statsmodels패키지를 이용해서, 일반화 회귀모형에 적용해 보았다. statsmodel은 회귀모형을 만드는 방법이 여러가지가 있는데, 그 중에서 fomula를 이용한 방법을 사용하였다.
import statsmodels.api as sm
import statsmodels.formula.api as smf
df["testing_cate"]=df["testing"].apply(lambda x:0 if x=="control" else 1)
glm_model = smf.glm(formula='like~testing_cate', data=df, family=sm.families.Binomial())
glm_result = glm_model.fit()
glm_result.summary()
선형모형 결과도 유의미하게 나왔다.
오늘은 이렇게 파이썬으로 A/B테스트를 하는 방법에 대해서 알아보았다. 다음에는 A/B테스트를 하기 위한 표본의 크기 등에 대해서도 알아보도록 하겠다.
'데이터 > 데이터 분석' 카테고리의 다른 글
범주형 데이터 기준 의사결정나무 알고리즘 만들기 (0) | 2022.01.17 |
---|---|
데이터 분석 용어 정리 - Funnel, adhoc 분석 (0) | 2022.01.17 |
XGBoost와 랜덤 포레스트 재학습 하는 방법은? (0) | 2022.01.17 |
SOM 군집 알고리즘이란? 파이썬 학습 방법은?! (0) | 2022.01.16 |
파이썬 판다스 데이터프레임 리스트로 추출하는 방법은?! (0) | 2022.01.15 |
파이썬 A/B테스트 필요샘플 크기 확인 법, 검정력 테스트?! (0) | 2022.01.15 |
지역별(시군구, 동단위까지) 소득 통계 데이터 수집하는 3가지 방법 (2) | 2022.01.14 |
데이터 유사도 알고리즘 알아보기! (0) | 2020.11.08 |