관리 메뉴

TEAM EDA

[Machine Learning Advanced] 8강. 머신러닝 강의 - 캐글에서 활용되는 알아두면 좋은 팁 (Tips) 본문

EDA Study/Machine Learning Advanced

[Machine Learning Advanced] 8강. 머신러닝 강의 - 캐글에서 활용되는 알아두면 좋은 팁 (Tips)

김현우 2023. 8. 26. 04:05

이번 글에서는 캐글에서 활용되는 알아두면 좋은 몇가지 팁들에 대해 알아보도록 하겠습니다. 먼저, 베이스라인을 만든 이후에 고려하면 좋을 사항들에 대해서 살펴본 이후 마지막 성능을 쥐어짤 테크닉들을 몇개 살펴보겠습니다. 

 

실험을 하기 전 고려하면 좋을 사항들 

첫째, 디버깅 모드가 있습니다. 

 

디버깅 모드 예시

 

디버깅은 프로그래밍에서 오류를 찾아내고 수정하는 필수적인 과정입니다. 특히 머신러닝에서는 전체 프로세스가 상당히 시간이 오래 걸리기 때문에 디버깅의 중요성이 크게 증가합니다. 

 

예를 들어, Amazon KDD 추천 대회에 참여했을 때 전체 파이프라인을 완료하는 데 2~3일이 걸렸습니다. 딥러닝 대회에서도 학습 단계만으로 며칠이 소요되는 경우가 흔하며, 최근 인기 있는 LLM 모델의 경우 학습에 몇 십일이 걸릴 때도 있습니다. 이렇게 긴 시간 동안 코드가 실행되다가 중간에 문제가 발생하면, 그동안 투입된 시간과 리소스가 손실됩니다. 

 

이러한 문제를 최소화하기 위해 "샘플링"이나 "하이퍼 파라미터 축소"와 같은 전략을 사용하여 전체 파이프라인을 빠르게 테스트해 볼 수 있습니다. 이렇게 초기 단계에서 빠른 테스트를 통해 문제점을 찾아내고 수정하면, 장기적으로 시간을 효과적으로 절약할 수 있습니다.

 

둘째, 시드의 고정이 필요합니다. 

 

시드 고정 예시

 

시드는 난수 생성기의 초기값으로 사용되는 값을 의미하며 이러한 시드 고정은 "재현성(Reproducibility)"의 관점에서 중요합니다. 재현성은 동일한 실험을 여러 번 반복하거나 다른 사람이 같은 코드를 돌려도 같은 결과가 나오는 것을 의미합니다. 이를 위해 초기에 설정한 시드 값을 위의 그림과 같이 고정하여 각 실험의 시작점을 일정하게 만들어주는 것이 필요합니다. 실제 베이스라인을 만들고 실험을 하다보면 많은 결과들이 나오게 됩니다. 새로운 모델, 하이퍼파라미터 튜닝, 데이터 전처리 방법 등 다양한 실험을 수행할 때, 만일 결과의 변동성이 크다면 공정하게 해당 실험이 의미가 있는지 판단을 할 수 없게되고 이를 막기 위해 "반드시" 해야하는 작업입니다. 

 

셋째, 실험의 기록이 있습니다. 

 

실험 기록 예시

 

위의 그림은 제가 예전에 참여한 대회에서 Augmentation이라는 실험을 기록한 그림입니다. 실제 실험을 하다보면 실험의 양이 많아져서  어떤 실험을 했고 결과가 어땠는지 까먹는 상황이나 팀원들과 중복해서 실험을 하게 되는 경우가 발생합니다. 이러한 부분을 미리 실험마다 간단하게라도 결과를 작성해두면, 팀원들과 공유 차원에서나 현업에서는 온보딩 차원에서도 많은 도움이 되고 추가실험의 관점에서도 어떤 것을 해왔고 어떤 것을 추가로 할지, 기존에 했던 실험에서 다시 해볼만한게 있는지 등 유의미하게 활용이 가능합니다. 또한, 대회가 끝난 이후에 포트폴리오 등 정리하는 관점에서도 내가 어떤 것들을 해왔는지 파악이 가능해서 많은 도움이 됩니다. 

 

 

성능을 높이는 시도1. Ensemble 

첫째, 성능을 높이는 시도로 가장 쉽게 적용이 가능한 방법은 앙상블입니다. 앙상블은 Bagging, Boosting에서 봤듯이 단일 모델들을 결합하여 단일 모델보다 높은 성능을 내는 시도이고, 이론적으로나 실험적으로 높아진다는 연구들이 많이 있습니다.  

 

KFold 구조

 

이전에 다루었던 데이터 셋 분할 방법들에서 본 KFold가 앙상블의 대표적인 예시입니다. KFold는 모델의 조건(하이퍼파라미터)은 동일하지만 학습 데이터를 다르게 해서 학습한 K개의 모델들의 결과를 평균내는 방법으로 데이터 셋의 분할 방법에 따라 KFold, Stratified KFold, GroupKFold, Timeseries KFold 등 다양하게 사용이 가능합니다. 

 

