인공지능/Pytorch

[Pytorch] torch.utils.data.DataLoader

바보1 2023. 3. 13. 20:32

앞선 글을 읽으시면 이해에 도움이 됩니다.

 

2023.02.25 - [인공지능/Pytorch] - [Pytorch] torch.utils.data.Dataset

 

[Pytorch] torch.utils.data.Dataset

1. torch.utils.data.Dataset torch.utils.data의 하위에 있는 Dataset은 Pytorch에서 데이터를 불러오고, 전처리하는 클래스입니다. 따라서 사용자가 자신의 데이터셋을 만들어 Pytorch에서 사용할 수 있도록 해줍

hi-guten-tag.tistory.com


1. torch.utils.data.DataLoader

 

 

  • torch.utils.data.dataloader PyTorch에서 제공하는 데이터 로더(data loader)입니다. 
  • 데이터 로더는 데이터셋(dataset) 읽어와서 배치(batch) 단위로 데이터를 불러옵니다. 이를 통해 모델 학습을 효율적으로 진행할 있습니다.
  • torch.utils.data.dataloader 데이터셋(dataset) 함께 사용합니다.
  • 데이터 로더(data loader) 멀티스레딩(multi-threading) 멀티프로세싱(multi-processing) 지원하여, 데이터를 병렬로 처리할 있습니다.
  • torch.utils.data.dataloader 다양한 파라미터를 제공합니다. 이를 통해 데이터 로딩에 대한 설정을 변경할 있습니다. 예를 들어, 배치(batch) 크기를 조정하거나, 데이터셋(dataset) 섞어서 학습을 효과적으로 진행할 있습니다.
  • 이러한 특징들로 인해 torch.utils.data.dataloader PyTorch에서 매우 중요한 역할을 합니다. 데이터 로딩을 효율적으로 처리함으로써, 모델 학습 속도를 높일 있고, 나은 성능을 얻을 있습니다.

