읽기일기

Data Loading and Processing Tutorial

http://pytorch.org/tutorials/beginner/data_loading_tutorial.html

Data Loading and Processing Tutorial

작성자: Sasank Chilamkurthy

어떠한 기계 학습 문제를 풀고자 할 때라도 데이터를 준비하는데 많은 노력이 들어갑니다. PyTorch는 데이터 로딩을 쉽게 하면서도 되도록이면 코드를 읽기 쉽게 하는 많은 도구들을 제공하고 있습니다. 이 튜토리얼에서는 어떻게 데이터를 읽어오고 어떻게 전처리하고 augment하는지를 볼 것입니다.

튜토리얼을 실행하기 위해 아래 패키지들이 설치되었는지 확인해봐야 합니다.

  • scikit-image: 이미지 입출력과 트랜스폼
  • pandas: 쉬운 csv 파싱

우리가 사용할 데이터셋은 얼굴 자세에 관한 데이터입니다. 얼굴에 다음과 같이 표시가 되어있습니다.

전체 다 해서 68개의 서로 다른 랜드마크 점들이 각 얼굴에 표시되어있습니다.

Note

데이터셋을 여기에서 다운받아 'faces/'라는 디렉토리 안에 이미지들이 들어가도록 하세요. 사실 이 데이터셋은 imagenet에서 'face'로 태그된 일부 이미지를 뽑아 dlib's pose estimation을 적용하여 생성한 것입니다.

데이터셋에는 다음과 같은 형식의 csv가 같이 따라옵니다.

CSV 파일을 읽은 다음 점들을 꺼내 (N, 2) 크기 배열에 넣어놓습니다. 여기서 N은 랜드마크 점의 수입니다.

Out :

이제 이미지와 랜드마크를 보여주는 간단한 헬퍼를 만들고 이를 이용해 샘플을 출력해봅시다.

Dataset class

torch.utils.data.Dataset은 데이터셋을 제공하는 추상 클래스입니다. Dataset을 상속받아 다음 메소드들을 오버라이드 하여 커스텀 데이터셋을 만들 수 있습니다.

  • len(dataset)을 했을 때 데이터셋의 크기를 리턴할 __len__
  • dataset[i]을 했을 때 i번째 샘플을 가져오도록 하는 인덱싱을 위한 __get_item__

이제 우리의 랜드마크 데이터셋을 위한 데이터셋 클래스를 만들어봅시다. __init__에서 csv를 읽어두겠지만 이미지는 __getitem__에서 읽도록 할 것입니다. 이는 메모리 효율성을 위해서인데, 모든 이미지를 메모리에 저장하지 않고 필요할 때에 한번 읽도록 위함입니다.

우리 데이터셋의 샘플은 dict로 {'image': image, 'landmarks': ladmarks}와 같은 형식이 될 것입니다. 또한 때에 따라 transform 매개변수를 받아 때에 따라 필요한 처리를 샘플에 적용할 수 있도록 할 것입니다. transform의 유용함은 다음 세션에서 보도록 합시다.

이제 이 클래스의 인스턴스를 만들고 데이터 샘플들을 하나씩 뽑아봅시다. 여기서는 처음 4개의 샘플과 그 랜드마크 점들을 출력하겠습니다.

Out:

Transform

앞에서 살펴본 것에서 한가지 문제는 샘플이 모두 같은 크기가 아니라는 것입니다. 대부분의 신경망은 고정된 크기의 이미지를 가정합니다. 따라서 전처리 코드를 작성할 필요가 있습니다. 이제 트랜스폼을 만들어봅시다.

  • Rescale: 이미지를 리스케일
  • RandomCrop: 이미지를 랜덤으로 크롭한다. 이는 데이터 augmentation이다.
  • ToTensor: numpy 이미지를 torch 이미지로 변환 (축을 바꿀 필요가 있다.)

단순한 함수들 대신 호출할 수 있는 클래스로 구현할 것입니다. 그래서 transform을 실행할 때마다 파라미터를 넘기지 않도록 할 것입니다. 이를 위해서 __call__메소드를 구현하고, 필요하다면 __init__메소드 또한 구현할 것입니다. 이렇게 하면 다음과 같이 transform을 사용할 수 있게 됩니다.

위에서 설명한 transform을 이미지와 랜드마크에 어떻게 적용하는지 살펴봅시다.

Compose transform

이제 샘플에 transform을 적용해봅시다.

이미지의 가로, 세로 중 짧은 쪽의 크기를 256으로 리스케일한 뒤, 크기 224의 정사각형으로 랜덤 크롭을 하고 싶다고 하자. 다시 말하면 RescaleRandomCrop transform을 조합해보도록 합시다.

torchvision.transforms.Compose는 이러한 작업을 하기 위한 callable 클래스입니다.

Iterating through the dataset

이제 transform 조합을 포함하여 모든 기능을 넣은 데이터셋을 만들어봅시다. 요약하자면, 데이터셋은 다음을 샘플링합니다.

  • 이미지를 즉성에서 파일로부터 읽어들인다.
  • 읽은 이미지를 트랜스폼한다.
  • 트랜스폼이 랜덤하게 이루어지기 때문에 데이터는 샘플링할 때 augmentate된다.

전에 본 것처럼 데이터셋은 for i in range로 방문할 수 있습니다.

Out:

하지만 for루프를 사용해서 모든 데이터에 대해 반복하면 많은 특별한 기능을 사용하지 못합니다. 특히 다음을 못하게 됩니다.

  • 데이터의 배치(batch)
  • 데이터의 셔플링
  • multiprocessing 워커를 통한 병렬 데이터 로드

torch.utils.data.Dataloader는 이러한 기능을 제공하는 iterator입니다. 아래 예제처럼 간결한 파라미터를 사용합니다. 한가지 흥미로운 파라미터는 collate_fn입니다. collate_fn을 사용하면 샘플이 얼마나 정확히 배치될 필요가 있는지 정할 수 있습니다. 하지만 대부분의 경우 기본 collate도 잘 작동합니다.

Out:

Afterword: torchvision

지금까지 데이터셋과 transform, dataloder를 어떻게 만들고 사용하는지 알아보았습니다. torchvision 패키지는 공통적으로 사용되는 데이터셋과 transform들을 제공합니다. 커스텀 클래스를 작성하지 않아도 될 수도 있습니다. 한가지 torchvision에서 기본으로 사용할 수 있는 데이터셋은 ImageFolder입니다. 이는 이미지가 다음과 같이 들어있다고 가정합니다.

여기서 'ants', 'bees' 등은 클래스 레이블입니다. 비슷한 기본 transform으로 PIL.Image와 같이 작동하는 RandomHorizontalFlip, Scale등도 있습니다. 다음처럼 dataloader를 만들때 같이 사용할 수 있습니다.

학습하는 코드와 함께 있는 예제는 튜토리얼 Transfer Learning tutorial을 참고하면 됩니다.


Tags:
Add a Comment Trackback