PyTorch Tutorial 00.

‎yeon·2023년 1월 20일
0
post-thumbnail

참고 자료 :https://pytorch.org/tutorials/beginner/basics/intro.html

Deep Learning이란?
인공 신경망(Artificial Neural Networks)의 한 종류인 심층 신경망(Deep Neural Networks)을 학습시켜 문제를 해결하는 것.

Deep Neural Networks를 학습시킬 수 있게 된 원인

1) 수학적 테크닉이 가미되어 깊은 신경망 학습이 가능해짐.
2) 심층 신경망을 학습시킬 수 있는 충분히 많은 데이터를 확보할 수 있게됨.
3) GPU의 발달로 병렬 연산 방법이 대중화 되어 신경망 학습 속도가 크게 증가함.

1. Tensor

🦄Tensor : Pytorch에서 model 입출력에 사용함. Array/Matrix와 매우 유사한 자료구조. Numpy의 ndarray와 동일한 underlying memory 공유 가능함. GPU와 같은 hardware accelerator에서 실행할 수 있고 automatic differentiation에 최적화 되어있음.

import torch
import numpy as np

Initializing a Tensor

1️⃣Directly from data

data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)

2️⃣From a Numpy array

arr = np.array(data)
x_np = torch.from_numpy(arr)

3️⃣With random or constant values
shape is a tuple of tensor dimenisons.

shape = (2, 3)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

4️⃣ From another tensor

x_ones = torch.ones_like(x_data)   #retain the properties of x_data
x_rand = torch.rand_like(x_data, dtype = troch.float)  #overrides the dtype of x_data

The new tensor retains the properties (ex. shape, dtype) of the argument tensor, unless explicitly overridden.

Attributes of a Tensor

1️⃣ shape
2️⃣ data type (dtype)
3️⃣ device on which tensor is stored.

Operations on Tensors

Bridge with NumPy

CPU 상의 Tensor와 ndarray는 메모리 공간을 공유하므로 하나를 변경하면 나머지도 변경됨. (변경사항이 반영됨)

2. Datasets & DataLoaders

from torch.utils.data import Dataset, DataLoader

💗Dataset이란?

  • Pytorch에서 지원하는 기능으로 dataset과 dataloader 이용하여 minibatch learning, data shuffle 등 간단히 수행가능.
  • input features(x), label(y)를 input tensor로 입력
  • init, len, getitem method 반드시 포함해야함.

__init__(self) : Dataset 객체가 생성 될 때, 한번만 실행됨.
__len__(self) : Dataset의 samples 개수 return
__getitem__(self, idx): 해당 idx의 data return

💗DataLoader란?

  • DataLoader library 활용하여 생성된 data를 batch 형태로 만들어줌.
  • 실제로 학습할 때 이용할 수 있는 data 형태 만들어주는 library.
DataLoader(dataset, batchsize = 20, 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)

🦄 Need for Custom Dataset/DataLoader : 많은 양의 데이터를 한 번에 전체를 불러오면 시간이 오래 걸릴 뿐만 아니라 RAM memory 상의 문제가 발생함. 이를 방지하기 위해 모든 데이터를 한 번에 불러와 사용하는 기존의 dataset 대신에 custom dataset을 만들어야 함.

DataSet : sample들과 sample의 label을 저장함.
DataLoader: sample에 쉽게 접근할 수 있도록 순회가능한 객체로 감쌈.

Loading a Dataset

parameters
root : train/test data 저장된 경로
train : training dataset인지 test dataset인지 지정
download=True : root에 data 없는 경우, 인터넷에서 download
transform, target_transform : feature와 label transform 지정

import torch
from torch.utils.data  import Dataset
from torchvision import datasets
from forchvision.transform 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()
)

Iterating and Visualizing the Dataset

Dataset은 list와 마찬가지로 idx 이용하여 접근 가능.

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 = plt.figure(figsize = (8, 8))
cols, rows = 3, 3
for i in range(1, col * rows + 1):
	sample_idx = torch.randint(len(training_data), size = (1, ).item())
    img, label = training_data[sampl_idx]
    figure.add_subplot(rows, cols, i)
    plt.title(lables_map[label])
    plt.axis("off")
 plt.show()

Creating a Custom Dataset for your files

사용자 정의 Datset Class는 반드시 3개의 함수 구현해야함