2. 파라미터

 

 

  • DataLoader의 파라미터는 매우 많습니다.
  • torch.utils.data.DataLoader
    • (datasetbatch_size=1shuffle=Nonesampler=Nonebatch_sampler=Nonenum_workers=0collate_fn=Nonepin_memory=Falsedrop_last=Falsetimeout=0worker_init_fn=Nonemultiprocessing_context=Nonegenerator=None*prefetch_factor=2persistent_workers=Falsepin_memory_device='')
  • 상단의 파라미터가 모두 DataLoader의 파라미터입니다.
  • 하나씩 설명을 보고, 중요한 batch_size와 shuffle만 예시를 보고 넘어갑시다.

 

  • 다른 파라미터에 대한 자세한 설명은 차후 다른 글에서 다루도록 하겠습니다.
  • dataset (Dataset): DataLoader가 불러올 데이터셋 객체입니다. 이 객체는 torch.utils.data.Dataset 클래스를 상속받은 사용자 정의 데이터셋 객체일 수 있습니다.
  • batch_size (int, optional): DataLoader가 반환할 배치(batch) 크기입니다. 기본값은 1입니다.
  • shuffle (bool, optional): 데이터셋을 무작위로 섞을지 여부를 결정하는 파라미터입니다. 기본값은 None이며, True로 설정하면 매 에폭(epoch)마다 데이터셋이 섞입니다.
  • sampler (Sampler, optional): 데이터셋에서 데이터를 샘플링하는데 사용하는 샘플러 객체입니다. shuffle 파라미터와 함께 사용할 수 없으며, sampler를 지정하면 shuffle 파라미터는 무시됩니다.
  • batch_sampler (Sampler, optional): 배치(batch) 단위로 데이터를 샘플링하는데 사용하는 샘플러 객체입니다. 이 파라미터를 사용하면 batch_size 파라미터를 지정하지 않아도 됩니다.
  • num_workers (int, optional): 데이터를 불러올 때 사용할 프로세스(worker) 수입니다. 기본값은 0이며, 이 경우 메인 프로세스에서 데이터를 불러옵니다. num_workers를 높이면 데이터를 불러오는 속도가 빨라질 수 있습니다.
  • collate_fn (callable, optional): 배치(batch) 단위로 데이터를 처리하는 함수입니다. 기본값은 None이며, 이 경우 데이터셋에서 불러온 데이터를 그대로 배치로 묶어서 반환합니다.
  • pin_memory (bool, optional): True로 설정하면, 반환된 배치 데이터는 CUDA 호환 GPU 메모리에 고정됩니다. 기본값은 False입니다.
  • drop_last (bool, optional): 마지막 배치(batch)가 batch_size보다 작을 경우 버릴지 여부를 결정하는 파라미터입니다. 기본값은 False입니다.
  • timeout (numeric, optional): 데이터를 불러오는데 걸리는 최대 시간입니다. 기본값은 0이며, 이 경우 무한정 기다립니다.
  • worker_init_fn (callable, optional): 프로세스(worker)를 초기화하는 함수입니다.
  • multiprocessing_context (Context, optional): 멀티프로세싱(multiprocessing) 컨텍스트(context) 객체입니다.
  • generator (torch.Generator, optional): 미리 생성된 배치(batch)를 사용하는 경우에만 지정합니다.
  • prefetch_factor (int, optional): 미리 읽어올 데이터의 배치(batch) 수를 결정하는 파라미터입니다. DataLoader가 데이터를 불러오는 동안 미리 다음 배치(batch)의 데이터를 불러와서 메모리에 적재합니다. 이를 통해 데이터를 불러오는 속도를 높일 수 있습니다. prefetch_factor를 높이면 미리 읽어올 데이터의 양이 늘어나기 때문에 DataLoader가 데이터를 불러오는 속도가 빨라질 수 있습니다.
  • persistent_workers (bool, optional): True로 설정하면, worker 프로세스(worker process)를 계속 사용합니다. 기본값은 False입니다. worker 프로세스를 계속 사용하면 데이터를 불러오는 속도가 빨라질 수 있습니다. 그러나 worker 프로세스를 계속 사용하면 프로세스간 통신(inter-process communication) 오버헤드가 발생할 수 있기 때문에, 실제로 성능이 향상되지 않는 경우가 있을 수도 있습니다.
  • pin_memory_device (Union[str, torch.device], optional): CUDA 호환 GPU 메모리에 고정할 디바이스(device)를 지정하는 파라미터입니다. 기본값은 ""(빈 문자열)입니다. pin_memory_device를 설정하면, DataLoader가 반환하는 배치(batch) 데이터가 해당 디바이스에 고정됩니다. 이를 통해 데이터를 GPU에서 더 빠르게 처리할 수 있습니다. 디바이스를 지정할 때는 문자열("cuda:0")이나 torch.device 객체를 사용할 수 있습니다.

3. 예시

 

 

  • torch.utils.data.DataLoader를 사용하기 위하여, 앞선 글에서 만든 Dataset을 이용합니다.
  • 우선 batch_size에 대한 예시부터 보겠습니다.
import torch
from torch.utils.data import DataLoader
from Dataset import MyDataset


if __name__ == "__main__":
    data = torch.randn(100, 3, 32, 32)
    target = torch.randint(0, 10, (100, ))

    mydataset = MyDataset(data, target)
    
    mydataloader = DataLoader(mydataset, batch_size=10)

    for i, (data, target) in enumerate(mydataloader):
        print(i, data.shape, target.shape, target)
        
        
----------결과----------
❯ python DataLoader.py
0 torch.Size([10, 3, 32, 32]) torch.Size([10])
1 torch.Size([10, 3, 32, 32]) torch.Size([10])
2 torch.Size([10, 3, 32, 32]) torch.Size([10])
3 torch.Size([10, 3, 32, 32]) torch.Size([10])
4 torch.Size([10, 3, 32, 32]) torch.Size([10])
5 torch.Size([10, 3, 32, 32]) torch.Size([10])
6 torch.Size([10, 3, 32, 32]) torch.Size([10])
7 torch.Size([10, 3, 32, 32]) torch.Size([10])
8 torch.Size([10, 3, 32, 32]) torch.Size([10])
9 torch.Size([10, 3, 32, 32]) torch.Size([10])
  • 위의 코드에서 batch_size를 10으로 설정하여, 한 번 데이터를 가져올 때 10개씩 가져오도록 설정했습니다.

 

  • 다음은 shuffle에 대한 예시입니다.
import torch
from torch.utils.data import DataLoader
from Dataset import MyDataset


