본문 바로가기

AI/PyTorch

[PyTorch] CNN 설계 4. Dataset 및 DataLoader 할당

 

1. Package load 
2. 데이터셋 다운로드 및 훈련, 검증, 테스트 데이터셋 구성 
3. 하이퍼파라미터 세팅 
4. Dataset 및 DataLoader 할당 
5. 네트워크 설계 
6. train, validation, test 함수 정의 
7. 모델 저장 함수 정의 
8. 모델 생성 및 Loss function, Optimizer 정의 
9. Training 
10. 저장된 모델 불러오기 및 test 
11. Transfer Learning

 

 

전체 흐름

 

DataLoader에서 기존에 MNIST와 같이 주어진 데이터셋이 아닌 경우 내가 class를 만들어서 사용해야 한다. 이렇게 만들어진 class를 이용해 DataLoader의 첫 번째 인자인 dataset에 해당 class를 넣어주는 것이다.

 

Dataset class를 커스텀하기 위해서는 torch.utils.data.Dataset class를 상속하고, __getitem__ 함수와 __len__ 함수를 구현해야 합니다.

  • __getitem__ 함수는 어떤 순번(index)를 인자로 받으면, 그에 상응하는 번호의 데이터를 반환하는 함수입니다.
  • __len__ 함수는 정의하고자 하는 데이터셋의 총 데이터 개수를 반환하는 함수입니다.

 

이 때 init, getitem, len을 오버로딩해야 한다. 

train, val, test 데이터를 경로에서 읽어와 transform을 해서 다시 저장한다.

이렇게 변형된 데이터셋을 DataLoader에 넣어주는 것이다.

 

 

  • self.all_data는 정의하는 데이터셋에 포함된 모든 데이터 파일의 경로를 저장하고 있습니다. 인자로 받은 mode('train' 또는 'val' 또는 'test')에 따라 훈련용 혹은 검증용 혹은 테스트용 데이터셋을 구분합니다. self.all_data의 변수 type은 파이썬 리스트이며, 그 안에는 다음과 같은 형식으로 데이터 파일의 경로가 저장되어 있습니다.

 

class CatDogDataset(Dataset):
    def __init__(self, data_dir, mode, transform=None):
        self.all_data = sorted(glob.glob(os.path.join(data_dir, mode, '*', '*')))
        self.transform = transform
    
    def __getitem__(self, index):
        # Step 1: 반환할 이미지 경로 정의 및 이미지 로드
        ## 코드 시작 ##
        data_path = self.all_data[index]    # 위의 설명 Step 1의 1. 을 참고하여 None을 채우세요.
        img = Image.open(data_path)          # 위의 설명 Step 1의 2. 를 참고하여 None을 채우세요.
        img = self.transform(img)                # 위의 설명 Step 1의 3. 을 참고하여 None을 채우세요.
        

        ## 코드 종료 ##
        
        # Step 2: 이미지에 대한 label 정의
        ## 코드 시작 ##
        label = 0 if os.path.basename(data_path).startswith('cat') else 1                # 위의 설명 Step 2 를 참고하여 None을 채우세요.
        ## 코드 종료 ##
        return img, label
    
    def __len__(self):
        ## 코드 시작 ##
        length = len(self.all_data)
        ## 코드 종료 ##
        return length
        

 


4. Dataset 및 DataLoader 할당

 

이제 우리가 사용할 데이터셋을 정의해야 합니다. 이전 실습에서는 PyTorch에 이미 정의되어 있는 FashionMNIST Dataset을 불러와서 사용하면 됐습니다. 따라서 따로 Dataset class를 구현해야 할 필요가 없었습니다.

이번 예제에서도 'Lab-10-4-1'강의에서 배웠던, PyTorch에 미리 정의되어 있는 ImageFolder Dataset class를 사용할 수 있습니다. 폴더에 맞게 라벨을 자동으로 지정해주는 매우 편리한 기능이죠. 하지만 PyTorch가 항상 입맛에 맞는 라벨을 미리 정의해 줄 수는 없습니다. 따라서 스스로 라벨을 정의하는 연습이 필요합니다.

 

 

 

 

 

data_transforms = {
    'train': transforms.Compose([
        transforms.RandomRotation(5),
        transforms.RandomHorizontalFlip(),
        transforms.RandomResizedCrop(120, scale=(0.96, 1.0), ratio=(0.95, 1.05)),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize([120, 120]),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}

train_data = CatDogDataset(data_dir='./data/my_cat_dog', mode='train', transform=data_transforms['train'])
val_data = CatDogDataset(data_dir='./data/my_cat_dog', mode='val', transform=data_transforms['val'])
test_data = CatDogDataset(data_dir='./data/my_cat_dog', mode='test', transform=data_transforms['val'])

train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, drop_last=True)
val_loader = DataLoader(val_data, batch_size=batch_size, shuffle=False, drop_last=True)
test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, drop_last=True)

 

data_transforms 딕셔너리에는 훈련용, 검증용(또는 테스트용) transforms 모듈이 정의되어 있습니다. 훈련용 transforms 모듈에서는 총 3가지의 데이터 증식 기법과, 이미지를 0~1 사이의 값으로 정규화하고 PyTorch Tensor로 변환하는 ToTensor(), 그리고 주어진 평균과 표준편차 값으로 입력값을 normalize 하는 Normalize()가 포함되어 있습니다.

여기서 각각의 데이터 증식 기법에 대한 설명은 다음과 같습니다.

  • transforms.RandomRotation: 주어진 범위 사이의 각도 중에서 무작위로 이미지를 회전시킵니다.
  • transforms.RandomHorizontalFlip: 주어진 확률로 이미지를 좌우 반전시킵니다.
  • transforms.RandomResizedCrop: 주어진 scale과 ratio를 통해 이미지 크기를 조정하고 잘라낸 후에, 주어진 이미지 크기로 다시 resize 해줍니다. 우리가 가진 원본 데이터는 이미지마다 크기가 다르기 때문에 모델에 입력으로 주기 위해서는 반드시 일정한 크기로 맞추어야 합니다. 우리 모델에서는 120x120로 입력 이미지의 크기를 고정하겠습니다.

훈련용 데이터에 대해 각가 기법이 차례대로 적용된 후, ToTensor()와 Normalize()가 적용됩니다. Normalization의 평균과 표준편차는 아래에 하드코딩한 평균과 표준편차를 사용하기도 합니다. 이 평균과 표준편차는 대규모 이미지 데이터셋인 ImageNet의 평균과 표준편차입니다.

검증 또는 테스트를 진행하는 경우에는, 실행할 때마다 일관된 결과가 나오도록 하기 위해 데이터 증식 기법을 적용하지 않습니다. 하지만 trasnforms.Resize을 통해 마찬가지로 120x120으로 이미지 크기를 고정해주도록 합니다.

이렇게 정의한 data_transforms를 기반으로 학습용, 검증용, 테스트용 Dataset과 DataLoader를 할당합니다.

 

 

 

 

 

 

참고사이트↓

 

사용자 정의 Dataset, Dataloader, Transforms 작성하기 — PyTorch Tutorials 1.9.0+cu102 documentation

Note Click here to download the full example code 사용자 정의 Dataset, Dataloader, Transforms 작성하기 저자 : Sasank Chilamkurthy 번역 : 정윤성 머신러닝 문제를 푸는

tutorials.pytorch.kr