Data Loader(1)

pppanghyun·2022년 7월 12일
0

Pytorch 기본

목록 보기
3/21

1. 데이터 불러오기

머신러닝이든 딥러닝이든 가장 핵심은 데이터.
데이터의 수집, 가공, 사용 방법에 따라 모델 성능이 크게 달라지기 때문에 데이터를 분석에 사용하기 위해 불러오는 일련의 과정이 매우 중요함.

(주피터나 colab으로 코딩하다가 코드를 모듈화해서 python사용할때 가장 난해한 부분이었음, benchmark dataset이나 이쁜 데이터가 아닌 경우 특히..)

import torch # 파이토치 기본 라이브러리 
import torchvision # 이미지 관련 된 파이토치 라이브러리
import torchvision.transforms as tr # 이미지 전처리 기능들을 제공하는 라이브러리
from torch.utils.data import DataLoader, Dataset # 데이터를 모델에 사용할 수 있도록 정리해 주는 라이브러리
import numpy as np # 넘파이 기본 라이브러리

2. torchvision.transforms(tr)라이브러리를 통한 전처리 기법

transf = tr.Compose([tr.Resize(16),tr.ToTensor()]) # Compose는 차례대로 연산하는 방법

# 아래와 같은 기법이 있음
# Transforms on PIL Image
# Pad, Grayscale, RandomCrop, Normalize ..
# Transforms on torch.*Tensor - tensor image
# torchvision.transforms.ToPILImage(mode=None)...

파이토치에서 제공하는 이쁘게 정렬된 데이터 다운

3. Dataset (trainset/testset) 만들기

# torchvision.datasets에서 제공하는 CIFAR10 데이터
# root에는 다운로드 받을 경로를 입력
# train=Ture이면 학습 데이터 train=False이면 테스트 데이터
# 미리 선언한 전처리를 사용하기 위해 transform=transf을 작성
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transf) #위에 전처리
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transf)

# 일반적으로 데이터셋은 이미지와 라벨이 동시에 들어가 있는 튜플 형태 (이미지, 라벨)
# trainset[0]은 학습 데이터의 첫 번째 데이터로 <이미지 한 장과 라벨 숫자 하나>
# 즉, trainset[0][0]은 이미지이며 trainset[0][1]은 라벨.

