2021 인공지능 온라인 경진대회 참가 후기
안녕하세요, 메이아이의 ML Engineer 정재민입니다.
메이아이는 작년 '2020 인공지능 온라인 경진대회'에 참가하여 우수한 성적을 거둔 바 있는데요. 올해에도 2년 연속 경진대회에 참여하여, '운전 사고 예방을 위한 운전자 부주의 행동 검출 모델 분야' 종합 1등이라는 우수한 성적을 거두었습니다.
이번 글에서는 메이아이가 '운전 사고 예방을 위한 운전자 부주의 행동 검출 모델' 문제를 어떻게 풀었는지, 그 속을 낱낱이 공개하고자 합니다. 이 글이 Object Detection 을 수행하시는 모든 분들께 도움이 되었으면 좋겠습니다 :)
Object Detection 문제는?
메이아이가 도전한 '운전 사고 예방을 위한 운전자 부주의 행동 검출 모델' 분야는 이미지 속에 있는 얼굴, 눈, 입, 담배, 휴대폰 등을 탐지하는 Object Detection 문제입니다. 메이아이는 Object Detection이라는 키워드를 보자마자 바로 이 문제를 선택했어요. 이미 오프라인 공간 분석 서비스인 매쉬를 개발하면서, 비슷한 종류의 문제를 많이 풀어왔기 때문입니다.
EDA, 답은 여기에!
저희는 먼저 데이터 셋이 어떻게 구성되어 있는지부터 살펴봤습니다. 데이터 셋을 구성하는 대부분의 이미지에서는 운전자가 한 명 등장하였고, 각 물체끼리의 occlusion은 거의 없었습니다. 이러한 운전자 이미지가 흑백 형태로 약 27만 장 정도 주어졌고, 각 class 간의 비율은 아래 차트와 같았습니다.
다들 이미 눈치채셨겠지만 data imbalance 문제가 심각한 것을 알 수 있습니다. 대회 초기에는 여러 가지로 모델 구조를 바꿔보는 등의 실험을 진행하기도 했지만, EDA 진행 후에는 이 imbalance한 데이터를 균형 있게 학습할 수 있는 방법을 취하도록 전략을 바꾸었습니다.
Data Preprocessing
앞서 EDA를 통해 Data Imbalance 문제가 심각하다는 것은 확인하였고, 이제는 이걸 어떻게 해결할지 생각해 봐야겠죠! 저희는 크게 '상대적으로 부족한 Class 데이터를 더 많이 만들자'라는 1번 아이디어와, '상대적으로 많은 Class 데이터를 줄이자'라는 2번 아이디어로 접근했습니다.
1번 아이디어를 적용하기 위해 선택한 방법은 Object Cut-Mix였습니다. 위의 차트를 살펴보면 'phone'과 'cigar'의 class 상대적으로 부족한 것으로 확인되는데, 메이아이는 이 Object들을 잘라서 적절하게 Augmentation을 한 뒤, 학습할 이미지의 빈 공간에 붙여주었습니다.
2번 아이디어는 아주 효과적이었는데요, 아래와 같은 기준으로 데이터 셋을 보기 좋게 '다이어트' 했습니다.
- cigar가 있거나 phone 이 있으면 데이터 셋에 포함
- eye_closed 와 mouth_closed 가 동시에 있으면 데이터 셋에 포함
- eye_closed 와 mouth_opened 가 동시에 있으면 데이터 셋에 포함
- mouth_opened 가 있는 이미지 중 1/3 을 데이터 셋에 포함
그 결과 아래와 같은 분포를 가진 데이터 셋을 얻을 수 있었고, 이를 사용하여 학습을 진행했습니다.
Model, Train Strategy
모델 구조면에서도 여러 시도들이 있었습니다. 원래 대회에서 제공하는 baseline Code는 yolov5였습니다. 이와 함께 yolov5l, Swin-L, Centernet 2 등의 여러 모델 구조를 테스트한 결과 yolov5l를 최종 선택하였고, 이 모델의 정확도를 향상하는 데에 집중하였습니다. 참고로 yolov5l는 coco-test에서 mAP(0.5:0.95) 0.48의 정확도를 보여주는 엄청난 모델입니다 :)
쪼개서 학습하기
일단 yolov5의 기본 학습 전략을, 앞서 data preprocessing 을 통해 만든 다이어트 데이터 셋에 적용하여 학습했습니다. epoch 은 학습할 데이터 셋을 전부 한 번씩 도는 방법인데요. 다이어트를 한 데이터 셋을 전부 도는 것이 생각보다 너무 오래 걸려서, 아예 epoch를 새로 정의했습니다.
(메이아이가 새로 정의한 epoch를 이하 'epoch*'로 표기합니다. 여기서 'epoch*는 다이어트 데이터 셋을 15 등분으로 쪼개어 shuffle 한 뒤, 첫 1 / 15의 작은 데이터 셋을 학습하는 것을 의미합니다.)
이렇게 학습한 결과 저희가 임의로 분리한 validation set의 'phone', 'cigar'에 대해 mAP가 잘 나와주었고요. 테스트셋에 적용했을 때도 1등을 달성하였습니다! 그렇다는 건 균형 있는 데이터 셋으로 generality 또한 잘 학습했다는 뜻이겠죠? 그럼 이제..!
Fine Tuning
다이어트 데이터 셋에 포함되지 않은 데이터로 fine tuning 을 진행합니다. 이 녀석들도 데이터 셋 크기가 상당하기 때문에 epoch*으로 50등분 하여 50 epoch*을 학습했습니다.
오, 무려 0.01 이나올랐네요!
Inference
이제 최종적으로 ML/DL 대회 국룰인 앙상블과 TTA(Test Time Augmentation)를 적용하여 제출하였습니다!
그 결과 최종적으로 분야 1위를 사수할 수 있었습니다.
대회 참가 후기
대회에 함께 참여해 주셨던 박준혁 대표님께서는 "잘 하는 팀들이 많이 참가해서 재밌게 경쟁할 수 있었고, 결과가 너무 좋아서 더욱 기뻤습니다. 대회에서 배운 지식과 자신감을 살려서 더욱 좋은 제품을 만들 수 있도록 노력할게요!"라는 후기를 남겨주셨습니다.
저도 메이아이에서 Object Detection 을 연구한 경험이 대회에서 도움이 많이 되었던 것 같아 기뻤습니다. 실제로 Data Preprocessing에서 1번 아이디어로 소개 드렸던 object cut-mix는 메이아이에서 영상 속 Detection FP(False Positive)를 학습하는 연구로도 진행되고 있거든요.
반면 아쉬웠던 점을 꼽자면, 데이터 수가 너무 많았던 탓에 1 epoch를 돌리기 어려워 epoch*라는 단위로 쪼갰던 것이 아닐까 합니다. 돌이켜 생각해 보니 너무 epoch-based train strategy만 생각했던 건 아닌가 싶은데요. 만약 iteration 단위의 step-based train strategy로 풀었다면 어떤 결과가 나왔을까 궁금해집니다.