1. 전수조사와 표본조사
- 전수조사
- 모집단 내에 있는 모든 대상을 조사하는 방법
- 모집단의 특성을 정확히 반영하지만 시간과 비용이 많이 소모됨
- 표본조사
- 모집단으로부터 추출된 표본을 대상으로 분석 실시
- 전수조사의 단점을 보완하지만 모집단의 특성을 반영하는 표본이 제대로 추출되지 못하면 수집된 자료가 무용지물
2. 용어
- Sample: 큰 데이터 집합으로부터 얻은 부분집합
- Population: 데이터 집합을 구성하는 전체
- N(n): 모집단의 크기
- 랜덤 표본추출: 무작위로 표본을 추출하는 것
- 층화 랜덤 표본추출: 모집단을 여러개의 층으로 나누고 각 층에서 무작위로 표본 추출
- 단순 랜덤 표본추출: 층화 없이 단순하게 무작위로 표본 추출
- 표본 편항 (Sample Bias): 모집단을 잘못 대표하는 표본 추출
- 표준 오차
- 통계에 대한 표본 분포의 변동성
- 표본 값들의 표준편차(s)와 표본 크기(n)를 기반으로 추정
- 표준오차와 표본 크기 사이의 관계는 n제곱근의 법칙이라고 하는데 표준오차를 2배 줄이려면 표본 크기를 4배로 증가시켜야 함
3. 표본 추출
- 전체 데이터(모집단) 중 일부를 표본(샘플)로 추출하는 작업이 데이터 분석에서 필수
- 훈련 데이터(80%), 테스트 데이터(20%)로 분리하여 데이터에 대한 모델링은 훈련 데이터로만 수행하고 모델의 성능은 테스트 데이터로 평가하면 모델의 성능을 가장 적절히 평가
- 데이터의 분포가 일정하지 않다면 가중치를 이용해서 데이터 추출하는 부분도 고려
- random.sample
3-1) 머신러닝에서 표본 추출
- train data(모델 생성) 와 test data(모델 테스트)로 나누는 방법
- train data 와 test data 와 validation data(모델 검증)로 나누는 방법
3-2) 복원추출과 비복원추출
- 복원 추출: 추출된 데이터를 모집단에 포함시켜서 추출
- python에서는 random.random, randint, randrange 등의 함수가 있음
- 비복원 추출: 한 번 추출된 데이터는 모집단에 포함시키지 않고 추출
- python에서는 random.sample 함수가 제공됨
import random
li = ["SES", "소녀시대", "f(x)", "레드벨벳", "에스파"]
#복원 추출
for i in range(5):
print(li[random.randint(0, len(li)-1)], end='\t')
print()
#비복원 추출
print(random.sample(li, k=5))
f(x) f(x) 레드벨벳 SES f(x) ['f(x)', '레드벨벳', '소녀시대', 'SES', '에스파'] |
3-3) 가중치를 적용한 표본추출
- 표본의 비율이 달라져야 하는 경우 표본을 추출할 때 비율을 설정해서 추출하는 것
- numpy.random.choice(a, size=None, replace=True, p=None)
- a: 배열, size: 개수, replace: 복원여부, p: 확률
- 추출하고자 하는 배열, 개수, 확률을 제시하면 가중치를 적용해서 표본 추출
- 현실 세계의 문제에서는 간혹 가중치를 적용한 표본 추출이 어려우면 표본 추출을 해서 분석을 한 후 가중치 적용
ar = ["라투", "오미크론", "다크스펙터", "나이즈", "슬리피"]
print(np.random.choice(ar, 10, [0.05, 0.15, 0.2, 0.3, 0.3]))
['다크스펙터' '라투' '나이즈' '슬리피' '다크스펙터' '라투' '라투' '슬리피' '오미크론' '슬리피'] |
3-4) pandas의 표본추출
- Series나 DataFrame에서 sample 함수 제공
- Series.sample(n=None, frac=None, replace=False, weights=None, random_state=None, axis=None)
- n: 추출한 샘플의 수 (frac과 중복 사용 불가)
- frac: 전체 개수의 비율만큼 샘플을 반환하려 할 경우 사용
- replace: 복원추출 여부, 기본값음 False(중복불가)
- weights: 샘플 추출 시 샘플마다 뽑힐 확률 조정
- random_state: 랜덤 샘플 추출 시 시드를 입력받음
- axis: 샘플을 추출할 방향. 기본=0(행)
ex_df = pd.DataFrame(np.arange(0,12).reshape(4, 3))
print(ex_df)
print()
#2개의 행을 추출
print(ex_df.sample(n=2))
print()
#1개의 열을 랜덤하게 추출
print(ex_df.sample(n=1, axis=1))
print()
0 1 2 0 0 1 2 1 3 4 5 2 6 7 8 3 9 10 11 0 1 2 2 6 7 8 0 0 1 2 0 0 0 1 3 2 6 3 9 |
3-5) sklearn을 이용한 샘플 추출
- scikit-learn.model_selection 의 train_test_split()
- 훈련 데이터 와 테스트 데이터를 분할하기 위한 API
- shuffle 옵션: 기본값은 True 로 되어 있는데 시계열 데이터와 같은 데이터를 추출할 때처럼 랜덤한 추출이 아닌 순차적 분할을 해야 하는 경우, False 를 설정해서 추출
- test_size: 테스트 데이터의 비율을 설정
- 일반적으로 8:2 또는 7:3을 선호하지만 데이터가 아주 많은 경우에는 5:5 설정 가능
- 이렇게 데이터가 많으면 테스트 데이터를 다시 테스트 데이터 와 검증을 위한 데이터로 분할하기도 함
- 리턴되는 데이터는 4개의 데이터 그룹에 대한 tuple
- 피처의 훈련데이터, 피처의 테스트 데이터, 타겟의 훈련 데이터, 타겟의 테스트 데이터
#데이터 생성
#특별한 경우가 아니면 피처는 대문자 X로 나타냅니다.
#타겟은 소문자 y로 나타냅니다.
#numpy 의 1차원 ndarray는 출력을 하면 옆으로 펼쳐지지만 하나의 열로 간주합니다.
X = np.arange(20).reshape(10, 2)
print(X)
y = np.arange(10)
print(y)
[[ 0 1] [ 2 3] [ 4 5] [ 6 7] [ 8 9] [10 11] [12 13] [14 15] [16 17] [18 19]] [0 1 2 3 4 5 6 7 8 9] |
#순차적 분할 7:3
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=False)
print('X_train shape:', X_train.shape)
print('X_test shape:', X_test.shape)
print('y_train shape:', y_train.shape)
print('y_test shape:', y_test.shape)
print()
print(X_train)
X_train shape: (7, 2) X_test shape: (3, 2) y_train shape: (7,) y_test shape: (3,) [[ 0 1] [ 2 3] [ 4 5] [ 6 7] [ 8 9] [10 11] [12 13]] |
- 무작위 추출
- shuffle 옵션 제거하고 동일한 데이터 추출을 위해 random_state에 seed값 고정
#순차적 분할 - 7:3
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print(X_train)
print()
print(y_train)
[[ 0 1] [14 15] [ 4 5] [18 19] [ 8 9] [ 6 7] [12 13]] [0 7 2 9 4 3 6] |
l1 = np.array(range(0, 10))
l2 = np.array(range(10, 20))
print(np.vstack((l1, l2)).T)
[[ 0 10] [ 1 11] [ 2 12] [ 3 13] [ 4 14] [ 5 15] [ 6 16] [ 7 17] [ 8 18] [ 9 19]] |
- 층화 추출
- 데이터를 일정한 비율로 무작위 추출
- 머신러닝에서 타겟의 비율의 일정하지 않은 경우 사용
- 타켓의 비율이 편차가 심한 경우 랜덤하게 추출했을 때 비율이 낮은 데이터가 추출이 안될 수 도 있고 너무 많이 추출될 수 도 있다.
- 이렇게 머신러닝의 결과가 엉뚱한 결과가 추출될 수 있습니다.
- 층화 추출을 할 때는 stratify 옵션에 리스트를 대입하면 비율 계산을 해서 추출
X = np.arange(30).reshape(15, 2)
y = np.arange(15)
grep = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
#단순한 방식으로 추출을 하게 되면 한쪽으로 샘플이 쏠리는 현상이 발생하고
#이렇게 되면 샘플 데이터에서는 잘 맞지만 실제 서비스 환경에서는 제대로 맞추지 못하는
#현상이 발생할 수 있습니다.
'''
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2,
shuffle=True,
random_state = 1004)
print(y_train)
print(y_test)
'''
#stratify 에 대입한 리스트의 비율을 확인해서 샘플링
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2,
shuffle=True,
stratify=grep,
random_state = 32)
print(y_train)
print(y_test)
[14 12 7 9 10 4 6 2 11 1 0 5] [ 8 3 13] |
3-6) 층화 추출 API
- scikit-learn.model_selection 의 StratifiedShuffleSplit()
- n_splits: 데이터를 몇 개의 그룹으로 분할할지를 설정
- 데이터를 리턴하지 않고 데이터의 인덱스를 리턴
- k-folds cross-validation을 수행하기 위해서 만든 API
- 모델을 만들고 이를 검증을 할 때 전체 데이터를 N 등분해서 N-1 개의 그룹으로 모델을 만들고 1개의 그룹으로 테스트를 수행하는데 N 번 수행
#교차 검증을 위해서 데이터를 n 등분 층화 추출을 해주는 API
#직접 사용하지 않고 머신러닝 모델이 내부적으로 사용
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=1002)
#인덱스를 리턴하므로 인덱스를 이용해서 데이터를 추출해서 확인
for train_idx, test_idx in split.split(X, grep):
X_train = X[train_idx]
X_test = X[test_idx]
y_train = y[train_idx]
y_test = y[test_idx]
print(y_train)
print(y_test)
[ 8 4 7 0 10 11 12 2 14 3 5 6] [13 9 1] |
3-7) 재표본 추출
- 랜덤한 변동성을 알아보자는 일반적인 목표를 가지고 관찰된 데이터의 값에서 표본을 반복적으로 추출하는 것
- 종류
순열 검정
- 두 개 이상의 표본을 함께 결합해서 관측값을 무작위로 재표본으로 추출하는 과정
- 두 개 이상의 표본을 사용하여 A/B 검정(하나의 UI 와 새로운 UI를 도입했을 때 결과 비교 등에 사용하는 방식) 등에 이용
- 여러 그룹의 결과를 하나의 데이터 집합으로 합침
- 결합된 데이터를 잘 섞은 다음 A 그룹과 동일한 크기의 표본을 비복원 무작위로 추출
- 나머지 데이터에서 B 그룹과 동일한 크기의 샘플을 비복원 무작위로 추출
- 그룹이 더 존재하면 동일한 방식으로 추출
- 원래의 표본에 대해 구한 통계량 또는 추정값이 무엇이었든지 간에 추출한 재표본에 대해서 다시 계산하고 기록을 한 다음 원래의 표본에 대해서 구한 값과 비교
- 이 작업을 여러 번 반복
부트스트래핑
- 모수의 분포를 추정하는 방법으로 현재있는 표본에서 추가적으로 표본을 복원 추출하고 각 표본에 대한 통계량을 다시 계산하는 것
- 개념적으로만 보면 원래 표본을 수천 수백만 번 복제하는 것
- 1억개의 모집단에서 200개의 표본을 추출
- 200개의 표본 중에서 하나를 추출해서 기록하고 복원
- 이 작업을 n번 반복
- n번 반복한 데이터를 가지고 통계량을 계산
- 이전 과정을 여러 번 반복해서 통계량을 구하고 이 통계량을 이용해서 신뢰구간을 구하는 방식
- 시간이 오래 걸린다.
- coffee_dataset.csv 파일의 데이터
21살 미만 여부
커피를 마시는지 여부
키에 대한 데이터
diffHeightListOver21 = []
for _ in range(iterationNum):
bootSample = df_sample.sample(200, replace=True) # 복원 추출
nonCoffeeHeightMeanOver21 = bootSample.query("age != '<21' and drinks_coffee == False").height.mean() # 21살 이상이며 커피를 마시지 않는 사람 평균 키
coffeeHeightMeanOver21 = bootSample.query("age != '<21' and drinks_coffee == True").height.mean() # 21살 이상이며 커피를 마시는 사람 평균 키
diff = nonCoffeeHeightMeanOver21 - coffeeHeightMeanOver21
diffHeightListOver21.append(diff)
np.percentile(diffHeightListOver21, 0.5), np.percentile(diffHeightListOver21, 99.5)
0.37151963778610253 3.266041922112605 |
# 1. 커피를 마시지 않는 사람과 커피를 마시는 사람의 평균 키 차이
print(df[df['drinks_coffee'] == False].height.mean() - df[df['drinks_coffee'] == True].height.mean())
# 2. 21살 이상과 21살 미만인 사람들의 평균 키 차이
print(df[df['age'] == '>=21'].height.mean() - df[df['age'] == '<21'].height.mean())
# 3. 21살 미만인 사람들 중 커피를 마시지 않는 사람과 커피를 마시는 사람의 평균 키 차이
print(df.query("age == '<21' and drinks_coffee == False").height.mean() - df.query("age == '<21' and drinks_coffee == True").height.mean())
# 4. 21살 이상인 사람들 중 커피를 마시지 않는 사람과 커피를 마시는 사람의 평균 키 차이
print(df.query("age != '<21' and drinks_coffee == False").height.mean() - df.query("age != '<21' and drinks_coffee == True").height.mean())
-1.9568024933369799 3.88229124992111 1.6993900935511732 1.9509354889786579 |
'Python' 카테고리의 다른 글
[Python] 지도학습 연습 _ 자전거 대여 수요 예측 (0) | 2024.03.06 |
---|---|
[Python] 벡터 연산에서 기억할 부분 (0) | 2024.02.27 |
[Python] 확률 분포 모형 (1) | 2024.02.26 |
[Python] 기술통계 (0) | 2024.02.22 |
[Python] 이미지 데이터 다루기 (0) | 2024.02.21 |