그로스해킹 : data를 들여다 보며, user를 더 많이 모으는 모든 작업들
- Correlation Analysis
- A/B test (with 독립표본 t - test)
- A/B test (with 카이 제곱 검정)
예를 들어, 지금 당신의 손에 주사위 하나가 있다고 치자. 우리는 주사위가 1부터 6까지 골고루 나온다고 알고 있다. 하지만 과연 당신의 손에 있는 주사위도 그럴까? 혹시 그 주사위는 무게 중심이 달라서 1이 제일 많이 나오고 6은 아예 안 나오지는 않을까? 당신은 주사위가 공평한 주사위인지 의심이 들었고, 한 번 확인해보기로 했다. 이럴 때 사용하는 게 바로 가설 검정이다. "이 주사위는 공평한 주사위이다."라는 가설을 세우고, 주사위를 n번 던진 뒤 관측값을 바탕으로 가설을 채택할지(주사위가 공평하다), 아니면 기각할지(주사위가 공평하지 않다)를 결정한다.
가설 검정 방법은 일종의 도구이다. 우리는 요리를 할 때 목적에 맞는 도구를 선택하여 사용한다. 식자재를 자르기 위해서는 칼을 사용하고, 음식을 끓이기 위해서는 냄비를 사용한다. 또 음식에 짠맛을 더하기 위해서는 소금을 사용하고, 단맛을 더하기 위해서는 설탕을 사용한다. 이렇게 각 도구마다 기능이 정해져 있으며, 목적에 맞게 적절한 도구를 선택하여 사용한다. 가설 검정 방법을 선택하는 것도 이와 같다. 각 가설 검정 방법은 각자가 검정할 수 있는 가설의 형태가 미리 정해져 있으며, 우리는 이를 임의로 바꿀 수 없다. 파를 썰고 싶은데 소금을 사용한다든지, 음식에 짠 맛을 더하고 싶은데 냄비를 사용하지는 않는 것처럼 말이다. 다시 말해서, 우리가 검정하고 싶은 가설의 형태에 따라서 해당 가설을 검정해줄 수 있는 알맞은 도구를 선택해야 한다.
T-test는 표본집단의 평균을 비교하고 싶을 때 선택하는 방법이다. T-test는 sample의 개수에 따라 one-sample T-test와 two sample T-test로 나뉘며, 귀무가설이 비슷하면서도 조금 다르다.
1) one sample T-test
Adelie 펭귄은 키가 약 70cm까지 자라는 펭귄이라고 한다. 이 말을 들은 당신의 머릿속에는 "키가 그 정도면 몸무게는 8kg 정도 될 것 같아"라는 생각이 들었다. 이러한 당신의 생각이 맞는지 확인하고 싶을 때 사용하는 것이 바로 one-sample T-test이다. one-sample T-test는 표본집단의 평균이 특정 값인지 추정할 때 사용한다. "Adelie 펭귄의 평균 몸무게는 8kg일 것이다"를 검정할 때에 가설은 아래와 같다.
- 귀무가설: Adelie 펭귄의 평균 몸무게는 8kg일 것이다.
- 대립가설: Adelie 펭귄의 평균 몸무게는 8kg이 아닐 것이다.
- 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["body_mass"]
stats.ttest_1samp(adelie, 8000) # 단위: g
# [out]
Ttest_1sampResult(statistic=-113.12763925848728, pvalue=2.511309970725206e-143)
one sample T-test 시행 결과, p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 Adelie 펭귄의 평균 몸무게는 8kg이 아니다.
이번에는 아래와 같이 가설을 세우고 one sample T-test를 한 번 해보자.
- 귀무가설: Adelie 펭귄의 평균 몸무게는 3.72kg일 것이다.
- 대립가설: Adelie 펭귄의 평균 몸무게는 3.72kg이 아닐 것이다.
- 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["body_mass"]
stats.ttest_1samp(adelie, 3720)
# [Out]
Ttest_1sampResult(statistic=-0.36452038810359905, pvalue=0.7160005111390735)
one sample T-test 시행 결과, p-value가 0.05보다 크기 때문에 귀무가설을 기각할 수 없다. 따라서 Adelie 펭귄의 평균 몸무게는 3.72kg이다.
이렇게 one sample T-test의 귀무가설은 "표본집단의 평균은 n이다."로 정해져 있다. 이에 대한 대립가설은 "표본집단의 평균은 n이 아니다."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.
2) two sample T-test
two sample T-test도 표본집단의 평균을 비교한다는 점에서는 one sample T-test와 동일하다. 다만, one sample T-test는 해당 표본집단의 평균과 특정한 값을 비교할 때 쓴다면, two sample T-test는 표본집단 A와 표본집단 B의 평균을 비교할 때 사용한다.
Adelie 펭귄은 Gentoo 펭귄 속의 펭귄 종이라고 한다. 그렇다면 Adelie 펭귄과 Gentoo 펭귄의 생김새가 비슷하지 않을까? Adelie 펭귄과 Gentoo 펭귄의 평균 부리 깊이가 같은지 아래처럼 two sample T-test를 시행하여 확인해보자.
- 귀무가설: Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같다.
- 대립가설: Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같지 않다.
- 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["bill_depth"]
gentoo = df[df["species"] == "Gentoo"]["bill_depth"]
stats.ttest_ind(adelie, gentoo)
# [Out]
Ttest_indResult(statistic=24.208855744860315, pvalue=6.91055572279657e-69)
two sample T-test 시행 결과, p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같지 않다.
그럼 이번에는 Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이가 같은지 확인해보자.
- 귀무가설: Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같다.
- 대립가설: Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같지 않다.
- 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["bill_depth"]
chinstrap = df[df["species"] == "Chinstrap"]["bill_depth"]
stats.ttest_ind(adelie, chinstrap)
# [Out]
Ttest_indResult(statistic=-0.41849509118137584, pvalue=0.6760088132938111)
two sample T-test 시행 결과, p-value가 0.05보다 크기 때문에 귀무가설을 기각할 수 없다. 따라서 Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같다.
위와 같이 two sample t-test의 귀무가설은 "두 표본집단의 평균이 같다."로 정해져 있다. 이에 대한 대립가설은 "두 표본집단의 평균이 같지 않다."이다. 그리고 one sample t-test에서 그랬던 것처럼, 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.
사실 Adelie 펭귄의 평균 몸무게를 정확히 구해보면 3.72kg이 아니라 약 3.706kg이 나온다. 그리고 Adelie 펭귄의 평균 부리 깊이는 18.35mm이고, Chinstrap 펭귄의 평균 부리 길이는 15mm로 차이가 있다. 그럼 T-test 결과가 틀린 게 아니냐고? T-test가 한 표본집단의 평균이 특정 값과 같은지 혹은 두 표본집단의 평균이 같은지 추정하는 테스트인 건 맞다. 그러나 두 값이 정확하게 같은지 확인하는 게 아니라 두 값 사이에 통계적으로 유의미한 차이가 있는지 추정하는 테스트이다. 즉, T-test 결과에 따르면 Adelie 펭귄의 평균 몸무게는 3.72kg라고 봐도 무방하고, Adelie 펭귄과 Chinstrap 펭귄의 평균 부리 깊이는 같다고 봐도 무방하다. 값이 완벽하게 같은지를 보는 게 아니라 '통계적으로 유의미한 차이가 있는지 추정한다'는 것은 T-test뿐만 아니라 아래 나올 Chi-squared test를 비롯한 다른 가설 검정 방법에서도 동일하다.
T-test는 표본집단의 평균을 비교할 때 선택하는 방법이었다면, Chi-squared test는 표본집단의 분포를 비교할 때 선택하는 방법이다. 다만, Chi-squared test는 categorical data에 대해서만 사용이 가능하다. Chi-squared test도 sample의 개수에 따라 one-sample Chi-squared test와 two sample Chi-squared test로 나뉜다.
1) one sample Chi-squared test
one sample Chi-squared test은 서론에서 말했던 "이 주사위는 공평한 주사위이다."에 대한 검정처럼, 데이터의 분포가 예상과 같은지 확인할 때 사용한다.
우리는 흔히 암컷과 수컷의 개체 수가 동일하리라 생각한다. 따라서 만약 펭귄 표본집단에 총 100마리의 펭귄이 있다면, 성별 분포의 기댓값은 암컷과 수컷이 각각 50마리씩 있는 것이다. 그럼 one sample Chi-squared test를 통해 펭귄 표본집단의 분포가 우리의 기대와 같은지 확인해보자.
- 귀무가설: 펭귄의 성비는 1:1일 것이다.
- 대립가설: 펭귄의 성비는 1:1이 아닐 것이다.
- 신뢰도: 95%
male = df["sex"].value_counts()["MALE"]
female = df["sex"].value_counts()["FEMALE"]
exp = len(df)/2
stats.chisquare(f_obs=[male, female], f_exp=[exp, exp])
# [Out]
Power_divergenceResult(statistic=0.02702702702702703, pvalue=0.8694170607412391)
p-value가 0.05보다 크므로 귀무가설을 기각할 수 없다. 따라서, 펭귄의 성비는 1:1이다.
이처럼 one sample Chi-squared test의 귀무가설은 "표본집단의 분포가 기대와 동일하다."이다. 이에 대한 대립가설은 "표본집단의 분포가 기대와 동일하지 않다."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.
2) two sample Chi-squared test
two sample Chi-squared test는 두 표본집단의 분포가 동일한지 확인할 때 사용한다. 즉, 두 표본집단이 연관이 있는지, 없는지를 확인할 수 있다.
펭귄의 몸무게와 플리퍼 길이는 관련이 있지 않을까? two sample Chi-squared test를 사용하면 "펭귄의 몸무게와 플리퍼 길이는 독립이다."라는 가설을 검정할 수 있다. 단, 여기서 주의해야 할 점은 Chi-squared test는 categorical data에만 사용할 수 있다는 점이다. 우리가 가지고 있는 데이터셋에서는 펭귄의 몸무게와 플리퍼 길이가 continuous data이다. 따라서 펭귄의 몸무게와 플리퍼 길이에 대한 Chi-squared test를 시행하려면 먼저 데이터를 categorical data로 바꿔줘야 한다.
mass_cut = pd.cut(df["body_mass"], 3).astype("category")
flipper_cut = pd.cut(df["flipper_length"], 3).astype("category")
data = pd.crosstab(mass_cut, flipper_cut)
data.columns = ["Short", "Middle", "Long"]
data.index = ["Light", "Middle", "Heavy"]
몸무게와 플리퍼 길이를 각각 세 그룹으로 나누고, 그 결과를 crosstab으로 만들었다. 이제 펭귄의 몸무게와 플리퍼 길이에 대해서 two sample Chi-squared test를 시행할 수 있다.
- 귀무가설: 펭귄의 몸무게와 플리퍼 길이는 연관이 없다.
- 대립가설: 펭귄의 몸무게와 플리퍼 길이는 연관이 있다.
- 신뢰도: 95%
chi, pvalue, _, _ = stats.chi2_contingency(data, correction=False)
chi, pvalue
# [Out]
(244.23390701043138, 1.1365768507791132e-51)
p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 펭귄의 몸무게와 플리퍼 길이는 연관이 있다.
이처럼 two sample Chi-squared test의 귀무가설은 "두 변수는 연관이 없다(두 변수는 독립이다)."이다. 이에 대한 대립가설은 "두 변수는 연관이 있다(두 변수는 독립이 아니다)."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.
지금까지 가설 검정 방법 중 T-test와 Chi-squared test에 대해서 알아봤다. 이 외에도 가설 검정 방법은 매우 많다. 하지만 가설 검정 방법은 저마다 고유한 기능을 가지고 있는 도구와 같다는 것은 변하지 않는다. 그러므로 오늘 T-test와 Chi-squared test를 살펴보면서 했던 것처럼, 각 검정 방법이 무엇을 확인하고자 할 때 사용하는 검정 방법인지, 귀무가설과 대립가설은 무엇인지 잘 살펴본다면 원하는 목적에 맞는 가설 검정 방법을 쉽게 선택할 수 있을 것이다.
p-value의 높고 낮음과 별개로 실제 실험의 효과 크기 역시도 중요하게 고려해야한다. 예를 들어 어떤 웹사이트의 구매 버튼의 디자인을 변경하여 구매 수가 n 만큼 증가되었고, 디자인 변경 전/후에 대한 구매 버튼 클릭 수 사이의 관계를 대상으로 통계 검정 후 p-value가 0.05보다 낮게 나왔더라도, 정작 증가된 구매 수에 해당하는 n이 미미하다면 낮은 p-value에도 불구하고 디자인 변경의 실질적인 효용이 적기 때문이다. (통계적으로만 유의미할 뿐 독립변수의 변화에 따른 종속변수의 변화값이 실질적/실용적인 의미를 갖지 않음)
t 검정은 단순히 두 그룹 간의 평균치 차이를 검정하는 기법
카이 제곱검정은 여러 그룹(두 그룹 이상)의 분포를 검정하는 기법
=> 두 그룹의 취미의 평균값 같은 범주형 data의 경우 카이제곱법을 사용
+ 피어슨 상관계수 값에 대한 해석 기준 (Strong/Moderate/Weak) : https://j.mp/3mH8FWN
+ 파이썬 프로그래밍 없이 상관관계 분석을 진행할 수 있는 도구 : https://j.mp/324551c