네이버 부스트캠프 학습 정리/2주차

[PyTorch] PyTorch의 데이터

AI쟁이J 2023. 3. 19. 15:39

파이토치는 대규모 데이터를 통해 딥러닝을 학습하는 경우 사용하는 툴인 만큼 그 대량의 데이터를 모델에 먹이는 과정이 중요하다. 이를 다루는 것이 datasets 와 dataloaders이다.

PyTorch의 데이터를 위한 모듈들

- torch.utils.data : 데이터셋의 표준을 정의하고, 자르고, 섞는데 쓰는 도구들이 들어있는 모듈. 데이터셋의 표준을 torch.utils.data.Dataset에 정의 후 이를 상속하는 파생 클래스는 torch.utils.data.DataLoader 인스턴스의 입력으로 사용함

 

- torchvision.dataset : torch.utils.data.Dataset을 상속하는 이미지 데이터셋의 모음으로 MNIST나 CIFAR-10 등의 CV 예제에 기본이 되는 데이터셋을 제공

 

- torchtext.dataset : torch.utils.data.Dataset을 상속하는 텍스트 데이터셋의 모음으로 IMDb, AG_NEWS 등의 NLP예제에 기본이 되는 데이터셋을 제공

 

- torchvision.utils : 이미지 데이터를 저장하고 시각화하기 위한 도구가 들어있는 모듈

 

Dataset의 기본 구성 요소

from torch.utils.data import Dataset

class CustomDataset(Dataset):
    def __init__(self,):
        pass

    def __len__(self):
        pass

    def __getitem__(self, idx):
        pass

의 형태로 map-style dataset과 같은 스타일에 적용

 

__init__ 메서드는 데이터의 위치나 파일명과 같은 초기화 작업으로 CSV, XML파일등의 데이터를 불러오며 이미지를 처리하는 transforms 등도 정의

 

__len__ 메서드는 Dataset의 최대 요소 수를 반환하며 이를 통해 데이터의 인덱스가 적절한 범위 안에 있는지 확인할 수 있음

 

__getitem__ 메서드는 데이터셋의 idx번째 데이터를 반환하는데 사용되며 원본 데이터를 전처리하고 데이터 증강하는 부분이 이곳에서 진행됨.

 

iris = load_iris()
iris_df = pd.DataFrame(iris['data'], columns=iris['feature_names'])
iris_df['target'] = iris['target']

유명한 데이터셋인 붓꽃 데이터를 불러와서 변수 X에 feature, y에 target을 넣어 한 행씩 반환하는 Dataset을 생성

class IrisDataset(Dataset):
    def __init__(self):
        iris = load_iris()
        self.X = iris.data # X 변수
        self.y = iris.target # y target
        self.feature_names = iris.feature_names # 각 요소(열)의 이름

    def __len__(self):
        len_dataset = None
        len_dataset = len(iris.data)
 
        return len_dataset # iris data의 최대 요소 수 반환

    def __getitem__(self, idx):
        X, y = None, None
        X = torch.FloatTensor(self.X[idx])
        y = torch.tensor(self.y[idx])
        
        return X, y

 

DataLoader

학습을 위해서 데이터를 미니 배치 단위로 제공해주는 역할을 하는 모듈

DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
           batch_sampler=None, num_workers=0, collate_fn=None,
           pin_memory=False, drop_last=False, timeout=0,
           worker_init_fn=None)

과 같은 방식으로 작동하며 해당 함수들은

 

dataset

앞서 생성한 Dataset의 인스턴스가 들어감

 

batch_size

인자의 뜻대로 배치 사이즈를 의미한다.

전체 트레이닝 데이터 셋을 여러 작은 그룹으로 나누었을 때 하나의 소그룹에 속하는 데이터 수

 

shuffle

데이터를 DataLoader에서 섞어서 사용하는지를 설정 가능, boolean 타입

 

sampler/batch_sampler

index를 컨트롤하는 방법으로 데이터의 index를 원하는 방식으로 조정한다. shuffle 기능과 함께 사용 불가능

● SequentialSampler : 항상 같은 순서

● RandomSampler : 랜덤, replacement 여부 선택 가능 (비복원, 복원)

● SubsetRandomSampler : 랜덤 리스트

● WeightRandomSampler : 가중치에 따른 확률

● BatchSampler : batch 단위로 sampling 가능

● DistributedSampler : 분산처리

 

num_workers

데이터를 불러올 때 사용하는 서브 프로세스 개수. (windows에서는 멀티프로세서의 제한으로 0만 가능)

 

collate_fn

sample list를 batch 단위로 바꾸기 위해 필요한 기능으로 zero-padding이나 Variable Size등 데이터 사이즈를 맞추기 위해 사용함. (collate는 '함께 합치다' 라는 뜻)

프린터기의 묶어서 인쇄하기와 같은 기능으로 

로 설명 가능

 

pin_memory

