PyTorch: 데이터셋
AI-PyTorch

데이터셋Dataset

모델 훈련에 사용되는 샘플과 레이블을 묶는 컨테이너를 데이터셋(Dataset)이라 한다.

데이터셋 불러오기

🧶torchvision.datasets 모듈은 인공지능 학습을 위한 다양한 데이터셋을 제공한다.

예를 들어, 유명한 데이터셋 중 하나인 FashionMNIST 데이터셋은 다음과 같이 불러올 수 있다.

1
2
3
4
5
6
7
8
9
10
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda

training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor()
    target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
)

FashionMNIST 데이터셋 클래스의 매개변수는 다음과 같다. 다른 데이터셋의 매개변수는 📌이곳에서 확인할 수 있다.

  • root(필수)

    데이터셋 저장 경로를 지정한다.

  • train

    훈련셋으로 사용할 경우 True로 지정한다. 테스트셋으로 사용할 경우 False로 지정한다.

  • download

    데이터셋의 다운 여부를 지정한다.

    True로 지정할 경우, root에 데이터셋이 없을 때 인터넷에서 다운로드한다.

  • transform

    데이터셋의 특징(Feature)에 적용할 변형을 지정한다.

    🧶torchvision.transforms 모듈은 여러 변형 함수를 제공한다.

    🧶torchvision.transforms.ToTensor 함수는 PIL 이미지FloatTensor로 변환한다.

  • target_transform

    데이터셋의 레이블(Label)에 적용할 변형을 지정한다.

    🧶torchvision.transforms.Lambda 함수는 사용자 정의 람다 함수를 적용한다.

    변형 전 y는 0부터 9까지의 값 중 하나이며, 다음 람다식을 적용해 y번째 인덱스의 값이 1이고 다른 인덱스의 값이 0인 크기 10의 1차원 텐서로 원-핫 인코딩할 수 있다.

    1
    
    Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
    

사용자 정의 데이터셋

🧶torch.utils.data.Dataset를 상속받는 클래스를 생성해 사용자 정의 데이터셋을 구성할 수 있다.

사용자 정의 데이터셋 클래스는 반드시 __init_, __len__, __getitem__ 메서드를 구현해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
from torch.utils.data import Dataset

class JointDataset(Dataset):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __len__(self):
        return len(self.x)

    def __getitem__(self, idx):
        return self.x[idx], self.y[idx]

사용자 정의 데이터셋 객체를 생성하고, 작동을 확인한다.

1
2
3
4
5
6
7
8
9
10
torch.manual_seed(1)

t_x = torch.rand([4, 3], dtype=torch.float32)
t_y = torch.arange(4)

joint_dataset = JointDataset(t_x, t_y)

print("length:", len(joint_dataset))
for example in joint_dataset:
    print(f"x: {example[0]}, y: {example[1]}")

실행 결과

1
2
3
4
5
length: 4
x: tensor([0.7576, 0.2793, 0.4031]), y: 0
x: tensor([0.7347, 0.0293, 0.7999]), y: 1
x: tensor([0.3971, 0.7544, 0.5695]), y: 2
x: tensor([0.4388, 0.6387, 0.5247]), y: 3

데이터로더(DataLoader)

모델 훈련 시 각 에포크(Epoch)마다 데이터셋 전체를 순회하며, 각 순회(Iteration)마다 배치 사이즈만큼의 샘플과 레이블을 사용한다.

이 과정에서 순회할 데이터셋의 배치 사이즈를 직접 지정하거나, 각 에포크가 끝날 때마다 데이터셋을 섞는 등의 기능이 필요할 수 있다.

데이터로더(DataLoader)를 사용하면 이러한 복잡한 과정들을 추상화할 수 있다.

🧶torch.utils.data.DataLoader 클래스의 매개변수는 다음과 같다. 전체 매개변수는 📌이곳에서 확인할 수 있다.

  • dataset(필수)

  • batch_size=1

    배치 사이즈를 지정한다. 만약 크기 10의 데이터셋에서 batch_size를 1로 지정하면 총 10/1 = 10번의 순회가 이루어진다.

  • shuffle=False

    과적합 방지를 위해 각 에포크가 끝날 때마다 데이터셋을 섞어서 사용할지 결정한다.

  • drop_last=False

    마지막 배치의 크기가 배치 사이즈보다 작은(나누어떨어지지 않는) 경우, 마지막 배치를 drop할지 결정한다.

데이터로더를 사용해 위에서 생성한 사용자 정의 데이터셋 객체를 순회하고, 작동을 확인한다.

1
2
3
4
5
6
7
8
torch.manual_seed(1)

data_loader = DataLoader(dataset=joint_dataset, batch_size=2, shuffle=True)

for epoch in range(2):
    print(f"epoch {epoch+1}")
    for i, batch in enumerate(data_loader, 1):
        print(f"    batch {i}:\n        x: {batch[0]}\n        y: {batch[1]}")

실행 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
epoch 1
    batch 1:
        x: tensor([[0.3971, 0.7544, 0.5695],
        [0.7576, 0.2793, 0.4031]])
        y: tensor([2, 0])
    batch 2:
        x: tensor([[0.4388, 0.6387, 0.5247],
        [0.7347, 0.0293, 0.7999]])
        y: tensor([3, 1])
epoch 2
    batch 1:
        x: tensor([[0.3971, 0.7544, 0.5695],
        [0.7347, 0.0293, 0.7999]])
        y: tensor([2, 1])
    batch 2:
        x: tensor([[0.7576, 0.2793, 0.4031],
        [0.4388, 0.6387, 0.5247]])
        y: tensor([0, 3])

📌REF