[통계/인강] 챕터3 - 유의성 검정(A/B 테스트) | 가설검정 | t-검정 | 다중검정 | 카이제곱검정 | 제 1종 오류와 제 2종 오류

유의성 검정 (A/B 테스트)

A/B 검정은 인터넷으로 유통을 하는 기업에서는 반드시 사용!

 

 

 

이 비율은 표본에 대한 비율이다!

과연 모집단에서도 동일한 비유을 가질 것이냐? 그것이 관건임!!

이걸 확인하기 위해서 가설검정을 하게 됨! A/B테스트도 이 중 한 가지!!

 

📌 A/B 검정이란, 두 버전 중 어느 것이 더 효과적인지 평가하기 위해 사용되는 검정 방법.
 - 마케팅, 웹사이트 디자인 등에서 많이 사용됨.
 - 사용자들을 두 그룹으로 나누고, 각 그룹에 다른 버전을 제공한 후 반응을 비교
 - 전환율, 클릭률, 구매수, 방문 기간, 방문한 페이지 수, 특정 페이지 방문 여부, 매출 등의 지표를 비교

두 그룹 간의 변화(차이)가 우연이 아니라 통계적으로 유의미한지 아직은 모르겠어... 그래서 이것만으로 판단하기에는 조금 아쉬워!!

더 확인해봐야 하는데,,,,,그 때 하는 것이 바로 "가설검정" 이다.

파이썬 실습

# a/b 테스트 후 가설검정!
import numpy as np
import scipy.stats as stats

# 가정된 전환율 데이터
group_a = np.random.binomial(1, 0.30, 100)  # 30% 전환율
group_b = np.random.binomial(1, 0.45, 100)  # 45% 전환율
print(group_a)
print('1의 개수', sum(group_a))
'''출력:
[0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1
 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0
 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0]
1의 개수 27
'''

print(group_b)
print('1의 개수', sum(group_b))
'''출력:
[1 0 0 1 0 0 1 1 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0 1 0 1 0 1 0 0 1 1 0
 1 1 1 0 0 0 1 0 1 0 1 0 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 1
 1 1 1 1 0 1 1 0 0 1 1 0 0 1 0 0 0 0 1 1 0 1 0 0 0 0]
1의 개수 47
'''
# t-test를 이용한 비교
t_stat, p_val = stats.ttest_ind(group_a, group_b)
print(f"T-Statistic: {t_stat}, P-value: {p_val}")
출력 >>> T-Statistic: -2.9790844182925245, P-value: 0.003252751939299291
이 결과 p-value 값이 유의수준(0.05)보다 낮게 나타났다!! 따라서 두 개 그룹이 다르다!고 본다. 즉 우연히 일어난 일이 아니다.
그렇다는 것은 B에 대한 결과가 의미가 있구나! 클릭율을 유도했구나!라고 볼 수 있을 것이다.

가설검정

✅ 데이터가 특정 가설을 지지하는지 검정하는 게 포인트 !

NULL(귀무가설) ❘ ALTERNATIVE(대립가설)

가설검정

표본 데이터를 통해 모집단의 가설을 검증하는 과정. 즉, 데이터가 특정 가설을 지지하는지 평가하는 과정
귀무가설과 대립가설을 설정하고, 귀무가설을 기각할지를 결정해야 함.
  • 확증적 자료분석 : 미리 가설을 먼저 세운 다음 검증해 나가는 분석
  • 탐색적 자료분석(EDA) : 가설을 먼저 정하지 않고 데이터를 탐색해보면서 가설 후보와 데이터 특징을 찾는 것

단계

  1. 귀무가설(H0)과 대립가설(H1)을 설정 
    • 기존약과 신약의 효과가 같다(=귀무가설), 기존약과 신약의 효과가 다르다(=대립가설)
  2. 유의수준 결정
  3. 검정 통계량 계산(평균 같은 것)
  4. p-value값과 유의수준 비교
  5. 결론 도출
📌 통계적 유의성 : 결과가 우연히 발생한 것이 아니라 효과가 실제로 존재함을 나타내는 지표
 - p값은 귀무 가설이 참을 때 → 관찰된 통계치가 나올 확률을 의미
📌 p-value
 - 귀무 가설이 참 일 때 → 관찰된 결과 이상으로 극단적인 결과가 나올 확률?
 - 일반적으로 p-value가 유의수준 보다 작으면 귀무가설 기각

📌 p-value 를 통한 유의성 확인
 - 값이 0.03 이라면, 3%의 확률로 굉장히 드물게, 우연히 이러한 결과가 나올 수 있음(결과가 다르다!)
 - 일반적으로 0.05 이하라면 유의성이 있다고 봄

가설을 설정하여 검증

  • 새로운 약물이 기존 약물보다 효과가 있는지 검정
  • 이 때 새로운 약물은 기존 약물과 큰 차이가 없다는 것이 귀무가설!
  • 새로운 약물이 기존 약물과 대비해 효과가 있다는 것이 대립가설!

 

파이썬 실습

