init : 데이터의 위치나 파일명과 같은 초기화 작업을 위해 동작한다. 일반적으로 CSV, XML파일과 같은 데이터를 불러온다. 여기에 이미지를 처리할 transforms들을 Compose해서 정의해둔다.
len : Dataset의 최대 요소 수를 반환하는데에 사용한다.
getitem : Dataset의 index번째 데이터를 반환하는데에 사용한다. 원본 데이터를 가져와서 전처리하고 데이터를 증강하는 부분이 여기에서 진행된다.
class CustomDataset(Dataset):
def __init__(self, x_tensor, y_tensor):
self.x = x_tensor
self.y = y_tensor
def __getitem__(self, index):
return (self.x[index], self.y[index])
def __len__(self):
return len(self.x)
Dataloader는 모델 학습을 위해서 데이터를 미니 배치 단위로 제공해주는 역할을 한다.
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None)
dataloader에는 앞서 생성한 Dataset 인스턴스가 들어간다.
next(iter(DataLoader(dataset_iris)))
batch_size는 배치 사이즈를 정하는 인자이다.
next(iter(DataLoader(dataset_iris, batch_size=4)))
shuffle은 data를 섞어서 사용할지를 결정한다.
next(iter(DataLoader(dataset_iris, shuffle=True, batch_size=4)))
num_workers는 데이터를 불러올 때 사용되는 subprocess의 개수이다. 학습 도중 CPU의 작업을 몇 개의 코어를 사용하여 진행할지에 대한 파라미터이다.
%%time
for data, label in DataLoader(dataset_big_random, num_workers=1):
pass
collate_fn은 map-style 데이터셋에서 sample list를 batch 단위로 바꾸기 위해 필요하다. 보통은 데이터 사이즈를 맞추기 위해 사용한다. Dataset의 getitem이 매번 다른 길이의 텐서를 return 하는 경우 batch_size를 2 이상으로 주기 위해서는 collate_fn 함수를 써서 넣어주어야 한다.
def make_batch(samples):
inputs = [sample['input'] for sample in samples]
labels = [sample['label'] for sample in samples]
padded_inputs = torch.nn.utils.rnn.pad_sequence(inputs, batch_first=True)
return {'input': padded_inputs.contiguous(),
'label': torch.stack(labels).contiguous()}
dataloader의 예시
dataloader_train_MNIST = DataLoader(dataset=dataset_train_MyMNIST,
batch_size=16,
shuffle=True,
num_workers=4,
)
images, labels = next(iter(dataloader_train_MNIST))
transform.Resize((200,200))(image) : 이미지의 크기를 200x200 으로 조정한다.
transform.RandomCrop((100,100))(image) : 이미지를 임의의 위치에서 100x100의 크기로 자른다.
transform.RandomRoatatation(30)(image) : 이미지를 임의의 각도(30) 만큼 회전시킨다.
transform.ToTensor()(image) : 이미지를 Tensor 데이터로 변경한다.
transform.Compose([함수들]) : compose를 통해 여러 함수들을 묶어서 한번에 처리할 수 있다.
전반적인 Dataset과 DataLoader의 구조는 다음과 같이 정리할 수 있다.
Dataset
class CustomDataset(Dataset):
def __init__(self,):
'''
데이터의 위치나 파일명과 같은 초기화 작업을 위해 동작
'''
pass
def __len__(self):
'''
Dataset의 최대 요소 수를 반환하는데 사용
'''
pass
def __getitem__(self, idx):
'''
데이터셋의 idx번째 데이터를 반환하는데 사용
'''
pass
dataset_custom = CustomDataset()
DataLoader
DataLoader(dataset, # Dataset 인스턴스가 들어감
batch_size=1, # 배치 사이즈를 설정
shuffle=False, # 데이터를 섞어서 사용하겠는지를 설정
sampler=None, # sampler는 index를 컨트롤
batch_sampler=None, # 위와 비슷하므로 생략
num_workers=0, # 데이터를 불러올때 사용하는 서브 프로세스 개수
collate_fn=None, # map-style 데이터셋에서 sample list를 batch 단위로 바꾸기 위해 필요한 기능
pin_memory=False, # Tensor를 CUDA 고정 메모리에 할당
drop_last=False, # 마지막 batch를 사용 여부
timeout=0, # data를 불러오는데 제한시간
worker_init_fn=None # 어떤 worker를 불러올 것인가를 리스트로 전달
)
dataloader_custom = DataLoader(dataset_custom)