오늘은 지난 2월 2일에 진행했던 캐글 경진대회 첫 참가한 소감을 적어볼 예정이다.

 

www.kaggle.com/c/2019-2nd-ml-month-with-kakr/overview

 

2019 2nd ML month with KaKR

캐글 코리아와 함께하는 2nd ML 대회 - House Price Prediction

www.kaggle.com

이미 지난 대회였기 때문에 각종 솔루션들이 많이 올라와 있어서 컴페티션에 처음 참가하는 나와 같은 사람들에게는 입문하기 좋은 대회였던 것 같다. 인공지능 분야 공부를 시작하면서 꼭 달성하고 싶은 목표 중 하나가 캐글 컴페티션에서 메달을 얻어보는 것인데, 그 시작의 첫 걸음이라고 생각했다.

 

첫 참가라 어떻게 해야 할지 막막했지만, 우선 Baseline이 되는 노트북을 하나 지정하여 해당 Baseline을 기준으로 성능을 향상시켜 나가기로 하였다. 목표는 Private Score를 11만점 이하로 낮추는 것이다.

 

데이터를 먼저 살펴보면 다음과 같은 데이터들이 있다.

  1. ID : 집을 구분하는 번호
  2. date : 집을 구매한 날짜
  3. price : 집의 가격(Target variable)
  4. bedrooms : 침실의 수
  5. bathrooms : 화장실의 수
  6. sqft_living : 주거 공간의 평방 피트(면적)
  7. sqft_lot : 부지의 평방 피트(면적)
  8. floors : 집의 층 수
  9. waterfront : 집의 전방에 강이 흐르는지 유무 (a.k.a. 리버뷰)
  10. view : 집이 얼마나 좋아 보이는지의 정도
  11. condition : 집의 전반적인 상태
  12. grade : King County grading 시스템 기준으로 매긴 집의 등급
  13. sqft_above : 지하실을 제외한 평방 피트(면적)
  14. sqft_basement : 지하실의 평방 피트(면적)
  15. yr_built : 지어진 년도
  16. yr_renovated : 집을 재건축한 년도
  17. zipcode : 우편번호
  18. lat : 위도
  19. long : 경도
  20. sqft_living15 : 주변 15 가구의 거실 크기의 평균
  21. sqft_lot15 : 주변 15 가구의 부지 크기의 평균

먼저 데이터를 모델에 학습시키기 전에 모델이 잘 학습할 수 있도록 데이터를 가공해주는 것이 중요하다. 데이터를 가공하는 기법 중 하나인 FE(Feature Engineerning)는 그대로 사용하기에는 어려운 데이터의 변수를 가공하여 데이터를 비교적 간단명료하게 만드는 작업이다. 실제로 대회를 진행하다보니 이 FE을 얼만큼 잘 했느냐에 따라서 점수가 생각보다 많이 차이났었다.

target인 price의 분포를 확인해보니 선형으로 표현하긴 어려울 것 같아서 log scale로 변환하였다.

이제 어느 정도 선형성을 가지는 것 같다.

위의 그림은 스피어만 순위 상관계수를 히트맵으로 나타내보았다. 스피어만 순위 상관계수는 범주형 변수가 포함되어 있을 때, 목적변수와 가장 상관관계가 높은 순서대로 정렬해주는 식이다. 위의 히트맵에 따르면 가격과 가장 상관관계가 높은 변수들은 grade, sqft_living, sqft_living15 순으로 나타나는 것을 확인할 수 있다.

이상치를 제거하기 위하여 몇 가지 변수들을 살펴보았다. 그 중 grade에서는 다음과 같은 요소들을 확인해보고 이상치라고 생각되는 값들은 제거해주었다.

  • 등급 3의 값이 큰 이유
  • 등급 7, 8, 9에서 이상치가 많은 이유
  • 등급 8과 11에서 큰 이상치가 나타나는 이유

모델이 더 잘 학습할 수 있도록 기존에 있는 변수들을 활용하여 새로운 Feature들을 생성해주었다.