True로 설정하는 경우 Tensor를 CUDA 고정 메모리에 할당하며 데이터 전송이 빨라짐 (일반적으로 잘 쓰지 않음)

 

drop_last

batch 단위로 데이터를 불러오면 batch_size에 따라 batch의 길이가 달라질 수 있다. 따라서 이에 따라 마지막 batch를 사용하지 않음으로서 길이를 맞출 수 있음

 

time_out

양수로 주어지는 경우, DataLoader가 data를 불러오는데 두는 제한시간

 

worker_init_fn

어떤 worker를 불러올 것인가를 리스트로 전달

 

torchvision의 transform 함수들

__init__ 메서드에서 transform을 통한 데이터의 모양을 조정하기 위해 사용할 때 사용되는 몇가지 함수

 

transforms.Resize

이미지의 사이즈를 변환

transforms.Resize((200,200))(im) # 200, 200으로 변환

transforms.RandomCrop

지정된 이미지를 임의의 위치에서 자름

transforms.RandomCrop((100,100))(im) # 임의의 위치에서 100, 100 사이즈로 자름

transforms.RandomRotation

지정된 이미지를 임의의 각도만큼 회전 

transforms.RandomRotation(30)(im) # 30도 회전

transforms.RandomVerticalFlip

이미지를 수평선을 기준으로 상하로 뒤집음

transforms.RandomVerticalFlip(p=1)(im) # 랜덤으로 뒤집음. p는 확률로 1일 경우 무조건 뒤집히게 출력

transforms.CenterCrop

이미지의 중간 부분에서 가로,세로기준으로 자름

transforms.CenterCrop(size = 150)(im) # 중간 기준으로 가로,세로 150씩 자름

Composer

이 기능들을 한번에 묶어서 처리하는 함수로 

transforms.Compose([transforms.Resize((224,224)),
                    transforms.RandomVerticalFlip(0.5),
                    transforms.CenterCrop(150)])(im)

처럼 다양한 변환을 Compose 안에 넣어 한번에 처리 가능

 

MNIST 데이터를 통한 Dataset, DataLoader 생성해보기

MNIST 데이터를 PATH 지정등을 통해 가져온 상태에서 대표적인 요소 init, len, getitem을 구성한 예시만 기록

class MyMNISTDataset(Dataset):
    def __init__(self, path, transform, train=True):
        self.train = train
        self.X = read_MNIST_images(path['image']) # X는 image 데이터
        self.y = read_MNIST_labels(path['label']) # y는 target으로 0~9의 라벨

        self.transform = transform # transform을 적용하기 위한 객체
        self.path = path 
        self.classes = [x for x in range(10)] # 0~9의 classification

    def __len__(self):
        len_dataset = None
        len_dataset = len(self.X) # 데이터의 길이 반환(X기준)
        
        return len_dataset

    def __getitem__(self, idx):
        X,y = None, None
        X = self.transform(self.X[idx]) # idx를 통해 transform이 적용된 X 데이터를 호출
        if self.train: 
          y = self.y[idx] # train 데이터일 경우에만 y 반환
          
        return torch.tensor(X, dtype=torch.double), torch.tensor(y, dtype=torch.long)
        # tensor 타입으로 X, y 반환
dataset_train_MyMNIST = MyMNISTDataset(path=TRAIN_MNIST_PATH,
                                       transform=transforms.Compose([
                                           transforms.ToTensor()
                                       ]),
                                       train=True
                                       )

compose 함수를 통해 ToTensor를 적용, train = True 지정한 데이터셋을 dataset_train_MyMNIST로 생성

dataset_train_MNIST
>>> Dataset MNIST
        Number of datapoints: 60000
        Root location: data/MNIST/
        Split: Train
        StandardTransform
    Transform: ToTensor()
len(dataset_train_MyMNIST)
>>> 60000
plt.imshow(image.numpy().squeeze(), cmap='gray')
plt.title("{}".format(dataset_train_MyMNIST.classes[label]))
plt.axis('off')
plt.show()

dataloader_train_MNIST = DataLoader(dataset=dataset_train_MyMNIST,
                                    batch_size=16, # 배치 사이즈 16
                                    shuffle=True, # 데이터를 섞음
                                    num_workers=4, # colab환경에서만 가능, windows에서 미지원
                                    )
plt.figure(figsize=(12,12))
for n, (image, label) in enumerate(zip(images, labels), start=1):
    plt.subplot(4,4,n)
    plt.imshow(image.numpy().squeeze(), cmap='gray')
    plt.title("{}".format(dataset_train_MyMNIST.classes[label]))
    plt.axis('off')
plt.tight_layout()
plt.show()

 

'네이버 부스트캠프 학습 정리 > 2주차' 카테고리의 다른 글

[PyTorch] PyTorch 알쓸신잡  (0) 2023.03.19
[PyTorch] parameter & buffer  (0) 2023.03.19
[PyTorch] nn.Module  (0) 2023.03.17
[PyTorch] 파이토치의 기본  (0) 2023.03.17