Dataset
Dataset 관련 모듈 알아보기
PyTorch에서 데이터를 다루기 위한 몇 가지 모듈을 알아보겠습니다.
- torch.utils.data: 데이터셋의 표준을 정의하고 데이터셋을 불러오고 자르고 섞는데 쓰는 도구들이 들어있는 모듈입니다. 파이토치 모델을 학습시키기 위한 데이터셋의 표준을 torch.utils.data.Dataset에 정의합니다. Dataset 모듈을 상속하는 파생 클래스는 학습에 필요한 데이터를 로딩해주는 torch.utils.data.DataLoader 인스턴스의 입력으로 사용할 수 있습니다.
- torchvision.dataset: torch.utils.data.Dataset을 상속하는 이미지 데이터셋의 모음입니다. MNIST나 CIFAR-10과 같은 데이터셋을 제공해줍니다.
- torchtext.dataset: torch.utils.data.Dataset을 상속하는 텍스트 데이터셋의 모음입니다. 기본적으로 IMDb나 AG_NEWS와 같은 데이터셋을 제공해줍니다.
- torchvision.transforms: 이미지 데이터셋에 쓸 수 있는 여러 가지 변환 필터를 담고 있는 모듈입니다. 예를 들어 Tensor로 변환한다던지, 크기 조절(Resize)과 잘라내기(Crop)으로 이미지를 수정할 수 있고 밝기(Brightness)와 같은 값을 조절하는데 사용될 수 있습니다.
- torchvision.utils: 이미지 데이터를 저장하고 시각화하기 위한 도구가 들어있는 모듈입니다.
PyTorch에서 제공하는 Dataset의 종류
- Map-style Dataset: 데이터를 인덱스로 접근 가능한 데이터셋
- 각 데이터를 인덱스로 접근할 수 있으며, __len__과 __getitem__ 메소드를 구현하여 데이터셋을 정의할 수 있습니다.
- torch.utils.data.Dataset을 상속받아 구현합니다.
- 대표적인 예시: torchvision.datasets.ImageFolder, torchvision.datasets.CIFAR10
- Iterable-style Dataset: 데이터를 순차적으로 접근 가능한 데이터셋
- 데이터셋을 순차적으로 접근하여 반환하는 __iter__ 메소드를 구현하여 데이터셋을 정의할 수 있습니다.
- torch.utils.data.IterableDataset을 상속받아 구현합니다.
- 대표적인 예시: 없음 (사용자 정의 데이터셋 구현 시 활용 가능)
일단 Map-Style Dataset을 기준으로 공부를 해보자.
map-style dataset을 사용하려면, 다음과 같은 메서드를 구현해야 합니다.
- __init__: 데이터의 위치나 파일명과 같은 초기화 작업을 위해 동작, csv 파일이나 xml같은 파일을 이 때 불러온다. 이것을 통해 모든 데이터를 메모리에 로드하지 않아도 된다. 또 transforms를 Compose해서 정의해둔다.
- __getitem__(self, index): 주어진 인덱스에 해당하는 데이터를 반환합니다.
- __len__(self): 데이터셋의 크기를 반환합니다.
DataLoader
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=shuffle, num_workers=num_workers)
DataLoader 클래스를 생성할 때 다양한 파라미터를 지정하여 로딩하는 데이터의 속성을 제어할 수 있습니다.
- dataset: 데이터셋 객체를 전달합니다. PyTorch의 Dataset 객체가 요구됩니다.
- batch_size: 로딩할 미니배치 데이터의 크기입니다. 기본값은 1입니다.
- shuffle: 데이터셋의 순서를 섞어줄지 여부입니다. 기본값은 False입니다.
- sampler: 데이터셋에서 데이터를 가져올 순서를 정의하는 Sampler 객체입니다. shuffle과 함께 사용될 수 있습니다.
- num_workers: 데이터를 로딩하는 데 사용될 프로세스 수입니다. 기본값은 0으로, 메인 프로세스에서 데이터를 로딩합니다. 멀티프로세싱을 사용하려면 이 값을 조정해야 합니다.
- collate_fn: 미니배치 데이터를 묶어주는 함수입니다. 기본값은 기본적으로 제공되는 함수를 사용하며, 사용자 정의 함수를 전달할 수도 있습니다.
- pin_memory: CUDA로 학습을 진행할 경우, 데이터를 CUDA로 복사하기 위해 메모리를 고정합니다. 기본값은 False입니다.
- drop_last: 마지막 미니배치 데이터가 batch_size보다 작을 경우 그 데이터를 무시할지 여부를 결정합니다. 기본값은 False입니다.
sampler/batch_size
map_style에서 컨트롤을 위해서는 __len__과 __iter__를 구현해줘야 한다. \
미리 선언된 sampler의 목록
불균형 데이터셋의 경우, 클래스의 비율에 맞게 데이터를 제공해야할 필요가 있고 이럴 때 sampler를 사용한다.
- SequentialSampler: 데이터셋의 인덱스를 순차적으로 반환하는 Sampler입니다. 기본값으로 사용됩니다.
- RandomSampler: 데이터셋에서 무작위로 인덱스를 샘플링하여 반환하는 Sampler입니다.
- SubsetRandomSampler: 데이터셋에서 지정된 인덱스의 서브셋에서 무작위로 샘플링하여 반환하는 Sampler입니다.
- WeightedRandomSampler: 가중치가 지정된 데이터셋에서 인덱스를 샘플링하여 반환하는 Sampler입니다.
- BatchSampler: 다른 Sampler를 사용하여 샘플링한 인덱스를 배치 단위로 반환하는 Sampler입니다.
- DistributedSampler: 분산 훈련을 위한 Sampler입니다. 분산 환경에서 각 프로세스가 고유한 데이터의 일부를 샘플링하여 반환합니다.
위 Sampler들은 torch.utils.data.sampler 모듈에서 가져올 수 있습니다.
from torch.utils.data import DataLoader
from torch.utils.data.sampler import SequentialSampler
data_loader = DataLoader(dataset, sampler=SequentialSampler(dataset))
참고 링크
https://towardsdatascience.com/pytorch-basics-sampling-samplers-2a0f29f0bf2a
PyTorch [Basics] — Sampling Samplers
This notebook takes you through an implementation of random_split, SubsetRandomSampler, and WeightedRandomSampler on image data.
towardsdatascience.com
참고) shuffle vs sampler
shuffle은 데이터의 순서를 무작위로 섞는 것이며, sampler는 데이터셋에서 데이터를 선택하는 방식을 결정합니다.
num_workers
무조건 많다고 좋은 것은 아닙니다. 많으면 gpu 와 cpu를 와리가리 많이 하면서 병목현상이 생길 수 있습니다.
collate_fn
collate_fn은 DataLoader에서 각 배치(batch)의 데이터를 어떻게 결합할 것인지를 정의하는 함수입니다. collate_fn은 기본적으로 Python의 기본 데이터 타입(list, tuple, dict)을 받아 텐서(Tensor)로 변환하는 기능을 수행합니다.
collate_fn을 직접 구현하는 경우, 일반적으로 배치(batch) 내의 각 샘플(sample)을 적절한 형태로 결합하는 방식을 정의합니다. 예를 들어, collate_fn이 리스트(list)를 입력으로 받고 이를 하나의 텐서로 변환하는 경우, 다음과 같이 코드를 작성할 수 있습니다:
import torch
def collate_fn(batch):
# batch: 리스트(list) 형태로 구성된 배치(batch)
data = [item[0] for item in batch] # 샘플(sample)의 데이터
target = [item[1] for item in batch] # 샘플(sample)의 레이블(label)
# 데이터와 레이블을 텐서(Tensor)로 변환하여 반환
return torch.tensor(data), torch.tensor(target)
위 예시에서는 리스트(list) 형태로 구성된 배치(batch)를 입력으로 받고, 각 샘플(sample)의 데이터와 레이블(label)을 나눠서 리스트(list)로 저장합니다. 그리고 이들을 PyTorch의 torch.tensor를 사용하여 텐서(Tensor)로 변환하여 반환합니다.
collate_fn을 사용하면 데이터셋의 크기가 일정하지 않은 경우에도 DataLoader에서 배치(batch)를 생성하는 데에 유용합니다. 예를 들어, 각 샘플(sample)의 길이가 다른 자연어 처리(natural language processing) 데이터셋의 경우, collate_fn을 사용하여 각 배치(batch)의 길이를 맞춰주는 등의 전처리(preprocessing)를 수행할 수 있습니다.
pin_memory
pin_memory는 DataLoader에서 사용하는 옵션 중 하나입니다. 이 옵션을 True로 설정하면 데이터를 CPU 메모리로 고정시킵니다. 이렇게 함으로써 GPU에서 데이터를 처리하는 동안 CPU에서 데이터를 읽어들이는 병목 현상을 줄일 수 있습니다.
GPU는 데이터를 읽어들이는 데 시간이 걸리기 때문에, GPU에서 데이터를 처리하는 동안 CPU가 데이터를 GPU로 전송해주어야 합니다. 이러한 전송 작업은 병목 현상을 일으키는 요인 중 하나입니다. 이 문제를 해결하기 위해 pin_memory 옵션을 사용하여 CPU에서 메모리를 고정시켜 CPU에서 GPU로 데이터를 직접 전송하면 GPU가 데이터를 읽어들이는 시간을 줄일 수 있습니다.
pin_memory 옵션을 사용하면 학습 시간을 단축시키고, 모델의 GPU 활용도를 향상시킬 수 있습니다. 그러나 pin_memory를 사용하면 GPU 메모리를 더 많이 사용하므로 시스템의 메모리 제한에 유의해야 합니다.
drop_last
마지막 남는 batch를 버려준다
time_out
dataloader가 data를 불러오는데 두는 제한시간이다.
worker_init_fn
num_workers를 설정한 경우 어떤 worker를 가져올 지 설정한다.
torchvision 의 transform 함수
데이터를 다루다보면 고정된 입력값이 아닌 데이터가 다수 존재 할 수있다. 예를 들어 이미지는 다양한 크기의 이미지가 존재한다. 이럴 경우 한 규격으로 통일해주어야 해서 사진 데이터를 변환시켜야 하는데 이럴 때 필요한 것이 torchvision 의 transforms 이다.
torchvision.transforms 모듈에서는 이미지 데이터를 전처리하는 다양한 함수들을 제공합니다. 대표적으로 많이 사용되는 함수들은 다음과 같습니다.
- transforms.ToTensor() : 이미지를 텐서로 변환합니다.
- transforms.Normalize(mean, std) : 정규화를 수행합니다. 입력 이미지의 평균과 표준편차를 이용하여 정규화합니다.
- transforms.Resize(size) : 이미지 크기를 조정합니다.
- transforms.CenterCrop(size) : 이미지의 중앙을 기준으로 이미지를 자릅니다.
- transforms.RandomCrop(size) : 이미지를 무작위로 자릅니다.
- transforms.RandomHorizontalFlip() : 이미지를 무작위로 좌우반전시킵니다.
- transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0) : 이미지의 밝기, 대조, 채도, 색상을 임의로 변경합니다.
- transforms.RandomRotation(): 이미지를 무작위로 회전시킵니다.
- transforms.RandomVerticalFlip(): 수평선을 기준으로 상하로 뒤짚음
- transforms.CenterCrop(): 중간 부분을 잘라냄.
참고!!!
torchvision에서 이미지 데이터를 다룰 때, 기본적으로 PIL (Python Imaging Library) 라이브러리의 이미지 객체로 다루게 됩니다. 이는 PIL 객체가 파이썬에서 이미지를 다루기에 유연하고 편리한 API를 제공하기 때문입니다.
tensor 나 numpy array 형태를 PIL 객체로 바꾸기 - ToPILImage()
ToPILImage() 함수는 torch.Tensor나 numpy.ndarray 형태의 이미지 데이터를 PIL 객체로 변환해주는 함수입니다. PIL 객체는 파이썬에서 이미지를 다루기 위한 라이브러리로, 유연한 API를 제공합니다.
ToPILImage() 함수는 다음과 같이 사용할 수 있습니다
from torchvision.transforms import ToPILImage
# tensor를 PIL 객체로 변환
tensor = torch.randn((3, 224, 224))
to_pil = ToPILImage()
pil_image = to_pil(tensor)
여러 transform 한번에 하기 - Compose
from torchvision import transforms
transform = transforms.Compose([
transforms.Resize((224,224)),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
그 외 torchvision 에서 제공하는 변환 라이브러리
- albumentations
- imgaug
- transformation에 의해 input값이 변하면 GT값도 변하는 경우가 있다. 객체인식의 경우 바운딩 박스가 존재하는데 이미지가 변환되게 되면 바운딩박스의 좌표도 같이 변환을 해줘야하는데 이럴 때 유용한 라이브러리이다.
torchvision 에서 제공하는 dataset
MNIST, CIFAR10
torchvision.datasets.MNIST()
torchvision.datasets.CIFAR10()
파라미터들
- root : 데이터셋이 저장될 경로입니다. 기본값은 ./data입니다.
- train : True로 설정하면 MNIST 학습 데이터셋을 가져옵니다. False로 설정하면 MNIST 테스트 데이터셋을 가져옵니다. 기본값은 True입니다.
- transform : 이미지 데이터에 적용할 전처리 함수입니다. 기본값은 None입니다.
- target_transform : 라벨 데이터에 적용할 전처리 함수입니다. 기본값은 None입니다.
- download : True로 설정하면 인터넷에서 MNIST 데이터셋을 다운로드합니다. 기본값은 False입니다.
torchtext에서 제공하는 dataset - AG_NEWS
tokenizer()
-> 소문자로 변환하여 문장을 token화 시켜 준다. 만약 i love hongik 이라는 문자가 들어가면 i, love, hongik으로 token 화 되어 반환되게 된다.
torchtext.vocab.vocab()
-> 문자를 인덱스와 연결시켜 준다. 약간 해시 느낌이랑 비슷 한 것 같다. 예를 들어 i love hongik이라는 문장이 들어가면 i, love , hongik 을 특정 숫자 34,234,123 이런 식으로 저장시켜주는 역할을 하는 것 같다. 반대로 index를 string으로 매칭시키는 것도 가능하다.
encode()
-> string 을 index 로 매칭시켜주는 함수이다. vocab.get_stoi() 함수를 이용한다.
decode()
-> index를 string으로 매칭시켜주는 함수이다. vocab.get_itos()함수를 이용한다.
to_bow()
-> bag of words의 약어. 위의 vocab등을 이용해 단어의 빈도수를 반환한다.
'AI > Pytorch' 카테고리의 다른 글
HyperParameter Tuning, Ray - tune 라이브러리 (0) | 2023.03.17 |
---|---|
Transfer learning (0) | 2023.03.17 |
nn.Module의 hook 과 apply (0) | 2023.03.17 |
모듈 분석,Docstring,repr (0) | 2023.03.16 |
Custom Model, Conatiner, Module (0) | 2023.03.16 |