일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Data_Engineering
- Algorithm_A/B_Test
- fastcampus
- Kaggle #EDA #Regression
- 경제신문스크랩
- kaggle
- lazypredict
- GCP
- e-commerce
- regression
- Soft_skills
- Hadoop
- Kaggle_Transcripition
- SPARK
- Today
- Total
AI & Data를 활용하는 기술경영자
가설검증 본문
Intro
코드와 함께 수학적인 내용을 정리하면 두 번 복습하는 효과가 있다는 것을 알리기 위해서 작성하게되었습니다.
목차
1. 통계적 가설검정
2. 2표본 문제- 독립비교 t검정
3. 월콕슨의 부호검정
4. 만, 위트니의 U검정(Mann-Whitney rank test)
5. 카이제곱검정
통계적 가설검정(Statistical Hypothesis Testing)
모집단의 모수에 관하여 두 가지 가설을 세우고, 표본으로부터 계산되는 통계량을 이용하여 가설이 옳은지 판단하는 통계적 기법이다.
대립가설(H1, Alternative Hypothesis):유의미한 차이 혹은 효과가 있다는 것을 주장하고 싶은 가설이다.
귀무가설(H0, Null Hypothesis): 대립가설의 반대되는 개념이다.
예시: 정책으로 예시를 들면, 기존의 정책이 귀무가설이고, 기존의 정책 대비 비용이 많이 들더라도 새로운 정책을 만들고 유의미한 정책을 주장하고 싶다면 대립가설로 가정
귀무가설 기각: 귀무가설은 옳지 않다.(-> 새로운 정책이 유의미하다)
귀무가설 채택: 귀무가설이 옳지 않다고 할 수 없다.(귀무가설이 옳다는 의미는 아님)
통계적 가설검정 용어
유의하다(Significant): 귀무가설 기각/채택의 판단은 귀무가설을 바탕으로 표본을 통해서 계산된 통계량이 특정 신뢰수준 범위 내에서 보기 드문 값인지 여부를 통해서 결정되는데, 보기 드문 값이면 기각 흔하면 채택이다.
예시
보스턴 주택의 평균 방 수가 6보다 크다라는 대립가설과 6보다 작거나 같다라는 귀무가설을 통해 모평균이 6으로 가정되고, 표폰 추출 시 95%의 확률로 표본평균 값 <=6.164라는 조건 만족한다.
예시 데이터처럼 6.164범위보다 바깥에 존재하는 표본평균은 6.192는 보기 드문 값이므로 귀무가설은 기각한다.
기각역: 귀무가설이 기각되는 구간
(예: 표본평균 > 6.164라면 귀무가설은 기각되므로 표본평균>6.164가 기각역이다.)
채택역: 귀무가설이 채택되는 구간
(예: 표본평균 <= 6.164라면 귀무가설은 기각되므로 표본평균<=6.164가 기각역이다.)
유의수준(신뢰수준, Level of Significance): 표본평균이 기각역에 들어갈 확률이다.
(예: 주황색으로 칠해진 영역의 면접, 예시=0.05)
임계값(Critical Value): 경계선상의 값이다.
(예:6.164)
검정통계량(Test Statistic): 검정에 사용할 통계량
(예:6.192)
P값(p-value): 검정통계량 기준으로 바깥영역의 면적
(예: 초록색으로 칠해진 영역의 면적, 예시:0.028)
#기본 세팅
import numpy as np
import pandas as pd
from scipy import stats
%precision 3
np.random.seed(1111)
from sklearn.datasets import load_boston
boston_houseprice_data = load_boston()
df = pd.DataFrame(
data = boston_houseprice_data.data,
columns = boston_houseprice_data.feature_names
)
rooms = np.array(df['RM'])
sample = np.array(df['RM'])[:20]
p_mean, s_mean = np.mean(rooms), np.mean(sample)
p_mean, s_mean #(6.285,6.192)
p_var, s_var = np.var(rooms), np.var(sample, ddof=1)
p_var, s_var #(0.493,0.232)
## 예시
# 모집단이 정규분포를 따르고 모분산이 0.2임을 알고 있다
# 보스턴의 가구당 평균 방 숙 6보다 큰지 여부 파악
# 모평균이 6이라는 가정
# 그 가정을 바탕으로 20개의 표본은X1,X2,X3...,X20 ~ N(6,0.2)를 따른다
# 표본퍙균~N(6,0.2,20)
#표본평균의 P = 0.05를 만족하는 x를 찾는다.
rv = stats.norm(6,np.sqrt(0.2/20))
rv.isf(0.05) #6.164
#5%확률로 표본평균이 6.164를 넘으므로 실제로 모평균이 6보다 클 수 있을 것 같다.라는 결론을 내리는 것을 가설검증
z = (s_mean - 6) / np.sqrt(0.2/20)
z #1.919
rv = stats.norm()
rv.isf(0.95) #-1.645
rv.cdf(z) #0.972
단측검정 & 양측검정
단측검정: 한 방향으로만 검정을 수행하는 방법이다.
(예: 대립가설이 모평균>6 혹은 모평균 <6)
주의할 점: 단측검정은 한쪽 방향으로 기각역 범위가 a이다.
양측검정: 양 방향으로만 검정을 수행하는 방법이다.
(예: 대립가설의 모평균!=6일 때)
주의할 점: 양측검정은 양쪽 방향으로 기각역 범위가 a/2이다.
z = (s_mean-6) / np.sqrt(0.2/20)
z #1.919
rv = stats.norm()
rv.interval(0.95) #(-1.960, 1.960)
rv.cdf(z) * 2 #1.945
가설검정의 두 가지
제 1종 오류
- 귀무가설이 옳을 때, 귀무가설을 기각하는 오류
- 현 정책을 유지하는 것과 큰 차이가 없음에도, 막대한 비용을 들여서 새로운 정책을 시도하는 오류
- (안 고쳐도 되는 걸 고치게 했으니 시간.돈 낭비)
- 하지 말아야할 것을 행한 것으로 오탐(False Positive)
- 제 1종 오류를 범할 확률은 위험률 a(알파)라고 하고 유의수준과 일치
- 분석기가 제어할 수 있는 오류
- 주어진 유의수준에 맞추어서 분석가가 의사결정을 할 수 있다
rv = stats.norm(6, np.sqrt(0.2))
#제 1종 오류
# 평균이 6인데 6보다 크다는 결론을 내리는 상황
c = stats.norm().isf(0.05)
n_samples = 10000
cnt = 0
for _ in range(n_samples):
sample_ = np.round(rv.rvs(20),2)
s_mean_ = np.mean(sample_)
z = (s_mean-6) / np.sqrt(0.2/20)
if z>c:
cnt +=1
cnt / n_samples #1.000
c#1.645
제 2종 오류
- 대립가설이 옳을 때, 귀무가설을 채택하는 오류
- 새로운 정책으로 변화가 유의미함에도 큰 비용을 들이지 않는 현 정책을 고수하는 오류
- (고쳐야 되는데 안 고쳤으니 훗날 문제가 생길 것)
- 행해야할 것을 제대로 인식하지 못했으므로 미탐(False Negative)
- 제 2종 오류를 범할 확률은 b(베타)라고 하며, 1-b를 검정력(power)
- 분석기가 제어할 수 없는 오류
- 분석가가 제어할 수 없는 비대칭 정보에 의하여 귀무가설 채택
#제 2종 오류
#평균이 6이상인데 6이랑이라는 결론을 얻을 수 없는 상황
#비대칭정보 모평균=6.15
#비대칭정보를 기반으로 샘플링이 될 때 이러한 오류가 날 확률을 할 수 있다.
#모평균을 몰라서 생기는 오류이다.
rv = stats.norm(6.15, np.sqrt(0.2))
c = stats.norm().isf(0.05)
n_samples = 10000
cnt = 0
for _ in range(n_samples):
sample_ = np.round(rv.rvs(20),2)
s_mean_ = np.mean(sample_)
z = (s_mean_ -6) /np.sqrt(0.2/20)
if z<=c:
cnt +=1
cnt / n_samples # 0.567
c #1.645
2표본문제 - 대응비교 t검정
2개 모집단에 관한 다양한 관계성 검증을 위한 문제로 2개 표본 각각의 대표값 사이에 차이가 있는지 검정을 통해서 문제를 해결한다.
2표본 문제 4가지 검정 방법
- 모집단에 정규분포를 가정할 수 있는지
- 데이터가 서로 대응이 있는지 독립이 있는지
- 대응이 있다는 것은 2개 표본의 서로 대응되는 동일한 개체에 대해 다른 조건 측정
- ex: 환자에게 약을 투여하기 전과 후의 활성화 수치 비교
- 대응이 없다는 것은 개체가 서로 다른 독립 표본데이터로서 구성됨
- ex: 1반 학생들과 2반 학생들의 시험 점수 비교
- 대응이 있다는 것은 2개 표본의 서로 대응되는 동일한 개체에 대해 다른 조건 측정
대응비교 t검정(Paired t-test)
- 대응하는 데이터가 존재하고, 데이터 차이에 정규분포를 가정할 수 있는 경우에 평균값 차이에 대한 검정 방법
- ex:)
- 근력운동을 진행하면 집중력 향상 여부 파악을 위해서 20명의 사람을 선정하여 2주간 근력운동 하기 전/후의 집중력 테스트 결과 생성
- 근력운동 전/후 집중력 테스트 결과값 차이 비교(양측 검증)
- 귀무가설: Mafter - Mbefore=0
- 대립가설: Mafter - Mbefore !=0
training_rel = pd.read_csv('/content/11_training_rel.csv')
print(training_rel.shape) #(20,2)
training_rel.head()
training_rel['차'] = training_rel['후'] - training_rel['전']
training_rel.head()
t,p = stats.ttest_1samp(training_rel['차'],0)
p #0.040
t,p =stats.ttest_rel( training_rel['후'] ,training_rel['전'])
p #0.040
"""
p값이 0.04로서 0.05보다 작으므로 귀무가설은 기각되고, 근력운동이 집중력에 유의한 차이를 가져온다
"""
2표본 문제 - 독립비교 t검정
독립비교 t검정(Independent t-test)
- 대응하는 데이터가 없고, 독립된 2표본 모집단에서 정규분포를 가정할 수 있는 경우의 평균값 차이에 대한 검정 방법
- 예시
- A학급은 근력운동을 평소에 잘 안함
- B학급은 평소에 근력운동을 꾸준히 함
- 근력운동을 자주하는 집단과 그렇지 않은 집단간의 집중력 차이가 있는지 여부 파악하여 독립적인 두 학급에서 집중력 테스트 결과를 생성
- A학급/B학급 집중력 테스트 결과값 차이 비교(양측 검증)
- 귀무가설: Mafter - Mbefore=0
- 대립가설: Mafter - Mbefore !=0
- 대응이 없는 독립표본 데이터이므로 개별 데이터간의 차이를 구하는 것은 의미가 없다
training_ind = pd.read_csv('/content/ 11_training_ind.csv')
print(training_ind.shape) #(20,2)
training_ind.head()
t, p = stats.ttest_ind(training_ind['A'], training_ind['B'],
equal_var=False)
p # 0.087
윌콕슨의 부호검정
대응하는 데이터에서, 독립된 2표본 모집단에서 정규분포를 가정할 수 없는 경우 중앙값 차이에 대한 검정 방식이다.
월콕슨의 부호순위검정 방법
- 방법이름 그대로 대응하는 데이터간의 차이를 절대값을 기준으로 순위화
- 차이의 부호가 마이너스인 것의 순위함 플러스인 것의 순위함을 고려하여 더 작은 쪽이 검정 통계량이 된다.
- 임계값 기준보다 작으면 차이가 있다는 주장이 가능
- Scipy.stats의 silcoxon함수를 활용하면, 부호의 순위합을 계산하고, 표준화를 수행한 뒤 정규분포로 검정을 통해서 검정통계량 값이 약간 바뀌긴하나 원리의 차이는 없다
training_rel = pd.read_csv('/content/11_training_rel.csv')
toy_df = training_rel[:6].copy()
toy_df
diff = toy_df['후'] - toy_df['전']
toy_df['차'] = diff
toy_df
rank = stats.rankdata(abs(diff)).astype(int)
toy_df['순위'] = rank
toy_df
r_minus = np.sum((diff < 0) * rank)
r_plus = np.sum((diff > 0) * rank)
r_minus, r_plus #(8,13)
toy_df['후'] = toy_df['전'] + np.arange(1, 7)
diff = toy_df['후'] - toy_df['전']
rank = stats.rankdata(abs(diff)).astype(int)
toy_df['차'] = diff
toy_df['순위'] = rank
toy_df
r_minus = np.sum((diff < 0) * rank)
r_plus = np.sum((diff > 0) * rank)
r_minus, r_plus #(11,10)
T, p = stats.wilcoxon(training_rel['전'], training_rel['후'])
p #0.038
T, p = stats.wilcoxon(training_rel['후'] - training_rel['전'])
p #0.038
n = 10000
diffs = np.round(stats.norm(3, 4).rvs(size=(n, 20)))
cnt = 0
alpha = 0.05
for diff in diffs:
t, p = stats.ttest_1samp(diff, 0)
if p < alpha:
cnt += 1
cnt / n # 0.878
cnt = 0
alpha = 0.05
for diff in diffs:
T, p = stats.wilcoxon(diff)
if p < alpha:
cnt += 1
cnt / n #0.869
만,위트니의 U검정(Mann-Whitney rank test)
대응되는 데이터가 없는, 독립된 2표본 모집단에 정규분포를 가정할 수 없는 경우
- 중앙값 차이에 대한 검정 방법
- Not 부호순위검정
- 2표본 데이터 전체에 대해서 값이 작은 순서대로 순위를 부여하고, 검정통계량은 한 표본 데이터의 순위합을 사용
- 좋은 순위가 모여있으면, 순위의 합이 작아지고 반대면 커지는 것을 통해서 데이터 편형 반영
- U검정의 검정통계량은 한 표본 데이터의 크기를 n1이라 할 때, 순위합에서 {n1(n1+1)} /2를 뺀 값
- Scipy.stats의 mannwhiteneyu함수를 사용하여 U검정 가능
- 데이터는 2표본, 파라미터 alternative는 two-sided설정
training_ind = pd.read_csv('/content/11_training_ind.csv')
toy_df = training_ind[:5].copy()
toy_df
rank = stats.rankdata(np.concatenate([toy_df['A'],
toy_df['B']]))
rank_df = pd.DataFrame({'A': rank[:5],
'B': rank[5:10]}).astype(int)
rank_df
n1 = len(rank_df['A'])
u = rank_df['A'].sum() - (n1*(n1+1))/2
u # 7.000
rank_df = pd.DataFrame(np.arange(1, 11).reshape(2, 5).T,
columns=['A', 'B'])
rank_df
u = rank_df['A'].sum() - (n1*(n1+1))/2
u #0.000
rank_df = pd.DataFrame(np.arange(1, 11).reshape(2, 5)[::-1].T,
columns=['A', 'B'])
rank_df
u = rank_df['A'].sum() - (n1*(n1+1))/2
u #25.000
u, p = stats.mannwhitneyu(training_ind['A'], training_ind['B'],
alternative='two-sided')
p #0.059
카이제곱검정
독립성 검정
- 두 변수 X와 Y에 관해 'X와 Y가 독립이다'라는 귀무가설을 기반으로 수행되는 검정
- 독립성 검정에는 카이제곱분포가 사용되기 때문에 카이제곱검정이라고도 불림
#교차집계표(Cross Table) 작성: 도수분포표의 2변수 버전
ad_df = pd.read_csv('/content/[패스트캠퍼스-확률및통계] 11_ad.csv')
n = len(ad_df)
print(n)#1000
ad_df.head()
ad_cross = pd.crosstab(ad_df['광고'], ad_df['구입'])
ad_cross
#A와B의 각각의 광고를 통해 상품을 구입한 비율이 어떻게 되는지 알아보기
ad_cross['했다'] / (ad_cross['했다'] + ad_cross['하지 않았다'])
"""
광고
A 0.1225
B 0.0850
dtype: float64
"""
#상품을 구입한 사람의 합계, 구입하지 않은 사람으 합계
#
n_not, n_yes = ad_cross.sum()
n_not, n_yes #(900, 100)
#광고A를 본 사람의 합계, 과옥 B를 본 사람의 합계를 구한다
n_adA, n_adB = ad_cross.sum(axis=1)
n_adA, n_adB # (400, 600)
#광고와 상관없이 상품을 구입한 비율은 10%
#광고와 구입이 독립이어서 광고에 따라 상품을 구입한 비율이 변하지 않는다면
#A광고를 본 후 구입하게 될 기대도수는 400*10% = 40
#실제로 관측된 데이터는 관측도수
#모들 셀에서 기대도수의 계산 수행
ad_ef = pd.DataFrame({'했다': [n_adA * n_yes / n,
n_adB * n_yes / n],
'하지 않았다': [n_adA * n_not / n,
n_adB * n_not / n]},
index=['A', 'B'])
ad_ef
"""
했다 하지 않았다
A 40.0 360.0
B 60.0 540.0
"""
y = ((ad_cross - ad_ef) ** 2 / ad_ef).sum().sum()
y #3.750
rv = stats.chi2(1)
1 - rv.cdf(y) #0.053
#Scipy.stats의 chi2_contingency함수를 사용해도 간단하게 계산 가능
#인수에는 교차집계표와 파라미터인 correction=False를 주면 반환값으로 검정통계량, 자유도, 기대도수 얻음
chi2, p, dof, ef = stats.chi2_contingency(ad_cross,
correction=False)
chi2, p, dof#(3.750, 0.053, 1)
ef
"""
array([[360., 40.],
[540., 60.]])
"""
'Statistics_Math' 카테고리의 다른 글
CS스터디 3주차 질문 (0) | 2022.05.07 |
---|---|
CS스터디 2주차 질문 (0) | 2022.05.02 |
CS스터디 1주차 질문 (0) | 2022.04.24 |