CutMix는 Data Augmentation의 방법 중 하나로
자랑스러운 우리 Naver Clova에서 작성한 논문이다.
2019년도에 나온 논문이지만 아직까지 상당한 영향을 미치고 있고
실제로 데이콘, 캐글같은 대회에서 Agumentation을 할때 무조건 등장하는 기법이다.
오늘은 이러한 CutMix의 논문인
CutMix : Regularization Strategy to Train Strong Classifiers with Localizable Features을 자세히 살펴보고
추가적인 설명과 코드를 살펴보려고 한다.
본 글은 논문의 1~3 부분까지 리뷰를 하고 있으며 4에 해당되는 실험결과 내용은 논문을 참고하기를 바란다
✅Paper : https://arxiv.org/pdf/1905.04899.pdf
✅Code : https://github.com/clovaai/CutMix-PyTorch
Intro
들어가기에 앞서 Augmentation은 매우 다양한 방법들이 존재하고 있다.
이러한 Augmentation중 가장 일반적인 방법은 사진을 Crop하거나 수직, 수평으로 변환하거나, 회전하여서 새로운 데이터 유형을 만들어 내는 방법들이 존재한다.
이러한 방법들은 Torchvision이나 albumentations같은 라이브러를 활용해서 간단하게 실행할 수 있다.
이 부분 실습은 시간이 나면 나중에 새로운 글로 소개해보겠다
또한 이런 방법 말고 Cutout(이것도 torchvison, albumentations에서 간단하게 사용가능), Mixup과 같은 여러 사진을 합쳐서Label을 합치거나, 이미지의 부분을 날려서(지운다) 학습을 하는 방법으로 모델의 일반화에서 조금더 좋은 성능을 내게하는 기법들도 존재한다. 이러한 방법들은 본 논문에서 CutMix와 비교하는 방법들이다)
오늘 소개할 CutMix는 서로 다른 이미지의 부분 영역을 합쳐서 하나의 이미지로 만드는 기법으로 설명만 들었을 때는 Mixup과 유사하다고 생각할 수 있다.
그러나 Mixup에 경우 5대5로 Label을 구성하며 Cutmix의 경우 비율에 따라서 Label을 구성하고 2장 이상(논문에서는 2장의 데이터만 활용하지만 실제 대회에서 활용되는 결과를 보면 2장 이상 변형해서 활용하는 경우도 있다.)의 사진을 활용해서 구성할 수 있다.
물론 Augmentation 같은 경우 모델 학습에 소요되는 시간을 증가시킬 수 있다.
그러나 시간 대비 정확성이 향상되면 캐글, 데이콘 같이 컴페티션 대회에서 필수적으로 활용해보아야할 기법이라고 할 수 있다.
Abstract
이미지 데이터에서 부분적으로 정보를 Dropout하는 (Cutmix)방법들은 CNN의 정확성 향상에 기여를 해왔다.
이러한 방법들은 CNN 모델이 덜 구별되는 부분에 집중할 수 있게 도와주었는데
하지만 이러한 방법들이 Train image를 검정색이나 랜덤 노이즈로 지워버리기 때문에 부분적으로 Train Image의 손실을 야기할 수 밖에 없으며 이는 모델 학습 과정에서 비효율적이거나 바람직하지 않을 결과를 낳을 수 있다.
그래서 본 논문은 이러한 Cutout 문제점을 해결한 Cutmix를 제시한다.
Cutmix는 Train image의 부분들을 합쳐서 하나의 이미지 데이터를 만드는 방법으로
이렇게 만들어진 데이터의 Label은 합쳐진 데이터의 선택 확률들로 구성되게 된다.
Cutmix의 경우 다양한 task에서 좋은 성능을 내고 있으며 Cutout, Mixup과 같은 비슷한 Augmemtation 기법들과 비교를 했을 때도 조금더 좋은 성능을 보여준다.
1. Introduction
CNN은 다양한 Task (classification, object detection, semantic segmentation...)에서 좋은 성능을 보여주고 있다.
이러한 CNN의 효율적으로 학습하기 위해서 다양한 학습 기법들이 소개되고 있는데 이중 data augmentation과 정규화 기술들이 대표적으로 나타났다.
CNN의 과적합을 방지하기 위해서 input image에 대해서 랜덤적으로 특징을 제거하는 정규화 방법들이 제시되었다.
이러한 방법들은 모델의 generalization과 localization의 문제 해결에 도움이 된다는 것을 어느 정도 증명했다.
이러한 방법들은 지워진 부분을 zero로 채워넣거나 랜덤 노이즈로 채워넣었는데 이는 train image의 pixel 정보의 비율을 줄이는 결과를 낳게 된다. CNN 모델을 학습시킬 때 일반적으로 데이터는 항상 부족하기 때문에 이를 생각한다면 이러한 방식들은 심각한 개념적 한계를 마주치게 된다. 어떻게 이러한 제거없이 dropout의 효과를 얻을 수 있는 새로운 방법은 없을까?
이러한 의문에서 등장하게 된 augmentation 기법이 본 논문에서 소개할 CutMix이다.
그저 간단하게 이미지의 pixel을 제거하기 보다. Cutmix 이러한 제거된 부분에 다른 이미지의 부분을 가져와 대체한다.
또한 이렇게 만들어진 데이터의 label 또한 가져온 pixel의 비율만큼 구성되게 된다.
Cutmix는 모델의 학습과정 도중 데이터가 없는 경우가 없게 되고 이는 학습의 효율성을 가져오면서 dropout의 효과도 가져올 수 있다. 또한 추가된 부분은 모델의 인식 능력을 더욱더 향상키기고 이는 모델 학습 및 추론 과정에서 기존의 방식들과 같은 연산량을 같게 한다. (즉, 연산적으로 증가하는 부분이 없다)
Cutmix는 Mixup과 비슷해 보이지만 Mixup의 경우 자연스럽지 않은 데이터를 만들어낸다.
이러한 효과는 다양한 task에서 둘을 비교했을 때 나타나는데
Mixup의 경우 classification에서 좋은 성능을 낼 수 있지만 다른 task에서는 조금 약한 것을 보여준다.
하지만 CutMix의 경우 다양한 task에서도 좋은 성능을 보여주었다.
실제로 논문에서 다양한 모델과 데이터셋을 활용하여 Cutmix를 실행했을 때
정확성향상에 좋은 결과들을 보여주었다.
2. Related Works
이 부분은 본논문과 관련된 다양한 연구들에 대해서 (사전연구) 소개해주고 있다.
관심있는 사람은 본 논문을 참고해서 살펴보는 것이 좋을 것 같다.
특히 Mixup과 관련해서 비교하는 부분이 나와있는데 Mixup의 단점을 자세히 설명해주고 있다.
3. CutMix
수식으로 CutMix의 알고리즘을 보면, (특히 수포자라면) 어렵다고 생각할 수 있다.
하지만 사실 엄청 간단한 수식이다. (진짜)
그래서 논문에서 알고리즘을 설명하는 파트도 반장 안에서 다 끝이 난다 :)
이해하기 쉽게 간단하게 살펴보자
우선 논문에서는 2장의 사진을 활용하여 설명하고 있다.
직관 적으로 설명하자면
위 사진과 같다.
A, B라는 사진이 있을 때
A사진의 부분 B사진의 부분을 합치는 것이다.
이렇게 합쳐진 데이터는 선택된 pixel의 비율만큼(차지하는 비중) Label을 구성하게 된다.
수식으로 표현하면 다음과 같다
우선 두 개의 이미지를 선택한다.
이후 균일분포 (0,1)에서 lamda를 sample한다. 여기서 선택된 lamda의 경우 부분 영역과 전체 영역의 비율을 조절하는 파라미터로 활용된다
이미지의 부분을 선택하기 위해서는 r_x와 r_y는 (0, W)와 (0,H)에서 sample된다.
그리고 이렇게 계산된 부분 영역은 제거되고 제거된 부분에 (r_w, r_h)/W H만큼 다른 이미지에서 영역이 선택되어 채우지게되고 이렇게 구성되어 있는 lamda를 활용해서 label값을 만들어 내게 된다.
이부분은 코드에서 조금더 자세히 살펴보겠다
실제로 이렇게 만들어진 CutMix에 대해서 Mixup Cutout과 비교화여 학습과정에서 모델이 집중하는 부분을 비교하면 위의 사진과 같은 결과를 낳았다.
Code
논문에서 소개된 CutMix를 코드로 실습하면 다음과 같다.
def cutmix(batch, alpha=1.0):
data, targets = batch
indices = torch.randperm(data.size(0))
shuffled_data = data[indices]
shuffled_targets = targets[indices]
lam = np.random.beta(alpha, alpha)
image_h, image_w = data.shape[2:]
cx = np.random.uniform(0, image_w)
cy = np.random.uniform(0, image_h)
w = image_w * np.sqrt(1 - lam)
h = image_h * np.sqrt(1 - lam)
x0 = int(np.round(max(cx - w / 2, 0)))
x1 = int(np.round(min(cx + w / 2, image_w)))
y0 = int(np.round(max(cy - h / 2, 0)))
y1 = int(np.round(min(cy + h / 2, image_h)))
data[:, :, y0:y1, x0:x1] = shuffled_data[:, :, y0:y1, x0:x1]
targets = (targets, shuffled_targets, lam)
return data, targets
실제 학습에 적용한 공식 코드는 아래 주소를 참고하길 바란다.
https://github.com/clovaai/CutMix-PyTorch/blob/master/train.py
'ML 🐼 > 딥러닝 🔫' 카테고리의 다른 글
[밑바닥 부터 식해보는 딥러닝] 01. 수치 미분과 역전파 (0) | 2024.04.09 |
---|---|
[논문 리뷰] Notion 논문리뷰 링크 (0) | 2023.08.31 |
[딥러닝]활성화 함수 (Activation) (0) | 2023.01.11 |
[딥러닝]규제 Regularization (0) | 2023.01.05 |
[딥러닝] 옵티마이저 (Optimizer) (0) | 2023.01.04 |