여름방학을 맞아 데이콘 Basic에서 진행하는 쇼핑몰 지점별 매출액 예측 경진대회에 참가했다.
머신러닝을 공부하면서 데이콘 교육용 대회에 참가하거나 이미 끝난 대회에 연습용으로 참가해봤던 경험밖에 없어서
실제 진행 중인 대회를 참가하는 것은 처음이었다.
결론부터 말하자면 Public 점수에서는 1등을 달성했고 대회 종료 후 나온 Private 점수에서는 11등을 달성했다.
Private 점수로 최종 등수가 매겨지는 것이기 때문에 사실상 11등을 기록했다고 보면 된다.
물론 11등도 상위 1%에 해당하는 성적이므로 못한 것은 아니지만 Public Score에서 1등을 기록했었기에 다소 아쉬움이 남는다.
따라서 본 포스팅은 대회를 진행하면서 마주쳤던 문제들과 지식들에 대해 정리하고 결론적으로 왜 Public Score에서는 좋았으나 Private Score에서는 상대적으로 좋지 않았는지에 대해 고민해보고자 한다.
전반적인 코드와 진행 과정은 github에 올려놓았다.
https://dacon.io/competitions/official/235942/leaderboar
* 대회 설명
1. 개요 : 쇼핑몰 매장별 프로모션 정보, 주변 날씨, 실업률, 연료 가격 등의 정보를 바탕으로 쇼핑몰의 각 지점별 주간 매출액을 예측
2. 평가 기준 : RMSE
* 데이터 설명
- id : 샘플 아이디
- Store : 쇼핑몰 지점
- Date : 주 단위(Weekly) 날짜
- Temperature : 해당 쇼핑몰 주변 기온
- Fuel_Price : 해당 쇼핑몰 주변 연료 가격
- Promotion 1~5 : 해당 쇼핑몰의 비식별화된 프로모션 정보
- Unemployment : 해당 쇼핑몰 지역의 실업률
- IsHoliday : 해당 기간의 공휴일 포함 여부
- Weekly_Sales : 주간 매출액 (목표 예측값)
* 코드 공유
https://github.com/seopp/github_dacon_shopping/tree/main
* 모델링 전략
전체적인 EDA와 모델링 과정은 깃허브에 올려놓았다.
간략하게나마 정리하자면 우선 Promotion 칼럼에 대해 정보가 없어서 굉장히 애를 먹었었다.
각 Promotion이 의미하는 것은 무엇인지, 그 값들은 어떻게 산출된 것인지에 대해 아무런 정보가 없었기 때문이다.
또한 Promotion에만 결측치가 다수 존재해서 이 결측치들을 처리하는 방안에 대해서도 마찬가지로 여러 가지를 시도해보았다.
따라서 단순 추측에 의해서만 전처리를 진행해야 했어서 시간을 많이 쏟았다.
지점별로 매출액을 확인한 후 지점마다의 매출액 편차가 큼을 확인하고 지점별로 모델을 각각 만들어주어 따로 예측을 해준 뒤 예측값들을 합치는 방안을 떠올렸다.
이후 나름의 방법대로 상관관계를 통한 Feature Selection을 진행하고 CatBoost를 이용한 모델링을 진행했다.
* 마주쳤던 문제들
마주쳤던 문제들은 꽤 있지만 코드에 기록하지 않고 겪었던 것들을 정리해보자면 다음과 같다.
1. 스케일링
데이터를 전처리 함에 있어 스케일링은 중요한 과정이라고 알고 있다. 따라서 이번 대회에서 전처리를 진행하면서 스케일링 방안에 대해서도 고민을 많이 했었다. 로그 변환, StandardSclaer, MinmaxScaler 등등 알고 있는 여러 가지 방법들을 모두 시도해보았다. 하지만 결국 마지막 모델을 선택하는 과정에서 XGBoost, LightGBM, CatBoost와 같은 Tree기반의 모델들을 선택했기 때문에 결론적으로 큰 의미가 없는 과정이었다.
이 부분에 대해 많이 찾아보고 실제로 스케일링을 진행한 모델과 그렇지 않은 모델을 비교한 결과 결국 Tree기반의 모델을 사용함에 있어서는 스케일링이 영향이 없다는 것이었다. 물론 몇몇 분들은 그럼에도 불구하고 스케일링을 진행했을 때 Tree기반 모델에서도 성능 향상이 있었다고 한다. 일리가 없는 말은 아니지만 나의 경험과 여러 가지 자료들을 종합해 보았을 때 Tree기반 모델에서는 스케일링이 영향이 없다고 판단했다.
물론 가장 좋은 방법은 시간만 충분하다면 모든 방향을 다 시도해보는 것이 좋다고 생각한다.
머신러닝을 공부하면서 느끼는거지만 결국 완벽한 정답은 없는 것 같다. 각 상황마다 변수가 굉장히 많기 때문에 결국 각자가 처한 상황마다 최선의 방법들을 모두 시도해보는 것이 해법인 것 같다.
2. 45개 지점마다 각각 모델 만들기
데이터를 살펴보면 결국 각 지점마다의 주간 매출액을 예측하는 것인데 각 지점별로 매출액 편차가 큼을 알 수 있었다.
다른 변수들의 영향보다 Store 즉, 지점이 무엇이냐가 굉장히 크게 관여를 하는 것으로 판단했다.
따라서 지점별로 나누어 각각 모델을 따로 만들고 예측을 해서 예측값들을 합치는 방향으로 모델링을 진행했다.
결론적으로 이렇게 진행한 모델링의 결과가 더 좋았다.
하지만 모델링을 진행하면서 의문이 들었다. "지점별로 데이터들을 나누면 각 지점마다의 데이터는 139개의 행으로 구성되어 있는데 이 적은 데이터만 가지고 예측 성능을 뛰어나게 할 수 있을까?"와 같은 고민 말이다.
결론적으로 성능이 좋아지긴 했으니 이 방법들 택했다. 이러한 이유를 나름대로 생각해보자면 변수들의 영향보다 Store가 가지는 영향력이 매우 컸기 때문에 데이터가 적음에도 불구하고 예측 성능이 매우 떨어지지 않았다고 생각한다.
이 부분에 대해서는 추가적인 깊은 학습이 필요할 것으로 생각된다.
3. Feature Selction
Feature Selection은 MachineLearning에서 매우 중요한 기술이다. 기본적인 아이디어는 모델링이 raw data의 모든 feature를 사용하는 것은 비효율적이기 때문에 일부 필요한 feature들만 선택해서 사용하자는 것이다.
Feature Selection은 모델 성능을 높이기 위해서 반드시 필요한 기술 중 하나이다.
Feature Selection의 방법론은 크게 3가지로 구분된다.
- Filter Method : Feature 간 관련성을 측정하는 방법
- Wrapper Method : Feature Subset의 유용성을 측정하는 방법
- Embedded Method : Feature Subset의 유용성을 측정하지만, 내장 metric을 사용하는 방법
이러한 방법들이 있지만 대회 진행 당시 학습이 부족했던 관계로 위의 방법론들을 사용해보지 못하였다.
따라서 상관관계를 통해 나름의 Feature Selection을 진행했다.
Promotion과 target과의 상관계수 중 0.4 이상인 것들만 골라 각 지점별로 Feature를 다르게 선택해주었다.
물론 근거가 매우 부족하고 수많은 방법 중에 고려해볼 만한 방법 하나를 사용해본 것이기 때문에 좋은 방법은 아니라고 생각한다. 하지만 조금이나마 성능 향상을 이뤄냈기에 이 방법을 택했다.
또한 피처들을 모두 넣어도보고 몇 개만 선택도 해보면서 결론적으로 Temperature, Fuel_Price, Unemployment는 모델의 성능 향상에 좋은 영향을 끼치지 못한 것으로 판단했다. 모든 Promotion을 피처에 넣어주는 것 또한 모델의 성능 향상에 좋은 영향을 끼치지 못한다고 판단하고 제거했다.
Feature Selection 에 대해서는 경험도 부족하고 학습도 부족하다는 것을 스스로 많이 느꼈다. 앞으로 이 부분에 대해서 집중적으로 학습한 뒤 다음 대회를 참가할 때는 여러 가지 근거 있는 방법들을 시도해보고 싶다.
* Public Score와 Private Score 간의 차이에 관한 고찰
데이콘 대회는 Test 데이터 셋에 대한 모델의 성능에 따라 순위가 결정된다. 데이콘은 Test 데이터 셋에 대한 정답을 가지고 있지만 최종적으로 참가자의 예측과 비교하기 위해 이를 보류한다. Public Score는 제출할 때마다 확인 가능한 점수이다. (해당 점수는 항상 평가 페이지에 설명되어 있는 통계적 평가 지표를 사용하여 계산됨.) 그러나 이 Public Score는 Test 데이터 셋의 일부(본 대회에서는 50%)에서만 결정된다. 이것은 공개 순위표이며 대회 중 어느 정도의 상대적인 성과를 보여준다.
대회가 종료되면 선택할 제출물을 선택하고 Test 데이터 셋에서 Public Score에 반영되지 않았던 나머지 데이터들을 가지고 Private Score를 계산한다. Private Score는 점수에 대한 지속적인 피드백을 받지 못하므로 비공개 리더보드인 것이다.
최종 대회 순위는 Private Score를 기반으로 하며, 우승자는 Private Score가 가장 높은 사람이다.
최종 순위가 Private Score를 기반으로 하는 이유는 Public Score를 기반으로 할 경우 해당 데이터의 특정 노이즈에 과적합되는 모델이 될 위험이 있기 때문이다. 현실에서는 과적합을 피하는 것이 중요하기 때문인 것 같다.
본 대회를 참가하면서 나는 Public Score만을 올리기에 집중했다. 사실 대회를 진행하면서도 Public과 Private의 차이점을 제대로 알지 못했었다. 하지만 Public Score로 상위권에 진입하고 난 뒤 Private Score에 대해 정확히 알 게 되었다.
데이콘의 종료된 다른 대회들을 확인해보았는데 Public 에서 최상위권이던 참가자가 Private에서는 등수가 굉장히 낮아지는 경우를 적지 않게 볼 수 있었다. 물론 이러한 경우는 참가자의 모델이 Public 데이터에 지나치게 과적합 되었기 때문이었을 것이다.
하지만 문제는 이러한 사실을 알아도 이 과적합에 대처할 방법을 아직 잘 모르겠다는 것이다. 일단은 대회를 진행함에 있어서 public스코어를 개선하는 방향으로 모델을 발전시킬 수밖에 없는데, 내가 만든 모델이 Private에서도 잘 예측이 될지 안 될지는 알 방법이 없기 때문이다. 그렇다고 Public에서의 과적합을 피하기 위해 다소 점수가 낮지만 과적합이 되지 않을 것 같은 모델을 택한다? 이 부분도 애매한 것이 명확한 기준이 없기 때문이다.
따라서 처음 참여한 대회였지만 Private Score에는 다소 운이 필요하다고도 느꼈다. Public에선 높았던 등수가 Private에서는 왜 내려갔는지. Public에선 낮았던 등수가 Private에서는 왜 올라갔는지. 알 수 없기 때문이다.
물론 내가 아직 학습이 부족하고 경험이 부족해서 해답을 찾지 못한 것일 수 있다.
머신러닝을 공부하면서 가장 중요하다고 느끼면서 가장 어렵다고 생각이 드는 부분이 과적합이기 때문에 앞으로 더 경험을 쌓고 공부를 해야겠다는 생각을 했다.