Joonas' Note

Joonas' Note

[딥러닝 일지] 데이터 늘리기 (Data Augmentation) 본문

AI/딥러닝

[딥러닝 일지] 데이터 늘리기 (Data Augmentation)

2022. 3. 25. 21:32 joonas

    이전 글 - [딥러닝 일지] 이미지 가지고 놀기 (변환하기)


    Data Augmentation

    용어로는 Data Augmentation. 데이터 증강, 데이터 첨가라고도 부르는 것 같은데, 데이터를 뻥튀기하는 것이다.

     

    이미지에서는 어렵지 않게 데이터를 늘릴 수 있다.

    이전 글에서 알아본 방법으로, PIL 이미지와 torchvision.transform의 내장 함수들로 의미있는 부분들만 적당히 유지해주면서, 이미지를 회전하거나 작게 줄이거나 일부를 가리거나 색조를 변경시키는 등의 방법으로 여러 개의 복제된 이미지를 만들 수 있다.

    특히, 이미지의 경우에는 방향을 뒤집기(flip)만 해도 Tensor 내의 값들이 전부 바뀌기 때문에, 같은 데이터로 과적합도 막을 수 있다.

    가위바위보

    이번에는 가위바위보 데이터를 사용해서 3개의 클래스로 다중 분류를 할 것이다.

    먼저 데이터 셋의 이미지들을 보면 아래와 같이 생겼다.

    가위, 바위, 보에 대해서 각 700개 정도로, 총 2188개의 이미지가 있다.
    VGG16, VGG19 등의 모델로 실험해봤을 때, 이정도의 데이터 개수도 충분히 잘 학습되었다.

    하지만 이전에 했던 개와 고양이 분류에서는 약 2만장의 이미지가 사용되었기때문에, 가위바위보 데이터 역시 레이블마다 1만장씩 두고 학습을 진행하고 싶었다.

    700장을 1만장으로 뻥튀기하려면, 거의 15배(1개의 원본 + 14개의 변형본)를 해야하기 때문에, 테스트 겸 3개씩만 만들어보기로 했다.

    transform

    이미지의 변형을 주는 transform을 아래와 같이 정의했다.

    def random_transform(image):
        bg_color = (30,150,45)
        transform = transforms.Compose([
            transforms.PILToTensor(),
            transforms.RandomRotation(180, fill=bg_color, expand=True),
            transforms.RandomErasing(scale=(0.025, 0.025), ratio=(1, 1), value=bg_color),
            transforms.RandomPerspective(fill=bg_color),
            # transforms.ColorJitter(brightness=.5),
            transforms.Resize((200, 300)),
            transforms.RandomCrop((180, 240)),
            transforms.GaussianBlur(kernel_size=(3, 3), sigma=(0.1, 5)),
            transforms.RandomHorizontalFlip(p=0.7),
            transforms.RandomVerticalFlip(p=0.7),
            transforms.RandomHorizontalFlip(),
            transforms.Resize((224, 224)),
        ])
        return transform(image)

    Rotation과 Erasing, Perspective 변형은 배경색과 최대한 맞게  rgb(30, 150, 45) 로 채워지도록 했다.

    그리고 Rotation을 할 때, 화면 밖으로 나가는 것을 방지하기 위해 expand=True를 했는데 이러면 이미지 사이즈가 바뀌는 것 같다. 그래서 이후에 Crop에 문제가 없도록 Resize((200, 300))을 다시 해준다.

    그 외에도 Flip이라던지 Blur도 주어서 확률적으로 최대한 원본과 다르게 만들어지도록 유도했다.

    15개의 변형 샘플

    가장 왼쪽 위에 있는 첫 번째 이미지만 원본이고, 나머지는 전부 변형된 이미지이다.

     

    여러 랜덤 효과들을 적용해봤는데, 일부 효과는 문제가 있었다.

    ColorJitter 적용한 결과

    VGG16 모델은 pretrained로 사용하려면, (224, 224) 크기에 논문에 있는 값으로 normalize 해야하는데, 밝기와 hue는 원본 데이터와 많이 다르게 만들어지는 것 같아서 제거했다.

    RandomCrop의 경우에도, 어느 부분으로 crop할 지 모르기때문에 손가락이 잘리거나 하는 등의 위험을 피하기 위해 사용하지 않았다.

    학습에 사용

    https://www.kaggle.com/code/joonasyoon/rps-classification?scriptVersionId=91176352

    왼쪽은 기본으로 주어지는 RPS 데이터를 그대로 train/valid로 나눠서 사용하였고,
    오른쪽은 train/valid set에는 원본 1개 + 3개의 변형된 이미지를, test set에는 원본 이미지만 넣어서 돌렸다.

    데이터 크기의 차이가 느껴지는 부분은, augmentate 하기 전에는 전체 2,100장으로 학습했기 때문에 학습은 빠르게 되었다. 하지만 valid보다 train이 계속 높은걸 보면 과적합 됐을수도 있고 test set에서 어떻게 되는 지는 봐야할 것 같다.

    확실히 train+valid 셋의 데이터가 7,500장으로 늘어나니 학습은 느려졌다. 이번에는 test 까지 찍어봤는데, 안정적으로 학습되는 것으로 보인다.

    아래는 22,000장으로 학습해봤던 Version 12의  실제 레이블과 측정 결과이다.
    이 때는 brightness도 랜덤으로 적용했고, 학습에 총 9시간 걸렸다.

    Comments