데이터 샘플을 처리하는 코드는 지저분 하고 유지보수가 어려울 수 있습니다. 그렇기에 데이터셋 코드를 모델 학습 코드로부터 분리하는 것이 좋습니다.
->더 나은 가독성과 모듈성을 위해서입니다.
Pytorch는 torch.utils.data.DataLoader 와 torch.utils.data.Dataset 두 가지 데이터 기본 요소를 제공하여 미리 준비해둔 데이터셋 뿐만 아니라 가지고 있는 데이터를 사용할 수 있도록 합니다.
-Dataset은 샘플과 정답(label)을 저장하고
-DataLoader는 Dataset을 샘플에 쉽게 접근할 수 있도록 순회 가능한 객체(iterable)로 감쌈
Pytorch의 도메인 특화 라이브러리들은 미리 준비해둔 다양한 데이터셋을 제공합니다.
-torch.utils.data.Dataset의 하위 클래스로 개별 데이터를 특정하는 함수가 구현되어 있음
-데이터셋은 모델을 만들어보고 성능을 측정하는데 사용할 수 있음
-제공 되는 데이터 셋 이미지 데이터셋 , 텍스트 데이터셋 , 오디오 데이터셋 이 링크에서 데이터셋 확인 가능
root
는 학습/테스트 데이터가 저장되는 경로입니다.train
은 학습용 또는 테스트용 데이터셋 여부를 지정합니다.download = True
는 root
에 데이터가 없는 경우 인터넷에서 다운로드합니다.transform
과 target_transform
은 feature과 label, transform을 지정합니다.import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor()
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
from torch.utils.data import Dataset
는 Dataset을 다루기 위한 기본 클래스from torchvision import datasets
이부분은 torchivision에서 제공되는 기본 데이터셋from torchvision.transforms import ToTensor
사용되는 데이터들을 Tensor형태로 바꾸기 위해 import합니다.import matplotlib.pyplot as plt
는 데이터를 시각화하기 위해 사용됩니다.root
이곳은 학습 데이터가 저장되는 곳입니다.train
훈련 여부입니다.download
데이터가 저장되어 있지 않다면 다운로드 합니다.transform=ToTensor()
사용할 데이터의 형식을 Tensor로 변경해줍니다.-결과
labels_map = {
0: "T-Shirt",
1: "Trouser",
2: "Pullover",
3: "Dress",
4: "Coat",
5: "Sandal",
6: "Shirt",
7: "Sneaker",
8: "Bag",
9: "Ankle Boot",
}
figure_1 = plt.figure(figsize=(8, 8))
#사진 하나 만들 때 사이즈를 초기화
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
sample_idx = torch.randint(len(training_data), size=(1,)).item()
img, label = training_data[sample_idx]
figure_1.add_subplot(rows, cols, i)
plt.title(labels_map[label])
plt.axis("off")
#x축 y축 표시 끄기
plt.imshow(img.squeeze(), cmap="gray")
plt.show()
label_map
은 정답이 쓰여져 있는 주소 정도로 보면 될 것 같습니다. figure_1 = plt.figure(figsize=(8, 8))
label과 img를 모두 표현하기 위해 8x8 크기의 사진으로 사이즈를 초기화합니다. img가 모두 여기 안에 들어가게 됩니다.sample_idx = torch.randint(len(training_data), size=(1,)).item()
여기에서 training_data
의 길이는 6만입니다. item을 이용하여 하나의 값을 뽑아옵니다.figure_1.add_subplot(rows,cols,i)
figure_1의 gird(격자)위에 이미지를 하나씩 올려두게 됩니다.plt.title
이부분에선 정답(label)을 나타냅니다.plt.axis("off")
이 부분에서는 x축과 y축이 나타나지 않게 합니다.plt.imshow(img.squeeze(), cmap = "gray")
여기서 squeeze는 차원을 줄이는 역할을합니다. import os
import pandas as pd
from torchvision.io import read_image
class CustomImageDataset(Dataset):
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
#자기자신, 정답, 패션의 이미지,
self.img_labels = pd.read_csv(annotations_file, names=['file_name', 'label'])
#names는 헤더(테이블 이름)가 없는 파일을 가져올 때 임의로 이름을 정해줌
self.img_dir = img_dir
#사용할 데이터의 디렉토리
self.transform = transform
self.target_transform = target_transform
def __len__(self):
return len(self.img_labels)
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
#iloc : 데이터 프레임의 행이나 칼럼의 순서를 나타내는 정수로 특정 값을 추출해오는 방법
image = read_image(img_path)
label = self.img_labels.iloc[idx, 1]
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
return image, label
-init
함수는 Dataset 객체가 생성될 때 한번만 실행됩니다. 여기서는 이미지와 주석 파일(annotation_file)이 포함된 디렉토리와 두가지 변형을 초기화합니다.
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
self.img_labels = pd.read_csv(annotations_file)
self.img_dir = img_dir
self.transform = transform
self.target_transform = target_transform
-len
함수는 데이터셋의 샘플 개수를 반환합니다.
def __len__(self):
return len(self.img_labels)
idx
에 해당하는 샘플을 데이터셋에서 불러오고 반환합니다.read_image
를 사용하여 이미지를 텐서로 변환하고self.img_labels
의 csv 데이터로부터 해당하는 정답(label)을 가져오고def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
image = read_image(img_path)
label = self.img_labels.iloc[idx, 1]
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
sample = {"image": image, "label": label}
return sample
Dataset
은 데이터셋의 특징을 가져오고 하나의 샘플에 정답(label)을 지정하는 일을 한 번에 합니다.multiprocessing
을 사용하여 데이터 검색 속도를 높이려함DataLoader
는 간단한 API로 이러한 복잡한 과정들을 추상화한 순회 가능한 객체입니다from torch.utils.data import DataLoader
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
DataLoader
에 데이터셋을 불러온 뒤에는 필요에 따라 데이터셋을 순회할 수 있습니다.train_features
와 train_labels
의 묶음을 반환합니다.shuffle = True
로 지정했으므로, 모든 배치를 순회한 뒤 데이터가 섞입니다.# 이미지와 정답(label)을 표시합니다.
train_features, train_labels = next(iter(train_dataloader))
#next, Iter https://dojang.io/mod/page/view.php?id=2408 확인
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
img = train_features[0].squeeze()
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {label}")