기존 약물 A 대비 새로운 약물 B가 효과가 있는지 "가설 검정"을 한다.
# 기존 약물A 와 새로운 약물B 효과 데이터 생성
A = np.random.normal(50, 10, 100)
B = np.random.normal(55, 10, 100)
# 평균 효과 계산
mean_A = np.mean(A)
mean_B = np.mean(B)
가설 설정
 - 귀무가설 : 기존과 신약의 효과가 동일하다. 같다!
 - 대립가설 : 기존과 신약의 효과가 차이가 있다. 댜르다!
# t-검정 수행
t_stat, p_value = stats.ttest_ind(A, B)

print(f"A 평균 효과: {mean_A}")
print(f"B 평균 효과: {mean_B}")
print(f"t-검정 통계량: {t_stat}")
print(f"p-값: {p_value}")
A 평균 효과: 48.88575339328362
B 평균 효과: 53.8934868834703
t-검정 통계량: -3.970043702942556
p-값: 0.00010049676015394152
# t-검정의 p-값 확인 (위 예시에서 계산된 p-값 사용)
print(f"p-값: {p_value}")
if p_value < 0.05:
    print("귀무가설을 기각합니다. 통계적으로 유의미한 차이가 있습니다.")
else:
    print("귀무가설을 기각하지 않습니다. 통계적으로 유의미한 차이가 없습니다.")
p-값: 0.00010049676015394152
귀무가설을 기각합니다. 통계적으로 유의미한 차이가 있다.

t-검정

: 두 집간 간의 평균 차이가 통계적으로 유의미한지 확인하는 검정 방법
  • 독립 표본 t-검정 : 독립된 두 그룹의 평균을 비교.
  • 대응 표본 t-검정 : 동일한 그룹의 사전/사후 평균을 비교.

: 두 클래스의 시험 성적 비교 (독립 표본 t-검정)

: 다이어트 전후 체중 비교 (대응 표본 t-검정)

파이썬 실습

# 학생 점수 데이터
scores_method1 = np.random.normal(70, 10, 30)
scores_method2 = np.random.normal(75, 10, 30)
# 독립표본 t검정
t_stat, p_val = stats.ttest_ind(scores_method1, scores_method2)
print(f"T-Statistic: {t_stat}, P-value: {p_val}")
T-Statistic: -1.658844435617136, P-value: 0.10254593006538337
p-value > 0.05 : 귀무가설 기각 불가(채택), 두 그룹 간의 평균이 같다. 보이는 차이는 통계적으로 유의미하지 않다!

다중 검정

여러 가설을 동시에 검정! 하지만 오류가 발생할 수 있음...!
  • 여러 가설을 동ㅅ이에 검정할 때 발생하는 문제
  • 각 검정마다 유의 수준을 조정하지 않으면 1종 오류(귀무가설이 참인데, 기각하는 오류) 발생 활률이 증가

보정 방법 ➡️  본페로니 보정(가장 대표적), 튜키 보정, 던넷 보정, 윌리엄스 보정 등이 있음 (유의수준을 엄격하게 해서 보정)

여러 약물의 효과를 동시에 검정 ➡️ 본페로니 보정 실습

파이썬 실습

import numpy as np
import scipy.stats as stats

# 세 그룹의 데이터 생성
np.random.seed(42)
group_A = np.random.normal(10, 2, 30)
group_B = np.random.normal(12, 2, 30)
group_C = np.random.normal(11, 2, 30)
# 세 그룹 간 평균 차이에 대한 t검정 수행
p_values = []
p_values.append(stats.ttest_ind(group_A, group_B).pvalue)
p_values.append(stats.ttest_ind(group_A, group_C).pvalue)
p_values.append(stats.ttest_ind(group_B, group_C).pvalue)
# 본페로니 보정 적용
alpha = 0.05
adjusted_alpha = alpha / len(p_values)
# 결과 출력
print(f"본페로니 보정된 유의 수준: {adjusted_alpha:.4f}")
for i, p in enumerate(p_values):
    if p < adjusted_alpha:
        print(f"검정 {i+1}: 유의미한 차이 발견 (p = {p:.4f})")
    else:
        print(f"검정 {i+1}: 유의미한 차이 없음 (p = {p:.4f})")
본페로니 보정된 유의 수준: 0.0167
검정 1: 유의미한 차이 발견 (p = 0.0000)
검정 2: 유의미한 차이 발견 (p = 0.0058)
검정 3: 유의미한 차이 없음 (p = 0.1461)

카이제곱 검정

범주형 데이터의 분석에 사용된다는 것이 포인트!!!
  • 범주형 데이터의 표본 분포가 모집단 분포와 일치하는지 검정 ➡️ 적합도 검정
  • 두 범주형 변수 간의 독립성을 검정 ➡️ 독립성 검정

적합도 검정

  • 관찰된 분포와 기대된 분포가 일치하는지 검정
  • p 값이 높으면 귀무 가설 잘 맞음 ➡️ 관찰된 데이터와 귀무 가설이 적합
  • p 값이 낮으면 귀무 가설 안맞음 ➡️ 관찰된 데이터와 귀무 가설이 부적합

