목차
0. 개요
- 참여 기간: 2023.06.29 ~ 2023.07.09 (약 10일)
1. Motivation
AI 관련 업무를 맡아 수행한지 벌써 3년이 거의 다 되어가는데, kaggle에 매우 늦게 입문했다. 사실은 계정을 만든지는 꽤 오래되었지만, 일에 치인다는 핑계와 높은 성과를 낼 수 없을 거라는 두려움에 시작하지 않았다. 이직하고 이제 딱 3개월이 되었는데, 이전 회사에 비해서 업무 자유도가 매우 높아서 역량 강화에 많은 시간을 할애할 수 있게 되었다. 마침 KPI에도 Competition 항목이 있어서, 이번 기회에 시작해보기로 했다.
2. Joined!!
- 목표
- AUROC 0.6 이상 달성하기
- 성능 높이는 노하우 터득하기
처음으로 성능을 내보겠다고 다짐하며 참여한 대회여서, 마음속에만 큰 꿈을 꾸고 대외적으로는 조그만 목표를 세웠다. 조인 시점에 leaderboard를 쭉 확인해보니, auroc가 0.6 언저리에 있길래, 높아져도 7 이상은 못가겠다 싶었고, 요걸 목표로 끝까지 달려보기로 했다. 그리고, 스타트인 만큼 성능을 높일 수 있는 다양한 시도들을 해보고 내 것으로 만들어봐야겠다 싶었다. 진행 중인 경진대회들은 보통 코드가 eda 선까지만 공개되곤하는데, 이 대회의 경우 playground 수준의 프로젝트여서 실력자분들께서 나름의 철학이 담긴 노트북을 많이 공개해주셨고, 요걸 매우 많이 참고하여 내 코드를 구성하였다.
참고한 노트북들
- 파라미터 튜닝 정보 얻음: hhps://www.kaggle.com/code/onurkoc83/xgboost-and-lgbm-cv-score-0-688-public-0-646
- feature engineering 정보 얻음: https://www.kaggle.com/code/ravi20076/playgrounds3e18-eda-baseline
3. Enormous Submissions
이 프로젝트의 경우, 매일 5개의 제출이 가능했으므로, 10일간 50번의 제출을 할 수 있었다. 44번의 제출을 통해 public score(average auroc) 0.534 → 0.597 까지 끌어올릴 수 있었다. 그 기간 동안 나는 다음의 시도들을 쌓아나갔다.
시도한 방법들
- baseline: binary classification code copy!
- hyperparameter tuning included by optuna
- voting included
- feature engineering
- ensemble (custom bagging method)
- multi-label stratified k fold split (5 → 10)
- multi-label oversampling (→ only balanced randomly)
1) ensembles
주요 모델로는 xgboost, sklearn의 mlp, keras로 직접 만든 mlp를 사용하였다. private score 공개 이후의 결과를 확인해보니 확실히, 앙상블은 선택이 아닌 필수라는 것을 알 수 있었다. 더 많은 모델로 앙상블할수록 성능이 더 좋아졌다.
2) custom mlp
keras 로 multi-label 문제를 풀 때에는 다음과 같은 구성이 필요했다.
- last layer
- units: the number of classes
- activation: sigmoid
- loss: binary crossentropy
3) multi-label stratified k fold split
sklearn의 splitter 들은 multi-label을 지원하지 않기 때문에, 특별히 iterstrat 라이브러리를 사용하여 split했다. 사용법은 매우 간단하다. sklearn의 splitter에서 이걸로 바꿔 k-fold 학습을 하니 성능이 훨씬 좋아졌던 것으로 기억한다.
from iterstrat.ml_stratifiers import MultilabelStratifiedKFold
mskf = MultilabelStratifiedKFold(
n_splits=n_splits, shuffle=True, random_state=42)
for i, (train_index, val_index) in enumerate(mskf.split(df_X, df_y)):
...
4) multi-label oversampling (→ only balanced randomly)
사실은 불균형의 해소를 문제 삼은 것이 아니라, 그저 데이터를 증강하고 싶었다. 근데 내가 직접 가우시안 노이즈 같은 걸 섞는 것보다는 메서드의 도움을 받는 게 좋을 것 같아서 찾다가보니 결론적으로는 multi-label의 불균형을 해소하는 방법으로 오버샘플링을 수행하게 됐다.
멀티레이블은 직접 오버샘플링이 안되어서, 다른 메서드의 도움을 받아 오버샘플링을 수행했다. 원래의 목적은 데이터 증강이라, parameter로 데이터의 개수를 전달할 수 있나? 했는데, 그런 건 없고 minority classes에 대해서 무작위로 major 클래스 개수만큼 샘플링하는 방법이 적용되었다. 시간도 없고 해서 대강 적용 가능한 코드를 빌려와 사용했는데, 다음 시도 때에는 random 말고 smote이나 다른 오버샘플링 방법들도 적용해보는 게 좋을 것 같다.
from skmultilearn.problem_transform import LabelPowerset
from imblearn.over_sampling import RandomOverSampler
lp = LabelPowerset()
ros = RandomOverSampler(random_state=42)
# Applies the above stated multi-label (ML) to multi-class (MC) transformation.
yt = lp.transform(train_y)
X_resampled, y_resampled = ros.fit_resample(train_X, yt)
# Inverts the ML-MC transformation to recreate the ML set
y_resampled = pd.DataFrame(
lp.inverse_transform(y_resampled).toarray(), columns=train_y.columns)
4. Growth and Reflections
우선 끝까지 여러 시도를 해보려고 노력한 것에 칭찬하고 싶다. 짧은 기간이었지만, 매일 밤낮으로 리서치하고, 그 내용을 구현하여 코드에 넣고 돌려보고, 결과를 확인하고 했던 것. 이런 시도들이 모이면 내가 모르는 새에 성장할 수 있을 거다.
사실 생성모델이나 멀티모달이 판을 치고 있는 이 시점에 정형데이터로 성능을 내는 건 엄청난 건 아닐 수 있다. 그럼에도 불구하고 이 시도는 적어도 나에게는 매우 큰 의미가 있는 시도였다. 회귀나 분류 문제는 자주 다룰 기회가 있었기에 다 할 줄 안다고 생각했는데, 사실 multi-class가 아닌 multi-label은 처음 경험한 거였다. 상용 라이브러리에도 제한이 있어, 우회적인 방법을 써야하는데 이번 시도가 없었다면, 이걸 몰라서 성능이 안나온다고 좌절했을 것 같다.
이번에 시도를 하면서, submission들을 날짜, 모델명, 성능으로 구분하였는데, 다른 기능을 적용하니 파라미터 정보와 로깅이 안되어서 구분이 잘 안되는 경험을 했다. 다음 시도부터는 submission과 submission meta 정보를 함께 저장하여 결과를 잘 확인할 수 있게끔 기능 개선을 하는 게 좋을 것 같다.
앗 그리고 초기에 목표로 설정했던 성능 0.6 넘기기와 노하우 습득하기는 어느정도 달성했다 (조금 억지이긴하지만 private score는 0.6 넘었으니까..) 고생했따 나 자신! 아직 갈길이 멀다. 호다닥 뛰어가쟈...
5. Next Step
이번에는 정형데이터로 맛보기를 해보았으니, 이미지나 시퀀스 쪽으로 해볼만한 competition이 있으면 또 한 번 시도해보아야겠다. 안해봤다고 두려워하지 말고, 도전해보쟈!
'인공지능' 카테고리의 다른 글
leave-one-out evaluation이란? (0) | 2023.07.18 |
---|---|
tf.matmul과 tf.multiply 차이 (행렬곱, 성분곱) (0) | 2023.07.18 |
Autoencoder & Anomaly Detection (오토인코더와 이상 탐지) (0) | 2023.07.14 |
MNIST 데이터 읽기 (0) | 2023.07.03 |
multi-label classification의 활성화 함수와 손실 함수 (0) | 2023.07.01 |