어떤 분포에서 생성된 지 모르는 n개의 데이터가 있다고 하자. 부트스트랩을 이용하지 않으면 우리는 1개의 sample median만을 알 수 있다.
하지만 Bootstrap sampling을 r번 수행하면 총 r개의 sample이 주어지게 되고, 이를 통해서 조금 더 정확한 sample median을 구할 수 있다.
이렇게 r개의 표본을 만들어내면 그로부터 분포를 그릴 수 있고, 결과적으로 표본에 따라 평균이 얼만큼 변하는지를 (표본의 변동성) 알 수 있다.
정리하자면 모수의 분포를 모를 때 신뢰 구간을 가늠하는 방법 이라고 할 수 있겠다.
이는 이전에 포스팅한게 있으므로 링크를 건다.
[통계] 부트스트랩
1) 첫 단계는 그룹 A와 그룹 B(그룹이 두 개라고 할 때)의 결과를 합친다.
-> 그룹 A와 그룹 B가 유의미한 차이가 없다는 귀무가설을 논리적으로 구체화한 것.
2) 결합된 데이터를 섞고 그룹 A와 동일한 크기의 표본을 무작위로 비복원추출한다. (이 때 다른 그룹의 데이터는 당연히 섞인다)
3) 나머지 데이터에서 그룹 B와 동일한 크기의 표본을 무작위로 비복원추출한다.
4) 원래 샘플에 대한 통계량과 무관하게, 추출한 표본에 대한 통계량을 기록한다.
5) 앞선 단계들을 반복하여 검정통계량의 순열분포를 얻는다.
이렇게 했을 때, 두 그룹이 통계적으로 차이가 없다면 원래 sample의 통계량이 순열분포 안쪽에 존재할 것이고, 차이가 있다면 순열분포 바깥쪽에 원래의 통계량이 존재하게 된다.
⭐️ 순열검정은 임의순열검정, 전체순열검정, 부트스트랩순열검정으로 나뉜다.
예제는 임의순열검정만 살펴볼 것인데, 전체순열검정과 부트스트랩순열검정의 특징은 다음과 같다.
데이터는 https://github.com/gedeck/practical-statistics-for-data-scientists/blob/master/data/web_page_data.csv 에서 가져왔다.
실습은 [데이터 과학을 위한 통계학] 을 참고했다.
import pandas as pd
session_time = pd.read_csv('/content/drive/MyDrive/KHUDA/통계학 스터디/2주차_통계적 실험과 유의성검정/data.csv')
session_time
import matplotlib.pyplot as plt
ax = session_time.boxplot(by='Page', column='Time')
ax.set_xlabel('')
ax.set_ylabel('Time (in seconds)')
plt.suptitle('')
그래프로 봤을 때는 page B에서 사람들이 사이트에 더 오래 머무는 것 같다.
이게 유의미한 통계적 차이가 있을까?
import random
def perm_fun(x, nA, nB):
n = nA + nB #데이터를 합친다
idx_B = set(random.sample(range(n), nB)) #B 크기의 무작위 그룹
idx_A = set(range(n)) - idx_B #A 크기의 무작위 그룹
return x.loc[idx_B].mean() - x.loc[idx_A].mean() #무작위 그룹의 평균 차이
import numpy as np
nA = session_time[session_time['Page'] == 'Page A'].shape[0] #그룹 A의 크기
nB = session_time[session_time['Page'] == 'Page B'].shape[0] #그룹 B의 크기
perm_diffs = [perm_fun(session_time.Time, nA, nB) for _ in range(1000)] #1000번 무작위 순열 생성
mean_a = session_time[session_time['Page'] == 'Page A'].Time.mean()
mean_b = session_time[session_time['Page'] == 'Page B'].Time.mean()
fig, ax = plt.subplots(figsize=(5, 5))
ax.hist(perm_diffs, bins=11, rwidth=0.9)
ax.axvline(x = mean_b - mean_a, color='black', lw=2)
ax.text(50, 190, 'Observed\ndifference', bbox={'facecolor' : 'white'})
ax.set_xlabel("Session Time differences (per seconds)")
ax.set_ylabel("Frequency")
plt.tight_layout()
plt.show()
무작위 순열로 만든 데이터들로 분포를 그려봤을 때, 실제로 관찰된 차이가 순열분포 내에 존재하는 것을 알아냈다.
그렇다면 실제로 관찰된 차이보다 더 극단적으로 차이가 발생할 확률은 얼마일까?
# 무작위 순열로 구한 세션 시간 차이가 실제 관찰된 것보다 클 확률?
print(np.mean(perm_diffs > mean_b - mean_a))
무작위 순열로 만든 분포이므로 값이 모두 다르겠지만, 필자는 0.135가 나왔다.
따라서 실제 관찰값보다 극단적인 케이스가 나올 확률은 13.5%.
관찰된 값이 순열분포 내에 있으므로 통계적으로 유의미한 차이가 있지는 않지만,
관찰된 값 혹은 그 이상의 차이가 13.5% 확률로 발생할 수 있다는 의미이다.