위와 같이 데이터의 측면에서 다양성을 만들 수도 있지만, 모델 차원에서의 다양성도 만들 수 있습니다. 

 

모델 앙상블 구조

 

예를들어, LightGBM + Catboost 등 여러 형태의 부스팅 모델을 결합하는 방법도 생각해볼 수 있고 Boosting + NN or Transformer 등 다양한 관점에서 앙상블을 시도해볼 수 있습니다. 경험상 부스팅 모델들의 결합보다는 모델간의 상관성을 파악해서 서로 못하는 점을 보완할 수 있게 하는게 좋고, 선형 모델과 비선형 모델의 결합이라든지 Boosting과 NN의 결합 등이 대표적인 것 같습니다. 단, 앙상블을 통해 성능이 오르려면 어느정도 모델의 성능이 보장해야합니다. 단순하게 앙상블을 한다고 반드시 오르는 것은 아니고, 둘의 상관성이 너무 높거나 하나의 성능이 너무 낮으면 오히려 떨어지는 경우도 발생하니 주의하셔야 합니다. 

 

앙상블에서 OOF 생성 과정

 

학습의 경우는 KFold와 결합해서 5 * 3 = 15개의 모델을 만들어서 사용할 수도 있고 Final OOF를 통해서 앙상블의 성능 검증을 진행하고, weight average의 경우 w의 값도 이를 통해 튜닝이 가능한 점 참고하시기 바랍니다. (w를 grid search나 하이퍼 파라미터의 튜닝 방법론을 통해 찾기도 합니다) 

 

Stacking 구조

 

위와는 반대로 Stacking이라는 방법도 있습니다. Stacking은 OOF를 모아서 파생변수로 활용해 새로운 모델을 예측하는 방법입니다. [Stage1] 이전에 모델 앙상블 파트에서 본 것 처럼 XGBoost, LightGBM, Catboost 등을 통해 다양한 OOF를 수집할 수 있습니다. [Stage2] 그리고, 이런 OOF들만을 변수로 활용 (혹은, 기존 5개의 Feature + 3개의 OOF Feature)을 하여 새로운 모델을 학습하여 최종 모델을 내는 방법입니다. 

 

출처 : https://www.kaggle.com/competitions/ieee-fraud-detection/discussion/111235

 

실제 캐글에서는 900+ 의 OOF를 수집하여 Feature selection과 결합해서 최종 모델을 만들어서 극한의 성능을 끌어올리기도 합니다. 하지만, 저는 개인적으로 Stacking은 별로 안좋아하고 잘 하지는 않는데 일단 OOF의 관리가 너무 힘들고 재현하는 측면에서 되게 어렵습니다. 또한, 실제 서비스 관점에서 900개 이상의 모델들을 학습하고 추론한다는 것 자체가 쉬운 일은 아닙니다. 그래도, 성능에 한정해서는 되게 효과적인 방법이고 좋은 아이디어이니 참고하시기 바랍니다. 

 

마지막으로, 적용하기 간단한 앙상블 중 SEED Ensemble이 있습니다. 

 

Seed 앙상블 예시

SEED 앙상블은 다른 조건은 모두 고정한채로 KFold 혹은 모델의 하이퍼 파라미터 중 랜덤 시드만을 변경해서 결과를 생성하는 방법을 의미합니다. 시드의 고정 파트에서 언급한 것처럼 시드가 달라지게 되면 결과의 변동성이 발생하게 됩니다. 그렇기에, 의도적으로 시드를 여러번 교체해서 다양성을 만들고 이를 앙상블하여 최종 결과의 분산을 줄이게 만드는 방법입니다. 실제 대회에서는 Public 리더보드는 알지만 Private 리더보드는 모르기에 시드 앙상블을 통해 최대한 안정성을 보장하려는 시도를 많이합니다. 다만, bias and variance의 관계와 같이 variance가 낮아지면서 bias 또한 낮아지는 것은 쉽지 않습니다. 그렇기에, 시드 앙상블을 통해 안정성은 보장해도 성능 자체는 떨어지는 경험을 많이 했던 것 같습니다. 

 

출처 : https://www.kaggle.com/competitions/home-credit-default-risk/discussion/64722

캐글에서는 이러한 앙상블을 위와 같이 전처리, 파생변수, 모델 등 다양한 측면에서 다양성을 만들어서 수행합니다. 실제 아래와 같이 혼자하기에는 어려움이 있지만, 여러 사람이 같이 작업을 했을때 좋은 시너지를 내기엔 앙상블만한 방법이 없는 것 같습니다. 

 

 

 

성능을 높이는 시도2. Pseudo Labeling (수도 레이블)

 

