본문 바로가기
Archive/데이터 분석 관련

[Data] A/B Test 사용해보기 : Cookie-Cats

by 다람이도토리 2024. 1. 16.

내 블로그에서 직접 이를 실험하면 좋겠지만 유의미하게 로그 획득을 정확하게 하기 어려울 것이기에 캐글에 존재하는 다른 데이터로 A/B Test 연습을 대체하였다. 아래 깃헙 링크를 통해 조금 더 구체적인 세부 코드들을 확인할 수 있다.

https://github.com/swtaktak/TIL_new/blob/main/data_analyst_practice/240116_AB_Test_Practice.ipynb

Data Link : https://www.kaggle.com/datasets/zahrazolghadr/ab-test-cookie-cats

위의 데이터는 "Cookie-Cats"라는 게임의 데이터이다.

문제 상황

게임 초반의 허들을 변화했을 때, 리텐션에 어떤 변화가 있을지를 살펴보는 A/B 테스트를 진행해보자.

우선 Cookie-Cats는 흔히 말하는 Match3의 변형으로, 한붓그리기 류의 퍼즐 게임이다. 즉 캔디크러시 사가처럼, 하나의 탄을 클리어하는 방식이다. 여기서 말하는 초반의 허들이란,

다음처럼, 일정 스테이지를 진행했을 때 "진행을 막는" 허들을 의미한다. (난이도 차원의 허들이 아니다.)

이번 데이터를 바탕으로 생각해 볼 문제는 다음과 같다.

인게임상 최초의 허들을 [stage 30 클리어 이후]에서  [stage 40 클리어 이후]로 뒤로 늦춘다면
리텐션이 개선될까?

이를 A/B 테스트로 수행하고자 한다.

 

기본 데이터 탐색 및 실험 설계, 가설 설정

데이터를 통해 실험 상황을 확인해보면 다음과 같다.

기존안 : Stage30에 1차 허들을 설치한다. (version = gate_30)
변경안 : Stage40에 1차 허들을 설치한다. (version = gate_40)

기존안에서 변경안으로 변경할 경우 D1 리텐션과 D7 리텐션은 개선된다. (재방문시에는 True)
기존안 유저인지, 변경안 유저인지는 version을 통해 확인 가능하다.

그럼 sum_gamerounds는 무엇일까? 이는 2주 동안의 총 플레이 횟수이다. 즉 2주동안 몇 판을 플레이 했는가이다.
여기서 중요한 점은 클리어 라운드 지표는 아니고, "플레이한 횟수"이므로 실패 횟수 자체는 반영되지 않았다.
하지만 하나 확실한 점은,

30판이나 40판을 플레이 하지 않았다면, 허들에 도달한 적이 없다.

라는 점이다. 이 점을 정말 명심해두자.

그럼 sum_gamerouns를 확인해 보았는데 어차피 작은 값은 상관없으니까, 큰 값만 보자.

아무리 생각해도 4만 9천판은 말이 안되는 데이터이다 나머지 최상위  판수를 보인유저들은 2000판 정도인데 값이 확 뛴 것을 보면 4만 9천판 관련 데이터는 지우는 것이 합리적일 것이다. 1개의 데이터만 지우고 분석을 진행하자.

 

전체 유저 대상의 A/B 테스트의 수행

우선 전체 유저를 대상으로 A/B 테스트를 수행하자. A/B 테스트를 위해 여기서는 먼저 카이제곱 검정을 활용한다.
이후 t-test를 활용하는 버전도 함께 살펴볼 것이다.

카이제곱 검정이므로, 가설 수립은 리텐션의 변화가 있다 / 없다 로 구분해야 할 것이다. 즉,

 - 귀무가설(H0) : gate를 뒤로 늦춰도 리텐션은 변화가 없다.
 - 대립가설(H1) : gate를 뒤로 늦추면 리텐션은 변화가 있다.

가설은 다음과 같이 세워지게 된다. 이제 실제 코드를 통해 확인하면 다음과 같다.

def click_abtest(a_click, total_a, b_click, total_b):
    click = [a_click, b_click]
    no_click = [total_a-a_click, total_b-b_click]
    chi2, p, dof, expected = scipy.stats.chi2_contingency([click, no_click])
    return p

다음과 같이 p-value를 뱉게 된다. 물론 검정력도 추후 확인해야겠지만 여기서는 우선 p-value에 조금 더 집중해보자.
유의 수준은 5%로 결정하였다.

항목 p-value
D1 리텐션 0.075
D7 리텐션 0.002

즉 D1 리텐션에는 유의미한 차이가 발생하지 않았으나, D7에서는 유의미한 차이가 발생하였다. 이를 확인하기 위해 실제 데이터를 바탕으로 값을 계산해 보았다.

    재방문 O 재방문X 리텐션 비율
D1 리텐션 gate30 유저 20034 24665 44.82%
gate40 유저 20119 25370 44.23%
D7 리텐션 gate30 유저 8501 36198 19.02%
gate40 유저 8279 37210 18.20%

D7 리텐션을 보면 gate40 유저가 30 대비 리텐션 비율이 낮아, 리텐션이 낮아지는 방향으로 변화가 일어났다고 말할 수 있을 것이다. (Remark. 사실 방향까지 말할려면 엄밀하게는 t-test로 해야 더 정확하긴 하다.)

