Skip to content

Commit

Permalink
Updated 2024.08.12
Browse files Browse the repository at this point in the history
  • Loading branch information
pervin0527 committed Aug 12, 2024
1 parent d7854e2 commit 40a8928
Show file tree
Hide file tree
Showing 18 changed files with 167 additions and 0 deletions.
167 changes: 167 additions & 0 deletions _posts/2024-08-12-CV-competition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
---
layout: single
title: "업스테이지 - 문서 이미지 분류 경진대회"
categories: Competition
tag: [Deep-Learning, ComputerVision, Competition]
use_math: true
---

업스테이시 x 패스트캠퍼스 - 문서 이미지 분류 경진대회

# 1.대회소개

본 대회는 upstage와 fastcampus가 주관하는 AiLab 3기에서 진행된 Document Type Image Classification의 개인 후기 레포트입니다.

<img src="{{site.url}}/images/240812/0017.png" width="1200" height="300">

저희 팀은 저를 포함해 총 4명으로 팀이 구성되었습니다. 이번 대회는 public 3위, private 3위로 마감하였습니다.

# 2.데이터 개요

<img src="{{site.url}}/images/240812/0001.png" width="1200" height="300">

학습 데이터는 위와 같이 클래스별로 서로 다른 "문서" 이미지들 입니다. 어떠한 노이즈나 변형이 적용되지 않은 클린 데이터입니다.

<img src="{{site.url}}/images/240812/0002.png" width="1200" height="300">

- 총 1570개의 이미지로 구성.
- 클래스별 이미지 수 분포를 확인해보면 이력서, 소견서, 임신 진료비 지급 신청서 3가지 클래스는 100개 미만이고 나머지는 100개 근처로 어느정도 균등한 분포를 보이고 있습니다.

<img src="{{site.url}}/images/240812/0003.png" width="1200" height="300">

- 테스트 데이터는 총 3140개의 이미지로 구성.
- 노이즈 + 변형이 적용되어 있습니다.

따라서 다음과 같은 데이터 처리 단계를 생각해볼 수 있습니다.

1. 학습 데이터를 테스트 데이터의 분포와 유사하게 만든다.
2. 테스트 데이터를 학습 데이터의 분포와 유사하게 만든다.

이번 대회에서는 1번을 학습에 적용하고 2번을 tta(Test Time Augmentation) 단계에 적용하여 점수를 높히고자 했습니다.

# 3.베이스라인 구축

## 3-1.데이터 증강.

테스트 이미지에 적용된 증강은 다음과 같이 정리할 수 있습니다.
- 이미지를 회전, 반전, 이동 시키는 Geometric Transform
- 노이즈를 부여하는 Pixel-Wise Transform

일반적으로 가장 많이 사용하는 Albumentations 라이브러리를 이용해 학습 이미지를 테스트 이미지와 유사한 형태로 변형하고자 했는데, Geometric Transform은 유사도가 높게 만들 수 있지만 Pixel wise transform은 그렇지 못했습니다.
추가적인 조사 결과 Augraphy라는 문서 이미지 전용 증강 라이브러리를 찾을 수 있었고 몇몇 노이즈 추가 함수들의 결과물이 테스트 이미지와 유사도가 높았습니다. 따라서 geometric transform은 albumentation을, pixel wise transform은 augraphy를 적용하도록 데이터 파이프라인을 설계, 구축했습니다.