수도 레이블링이란 라벨이 없는 데이터에 가짜 레이블을 만드는 과정을 의미합니다. 이렇게 만든 가짜 레이블을 가진 데이터를 기존의 학습 데이터와 결합해서 학습시켜서 라벨이 없는 데이터의 분포 또한 모델한테 학습시키려는 목적을 가지고 수행됩니다. 보통 대회에서는 테스트 데이터를 맞추는게 중요하고 레이블이 없다보니 수도 레이블을 만들어서 학습 데이터와 같이 학습시키는 전략을 사용합니다.

 

실제 수도 레이블의 과정을 보면 위의 그림과 같이 총 3단계로 진행됩니다. 

 

1. 학습 데이터를 기반으로 모델의 학습을 한 후, 테스트 데이터에 대해 예측을 수행 

이렇게 되면, 보라색의 테스트 데이터에 대한 예측값의 히스토그램이 만들어지고 0~1에 대한 분류 문제라 치면 잘 학습되었다고 했을때 0과 1쪽에 치우친 히스토그램이 만들어지게 될 것입니다. 

 

2. Pseudo Label 생성 

이후, 예측값을 통해 수도 레이블을 생성합니다. 이때, 생각해볼만한 점은 수도 레이블이 신뢰할만한 가? 입니다. 사실, 예측값을 보면 0과 1에 가까운 것도 있지만 0.5 근방으로 모델이 0과 1 둘 중 잘 모르겠다하고 찍은 값들도 존재합니다. 그렇기에, 이러한 값을 학습에 참여하는건 리스크가 너무 큽니다. 그렇기에, Pseudo Labeling은 0과 1에 매우 가까운 즉, 모델이 굉장히 확신을 가지고 예측한 결과들만을 가지고 0과 1로 레이블을 부여한 다음에 학습을 시키게 됩니다. 실제 위의 예시에서는 0.0001과 0.969처럼 0과 1에 가까운 값들만을 선택한 걸 볼 수 있습니다. 

 

3. Pseudo Label을 같이 학습 

마지막으로, 이렇게 만든 기존의 학습데이터와 수도 레이블을 만든 테스트 데이터를 결합하여 다시 모델을 학습하고 테스트에 대해 추론을 하면 해당 과정이 끝납니다. 단, 이때 경우에 따라서 2의 과정으로 돌아가서 다시 수도 레이블을 만들고 학습하는 과정을 반복하기도 합니다. 개인적인 경험으로는 반복할수록 성능이 좋아지기는 하지만 어느정도 세츄레이션 되어 일정 수준 이상으로는 높아지지 않는 것 같습니다. 

 

실험을 도와주는 시도1. 분석 자동화 

첫째, 실험을 도와주는 시도로 분석을 자동화하는 도구를 생각해볼 수 있습니다. 대표적으로 Dataprep.eda 등과 같인 EDA 자동화 툴인데 자세한 내용은 Dataprep.eda : Accelerate your EDA (EDA 자동화 패키지)의 글을 참고하시기 바랍니다. 해당 도구는 단일 변수의 분석, 변수들간의 관계 분석, 결측치 분석을 도와줍니다. 실제, 예시 데이터로 진행 과정을 보면 

 

[단일 변수의 분석]

 

 

 

[변수들 간의 분석]

 

 

[결측치에 대한 분석] 

 

등과 같이 원하는 시각화나 분석을 하기에 용이한 장점이 있습니다. 사용한 자세한 코드를 보고 싶은 분은 링크를 참고하시기 바랍니다. 

 

실험을 도와주는 시도2. WanDB

둘째, 실험의 결과를 저장해주고 비교, 관리하는 도구를 생각할 수 있습니다. 대표적으로 Weight & Bias (WanDB) 입니다. 해당 도구는 웹을 통해서 결과를 저장하고 관리하기에, 실험을 돌려놓고 다른 작업을 진행하기도 편리하고 실시간으로 모델이 돌아가는 결과를 확인할 수 있을 뿐더러 이 로그 기록이 남아서 관리하기에도 용이합니다. 저는 쥬피터에서 실험을 많이 하는데, 쥬피터의 로그가 모르고 지워졌을 때도 웹 상에 로그가 남아서 기존에 남았던 로그들을 비교해보고 파악하기도 좋았다는 장점이 있습니다. 그리고 여러 실험에 대한 결과를 한 번에 비교하기 편하고 성능 뿐만 아니라 다른 요소들 (하이퍼 파라미터)에 대해 어떤 값을 설정했는지도 파악하기 좋습니다. 

 

 

추가로, WanDB에서 하이퍼 파라미터의 튜닝을 도와주는 Sweep 기능도 있어서 이걸 활용하여 튜닝과 하이퍼 파라미터에 따른 모델의 성능을 파악하기에도 좋습니다. 

 

출처 : https://docs.wandb.ai/guides/sweeps