하지만 정말 그 결론이 맞을까?

 

게이트 돌파 유저 대상의 A/B 테스트의 수행

앞에서 명심해야 한다는 포인트로 돌아가자. 30~40탄에 가보지 않았다면 게이트의 존재도 몰랐을 수도 있고, 혹은 미리 게이트를 봐서 질려버렸을 수도 있다. 아무튼 여러 이유로 극 초기의 이탈이라고 볼수도 있고 퍼즐류 게임의 특성상 상품의 대부분은 "아이템 구매"로 나오기 때문에 이런 극초반 유저들은 어차피 매출로 이어질 가능성이 없어 일정 구간을 넘긴 유저들의 리텐션이 중요하다. 

따라서 유저를 한정해야 하는데, 게이트를 돌파할 가능성이 있는 유저를 기준으로 할 것이다. 물론 스테이지 클리어 데이터가 있어야 정확하나 이는 주어지지 않았으므로 다음 기준으로 유저를 선별한다.

기존안 유저 : sum_gamerounds >= 30
변경안 유저 : sum_gamerounds >= 40

두 집단의 경험은 다르기 때문에 이 조건식이 달라도된다, 다만 첫 관문 돌파라는 동일한 상황을 경험했다는 것만 맞춰주면 그만이기에 이렇게 조건을 잡는 것은 합리적이다.

이 조건에 해당하는 유저들을 대상으로 다시 A/B 테스트를 수행하면 다음과 같다.

항목 p-value
D1 리텐션 7.8e-11
D7 리텐션 7.0e-16

유의수준 미만의 p-value이므로 통계적으로는 유의미한 차이인데 과연 방향은 어떨까?

    재방문 O 재방문X 리텐션 비율
D1 리텐션 gate30 유저 13341 3314 80.10%
gate40 유저 11479 2348 83.02%
D7 리텐션 gate30 유저 7307 9348 43.87%
gate40 유저 6707 7120 48.51%

이렇게 본 결과 오히려 리텐션은 개선되었다.

즉, 핵심 유저들을 대상으로 A/B테스트를 분석한 결과 gate40으로 옮기는 것이 리텐션 개선등에 더욱 합당하다는 판단을 할 수 있고, 실제 인게임 스샷을 다시 보면 정말로 40stage에 최초의 게이트가 설치되어 있다.

 

Remark. t-test 버전

t-test에서는 one-sided한 검정이 가능하다. 여기서는 특히 밑바닥부터 직접 만들어보았다.

우선 가설이 달라짐에 주의해야 한다.

 - 귀무가설(H0) : gate를 뒤로 늦춰도 리텐션 개선에 효과가 없다. (u0 = u1)
 - 대립가설(H1) : gate를 뒤로 늦추면 리텐션 개선에 효과가 있다. (u0 < u1)
# 다음과 같이 t-test를 활용하여 값을 직접 넣어 계산 가능하다.
# 등분산의 보장이 없으므로, 합동 표본표준편차로 t값을 계산 가능하다.
# 즉, 유의미한 개선인지 t-값으로도 확인 가능하다.

def ttest(click_a, total_a, click_b, total_b):
    rate_diff = click_b/total_b - click_a/total_a
    total_prob = (click_a+click_b) / (total_a + total_b)
    std = (total_prob * (1 - total_prob) * (1/total_a + 1/total_b))**0.5
    z_val = rate_diff/std
    rv = scipy.stats.norm(0, 1)
    p_val = 1 - rv.cdf(z_val)
    return z_val, p_val

ttest(13341, 13341+3314, 11479, 11479+2348)

이에 대한 결과는 z값 6.5,   p-val 3.5e-11 정도이다.  one-sided 기준 귀무가설이 기각되고 리텐션이 개선되었다고 말할 수 있다.

Additional : Feed-Back 내용 : A/B 집단의 구분

A/B 테스트에서는 집단에 대한 구분은 "동질성"을 가져야 하는데, 대조군은 30레벨까지 클리어, 실험군은 40레벨까지 클리어를 기준으로 잡을 경우 대조군와 실험군의 동질성이 깨져버리게 된다. 애초에 리텐션을 보는 상황에서 플레이 횟수 자체를 다르게 잡을 경우 리텐션은 당연히 차이가 날 수 밖에 없게 된다. 따라서 두 집단 모두 30스테이지 클리어 이후 등으로 동일한 스테이지 컷을 잡는 것이 더 정확할 것이다.

물론 생각했던 부분은 "허들을 만났을 때"의 경험에 의한 차이를 고려한 것이라 허들을 기준으로 분석을 진행하였지만 최종 결과는 리텐션을 보는 것이기에, 이 점에 주의해야 할 듯하다.

Rmk. 실제로 30스테이지 기준으로 하면 오히려 리텐션이 개선되었다고 말할 수 없게 된다. 아마 정확하게 클리어 데이터로 해야 정확한 수치가 나오지 않을까 싶다.

 

'Archive > 데이터 분석 관련' 카테고리의 다른 글

[Data] RFM 분석이란? (실전편)  (1) 2024.01.19
[Data] RFM 분석이란? (이론편)  (0) 2024.01.17
[Data] Retention  (2) 2024.01.15
[Data] CLV  (0) 2024.01.13
[Data] A/B test 간단 정리  (1) 2023.12.31