독립성 검정

  • 두 범주형 변수 간의 독립성을 검정
  • p 값이 높으면 두 변수 간의 연관성 없음 ➡️ 독립성 있음
  • p 값이 낮으면 두 변수 간의 연관성 있음 ➡️ 독립성 없음

✅ 범주형 데이터의 분포 확인 및 독립성 확인을 위해 사용

  • 주사위의 각 면이 동일한 확률로 나오는지 검정 (적합도 검정)
  • 성별과 직업 만족도 간의 독립성 검정

 

파이썬 실습

- scipy.stats.chisquare : 카이제곱 적합도 검정을 수행 → 관찰된 빈도 분포가 기대된 빈도 분포와 일치하는지 평가

# 적합도 검정
observed = [20, 30, 25, 25]
expected = [25, 25, 25, 25]
chi2_stat, p_value = stats.chisquare(observed, f_exp=expected)
print(f"적합도 검정 카이제곱 통계량: {chi2_stat}, p-값: {p_value}")
적합도 검정 카이제곱 통계량: 2.0, p-값: 0.5724067044708798
p > 0.05 : 귀무가설 채택 > 데이터가 모집단과 일치 > 관측 데이터와  기대 데이터 간 차이가 없다.

- scipy.stats.chi2_contingency : 카이제곱 독립성 검정을 수행 → 두 개 이상의 범주형 변수 간의 독립성을 검정

# 독립성 검정
observed = np.array([[10, 10, 20], [20, 20, 40]])
chi2_stat, p_value, dof, expected = stats.chi2_contingency(observed)
print(f"독립성 검정 카이제곱 통계량: {chi2_stat}, p-값: {p_value}")
독립성 검정 카이제곱 통계량: 0.0, p-값: 1.0
p > 0.05 : 귀무가설 채택 > 독립성이 있다 > 두 변수 간 연관성 없다.
# 나이와 흡연 여부 독립성 검정
observed = np.array([[30, 10], [20, 40]])
chi2_stat, p_value, dof, expected = stats.chi2_contingency(observed)
print(f"독립성 검정 카이제곱 통계량: {chi2_stat}, p-값: {p_value}")
독립성 검정 카이제곱 통계량: 15.041666666666666, p-값: 0.00010516355403363106
p < 0.05 : 귀무가설 기각 > 독립성이 없다 > 두 변수 간 어떤 연관성이 있구나!!

제 1종 오류와 제 2종 오류

제 1종 오류

  • 귀무가설이 참인데 기각하는 오류
  • 잘못된 긍정 ( 아무런 영향이 없는데 영향이 있다고 하는 것 ) : 범인이 아닌데, 범인이라고 하는 것!! ㄷㄷ
  • α(알파)를 경계로 귀무가설을 기각하기 때문에 제1종 오류가 α만큼 발생
  • 유의수준(α)을 정함으로써 제 1종 제어 가능

▼ 다중 검정시 제 1종 오류가 증가하는 이유?

제 2종 오류

  • 귀무가설이 거짓인데 기각하지 않는 오류
  • 잘못된 부정 ( 영향이 있는데 영향이 없다고 하는 것 ) : 범인이 맞는데, 범인이 아니라고 하는 것!! ㄷㄷ
  • 제 2종 오류가 일어날 확률은 β(베타)로 정의
  • 이를 직접 통제할 수 없음
    • 표본 크기 n이 커질 수록 β가 작아짐
    • α와 β는 상충관계에 있어서 낮은 α를 갖게 되면 β는 더욱 높아짐
🔍 예시
 - 새로운 약물이 효과가 없는데 있다고 결론 → 제 1종 오류 
 - 효과가 있는데 없다고 결론 → 제 2종 오류

문제

▼ 정답 및 해설

더보기
  • 정답은 1번
    1. 대응 표본 t검정
    2. 분산 분석
    3. 카이제곱검정
  • 1) 독립 표본 t검정
  • 독립 표본 t검정은 두 개의 독립된 그룹 간의 평균을 비교할 때 사용되며, 대응 표본 t검정은 같은 그룹의 두 시점(사전/사후) 간 평균을 비교할 때 사용됩니다.

▼ 정답 및 해설

더보기
  • 정답은 2번
    1. 연속형 데이터
    2) 범주형 데이터
    1. 비율 데이터
    2. 순서형 데이터
  • 카이제곱검정은 범주형 데이터의 독립성이나 적합성을 검정하는 데 사용됩니다.

▼ 정답 및 해설

더보기
  • 정답은 1번
    1. 제 1종 오류는 대립가설이 참인데 기각하는 오류이고, 제 2종 오류는 귀무가설이 참인데 기각하는 오류이다.
    2. 제 1종 오류와 제 2종 오류는 동일한 개념이다.
    3. 제 1종 오류는 표본 크기와 관련이 없고, 제 2종 오류는 표본 크기와 관련이 있다.
  • 1) 제 1종 오류는 귀무가설이 참인데 기각하는 오류이고, 제 2종 오류는 대립가설이 참인데 기각하는 오류이다.
  • 제 1종 오류는 귀무가설이 참인데도 불구하고 기각하는 오류이며, 제 2종 오류는 대립가설이 참인데도 불구하고 기각하는 오류입니다.

끝...