새로 생성한 Feature에는 방의 전체 갯수, 거실의 비율, 면적대비 거실의 비율, 재건축 여부, 평당 가격, zipcode를 이용하여 위치에 따른 가격 등이 있다.

실제로 zipcode를 기준으로 평균 가격정보를 시각화 해보았더니 어느 정도 유의미한 변수인 것으로 볼 수 있었다.

FE를 끝내고 나면, train data에서 target인 price를 분리하여 train data를 모델에 학습시킨다.

사용한 모델은 XGBoost와 LightGBM 여러 개의 모델을 VotingRegressor로 앙상블 하여 사용하였다.

xgboost = XGBRegressor(learning_rate=0.024, max_depth=8, n_estimators=1000, random_state=random_state)
lightgbm0 = LGBMRegressor(boosting='goss', learning_rate=0.015, max_depth=7, n_estimators=1600, random_state=random_state)
lightgbm1 = LGBMRegressor(boosting='gbdt', learning_rate=0.015, max_depth=13, n_estimators=1400, random_state=random_state)
lightgbm2 = LGBMRegressor(boosting='goss', learning_rate=0.015, max_depth=7, n_estimators=1400, random_state=random_state)
lightgbm3 = LGBMRegressor(boosting='gbdt', learning_rate=0.015, max_depth=11, n_estimators=1400, random_state=random_state)
ereg = VotingRegressor(estimators=[('xgb', xgboost), ('lgbm0', lightgbm0), ('lgbm1', lightgbm1), ('lgbm2', lightgbm2), ('lgbm3', lightgbm3)])

Hyperparameter는 GridSearch를 이용하여 찾은 값을 사용하였다.

결과는 최종 Public Score 108111.71518, Private Score 106922.61196 으로 마무리하였다.

대회를 진행하면서 느낀점은, 모델을 향상시킨다는 것은 생각보다 어렵고 복잡한 일이라는 것이었다. 처음에는 추가로 FE를 진행하지 않고 있는 데이터만으로 모델을 학습시켰었는데 원하는 만큼의 성능이 나오질 않아서 다른 노트북을 참고하여 추가로 FE를 진행하였더니 그것 만으로도 엄청나게 성능이 향상되어 한 번에 원하는 결과를 얻을 수 있었다. 그 이전까지는 Hyperparameter 튜닝만으로는 어떻게 해도 11만점 이하가 나오질 않았었다.

또한, 학습 시의 결과가 좋다고 항상 실전 결과가 좋은 것은 아니었다. 물론 어느 정도의 경향성은 있지만 절대적인 것은 아니었다. 테스트 시에는 XGB가 가장 좋은 결과를 보여줘서 제출했는데 Public Score는 좋았지만 Private Score는 좋지 못했다. 이 부분은 아마 너무 train dataset에만 Overfitting 되어있어서 Private Score를 측정하는 test dataset에는 잘 예측을 하지 못한 것 같다.

이번 대회를 진행하면서 확실히 성장했다고 느낄 수 있었다. 더 좋은 Hyperparameter를 찾기 위해 GridSearch가 아닌 Optuna라는 라이브러리를 이용하여 RandomSearch도 시도해보고, 노드에서 가르쳐주지 않은 VotingRegressor나 HistGradientBoostingRegressor와 같이 다른 앙상블 모델도 사용해보면서 모델 설계에 대한 이해도가 조금은 높아진 것 같다.

생각보다 11만점의 벽이 높아서 거의 2주 정도를 매달렸지만, 그래도 원하는 목표치를 달성할 수 있어서 기분도 좋고, 무엇보다 공부하면서 모델을 학습시키는 과정이 지루하지 않아서 재미있었다.

지금은 더 경험을 쌓기 위하여 다른 친구와 함께 Dacon에 참가하고 있는데, Baseline도 없이 데이터 처리부터 모델 설계를 하려고 하니 내가 무엇이 부족한지를 너무 뼈저리게 느낄 수 있어서 더 공부를 열심히 하는 계기가 되고 있다.

 

해당 노트북의 전체 코드 : github.com/ceuity/AIFFEL/blob/main/exploration_09/%5BE-09%5Dkaggle_kakr_housing.ipynb

+ Recent posts