if __name__ == "__main__":
    data = torch.randn(100, 3, 32, 32)
    target = torch.randint(0, 10, (100, ))

    mydataset = MyDataset(data, target)
    
    mydataloader = DataLoader(mydataset, batch_size=10, shuffle=True)

    for epoch in range(2):
        print(f'----------epcho : {epoch}----------')
        for i, (data, target) in enumerate(mydataloader):
            print(target)
            
            
----------결과----------
❯ python DataLoader.py
----------epcho : 0----------
tensor([7, 2, 0, 3, 6, 0, 9, 4, 5, 8])
tensor([8, 9, 3, 4, 8, 7, 1, 4, 6, 5])
tensor([8, 5, 2, 4, 4, 7, 7, 4, 2, 1])
tensor([7, 2, 8, 2, 8, 2, 1, 1, 6, 7])
tensor([3, 4, 1, 4, 1, 0, 8, 4, 3, 0])
tensor([4, 6, 8, 5, 0, 0, 1, 7, 3, 0])
tensor([6, 6, 8, 7, 0, 7, 4, 2, 1, 8])
tensor([1, 3, 3, 3, 7, 1, 3, 6, 9, 7])
tensor([7, 3, 1, 2, 9, 4, 3, 5, 1, 0])
tensor([6, 5, 6, 5, 6, 1, 0, 4, 0, 5])
----------epcho : 1----------
tensor([3, 4, 2, 4, 1, 7, 8, 1, 8, 2])
tensor([3, 3, 7, 7, 4, 2, 2, 5, 6, 8])
tensor([0, 7, 2, 9, 1, 1, 0, 3, 4, 0])
tensor([5, 2, 4, 4, 5, 0, 4, 6, 6, 4])
tensor([5, 4, 5, 5, 1, 7, 7, 5, 7, 8])
tensor([1, 1, 8, 7, 3, 8, 4, 3, 1, 5])
tensor([4, 8, 3, 0, 4, 9, 1, 3, 2, 6])
tensor([8, 1, 7, 1, 0, 0, 3, 0, 3, 4])
tensor([1, 9, 0, 7, 6, 6, 6, 1, 6, 6])
tensor([9, 7, 7, 0, 3, 8, 8, 2, 0, 6])
  • 보시다시피 shuffle = True로 설정하니 매 epochs마다 데이터를 섞는 모습을 볼 수 있습니다.
  • 반대로 False로 설정하면 매 epochs마다 동일한 데이터가 출력됩니다.

 

  • 마지막으로 drop_last 파라미터에 대해 알아보겠습니다.
import torch
from torch.utils.data import DataLoader
from Dataset import MyDataset


if __name__ == "__main__":
    data = torch.randn(100, 3, 32, 32)
    target = torch.randint(0, 10, (100, ))

    mydataset = MyDataset(data, target)
    
    mydataloader = DataLoader(mydataset, batch_size=9, shuffle=True, drop_last=False)

    for i, (data, target) in enumerate(mydataloader):
        print(i, data.shape, target.shape, target)


----------결과----------
❯ python DataLoader.py
0 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([2, 4, 6, 4, 5, 0, 2, 2, 0])
1 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([8, 6, 6, 6, 3, 5, 7, 5, 9])
2 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([3, 6, 9, 1, 9, 0, 4, 3, 2])
3 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([2, 7, 5, 5, 4, 1, 0, 4, 0])
4 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([8, 9, 7, 8, 8, 8, 2, 2, 2])
5 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([9, 9, 4, 1, 8, 6, 0, 1, 1])
6 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([6, 1, 9, 9, 1, 4, 0, 0, 6])
7 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([5, 6, 4, 8, 0, 2, 8, 3, 1])
8 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([9, 4, 9, 1, 9, 6, 9, 1, 4])
9 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([3, 6, 8, 5, 8, 6, 4, 7, 9])
10 torch.Size([9, 3, 32, 32]) torch.Size([9]) tensor([1, 0, 5, 9, 5, 5, 9, 9, 9])
11 torch.Size([1, 3, 32, 32]) torch.Size([1]) tensor([3])
  • 보시다시피 drop_last = False로 설정하면, 맨 마지막에 남은 1개의 데이터를 버리지 않고 가져옵니다.
  • 반대로 True로 설정하면 11번의 반복문 이후, 남은 데이터 1개는 버립니다.

'인공지능 > Pytorch' 카테고리의 다른 글

[Pytorch] torch.utils.data.Dataset  (2) 2023.02.25