ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [pytorch] DataLoader 알아보기
    AI-ML 2022. 7. 18. 03:48
    728x90
    반응형

     

    - 목차

     

    키워드.

    • - DataLoader
    • - Dataset
    • - Iteration

     

    들어가며.

    pytorch 는 학습할 데이터의 관리를 위해서 DatasetDataLoader 클래스를 제공합니다.

    Dataset 클래스는 학습 또는 테스트를 위한 데이터를 수월하게 관리하기 위한 인터페이스를 제공합니다.

    예를 들어서 데이터의 총 갯수를 알려주는 len 함수, Iteration 을 위해 개별 데이터를 획득할 수 있는 getitem 함수 등이 제공됩니다.

    즉, 데이터 관리를 손쉽게 하기 위한 유틸리티 함수들이 첨가된 클래스라고 생각하시면 됩니다.

    이러한 Dataset 과 더불어 DataLoader 는 Iteration 을 위한 인터페이스가 제공됩니다.

    흔히 epoch, batch 등과 같이 용어들이 사용되죠 ?

    이는 학습 과정에서 전체 학습 데이터를 하나씩 또는 batch 단위로 조회하여 학습이 수행되는데,

    Dataset 과 DataLoader 를 통해서 간단하고 깔끔하게 학습을 위한 Iteration 이 제공됩니다.

     

    Epoch, Batch, Iteration 이란 ?

    그럼 머신러닝에서 흔히 사용되는 용어인 Epoch, Batch, Iteration 에 대해서 간단히 살펴보겠습니다.

    먼저 Epoch 는 전체 학습 데이터를 학습하는 총 횟수를 의미합니다.

    만약 Train Dataset 의 사이즈가 1만개라고 가정합니다.

    그리고 Epoch 가 10 회라면 Train Dataset 은 10 회만큼 학습이 되고,

    총 1만 ( Train Dataset size ) x 10 ( Epoch ) 인 10만 번의 순회가 발생합니다. ( For Loop )

    # trainset.size == 1만
    # epoch == 10
    
    for _ in range(epoch):
        for train_item in trainset: 
        	train_each_item(train_item)

     

     

    Batch 는 한번의 학습과정에서 몇개의 데이터를 학습할지를 결정합니다.

    위와 같이 Train Dataset 의 사이즈가 1만개, Epoch 이 10회, 그리고 Batch Size 는 5개라고 가정합니다.

    그럼 1번의 Iteration 단계에서 1개가 아닌 5개의 Batch 만큼 한번에 학습이 이뤄지기 때문에

    1만 ( Train Dataset size ) / 5 ( Batch ) ==> 2천 번의 Batch

    2천 ( Batch Size ) * 10 ( Epoch ) ==> 2만 번의 순회가 발생합니다.

     

    # trainset.size == 1만
    # epoch == 10
    # batch == 5
    
    
    for _ in range(epoch):
    
        batches = trainset.get_batches()
        
        for train_batch in batches: 
        	train_batch(train_batch)

     

    마지막으로 iteration 은 최종적으로 반복문이 수행되는 횟수를 의미합니다.

    이는 batch 사이즈가 클수록 Iteration 은 줄어듭니다.

    Iteration = ( TrainSize / Batch Size ) * Epoch 와 같은 관계가 있다고 생각하시면 됩니다.

     

     

    DataLoader .

    위 설명에서 말씀드렸듯이, DataLoader 은 Data Iteration 을 위한 간편한 인터페이스를 제공합니다.

    먼저 간단한 Dataset 의 구현법에 대해 말씀드리겠습니다.

    Dataset 은 __init__, __getitem__, __len__ 세가지의 내장함수를 구현해야합니다.

    이 내장함수들이 기본적으로 구현되어야하구요.

    __init__ 함수에선 Dataset 이 갖추어야할 학습 데이터들이 할당됩니다.

    그리고 __getitem__ 은 개별 데이터의 조회를 위한 함수이고, __len__ 함수는 총 데이터셋의 사이즈를 반환합니다.

    import torch
    from torch.utils.data import DataLoader, Dataset
    
    class CustomDataset(Dataset):
    
        def __init__(self):
            self.dataset = torch.randn((1000, 10), dtype=torch.float32)
    
        def __getitem__(self, index):
            return self.dataset[index]
    
        def __len__(self):
            return self.dataset.shape[0]
    
    
    dataset = CustomDataset()
    print(len(dataset))
    print(dataset[0])
    1000
    tensor([-0.3321,  0.0619, -1.5934, -0.3039, -0.4531,  0.3067,  0.2438, -0.5781,
            -1.2296,  0.2076])

     

    Dataset 이 생성되었다면, 생성된 Dataset 을 Load 하는 DataLoader 를 구축할 수 있습니다.

    DataLoader 의 사용법은 아래와 같습니다.

    dataset = CustomDataset()
    loader = DataLoader(
        dataset=dataset,
        batch_size=10,
        shuffle=True,
        num_workers=0
    )
    
    loader_iter = iter(loader)
    tensor = next(loader_iter)

     

    batch_size.

    DataLoader 는 batch_size 를 설정할 수 있습니다.

    이는 각 Iteration 에서 batch_size 만큼의 Tensor 를 반환합니다.

    아래 예시와 같이 DataLoader 에 설정된 batch_size 만큼 Iteration 에서 반환하는 Tensor 의 크기가 달라집니다.

    즉 Tensor 의 row 갯수가 batch_size 의 크기만큼 결정되죠.

    dataset = CustomDataset()
    
    for batch_size in range(1, 10):
        loader = DataLoader(
            dataset=dataset,
            batch_size=batch_size
        )
        tensor = next(iter(loader))
        print(f'batch_size : {batch_size}, tensor.shape : {tensor.shape}')
    batch_size : 1, tensor.shape : torch.Size([1, 10])
    batch_size : 2, tensor.shape : torch.Size([2, 10])
    batch_size : 3, tensor.shape : torch.Size([3, 10])
    batch_size : 4, tensor.shape : torch.Size([4, 10])
    batch_size : 5, tensor.shape : torch.Size([5, 10])
    batch_size : 6, tensor.shape : torch.Size([6, 10])
    batch_size : 7, tensor.shape : torch.Size([7, 10])
    batch_size : 8, tensor.shape : torch.Size([8, 10])
    batch_size : 9, tensor.shape : torch.Size([9, 10])

     

     

    shuffle.

    shuffle 는 Iteration 단계에서 Dataset 의 순서를 무작위로 섞을 수 있습니다.

    아래의 예시는 0 부터 99 까지의 값을 가지는 Dataset 의 Iteration 을 테스트합니다.

    import torch
    import numpy as np
    from torch.utils.data import DataLoader, Dataset
    
    class CustomDataset(Dataset):
    
        def __init__(self):
            self.dataset = torch.from_numpy(np.array([list(range(100))]).T)
    
    
        def __getitem__(self, index):
            return self.dataset[index]
    
        def __len__(self):
            return self.dataset.shape[0]
    
    
    dataset = CustomDataset()
    loader = DataLoader(
        dataset=dataset,
        batch_size=1,
        shuffle=False,
        num_workers=0
    )
    
    loader_iter = iter(loader)
    print(f'tensor 1 : {next(loader_iter)}')
    print(f'tensor 2: {next(loader_iter)}')
    
    loader_iter2 = iter(loader)
    print(f'tensor 1: {next(loader_iter2)}')
    print(f'tensor 2: {next(loader_iter2)}')

     

    아래의 결과처럼 Shuffle 을 적용하지 않은 경우에는 동일한 순서대로 결과가 출력됩니다.

    tensor 1 : tensor([[0]])
    tensor 2: tensor([[1]])
    tensor 1: tensor([[0]])
    tensor 2: tensor([[1]])

     

    반면 shuffle=True 로 설정하게 되면, 출력 결과는 아래와 같이 무작위로 셔플링됩니다.

    dataset = CustomDataset()
    loader = DataLoader(
        dataset=dataset,
        batch_size=1,
        shuffle=True,
        num_workers=0
    )
    
    loader_iter = iter(loader)
    print(f'tensor 1 : {next(loader_iter)}')
    print(f'tensor 2: {next(loader_iter)}')
    
    loader_iter2 = iter(loader)
    print(f'tensor 1: {next(loader_iter2)}')
    print(f'tensor 2: {next(loader_iter2)}')
    tensor 1 : tensor([[67]])
    tensor 2: tensor([[47]])
    tensor 1: tensor([[49]])
    tensor 2: tensor([[86]])

     

    For Loop Iteration.

    iter 또는 next 와 같은 함수를 사용하지 않고, DataLoader 와 반복문을 함께 사용하는 것이 가능합니다.

    예시는 아래와 같습니다.

    dataset = CustomDataset()
    loader = DataLoader(
        dataset=dataset,
        batch_size=10,
        shuffle=True,
        num_workers=0
    )
    
    for tensor in loader:
        print(tensor)

     

    batch_size 가 10 이기 때문에 조회되는 Tensor 의 row 갯수는 10개가 됩니다.

    tensor([[ 7],
            [54],
            [31],
            [33],
            [75],
            [12],
            [64],
            [30],
            [87],
            [71]])
    tensor([[48],
            [62],
            [29],
            [43],
            [15],
            [39],
            [41],
            [82],
            [68],
            [20]])
    //...

     

     

    반응형
Designed by Tistory.