__init__, __len__, and __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_transtorm = Non):
    	self.img_labels = pd.read_csv(annotations_file, names = ['file_namme', 'label']
    	self.img_dir = img_dir
    	self.transform = transfor
    	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[idxm 0])
        image = read_image(img_path)
        label = self.img_labels.iloc[idx, 1]
        if self.transform:
        	image = self.target_transform:
        if self.target_transform:
        	label = self.target_transform(label)
        return image, label
        

Preparing your data for training with DataLoaders

Dataset은 data의 feature을 가져오고 label을 지정하는 일을 한 번에 수행함.

from torch.utils.data import DataLoader

train_dataloader = DataLoader(training_data, batch_size = 64, shuffle = True)
test_dataloader = DataLoader(test_data, batch_size = 64, shuffl = True)
# samples를 minibatch로 전달하고 epoch 마다 data shuffle 적용하여 overfitting 막음.

## 간단한 예시 ##

# import
import torch
from torch.utils.data import DataLoader, Dataset
import numpyt as np

# 사용할 data 불러오기
train_imgs = np.random.randint(256, size = (20, 32, 32, 3))  # 임의 data 생성(가짜 img)
train_labels = np.random.randint(2, size = (20, 1))

# Custom Dataset 만들어주기
class TensorData(Dataset):
	def __init__(self, x_data, y_data):
    	self.x_data = torch.FloatTensor(x_data)  # tensor 형태로 변환
    	self.x_data = self.x_data.permute(0, 3, 1, 2) # idx 순서 변환 (0, 1, 2, 3)->(0, 3, 1, 2)
    	self.y_data = torch.LongTensor(y_data)
    	self.len = self.y_data.shape[0]
    def __getitem__(self, idx):
    	return self.x_data[idx], self.y_data[idx]
      
    def __len__(self):
    	return self.len
 
# data 생성 및 batch 전환
train_data = TensorData(train_imgs, train_labels)   # data instance 생성
train_loader = DataLoader(train_data, batch_size = 10, shuffle = True)

3. Transform

Transform 하여 학습에 적합한 형태로 data 조작.

(FashionMNIST: features-PIL image format/ label - integer, 학습을 위해서는 normalized feature와 one-hot encoding된 tensor 형태의 label이 필요함. 이러한 transform 하기 위해 ToTensorLambda 사용함.)

import torch
from torchvision import datasets
from torchvision.transfoms import ToTensor, Lamda

ds = datasets.FashionMNIST(
	root = "data",
    trian = True,
    download = True,
    transform = ToTensor().
    target_transform = Lamda(lamda y : torch.zeros(10, dtype = torch.float).scatter_(0, torch.tensor(y), value = 1)

ToTensor() : PIL Image나 ndarray를 FloatTensor로 변환하고 img'ㄴ pixel intensity value를 [0., 1.] 범위로 scaling.
Lambda Transform : intiger 행태의 label을 one-hot encoding된 tensor로 바꾸는 함수 정의. zero tensor 만든 후 scatter_ 호출하여 주어진 label(y)에 해당하는 idx에 value = 1을 할당함.

4. Build The Neural Network

Import

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, trasnforms

Get Device for Training

device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

Define the Class

layers
nn.Flatten : Tensor img를 1차원 array로 변경. ex) 28*28의 img를 784개의 픽셀 값을 가지는 연속된 배열로 변환

input_image = torch.rand(3,28,28)
print(input_image.size())

flatten = nn.Flatten()
flat_img = flatten(input_img)
print(flat_img.size())

Out:

torch.Size([3, 28, 28])
torch.Size([3, 784])

nn.Linear : weight와 bias 사용하여 input에 linear regression 적용하는 module.

layer1 = nn.Linear(in_features = 28*28, out_features = 20)
hidden1 = layer1(flat_img)
print(hidden1.size())

Out:

torch.Size([3, 20])

nn.ReLU : Relu, Activation Function.
nn.Sequential

seq_modules = nn.Sequential(
    flatten,
    layer1,
    nn.ReLU(),
    nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)

nn.Softmax : 각 Class에 대한 prediction을 probability로 나타내는 함수로 [0, 1] 범위에 있음.

softmax = nn.Softmax(dim=1)    
pred_probab = softmax(logits)

Define the Class

class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

5. Automatic Differentiation with torch.autograd

torch.autograd 이용하면 back propagation 과정에서 loss function의 gradient 계산하여 parameter를 update할 수 있음.

0개의 댓글