[후기글] 바이오헬스 데이터 경진대회 치의학분야 후기글

    본교에서 좋은 데이터 경진대회가 열려서 동기와 함께 참여하였다. 

    본 대회는 바이오 헬스 데이터와 AI 기술을 활용하여 치의학 분야 내 위험성 평가와 예측 모델 개발을 하는 것이 목표였다.

    우리 팀은 본교 재학생이라는 조건하에 Track1에 어금니라는 이름으로 참여하여 치아 파노라마 이미지로부터 Crop 한 사랑니 이미지를 가지고 사랑니 발치 수술 후 위험도 예측을 하는 모델의 성능을 높이는 방식을 생각해 냈다. 

     

    1. Data EDA 및 Augmentation

    사실 폐쇄형 경진대회라는 점은 알고있었지만 이전에 참여했던 대회들은 이렇게까지 폐쇄형은 아니어서 눈으로 사진을 직접 확인하는 과정이 가능했다. 하지만 이 대회의 경우 사진을 직접 눈으로 볼 수 없기 때문에 데이터들의 특징을 찾아내기가 어려웠다. 그나마 픽셀을 터미널에 찍어주는 방식의 plotext를 활용해서 넓은 모니터를 활용해 구현해 보았지만 픽셀값들의 비율이 안 맞고 모자이크처럼 보이는 현상은 막을 수 없었다. 따라서 별다른 데이터의 인사이트는 얻지 못했고 이전에 참여해 본 적 있는 X-ray image Dataset에서 적용했을 때 효과가 좋았던 randomcrop, gaussian, horizontalflip, elastic transform, ColorJitter, Autoaugmentation, Gamma값 조정, Equalize, EraseAugmentation, Autocontrast, Augmix, Sharpen 이런 augmentation들을 다 실험해 보기로 했다. 우리는 queue에다가 우리가 실험하고자 했던 config들을 다 저장해 두고, 자동으로 학습시킬 수 있는 auto_trainer를 구현하여 진행하였기 때문에 많은 양의 실험을 할 수 있었다. 이 많은 Augmentation에서 효과가 있었던 것은 RandomResizedCrop, RandomRotation, gamma값 조정, ColorJitter, autoContrast 정도였기에 이들만 가져가기로 하였다. 

     

     2. Model 실험

    폐쇄형 서버환경이라서 대회가 본격적으로 시작하기전인 서버 세팅기간에 우리가 실험해 볼 여러 모델들의 가중치를 다운로드하여놓았어야 했다. 우리 팀은 CNN계열의 모델과 transformer 계열의 모델들을 앙상블 하여 제출하자는 전략하에 여러 CNN모델과 여러 transformer모델 위주로 가중치를 다운로드하여놓았다.

    우리가 받아놓은 모델은 CNN계열로는, ResNet50, ResNet101, MobileNetv2, MobileNetv3_Large, EfficientNetb4, DenseNet121, SEResNeXt101, Convnext_base, Convnext_large 등이 있었다. Transformer 계열로는 Vit_base, Swin_base 정도가 있었다. 적고 보니 실험한 CNN계열 모델 대비 Transformer모델 개수가 적은 것 같기도 하다. 

    아무튼 제로샷성능을 비교했을 때 기본 성능이 뛰어나서 우리가 깎아가기로 했던 모델들은 Convnext, Swin_base, Densenet121 정도였고 이중에, Convnext가 가장 성능이 좋았다. 

     

    3. optimizer

    우리는 베이스라인에서 주어져있던 Adam대신에 보편적으로 가장 성능이 좋았었던 AdamW로 바꾸어 실험을 진행했었다. 또한 AdamP라는 optimizer도 실험해 보았지만, 별다른 성능향상을 확인하지 못했다. Learning Rate Scheduler로는 CosineAnnealingWarmupRestarts를 사용했고, 각 argument (ex. first_cycle_step, gamma)도 실험하였다. 

    하지만 성과공유회에서 최근 나왔던 LION(EvoLved Sign Momentum)이라는 optimizer도 알게 되었고, 이 부분을 공부해야겠다는 생각을 했다. +) 시시각각 새로운 유의미한 논문들이 나오는 현시점에서 최신 트렌드에 뒤처지지 않도록 끊임없이 공부해야겠다는 생각도 하였다.

    또한 validation loss를 기준으로 5번 연속 최소를 달성하지 못했을 경우 멈추는 방식으로 학습을 진행하였다. 

    *항상 early stopping이나 앙상블을 할 때 가장 잘 나왔던 에폭을 select 할 때 validation loss가 가장 낮은 epoch을 기준으로 할지, 평가메트릭인 macro f1 score가 가장 높았을 때를 기준으로 할지를 고민하는데, 이번에는 정석이라 생각하는 loss를 기준으로 하였는데 결과가 잘 안 나왔다. 다음번에는 평가 metric을 사용해봐야 할 것 같다. 

     

    4. Loss 

    Loss는 처음에 Baseline에 설정되어 있던 것으로는 Binary Cross Entropy Loss였다. 예전이나 지금이나 Cross Entropy라는 개념을 확실하게 설명하기 힘든데, 내가 예측한 값과 실제 정답값이 얼마만큼 다른지를 나타내는 정보로 표현할 수 있겠고, CrossEntropy에서도 이번 경진대회로는 위험함을 나타내는 High와 위험하지 않음을 나타내는 Low 라벨 2개로 classification을 하므로 Binary CrossEntropy를 사용하였던 것이다. 

    이 loss 말고 모델이 확신하지 않도록 만들어주는 Label smoothing Loss나 F1 loss를 적절한 비율로 곱하여 만들어낸 loss도 사용해 보았는데 별다른 효과를 보지 못하였다. 

    5. Threshold

    원래 low와 high를 결정하는 기준은 0.5였다. Baseline에서는 모델에서 뱉어낸 값에다가 sigmoid함수로 0에서 1까지의 값을 만들어주고 반올림처리(round)를 해주어서 0.5 이하까지는 low로, 0.5를 초과하는 경우에는 high로 분류한다. 다시 말해, threshold를 0.5로 정해두고 있었다. 하지만 내가 학습을 시켰을 때 log를 찍어서 확인했던 macro F1 score에서는 precision이 Recall보다 비교적 낮은 값이었기 때문에 threshold를 올려주는 실험을 하였고, 그렇게 validation에서 결과를 확인하니까 성능이 확실히 올랐음을 확인할 수 있었다. threshold는 여러 값으로 실험한 결과 0.55로 적용해 주었다. 

    6. TTA

    TTA는 Train을 다 시킨 가중치로 predict를 실행할 때 TTA에서 N개의 augmentation을 적용시킨다고 가정할 때 하나의 이미지에 대해서 2의 N승만큼의 이미지로 예측을 하여 그중에 hardvoting 하여 정답을 결정하는 방법론이다. 우리도 마지막 TTA를 적용하려 했지만 실험을 하고 가설에 대한 결과를 확인하기까지가 시간이 부족했기 때문에 코드만 작성해 두고 제출해보지 못했다. 

    7. Ensemble 및 Stratified K-fold

    앙상블을 총 3가지 진행해 보았다. 

    우선 우리 실험 내용 중 가장 성능이 좋았던 top2를 hard voting 했었는데 결과가 많이 안 좋았다. 그래서 soft voting을 총 2가지 시도해 봤는데 sigmoid를 씌우기 전 결과를 합산해서 평균을 내는 것과 sigmoid를 씌운 후의 결과를 평균 내는 것 2가지를 시도했다. 

    public dataset 결과상으로는 전자가 성능이 좋았고, 그래서 제출도 그렇게 했던 것 같다. 

    결론적으로 우리가 제출했던 모델은 Convnext_base모델과 Swin_base모델을 각각 5 kfold 하여 softvoting 한 결과값을 제출하였다. 

    성과

    대회는 서버세팅기간 제외 5일 정도 간 진행되었는데 4일 차에 (마감 하루 전날) 우리가 제출한 모델이 public score기준 1등을 해서 기념으로 스샷을 찍었다. 하지만 원래 이 다음날 27일 13시에 서버가 마감되어야 했는데 아마 27일 0시부터 10시까지 서버가 제출이 안 되는 상황이 발생해 버렸다. 주최 측의 실수 때문에 대회 기간이 27일 22시까지 연장되어 버렸고, 우리 팀은 뇌정지가 와버렸다. 

    아무튼 우리가 공지해 줬던 시간 내에 할 수 있는 실험은 다 했었던 상황이었고 다른 아이디어나 기능을 구현할 의지를 잃어버렸던 것 같다. 그렇게 이전에 정해졌던 시간보다 9시간 정도가 더 흐르고 우리는 public score가 4등이 되어버렸고, private score와 final score를 확인하니까 딱 순위권 밖이었다. 

    * 우리 팀 이름은 어금니 팀이다. 

     

     

    마지막 public score과 private score

    결과는 인정한다.(내가 인정 안 하면 어쩔 수 있는 게 없는 게 팩트이기도 하지만..)

    추가로 주어진 9시간 동안 열심히 달린 다른 팀들의 노고를 인정해야 하는 이유도 있겠다만,

    그것보다 객관적으로 봤을 때 우리가 제출했던 public 4등에 위치한 제출시간과 private 4등에 위치한 제출시간이 다른 것을 보았을때 public에서는 2모델을 k-fold로 앙상블했던 모델이 성능이 좋았지만 private 데이터셋으로 봤을때 이전에 단일모델(convnext_base)로 제출했던 결괏값이 더 좋았고, 우리가 최종으로 선택했던 모델인 앙상블 모델이 private score가 조금 떨어지긴 했으니까..

     

    아쉬움이 남았던 부분은 다른 팀들이 final로 제출했던 모델들의 제출 시간을 보면 원래 공지되었던 시간 이후에 제출한 모습임을 알 수 있다.  그러니까 1팀 빼고 추가적으로 주어진 시간을 의미 있게 쓴 팀들이 수상을 했다는 말이다. 동기 1명과 제대로 준비해서 나간 첫 외부대회였는데 수상을 하지 못해서(수상은 6등까지이다.) 아쉬웠지만 좋은 경험이 되었던 것 같다. 

     

    번외로..

    번외로 우리가 주최 측 운영상의 실수로 수상을 하지 못했다고 자기 합리화를 하고 있던 중에 비슷한 류의 다음 대회를 참가하였는데..

    서버 이슈와 운영 측의 문제로 대회 3일 참여 후 포기를 선언하였다. 시간은 시간대로 낭비하고 제출은 하지 못하고.. 3일간 극심한 스트레스에 시달렸다.

    그 대회를 겪고 이 바이오 헬스 대회는 굉장히 운영이 좋은 편이었던 것이라고 정정하고 좋은 대회를 열어주신 분들께 감사하다는 말씀을 전하고 싶다. 

    댓글