글 목록
#1 불균형한 데이터 분포 전처리하기
#2 (Random Forest) train-test 분할 및 간단한 모델 학습
#3 Validation 데이터 분할, K-fold 교차검증
1. Validation 데이터 분할
- 사이킷런의 model_selection의 train_test_split을 활용
(여기서 'test'이라는 표현에 혼동이 있을 수 있으나 'validation'의 의미로 생각하면 됨)
- stratify
- 기존에 train과 test로만 분리된 데이터를 => train, val, test의 세 가지로 나눔
(train에서 일정 비율을 떼어내 val 데이터로 만듦)
| train_x |
train_y |
| val_x |
val_y |
| test_x |
test_y |
from sklearn.model_selection import train_test_split
X_train, X_val, Y_train, Y_val = train_test_split(train_x, train_y,
stratify = train_y,
test_size = 0.25,
random_state = 10086)
아까 방법 그대로. clf 분류기를 학습시켜보자!
이후, (최종 test 데이터에 대한 예측 전), valid 데이터에 대한 예측을 우선적으로 진행해보자.
clf = RandomForestClassifier()
clf.fit(X_train, Y_train)
Y_proba = clf.predict_proba(X_val)
val 데이터에 대한 모델의 예측 점수(성능)을 계산해보자.
- 사이킷런의 함수 통해 점수 반환하려면, Y_val을 원핫인코딩 형태로 변환해야 함.
pandas의 get.dummies()
- val에 대한 점수 반환해보기
사이킷런의 metrics의 log_loss 함수 이용
log_loss(정답, 예측값)
Y_val_onehot = pd.get_dummies(Y_val)
from sklearn.metrics import log_loss
log_loss(Y_val_onehot, Y_proba)
2. K-fold 교차검증
2.1 Fold 생성
상대적으로 데이터량이 충분하지 않은 경우, 머신러닝에서는 나에게 주어진 데이터를 얼마나 효율적이고 효과적으로 사용해내느냐가 중요하다. 이때 활용할 수 있는 것이 'K-fold 교차검증'이다.
- 과적합 방지 위한 툴
- 데이터를 k개의 폴드로 쪼개어 하나씩 돌아가며 valid data를 수행함 => k개 경우의 성능 평균을 산출
- 사이킷런의 model_selection에서 (Stratified)KFold 사용
StratifiedKFold(n_splites = n, shuffle = True, randome_state = n)
각 데이터의 인덱스 숫자를 기준으로.
from sklearn.model_selection import StratifiedKFold
folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=55)
잠깐, StratifiedKFold가 어떠한 방식으로 데이터를 쪼개는지 간단히 살펴보자.
K개의 폴드가 생성되므로, 쪼개는 경우의 수 역시 K일 것이다. 그 가운데 첫 번째 경우는 이하와 같이 쪼개진다.
(array([ 0, 1, 2, ..., 26454, 26455, 26456]), #train_index에 해당
array([ 4, 12, 23, ..., 26442, 26443, 26446])) #val_index에 해당
따라서 iloc을 이용하면 train에 해당하는 데이터와 val에 해당하는 데이터를 '인덱스'를 기준으로 쪼갤 수 있다.
KFold를 생성하고 각 경우에 대한 학습 성능을 산출하는 일련의 과정을 for문으로 합쳐보자.
2.2 for문으로 합치기: 각 폴드에서의 예측 점수를 반환
- enumerate : 출력되는 현재 for문에 몇번째에 대한 for문인지 알려줌
- 각각의 학습이 서로 독립적으로 이루어지도록, classifier를 매번 새롭게 선언해야 함.
- 문자열 formatting 문법 기억!"%d번째 학습 결과는 %.4f점 입니다.\n\n"%(n_fold+1,score)
https://studymake.tistory.com/179
scores = []
n_splits=5
folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=55)
for n_fold, (train_index, val_index) in enumerate(folds.split(train_x, train_y)):
X_train, X_val = train_x.iloc[train_index], train_x.iloc[val_index]
Y_train, Y_val = train_y.iloc[train_index], train_y.iloc[val_index]
clf = RandomForestClassifier()
clf.fit(X_train, Y_train)
Y_val_proba = clf.predict_proba(X_val)
Y_val_onehot = pd.get_dummies(Y_val)
score = log_loss(Y_val_onehot, Y_val_proba)
print("%d번째 학습 결과는 %.4f점 입니다.\n\n"%(n_fold+1,score))
scores.append(score)
if n_fold+1 == n_splits:
avg_score = sum(scores)/n_splits
print("평균 점수는 %.4f점 입니다!"%avg_score)
break
>>> 1번째 학습 결과는 1.0524점 입니다.
2번째 학습 결과는 1.0799점 입니다.
3번째 학습 결과는 1.1412점 입니다.
4번째 학습 결과는 1.0329점 입니다.
5번째 학습 결과는 1.0653점 입니다.
평균 점수는 1.0743점 입니다!
2.3 최종 Test (앙상블)
KFold를 사용함에 따라, 주어진 데이터로 총 K번의 서로 다른 학습을 진행할 수 있게 되었다.
이같은 방식으로 랜덤포레스트 classifier를 튜닝하고, 더 좋은 성능의 모델을 만들 수 있다.
=> 이때 각 fold별 모델을 test 데이터에 대한 추론으로 바로 사용하여 제출물을 만들 수도 있다. (= 앙상블)
=> 1개밖에 없던 분류기를 -> k개로 늘린 것 -> val은 각 분류기의 성능을 대략 예측해줌 -> 동일한 test 데이터에 대해 각 분류기가 k가지의 서로 다른 예측 결과를 반환함
➡️모델 전체에 대한 최종 성능 = mean(k개의 성능 점수)
➡️모델이 test에 대해 최종 예측한 결과 = mean(k개의 예측 결과)
scores = []
sub = np.zeros((test_x.shape[0],3))
for n_fold, (train_index, val_index) in enumerate(folds.split(train_x, train_y)):
X_train, X_val = train_x.iloc[train_index], train_x.iloc[val_index]
Y_train, Y_val = train_y.iloc[train_index], train_y.iloc[val_index]
clf = RandomForestClassifier()
clf.fit(X_train, Y_train)
Y_val_proba = clf.predict_proba(X_val)
Y_val_onehot = pd.get_dummies(Y_val)
sub += clf.predict_proba(test_x)
score = log_loss(Y_val_onehot, Y_val_proba)
scores.append(score)
sub = sub / 5
np.mean(scores)
sample_submission.to_csv("5fold_prediction.csv", index=False)
출처
https://www.youtube.com/watch?v=fBBHiShcJZo&list=LL&index=3
가쟈가쟈가쟈~