모델 평가 및 선정 > Bootstrap Method

2021. 6. 28. 23:26머신러닝

반응형

머신러닝에서 일반적으로 bootstrap 방법은 Trianing dataset이 부족할 때, dataset의 규모를 늘릴 때 많이 활용되는 방법입니다. 통계학관점에서는, 평균과 같은 측정된 통계치에 대한 통계적 검증 및 신뢰성 확보를 위해 활용하곤 합니다.

Bootstrap을 수행하는 기본적인 방법은 복원추출을 활용하여 기존 Training data의 수와 똑같은 수의 dataset을 추출하는 것입니다. 

만약 N개의 Bootstrap data set을 만든 후 data의 총 합과 같은 어떤 관측값을 도출해본다고 생각해보겠습니다. 원래 하나의 dataset만 있다면 해당 값의 분산을 구하는 것은 어렵지만 Bootstrap을 활용한다면 이러한 것이 가능하게 됩니다.

이와 마찬가지 생각을 모델 Error에도 적용해보겠습니다. 

Bootstrap이 된 데이터마다 모델을 Fitting하여 Error를 확인해볼 수 있습니다. 다만, Bootstrap된 데이터도 기존 Training data set에 있는 값들이 나온 것이므로, Overfitting될 위험이 있습니다. 그렇기 때문에 Cross-validation 개념을 적용하는데, 특정 Sample을 제거하고 Bootstrap을 수행한 후 Error를 측정하는 것입니다. leave-one-out cross-validation과 유사하게 하나의 Sample을 제거하고 Bootstrap을 수행하는  leave-one-out bootstrap의 Error는 다음과 같습니다.

leave-one-out bootstrap은 Overfitting 문제를 다소 해결할 수 있으나, Training dataset의 size가 작을 때 outlier에 영향을 쉽게 받을 수 있으며, training dataset의 사이즈가 크면 계산에 들어가는 Resource가 커지게 됩니다.

Cross-validation 및 Bootstrap관련하여 간단한 Python Code를 정리해 보겠습니다. 아래 사이트를 참고하였습니다.

https://davinci-ai.tistory.com/18

https://dlearner.tistory.com/21?category=828987 

https://machinelearningmastery.com/a-gentle-introduction-to-the-bootstrap-method/

Cross-Validation

import pandas as pd
import numpy as np 

## K-Fold
from sklearn.model_selection import KFold 

X = ["a", "b", "c", "d"] 

kf = KFold(n_splits=2) 
for train, test in kf.split(X): 
    print("%s %s" % (train, test)) ##

'''
 index 반환
[2 3] [0 1]
[0 1] [2 3]
'''


## Repeated K-Fold
from sklearn.model_selection import RepeatedKFold

X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]]) 

rkf = RepeatedKFold(n_splits=2, n_repeats=2, random_state=123) 
for train, test in rkf.split(X): 
    print("%s %s" % (train, test))
    
'''
 index 반환
[1 2] [0 3]
[0 3] [1 2]
[0 2] [1 3]
[1 3] [0 2]
'''

## Leave One Out
from sklearn.model_selection import LeaveOneOut
X = [1, 2, 3, 4] 
loo = LeaveOneOut() 
for train, test in loo.split(X): 
    print("%s %s" % (train, test)) 
    
 '''
 index 반환
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]
'''   

## Leave P Out
from sklearn.model_selection import LeavePOut 
X = np.ones(4) 
lpo = LeavePOut(p=2) 
for train, test in lpo.split(X): 
    print("%s %s" % (train, test))

    
 '''
 index 반환
[2 3] [0 1]
[1 3] [0 2]
[1 2] [0 3]
[0 3] [1 2]
[0 2] [1 3]
[0 1] [2 3]
'''   




## Stratified K-Fold
from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=2)

iris= load_iris()
iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
iris_df['label']=iris.target
iris_df['label'].value_counts()

for train_index, test_index in skf.split(iris_df, iris_df['label']):
    
    label_train = iris_df['label'].iloc[train_index]
    label_test = iris_df['label'].iloc[test_index]
    print('학습 레이블 데이터 분포:\n', label_train.value_counts())
    print('검증 레이블 데이터 분포:\n', label_test.value_counts())
    
 '''
 Label 비율 동일 여부 확인, 150개 데이터를 75개씩 2개 그룹으로 나눔(2-Fold)
학습 레이블 데이터 분포:
 2    25
1    25
0    25
Name: label, dtype: int64
검증 레이블 데이터 분포:
 2    25
1    25
0    25
Name: label, dtype: int64
학습 레이블 데이터 분포:
 2    25
1    25
0    25
Name: label, dtype: int64
검증 레이블 데이터 분포:
 2    25
1    25
0    25
Name: label, dtype: int64
'''

## Cross-validation 활용
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

logreg = LogisticRegression()
logreg.fit(iris.data, iris.target)

kfold5 = KFold(n_splits=5) 
cross_val_score(logreg, iris.data, iris.target , cv= kfold5 ,scoring='accuracy')


logreg.predict(iris.data)

loo = LeaveOneOut() 
cross_val_score(logreg, iris.data, iris.target , cv= loo,scoring='accuracy')

logreg.predict(iris.data)

Bootstrap

##Bootstraping

from sklearn.utils import resample
from sklearn.metrics import mean_squared_error

data = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]

boot = resample(data, replace=True, n_samples=100, random_state=1)

print(boot)

'''
bootstrap 결과
[0.6, 0.4, 0.5, 0.1, 0.2, 0.4]

'''
## bootstrap 활용

target = iris.target.reshape(-1,1)
df = np.hstack((iris.data, target))
df  = pd.DataFrame(df)
df.columns = ["f1","f2","f3","f4","target"]

df_index = [i for i in df.index]

mse_list = []
for k in range(5):
    bootstrap = resample(df_index, replace = True, n_samples = 150)
    x = df.iloc[bootstrap][["f1","f2","f3","f4"]]
    y = df.iloc[bootstrap]["target"]
    
    temp_y = logreg.predict(x)
    mse_list.append(mean_squared_error(y, temp_y))
    

np.mean(mse_list)
반응형