앞선 글을 읽으시면 이해에 도움이 됩니다.
2023.02.25 - [인공지능/Pytorch] - [Pytorch] torch.utils.data.Dataset
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
- (dataset, batch_size=1, shuffle=None, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None, *, prefetch_factor=2, persistent_workers=False, pin_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 |
---|