model training시 cross validation을 통해서 model의 fold를 여러개 나눠서 out of fold validation 성능을 측정하고 test data예측을 통해 성능 향상을 유도

대충 데이터가 다음과 같이 생겼는데

2009/12~2011/11까지 데이터가 존재하고 우리가 예측해야할 것은 2011/12
train data는 2009/12~2011/11이고 test data는 2011/12
1) 2009/12~2011/11에서 적절하게 train과 validation을 label별로 고른 비율을 가지도록 stratified k fold split함
2) 각 fold별로 validation 예측을 하고 예측한 것을 out of fold에 하나 하나 다 모으는 거
3) 그리고 각 fold에서 만든 모델을 test data에 대해 prediction을 함
4) fold를 다 돌면 out of fold에 모인 것은 사실 결국에는 전체 train data에 대한 예측치가 다 모여서
train data 정답과 비교해서 out of fold validation 성능 계산 가능
5) 각 fold에서 예측한 test prediction을 모두 모아 ensemble를 하여 최종 test prediction으로 사용함
ensemble에 soft voting이나 hard voting을 사용할 수 있지 않을까
아무튼 이렇게 하면 test data를 제출하기전에 미리 성능을 어느정도 예측해볼 수 있다는거임
*기타
경험상 실제 테스트 성능과 꽤 비슷해짐
+ class unbalance일때 stratified k - fold training을 하면 효과가 있을 수 있다고 알려져있다
+ 정형데이터 뿐만 아니라 비정형데이터의 딥러닝에서도 사용하는 경우 종종 있다
예시 코드
def make_lgb_oof_prediction(train, y, test, features, categorical_features='auto', model_params=None, folds=10,threshold=0.60):
x_train = train[features]
x_test = test[features]
# 테스트 데이터 예측값을 저장할 변수
test_preds = np.zeros(x_test.shape[0])
# Out Of Fold Validation 예측 데이터를 저장할 변수
y_oof = np.zeros(x_train.shape[0])
# 폴드별 평균 Validation 스코어를 저장할 변수
score = 0
# 피처 중요도를 저장할 데이터 프레임 선언
fi = pd.DataFrame()
fi['feature'] = features
# Stratified K Fold 선언
skf = StratifiedKFold(n_splits=folds, shuffle=True, random_state=SEED)
for fold, (tr_idx, val_idx) in enumerate(skf.split(x_train, y)):
# train index, validation index로 train 데이터를 나눔
x_tr, x_val = x_train.loc[tr_idx, features], x_train.loc[val_idx, features]
y_tr, y_val = y[tr_idx], y[val_idx]
print(f'fold: {fold+1}, x_tr.shape: {x_tr.shape}, x_val.shape: {x_val.shape}')
# LightGBM 데이터셋 선언
dtrain = lgb.Dataset(x_tr, label=y_tr)
dvalid = lgb.Dataset(x_val, label=y_val)
# LightGBM 모델 훈련
clf = lgb.train(
model_params,
dtrain,
valid_sets=[dtrain, dvalid], # Validation 성능을 측정할 수 있도록 설정
feval = lgb_f1_score,
categorical_feature=categorical_features,
)
# Validation 데이터 예측
val_preds = clf.predict(x_val)
# Validation index에 예측값 저장
y_oof[val_idx] = (val_preds >= threshold).astype(int)
# 폴드별 Validation 스코어 측정
print(f"Fold {fold + 1} | F1: {f1_score(y_val, (val_preds >= threshold).astype(int),average='macro',zero_division=0)}")
print('-'*80)
# score 변수에 폴드별 평균 Validation 스코어 저장
score += f1_score(y_val, (val_preds >= threshold).astype(int),average='macro',zero_division=0) / folds
# 테스트 데이터 예측하고 평균해서 저장
test_preds += clf.predict(x_test) / folds
# 폴드별 피처 중요도 저장
fi[f'fold_{fold+1}'] = clf.feature_importance()
del x_tr, x_val, y_tr, y_val
#gc.collect()
print(f"\nMean f1 = {score}") # 폴드별 Validation 스코어 출력
print(f"OOF f1 = {f1_score(y, y_oof,average='macro',zero_division=0)}") # Out Of Fold Validation 스코어 출력
# 폴드별 피처 중요도 평균값 계산해서 저장
fi_cols = [col for col in fi.columns if 'fold_' in col]
fi['importance'] = fi[fi_cols].mean(axis=1)
return y_oof, test_preds, fi
'정형데이터' 카테고리의 다른 글
정형데이터 분석에서 feature selection하는 몇가지 방법 (0) | 2024.04.03 |
---|---|
정형데이터 분석에서 feature importance와 permutation importance (0) | 2023.12.08 |
time series data의 cross validation에 대한 여러가지 고찰 (0) | 2022.06.28 |
데이터 전처리 - 이상치를 처리하는 방법의 기초 (0) | 2022.06.26 |
정형데이터에서 결측치를 처리하는 방법 (0) | 2022.06.24 |