플레이데이터 엔지니어링 - 머신러닝 경진대회 최종 Report

2023.10.12 ~ 2023.10.20
플레이데이터 엔지니어링 - 머신러닝 경진대회 최종 Report
notion image
notion image
Public #1, Private #3으로 마감! 동메달에 만족 🤗
 
 
 

사용 데이터셋

모의 경진대회는 titanic을 일부 변형한 자체 dataset으로 진행했음
 

EDA 요약

  • Drop
    • passengerid → index의 성격을 가지고 있어서 drop
    • cabin → 결측치 비율이 과도하게 높아 (0.783) drop
      • kaggle에 쳐보니 타이타닉 배 설계도를 가져와서 cabin의 위치를 파악하고 구역별로 나누어서 범주화시켜서 하던데.. 차마 그렇게까진..
    • ticket → 문자/숫자열 섞여있음, 현실세계에서 티켓번호는 랜덤하게 나누어주기 때문에 특별한 의미를 갖고 있다고 보기 어려움
      • 물론, 비슷한 번호의 티켓끼리는 가족 등의 가까운 사이라고 해석할 수도 있겠으나.. 애매하여 drop
  • Fillna
    • age → pclass와 강한 음의 상관관계가 있어, pclass로 groupby한 뒤 group 내에서 median
      • notion image
    • fare → mean. +) 히스토그램으로 찍어보니 전체적으로 편향되어있어 해소하기 위해 log를 씌움
      • notion image
    • embarked → mode
 

데이터 전처리 : 데이터 분리(split)

  • stratify = y 옵션을 줘서 train case와 test case를 target 기준으로 균등하게 나눔 → 이진분류에 유리
 

데이터 전처리 : 결측치 치환

  • age
  • fare → median
  • embarked → mode
 

데이터 전처리 : 데이터 왜곡 수정

  • fare
 

데이터 전처리 : feature 생성

  • familysize = sibsp + parch + 1
    • sibsp와 parch 자체만으로는 관여도가 높아보이지 않아 두 feature 묶어서 family size를 만들어냄
    • + 1 붙인건 자신을 포함해야하므로 ㅎㅎ (사실 필요없지만)
  • infant
    • is_alone
      • 혼자있을 때 생존율이 높음 (가족을 위해 희생해서?)
      • notion image
      • is_alone은 family_size의 파생형이여서, family_size에 또 다른 인사이트가 없었다면 family_size는 drop 하는 편이 나았을 것 같다.
    • title

      데이터 전처리 : 인코딩

       

      데이터 전처리 : 스케일링

      • fare는 앞에서 log를 씌워 첨도수정을 했기 때문에 굳이 두번 할 필요가 있나 싶었다
        • 그렇지만 output이 두 번 하는 쪽이 더 잘 나왔기 때문에 scaling에 포함함
      • family_size는 솔직히, 스케일링 할 명확한 근거가 없는 상태로 넣었다
        • feature 생성 후에도 EDA를 하는 것이 필요하다고 생각했음
       

      모델 : RandomForest(modelV3)

      • Best hyperparameter를 찾기 위해 RandomSearchCV를 사용하였음
      • ‘hp’ 보다는 ‘hp_randomgrid’ 같은 변수로 했으면 좀 더 명확했을 것 같다
      • 각 패러미터들의 Min, Max 값을 정했어야했는데 너무 감이 없어서 구글링으로 대략적으로 어느정도 하는지를 확인해봄
      • 결과는 아래와 같음
      • 학습 후 train_score, test_score = (0.860655737704918, 0.8641304347826086)
       

      모델 : XGBoost(modelV4)

      • 원리는 V3모델과 동일
      • Random Search 진행
      • 결과는 아래와 같음
      • 학습 후 train_score, test_score = (0.8920765027322405, 0.875)
      • Auc : 0.9008771929824562
      • train score가 높고 (훈련 잘되었고), Auc 점수도 적당해서 (과적합 발생 안함) 위 Case가 Best model이라고 판단되어 최종 Submission 진행함
      • LightGBM은 Score가 생각보다 좋지 않아서, CatBoost는 속도이슈로 진행하지 않았음

      학습평가

      notion image
      • FP는 0.07, FN은 0.21이어서 FN 데이터에 대해 반복적인 EDA를 진행했으면 좀 더 나은 feature를 만들 수 있었을 것 같음
       
      notion image
      • fare의 중요도가 엄청 높은 상황을 확인하였는데, 이 결과를 보고 어떤 action을 취해야하는지 잘 감이 잡히지 않았음
        • 지금이라면 fare와 인과관계가 높은 feature들은 drop하여 다시 학습했을 것 같음 (pclass 등)

      결론

      • 요약
      🍀
      Titanic 데이터셋을 이용하여 승객들의 Survived(생존 유무)를 예측하는 이번 프로젝트를 통해 전반적인 머신러닝 과정을 경험해보고 여러가지 모델을 사용해본 의의가 있었음 (train : 0.892077, test : 0.87500, auc score : 0.900877)
      • 느낀점
      🍀
      나름 Overfitting을 잘 잡았다고 생각했는데, Public → Private 결과가 하락한 것으로 보아 L2가중치를 적용해보았으면 어땠을까 싶었음
      🍀
      train이 0.90을 넘는 것이 목표였음. feature들을 좀 더 개선했다면 90을 넘길 수 있지 않았을까 싶음
      🍀
      나름의 버전관리를 열심히 했지만, 노션으로 기록하는 방식이 그닥 효율적으로 느껴지지 않았음. 다음 부터는 ipynb파일 내부 최상단에 버전 및 수정내역을 기록하는 방식을 사용해야할 듯 함
       

      강사님 Feedback

      • Feature Importance : 수치형이 상위에 올라오는 것은 당연하다. 수치형과 범주형을 동일선상에서 비교해선 안된다.
      • fare와 pclass는 사실상 동일 의미다. 따라서 pclass를 drop했어야 한다.
        • 각 Feature간의 상관관계는 없어야 한다 (feature 간 유사도가 낮아야한다)
        • fare - pclass 쪽에서 overfitting이 발생했을 것이다
      • 전반적으로, 주먹구구식으로 했다.
        • 점수가 낮게나오더라도 그렇게 한 이유가 명확했다면 다음에는 개선할 수 있는데, 어떤 Action을 취할 때 명확한 이유가 없는 경우도 많았고 그런 Action을 했던 이유를 기록하지 않았던 경우도 있었다.
        • 노력을 한 것 대비, 그런 점이 아쉽다.
      Share article
      RSSPowered by inblog