Pytorch 공식 문서와 함께하는 Pytorch 튜토리얼_2(Dataset과 DataLoader)

bellfollow·2023년 8월 19일
0

Pytorch_tutorial

목록 보기
3/7
post-thumbnail

모든 내용은 파이토치 공식 문서의 Google Colab 공부 문서를 이용해 공부했습니다.

Dataset과 DataLoader

  • 데이터 샘플을 처리하는 코드는 지저분 하고 유지보수가 어려울 수 있습니다. 그렇기에 데이터셋 코드를 모델 학습 코드로부터 분리하는 것이 좋습니다.
    ->더 나은 가독성과 모듈성을 위해서입니다.

  • Pytorch는 torch.utils.data.DataLoader 와 torch.utils.data.Dataset 두 가지 데이터 기본 요소를 제공하여 미리 준비해둔 데이터셋 뿐만 아니라 가지고 있는 데이터를 사용할 수 있도록 합니다.
    -Dataset은 샘플과 정답(label)을 저장하고
    -DataLoader는 Dataset을 샘플에 쉽게 접근할 수 있도록 순회 가능한 객체(iterable)로 감쌈

  • Pytorch의 도메인 특화 라이브러리들은 미리 준비해둔 다양한 데이터셋을 제공합니다.
    -torch.utils.data.Dataset의 하위 클래스로 개별 데이터를 특정하는 함수가 구현되어 있음
    -데이터셋은 모델을 만들어보고 성능을 측정하는데 사용할 수 있음
    -제공 되는 데이터 셋 이미지 데이터셋 , 텍스트 데이터셋 , 오디오 데이터셋 이 링크에서 데이터셋 확인 가능

데이터셋 불러오기

  • TorchVIsivion에서 Fashion_MNIST 데이터셋을 불러오는 예제
  • Fashion-MNIST는 Zalando의 기사 이미지 데이터셋으로 6만개의 학습 예제와 1만개의 테스트 예제로 이루어져 있습니다.
    - 각 예제는 grayscale의 28X28 이미지와 10개의 분류 중 하나인 정답(label)으로 구성됩니다.
  • 아래 매개변수들을 사용해 FashionMNIST 데이터셋을 불러옵니다.
    -root는 학습/테스트 데이터가 저장되는 경로입니다.
    -train은 학습용 또는 테스트용 데이터셋 여부를 지정합니다.
    -download = Trueroot에 데이터가 없는 경우 인터넷에서 다운로드합니다.
    -transformtarget_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()
)
  • import 부분부터 살펴보면
    -from torch.utils.data import Dataset 는 Dataset을 다루기 위한 기본 클래스
    -from torchvision import datasets 이부분은 torchivision에서 제공되는 기본 데이터셋
    -from torchvision.transforms import ToTensor 사용되는 데이터들을 Tensor형태로 바꾸기 위해 import합니다.
    -import matplotlib.pyplot as plt 는 데이터를 시각화하기 위해 사용됩니다.
  • training_data 부분
    -root 이곳은 학습 데이터가 저장되는 곳입니다.
    -train 훈련 여부입니다.
    -download 데이터가 저장되어 있지 않다면 다운로드 합니다.
    -transform=ToTensor() 사용할 데이터의 형식을 Tensor로 변경해줍니다.
  • test_data
    - 위부분은 train부분을 제외하면 training_data와 차이가 없습니다.

-결과

  • 경로의 시작점에 모두 data가 들어가는 것을 볼 수 있습니다.
  • 오른쪽 폴더 모양을 클릭해보면 data 폴더가 생긴 것을 확인하고 그 안에 FashionMNIST가 생긴것을 확인할 수 있습니다.

데이터셋을 순회하고 시각화하기

  • Dataset에 list처럼 index에 접근할 수 있습니다
    -training_data[index], matplotlib을 사용하여 학습 데이터의 일부를 시각화 할 수 있음
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는 차원을 줄이는 역할을합니다.
  • 결과

파일에서 사용자 정의 데이터셋 만들기

  • 사용자 Dataset 클래스는 반드시 3개의 함수를 구현해야 합니다.
    -init , len, getitem
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

-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

-len 함수는 데이터셋의 샘플 개수를 반환합니다.

def __len__(self):
    return len(self.img_labels)

getitem

  • 주어지 인덱스 idx에 해당하는 샘플을 데이터셋에서 불러오고 반환합니다.
    -인덱스를 기반으로
    -디스크에서 이미지의 위치를 식별하고
    -read_image를 사용하여 이미지를 텐서로 변환하고
    -self.img_labels의 csv 데이터로부터 해당하는 정답(label)을 가져오고
    -변형 함수들을 호출한뒤
    -텐서 이미지와 라벨을 Python 사전형으로 반환합니다.
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

DataLoader로 학습용 데이터 준비하기

  • Dataset은 데이터셋의 특징을 가져오고 하나의 샘플에 정답(label)을 지정하는 일을 한 번에 합니다.
  • 모델을 학습할 때
    -일반적으로 샘플들을 'minibatch'(미니배치)로 전달하고
    -매 'epoch'(에폭)마다 데이터를 다시 섞어서 과적합(overfit)을 막고
    -Python의 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를 통해 순회하기(iterable)

  • DataLoader에 데이터셋을 불러온 뒤에는 필요에 따라 데이터셋을 순회할 수 있습니다.
  • 아래의 각 순회는 train_featurestrain_labels의 묶음을 반환합니다.
    -각각 batch_size = 64의 feature와 label을 포함
  • shuffle = True로 지정했으므로, 모든 배치를 순회한 뒤 데이터가 섞입니다.
    -데이터 불러오기 순서를 보다 세밀하게 제어하려면 [samplers] 를 살펴보면 된다.(https://pytorch.org/docs/stable/data.html#data-loading-order-and-sampler)
# 이미지와 정답(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}")
  • 결과
profile
코딩 함 맛있게 요리해보겠심더

0개의 댓글