본문 바로가기
AI/파이썬

파이토치(PyTorch) - Data Sets & Data Loaders

by 알푼 2023. 6. 27.
728x90
728x90

Data Sets & Data Loaders


PyTorch가 제공하는 데이터 형식

  • torch.utils.data.DataLoader
  • torch.utils.data.Dataset

Dataset은 샘플과 레이블을 저장하고, DataLoader는 Dataset을 감싸서 이를 iterable로 만들어 샘플에 쉽게 access할 수 있게 한다. PyTorch의 domain library들은 (ex. Fashion-MNIST) 사전에 로드된 데이터셋을 제공한다. 이 데이터셋들은 torch.utils.data.Dataset을 상속하며 특정 데이터에 대한 함수를 구현한다. 이러한 데이터셋은 모델을 프로토타입하고 벤치마킹 하는데 사용 할 수 있으며, Image, Text, Audio 등의 데이터셋들이 있다.

 

Loading a Dataset


TorchVision을 사용한 Fashion-MNIST 데이터셋 로드 방법 예시

 

  • Fashion-MNSIT는 Zalando의 의류 이미지 데이터 셋
  • 6만개의 훈련 예제외 1만 개의 테스트 예제로 구성
  • 28x28 그레이스케일 이미지와 10개 클래스 중 하나의 label 포함

 

import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt

# root : 훈련/테스트 데이터가 저장된 경로
# train : 훈련 데이터셋 또는 테스트 데이터셋 지정 (True -> training set // False -> test set)
# download : True는 데이터가 root에 없으면 인터넷에서 데이터를 다운로드
# transform / target_transform : 특징 및 label 변환 지정

training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
)

test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor()
)

→ Dataset을 이용한 데이터 생성, 로드

 

Iterating and Visualizing the Dataset


매뉴얼로 Label을 만들어주고 matplotlib를 통하여 일부 샘플을 시각화 한다. (이미 데이터셋에서 0번이 T-Shirt 종류라는 것을 알고 있음)

labels_map = {
    0: "T-Shirt",
    1: "Trouser",
    2: "Pullover",
    3: "Dress",
    4: "Coat",
    5: "Sandal",
    6: "Shirt",
    7: "Sneaker",
    8: "Bag",
    9: "Ankle Boot",
}
figure = plt.figure(figsize=(8, 8))
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
    sample_idx = torch.randint(len(training_data), size=(1,)).item()
    img, label = training_data[sample_idx]
    figure.add_subplot(rows, cols, i)
    plt.title(labels_map[label])
    plt.axis("off")
    plt.imshow(img.squeeze(), cmap="gray")
plt.show()

 

Creating a Custom Dataset for your files


Custom Dataset class는 init, len, getitem 세 가지 함수를 구현해야 한다. 다음 예제는 Fashion-MNIST 이미지가 img_dir 디렉토리에 저장되고 해당 label이 CSV파일 annotations_file에 별도로 저장되어 있는 예시이다. 이미지를 불러와서 Tensor로 변환 후, 해당 이미지와 label을 (label CSV 파일 이용) 반환하는 class이다.

import os
import pandas as pd
from torchvision.io import read_image

class CustomImageDataset(Dataset):
    def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file)
        self.img_dir = img_dir
        self.transform = transform
        self.target_transform = target_transform

    def __len__(self):
        return len(self.img_labels)

    def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
        image = read_image(img_path)
        label = self.img_labels.iloc[idx, 1]
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        return image, label

 

Preparing your data for training with DataLoaders


모델을 훈련할 때 일반적으로 미니배치를 사용하고, epoch가 진행될 때마다 overfitting을 줄이기 위해 데이터를 섞어준다. 또한 파이썬의 multiprocessing을 사용하여 검색 속도를 높인다. DataLoader는 이러한 복잡성을 가진 특성에서도 우리에게 쉬운 API로 추상화한 iterable이다.

from torch.utils.data import DataLoader

train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)

→ DataLoader를 이용한 shuffle

 

Iterate through the DataLoader


위 코드에서 데이터셋을 DataLoader에 로드하고 필요에 따라 데이터셋을 반복(iterate)할 수 있다. 아래 각 iteration은 train_features와 train_labels의 배치(batch)를 반환하며 (각각 batch_size=64개의 특징과 레이블을 포함), shuffle=True로 지정하여 모든 배치를 반복한 후 데이터가 섞인다.

# Display image and label.
train_features, train_labels = next(iter(train_dataloader))
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
img = train_features[0].squeeze()
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {label}")

💡 Out:

Feature batch shape: torch.Size([64, 1, 28, 28])
Labels batch shape: torch.Size([64])
Label: 2

 

 

Transform


데이터가 항상 머신러닝 알고리즘 학습을 바로 적용할 수 있도록 정제된 형태로 제공되지는 않는다. 그래서 Transform을 해서 데이터를 조작하고 학습에 적합하게 만들어야 한다. 모든 TorchVision 데이터셋들은 특징(feature)을 변경하기 위한 transform과 label을 변경하기 위한 target_transform을 갖는다.

Fashion-MNIST의 feature는 PIL Image 형식이며, label은 정수(integer)이다. 이 데이터를 학습하려면 정규화(normalize)된 텐서 형태의 feature와 One-hot encoding 된 텐서 형태의 label이 필요하다. 이를 위해 Transform이 필요하고, 이 때 ToTensor와 Lambda를 사용한다.

import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

ds = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
		# ToTensor는 PIL image나 NumPy ndarray를 FloatTensor로 변환하고, 이미지의 픽셀의 크기(intensity) 값을 [0, 1] 범위로 비례하여 조정(scale)
    transform=ToTensor(),
		# 정답 개수인 크기 10짜리 zero tensor 생성 후, scatter_를 호출하여 정답 y에 해당하는 인덱스에 value=1 할당
    target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
)

 

출처 : 파이토치 공식 문서

https://pytorch.org/tutorials/beginner/basics/data_tutorial.html

728x90
반응형

댓글