참고 자료 :https://pytorch.org/tutorials/beginner/basics/intro.html
Deep Learning이란?
인공 신경망(Artificial Neural Networks)의 한 종류인 심층 신경망(Deep Neural Networks)을 학습시켜 문제를 해결하는 것.
1) 수학적 테크닉이 가미되어 깊은 신경망 학습이 가능해짐.
2) 심층 신경망을 학습시킬 수 있는 충분히 많은 데이터를 확보할 수 있게됨.
3) GPU의 발달로 병렬 연산 방법이 대중화 되어 신경망 학습 속도가 크게 증가함.
🦄Tensor
: Pytorch에서 model 입출력에 사용함. Array/Matrix와 매우 유사한 자료구조. Numpy의 ndarray와 동일한 underlying memory 공유 가능함. GPU와 같은 hardware accelerator에서 실행할 수 있고 automatic differentiation에 최적화 되어있음.
import torch
import numpy as np
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.
1️⃣ shape
2️⃣ data type
(dtype)
3️⃣ device
on which tensor is stored.
CPU 상의 Tensor와 ndarray는 메모리 공간을 공유하므로 하나를 변경하면 나머지도 변경됨. (변경사항이 반영됨)
💗Dataset이란?
__init__(self)
: Dataset 객체가 생성 될 때, 한번만 실행됨.
__len__(self)
: Dataset의 samples 개수 return
__getitem__(self, idx)
: 해당 idx의 data return
💗DataLoader란?
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에 쉽게 접근할 수 있도록 순회가능한 객체로 감쌈.
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()
)
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()
사용자 정의 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
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)
Transform 하여 학습에 적합한 형태로 data 조작.
(FashionMNIST: features-PIL image format/ label - integer, 학습을 위해서는 normalized feature와 one-hot encoding된 tensor 형태의 label이 필요함. 이러한 transform 하기 위해 ToTensor
와 Lambda
사용함.)
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을 할당함.
import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, trasnforms
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")
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
torch.autograd
torch.autograd
이용하면 back propagation 과정에서 loss function의 gradient 계산하여 parameter를 update할 수 있음.