print(trainset[0][0].size() 

#result
torch.Size([3, 16, 16]) # 이미지 사이즈 3x16x16 

# 일반적인 원본 이미지(RGB): 너비 x 높이 x 채널(3) = W x H x C 
# 파이토치: 채널(3) x 너비 x 높이 = C x W x H

4. DataLoader는 데이터를 미니배치 형태로 만들어 줌! (배치사이즈, 셔플 여부 등을 선택할 수 있음)

위에서 만든 Dataset(trainset/testset 넣어주면 됨)


trainloader = DataLoader(trainset, batch_size=50, shuffle=True)
testloader = DataLoader(testset, batch_size=50, shuffle=False)

len(trainloader)
# CIFAR10의 학습 이미지는 50,000장이고 배치 사이즈가 50장이므로 1,000은 배치의 개수

#result
1000 # 즉 trainloader가 잘 만들어졌다는 것을 확인 가능

# iter, next를 이용해 일부 데이터를 확인할 수 있음 (배치 넘기는 함수)
dataiter = iter(trainloader)
images, labels = dataiter.next()

# 일반적으로 학습 데이터는 4차원 형태로 모델에서 사용
# (배치 크기)x(채널 수)x(너비)x(높이) = (B, C, W, H)
print(images.size())

5. 데이터가 이쁘게 정렬된 경우 (같은 클래스 별로 폴더가 정리된 경우)

# 데이터가 같은 클래스 별로 미리 폴더를 정리 된 경우, ImageFolder의 1줄 선언으로 개인 데이터를 사용할 수 있음.
# 별도의 라벨링이 필요 없으며 폴더 별로 자동으로 라벨링을 한다.
# 예를 들어 class 폴더에 tiger, lion 폴더(./class/tiger와 ./class/lion)를 미리 만든다.
# 다음으로 ImageFolder에 상위 폴더 ./class를 입력하면 이미지와 라벨이 정리 되어 데이터를 불러온다.

transf = tr.Compose([tr.Resize((128, 128)),tr.ToTensor()]) # 128x128 이미지 크기 변환 후 텐서로 변환
trainset = torchvision.datasets.ImageFolder(root='./class', transform=transf) # 커스텀 데이터 불러온다 (with Transform)
trainloader = DataLoader(trainset, batch_size=2, shuffle=False) # 데이터를 미니 배치 형태로 만들어 준다.

dataiter = iter(trainloader)
images, labels = dataiter.next()

print(images.size(), labels)

#result
torch.Size([2, 3, 128, 128]) tensor([0, 1])

6. 정형화되지 않은 커스템 데이터 불러오는 방법

# 32x32 컬러 이미지와 라벨이 각각 100장이 있다고 가정

train_images = np.random.randint(256,size=(100,32,32,3)) # (이미지 수)x(너비)x(높이)x(채널 수)
train_labels = np.random.randint(2,size=(100,1)) # 라벨 수

print(train_images.shape, train_labels.shape)

#result
(100, 32, 32, 3) (100, 1)

# 이미지 전처리 작업이 필요할 경우 openCV와 같은 라이브러리를 이용하여 이 곳에서 작업할 수도 있음.
# 이 단계에서 전처리하는 것이 좋음. 그 이유는 torchvision.transforms 라이브러리 보다 OpenCV, SciPy와 같은 라이브러리가 더 많은 전처리 기술을 제공
# 또한 이미지를 미리 처리해 놓고 전처리 된 이미지를 살펴보면서 작업하기 용이

중요!! (아래 양식을 통으로 들고 다니자)

from torch.utils.data import Dataset

class MyDataset(Dataset):
    
    def __init__(self):
    
    def __getitem__(self, index):
    
    def __len__(self):

예시)

class TensorData(Dataset): # pytorch의 Dataset을 상속! 즉 Dataset의 기능을 TensorData에 상속!

    def __init__(self, x_data, y_data): # 처음에 필요한 기본값
        self.x_data = torch.FloatTensor(x_data) # 이미지 데이터를 FloatTensor로 변형
        self.x_data = self.x_data.permute(0,3,1,2) 
        # (이미지 수)x(너비)x(높이)x(채널) -> (배치 크기)x(채널)x(너비)x(높이) torch는 무조건 (B * C * W * H)
        
        self.y_data = torch.LongTensor(y_data) # 라벨 데이터를 LongTensor로 변형
        self.len = self.y_data.shape[0] # 클래스 내의 들어 온 데이터 개수 

    def __getitem__(self, index): # 실제 나가는 데이터
        return self.x_data[index], self.y_data[index] # 뽑아 낼 데이터를 적어줌

    def __len__(self): # 길이 반환
        return self.len # 클래스 내의 들어 온 데이터 개수 
        
# 중요
# 파이토치에서는 (배치 크기)x(채널 수)x(너비)x(높이) 데이터가 사용 
# 따라서  원래 데이터 (이미지 수)x(너비)x(높이)x(채널 수)를 변경해야만 함
# permute에서 0(이미지 수), 1(너비),2 (높이), 3(채널 수)을 
# 0(이미지 수), 3(채널 수), 1(너비),2 (높이)로 바꿔주는 것!
# permute(0,3,1,2)을 사용하는 것이다.

train_data = TensorData(train_images,train_labels) # 텐서 데이터 불러오기 
train_loader = DataLoader(train_data, batch_size=10, shuffle=True) # 미니 배치 형태로 데이터 갖추기

참고하면 좋은 자료

  1. Pytorch 공식 문서
    https://tutorials.pytorch.kr/beginner/basics/data_tutorial.html
  2. PyTorch로 시작하는 딥 러닝 입문
    https://wikidocs.net/57165
profile
pppanghyun

0개의 댓글