코드 : [https://github.com/pervin0527/Upstage_Ai_Lab/blob/main/11-ComputerVision/project/data/augmentation.py](https://github.com/pervin0527/Upstage_Ai_Lab/blob/main/11-ComputerVision/project/data/augmentation.py)

## 3-2. 모델 학습

학습 모델은 크게 CNN 계열과 Transformer 계열로 나눠서 실험했습니다.

- CNN : ResNet, EfficientNet
- Transformer : ViT, Swin

실험 결과로 EfficientNet이 transformer 모델들보다 2~3점 정도 더 높은 점수를 보였습니다.

# 4.문제점

## 4-1.데이터 반영 방식

<img src="{{site.url}}/images/240812/0004.png" width="1200" height="300">

베이스라인 기반 실험 과정에서 Pytorch Dataset 클래스에서 증강을 하느냐(Online) 또는 증강한 이미지를 파일로 저장하고 학습에 사용하는가(Offline)에 따라 상이한 결과를 보여주었는데, 학습 데이터의 양이 작기 때문에 online 방식으로는 정확도가 빠르게 포화되는 양상을 보였습니다.

## 4-2.예측 결과 분석

<img src="{{site.url}}/images/240812/0005.png" width="1200" height="300">

모델의 예측 결과를 정성 분석하면서 오답을 정답으로 하나하나 수정하다보니 정답으로 구성된 csv 파일을 만들 수 있었습니다. 물론 눈으로 봐서도 어떤 것인지 구분할 수 없는 데이터도 있었기 때문에 완전하다고는 할 수 없습니다.

어쨋든 이를 제출 이전에 대략적인 성능 파악용으로 사용할 수 있었고, 결과를 분석해보니 3, 4, 7, 14번 클래스에서 오답률이 높은 것을 확인할 수 있었습니다. 또한 3번을 7번으로 예측하거나 7번을 3번으로 예측하는 오답의 패턴을 찾아낼 수 있었는데 이는 해당 클래스들 간에 결정 경계가 제대로 만들어지지 못한 게 아닐까라고 의심할 수 있었습니다.

# 5.해결책(시도한 방법들)

## 5-1.LR Scheduler
첫번째로 LR Scheduler입니다.

<img src="{{site.url}}/images/240812/0006.png" width="1200" height="300">

저는 오프라인 증강 방식을 사용했을 때 학습 시간이 늘어나는 것 대비 다양성의 상한선이 정해져 있어 조금 비효율적이지 않나라고 생각했었습니다. 이를 해결하기 위해 학습 방식에 변화를 주면 온라인 증강 방식도 좋은 점수를 얻을 수 있을 것 같았고, 몇 가지 LR scheduler를 실험해봤습니다. 그 중 Cosine-Annealing WarmUp Restart를 적용했을 때 온라인 증강 방식임에도 높은 점수를 얻을 수 있었습니다.

이 스케쥴러는 0에 가까운 초기 학습률부터 일정 에폭까지 학습률을 점진적으로 높히다가 다시 점진적으로 학습률을 감소시키는 방식으로 이와 같은 패턴을 특정 에폭마다 반복하게 됩니다. 시간상 논문 리뷰들을 참고 했는데 가장 크리티컬하다고 느낀 부분은 학습률을 높히는 warmup 단계가 saddle point 같은 정체 구간을 벗어나게 도와준다라는 내용이었습니다.

실제로 이 스케쥴러를 도입하고 난 후 Online Augmentation 방심임에도 베이스라인 성능이 91점까지 높아졌습니다.

## 5-2.Crop

두번째는 Crop입니다.

이 방식은 앞서 봤던 특정 클래스에 대한 결정 경계가 뚜렷하지 않은 문제를 해결하기 위해 나온 아이디어로 랜덤 크롭이외에 이미지를 규격화 해서 자르는 방식을 적용해봤고 그 결과 1~2점 정도의 향상이 있었습니다.

<img src="{{site.url}}/images/240812/0007.png" width="1200" height="300">

먼저 결정 경계가 뚜렷하지 못한가를 객관적으로 확인하기 위해 grad cam을 확인했는데 실제로 문서의 내부가 아닌 외부 영역에 집중하고 있음을 볼 수 있었습니다. 따라서 이미지를 규격화해서 분할한다면 쓸데 없는 내용은 제거되고 문서의 내용에 더 집중할 수 있지 않을까라는 의도로 실험해본 것입니다.

<img src="{{site.url}}/images/240812/0008.png" width="1200" height="300">

첫번째 샘플을 보시면 왼쪽은 가로 세로 중심선을 기준으로 4분할, 오른쪽은 정사각형 형태로 6분할

<img src="{{site.url}}/images/240812/0009.png" width="1200" height="300">

두번째 샘플을 보시면 왼쪽은 세로선 기준 2분할, 오른쪽은 세로선 기준 3분할한 결과 입니다.

## 5-3.Calibration Model

<img src="{{site.url}}/images/240812/0010.png" width="1200" height="300">

세번째는 calibration 모델입니다.

이는 자주 틀리는 클래스들만 선별해 학습하는 모델로 전체 클래스를 학습한 모델의 결과 기반 선택적으로 동작하는 모델입니다. 실제로 약간의 성능 개선은 있었지만 예측 결과를 분석했을 때 여전히 동일한 문제가 발생하고 있었고 이후에는 사용되지 않았습니다.

## 5-4.Model ScaleUp

<img src="{{site.url}}/images/240812/0011.png" width="1200" height="300">

네번째는 Model Scale Up입니다.

calibration 이후에 어떤 것을 더 시도할 수 있을까 고민 중에 멘토링을 하게됐었는데 멘토님은 저희 학습 로그를 보시고 정확도가 빠르게 포화되기 때문에 오버피팅이 의심된다라고 말씀해주셨습니다. 해결책으로는 더 큰 모델을 사용해보라고 추천해주셨는데요 실제로 EfficientNet에서 EfficientNetV2 large나 XL로 바꿔서 실험했더니 train f1 score가 98로 더 높아지게 되었고 리더보드 점수도 단일모델 기준 1~2점 정도 더 높아졌습니다.

## 5-5.OCR

<img src="{{site.url}}/images/240812/0012.png" width="1200" height="300">

다섯번째는 OCR입니다. OCR도 멘토님이 추천해주신 내용인데 저희는 두 가지 활용 방안을 생각할 수 있었습니다.

첫번째는 테스트 단계에서 OCR을 이용한 예측 결과 보정이었는데 테스트 이미지는 증강에 의해 글자 추출 결과가 딱히 좋지 않았습니다. 또 추출된 글자를 클래스 분류로 연결하기 위해 핵심 키워드 리스트를 만들었었는데 테스트 이미지 종류가 많다보니 키워드 리스트의 신뢰도가 떨어져 점수향상으로 이어지지 못했습니다.

<img src="{{site.url}}/images/240812/0013.png" width="1200" height="300">

두번째는 글자 탐지 결과를 활용한 데이터 생성이었습니다.

CRAFT 모델을 학습 데이터에 적용해서 얻은 글자 영역을 기반으로 표나 블랙박스와 같은 요소들을 제거하여 글자에 더 집중할 수 있지 않을까 하는 아이디어였는데요. 아직도 의문인 점은 Efficientnet v2에서는 성능 개선이 없었으나 EfficientNet에서는 성능 개선이 있었고, 여기에 학습 이미지 사이즈 확대와 라벨 스무딩을 적용했더니 더 높은 성능 개선이 있었습니다.

<img src="{{site.url}}/images/240812/0014.png" width="1200" height="300">

샘플을 보시면 왼쪽은 추출된 글자영역을 넘파이 랜덤 배열에 붙여넣은 것이고 오른쪽은 원본 이미지에 mixup한 결과입니다.

## 5-6.TTA

<img src="{{site.url}}/images/240812/0015.png" width="1200" height="300">

마지막은 tta입니다. 이번에는 테스트 이미지를 학습이미지와 유사하게 만들어보자는 아이디어로 tta 파이프라인을 설계했는데요.

1. 원본과 Denoising을 적용한 이미지로 구성합니다.
2. 다양한 크기로 Resize합니다.
3. 15도 단위로 360도까지 회전 후 각각을 horizontal, vertical, transpose합니다.
4. 마지막으로 분할을 적용하지 않은 이미지와 분할을 적용한 이미지로 구성합니다.

파생된 이미지들을 독립적으로 모델에 입력하고, 임계치 이상의 확률로 가장 많이 등장한 클래스를 결과로 선정하게 됩니다. 마지막 날에 이 방법에 올인 했었고 결과적으로 퍼블릭 98.14까지 점수를 높힐 수 있었습니다.

<img src="{{site.url}}/images/240812/0016.png" width="1200" height="300">

샘플로 디노이징 이미지를 가져와봤는데요. 저희가 적용한 SwinIR은 범용적인 이미지 복구 모델이기 때문에 테스트 이미지를 학습할 수 없다는 룰을 지키면서 노이즈를 제거할 수 있겠다고 판단해 적용했습니다.

결과를 보시면 완전하게 클렌징되지 않았고 글자나 선이 조금 지워지는 부분도 있으나 디노이징만 tta에 적용했을 때 0.5~1점 정도 더 높아지는 결과를 확인했기 때문에 사용해도 좋을 것 같았습니다.

# 6.후기
끝으로 대회 후기를 짧게 적어보겠습니다.

일단 저희팀은 예측 결과를 분석하면서 어떤 문제가 있는지 확인하고 개선하고자 노력했던 점이 인상깊었다고 느끼고 있습니다. 다만 결과적으로는 근본적인 문제가 해결되지는 못했다고 생각하고 있습니다. 관련 분야의 SOTA 모델들을 보니 대부분 글자를 추출해서 이미지와 텍스트를 동시에 활용하는 multi modal로 접근하던데 어떻게 텍스트 데이터를 다뤄야할지 몰라 시도해보지 못한 점이 조금 아쉬웠다고 생각합니다.
Binary file added images/240812/0001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0003.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0005.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0006.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0007.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0008.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0009.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0010.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0011.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0012.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0013.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0014.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0015.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0016.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/240812/0017.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 40a8928

Please sign in to comment.