โ ํ์ดํ ์น ๊ธฐ์ด
https://colab.research.google.com/drive/1ki4W3rwTExhmZp5E-Ic81ab2NMe8iRHB?usp=sharing
1๏ธโฃ ํ์ดํ ์น ๊ฐ์
๐น ํน์ง ๋ฐ ์ฅ์
โ ์ฐ์ฐ์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ → ๋ฅ๋ฌ๋ ํ๋ ์์ํฌ๋ก ๋ฐ์
โ GPU ์์ ํ ์ ์กฐ์ ๋ฐ ๋์ ์ ๊ฒฝ๋ง ๊ตฌ์ถ์ด ๊ฐ๋ฅํ ํ๋ ์์ํฌ
โ GPU : ์ฐ์ฐ์ ๋น ๋ฅด๊ฒ ํ๋ ์ญํ , ๋ด๋ถ์ ์ผ๋ก CUDA, cuDNN ๊ฐ์ API ๋ฅผ ํตํด ์ฐ์ฐ ๊ฐ๋ฅ
โ ํ ์ : ํ์ดํ ์น์ ๋ฐ์ดํฐ ํํ๋ก, ๋ค์ฐจ์ ํ๋ ฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ค. .cuda() ๋ฅผ ์ฌ์ฉํด GPU ์ฐ์ฐ์ ์ํํ ์ ์๊ฒ ํ ์ ์๋ค.
- axis 0 : ๋ฒกํฐ, 1์ฐจ์ ์ถ
- axis 1 : ํ๋ ฌ, 2์ฐจ์ ์ถ
- axis 2 : ํ ์, 3์ฐจ์ ์ถ
โ ๋์ ์ ๊ฒฝ๋ง : ํ๋ จํ ๋๋ง๋ค ๋คํธ์ํฌ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ (์๋์ธต ์ถ๊ฐ ๋ฐ ์ ๊ฑฐ) ์ ๊ฒฝ๋ง
import torch
torch.tensor([1,-1], [1,-1])
๐น ์ํคํ ์ฒ
โ ํ์ดํ ์น API - ํ์ดํ ์น ์์ง - ์ฐ์ฐ์ฒ๋ฆฌ
โ ํ์ดํ ์น API : ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ํคํ ์ณ ๊ฐ์ฅ ์๊ณ์ธต์ ์์นํด์๋ค.
โ ํ์ดํ ์น ์์ง : ๋ค์ฐจ์ ํ ์ ๋ฐ ์๋ ๋ฏธ๋ถ์ ์ฒ๋ฆฌํ๋ค
โ ์ฐ์ฐ์ฒ๋ฆฌ : ํ ์์ ๋ํ ์ฐ์ฐ์ ์ฒ๋ฆฌํ๋ค.
โ API
- torch : GPU ๋ฅผ ์ง์ํ๋ ํ ์ ํจํค์ง, ๋น ๋ฅธ ์๋๋ก ๋ง์ ์์ ๊ณ์ฐ์ด ๊ฐ๋ฅํ๋ค.
- torch.autograd : ์๋ ๋ฏธ๋ถ ํจํค์ง. ํ ์ํ๋ก, Caffe ์ ๊ฐ์ฅ ์ฐจ๋ณ๋๋ ์ง์ ์ผ๋ก, ์ผ๋ฐ์ ์ผ๋ก ์๋์ธต ๋ ธ๋ ์ ๋ณ๊ฒฝ๊ณผ ๊ฐ์ด ์ ๊ฒฝ๋ง์ ์ฌ์ํ ๋ณ๊ฒฝ์ด ์๋ค๋ฉด ์ ๊ฒฝ๋ง ๊ตฌ์ถ์ ์ฒ์๋ถํฐ ๋ค์ ์์ํด์ผ ํ๋๋ฐ, ํ์ดํ ์น๋ ์๋ ๋ฏธ๋ถ ๊ธฐ์ ์ ํํ์ฌ ์ค์๊ฐ์ผ๋ก ๋คํธ์ํฌ ์์ ์ด ๋ฐ์๋ ๊ณ์ฐ์ด ๊ฐ๋ฅํด ์ฌ์ฉ์๋ ๋ค์ํ ์ ๊ฒฝ๋ง์ ์ ์ฉํด๋ณผ ์ ์๋ค.
- torch.nn : CNN, RNN, ์ ๊ทํ ๋ฑ์ด ํฌํจ๋์ด ์์ด ์์ฝ๊ฒ ์ ๊ฒฝ๋ง์ ๊ตฌ์ถํ ์ ์๋ค.
- torch.multiprocessing : ํ์ดํ ์น์์ ์ฌ์ฉํ๋ ํ๋ก์ธ์ค ์ ๋ฐ์ ๊ฑธ์ณ ํ ์์ ๋ฉ๋ชจ๋ฆฌ ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๋ค. ์๋ก ๋ค๋ฅธ ํ๋ก์ธ์ค์์ ๋์ผํ ๋ฐ์ดํฐ (ํ ์) ์ ๋ํ ์ ๊ทผ ๋ฐ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
โ ํ ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ธฐ
- ์คํ ๋ฆฌ์ง : ํ ์๋ ์ด๋ค ์ฐจ์์ ๊ฐ์ง๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ ๋๋ 1์ฐจ์ ๋ฐฐ์ด ํํ๊ฐ ๋๋ค. ๋ณํ๋ 1์ฐจ์ ๋ฐฐ์ด์ ์คํ ๋ฆฌ์ง๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- ์คํ์ offset : ํ ์์์ ์ฒซ๋ฒ์งธ ์์๊ฐ ์คํ ๋ฆฌ์ง์ ์ ์ฅ๋ ์ธ๋ฑ์ค์ด๋ค.
- ์คํธ๋ผ์ด๋ stride : ์ฐจ์์ ๋ฐ๋ผ ๋ค์ ์์๋ฅผ ์ป๊ธฐ ์ํด ๊ฑด๋๋ฐ๊ธฐ๊ฐ ํ์ํ ์คํ ๋ฆฌ์ง์ ์์ (์ธ๋ฑ์ค์) ๊ฐ์ (๋ฉ๋ชจ๋ฆฌ์์์ ํ ์ ๋ ์ด์์) . ์์๊ฐ ์ฐ์์ ์ผ๋ก ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ ํ ์ค์ฌ์ผ๋ก ์คํธ๋ผ์ด๋๋ ํญ์ 1์ด๋ค.
→ stride = (์ด๋ฐฉํฅ์ผ๋ก ๋ค์์ ์์นํ ์์์ ์ ๊ทผํ ๋ ๊ฑด๋๊ฐ์ผ ํ ์ธ๋ฑ์ค ์ , ํ๋ฐฉํฅ์ผ๋ก ๋ค์์ ์์นํ ์์์ ์ ๊ทผํ ๋ ๊ฑด๋๊ฐ์ผ ํ ์ธ๋ฑ์ค ์)
2๏ธโฃ ํ์ดํ ์น ๊ธฐ์ด ๋ฌธ๋ฒ
๐น ํ ์ ๋ค๋ฃจ๊ธฐ
A. ํ ์ ์์ฑ ๋ฐ ๋ณํ
• torch.tensor( )
- device = 'cude:0' : GPU ์ ํ ์ ์์ฑํ๋ ์ต์
- dtype = torch.float64 : dtype ์ ์ฌ์ฉํ์ฌ ํ ์ ์์ฑ
# ํ
์ ์์ฑ ๋ฐ ๋ณํ
import torch
print(torch.tensor([[1,2],[3,4]])) # 2์ฐจ์ ํํ์ ํ
์ ์์ฑ
print(torch.tensor([[1,2],[3,4]], device = 'cuda:0')) # GPU ์ ํ
์ ์์ฑ
print(torch.tensor([[1,2],[3,4]], dtype = torch.float64)) # dtype ์ ์ด์ฉํด ํ
์ ์์ฑ
• .numpy()
- ํ ์๋ฅผ ndarray ๋ก ๋ณ๊ฒฝ
- .to('cpu').numpy() : GPU ์์ ํ ์๋ฅผ CPU ์ ํ ์๋ก ๋ณํํ ํ ndarray ๋ก ๋ณํ
# ํ
์๋ฅผ ndarray ๋ก ๋ณํ
temp = torch.tensor([[1,2],[3,4]])
print(temp.numpy())
temp = torch.tensor([[1,2],[3,4]] , device = 'cuda:0')
print(temp.to('cpu').numpy())
B. ํ ์ ์ธ๋ฑ์ค ์กฐ์
• ๋ฐฐ์ด์ฒ๋ผ ์ธ๋ฑ์ค๋ฅผ ๋ฐ๋ก ์ง์ ํ๊ฑฐ๋ ์ฌ๋ผ์ด์ค ๋ฑ์ ์ฌ์ฉํ ์ ์๋ค.
• torch.FloatTensor : 32๋นํธ์ ๋ถ๋ ์์์
• torch.DoubleTensor : 64๋นํธ์ ๋ถ๋ ์์์
• torch.LongTensor : 64๋นํธ์ ๋ถํธ๊ฐ ์๋ ์ ์
• ์ธ๋ฑ์ค ์กฐ์ : [ ] ์ค๊ดํธ๋ฅผ ํตํด ์ํ๋ ์์๋ฅผ ๊ฐ์ ธ์จ๋ค.
# ์ธ๋ฑ์ฑ & ์ฌ๋ผ์ด์ฑ
temp = torch.FloatTensor([1,2,3,4,5,6,7])
print(temp[0],temp[1],temp[-1]) # ์ธ๋ฑ์ค๋ก ์ ๊ทผ
print('------------------------------------------')
print(temp[2:5], temp[4:-1]) # ์ฌ๋ผ์ด์ค๋ก ์ ๊ทผ
C. ํ ์ ์ฐ์ฐ ๋ฐ ์ฐจ์ ์กฐ์
• ํ ์ ๊ฐ์ ํ์ ์ด ๋ค๋ฅด๋ฉด ์ฐ์ฐ์ด ๋ถ๊ฐ๋ฅํ๋ค (FloatTensor ์ DoubleTensor ๊ฐ์ ์ฌ์น ์ฐ์ฐ์ ์ํํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์)
• view( ) : ํ ์์ ์ฐจ์์ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ (reshape ๊ธฐ๋ฅ๊ณผ ์ ์ฌ)
• stack, cat : ํ ์๋ฅผ ๊ฒฐํฉ
• t, transpose : ์ฐจ์์ ๊ตํ
# ์ฐ์ฐ
temp = torch.tensor([[1,2],[3,4]])
print(temp.shape)
print()
print(temp.view(4,1))
print()
print(temp.view(-1)) # 2x2 ํ๋ ฌ์ 1์ฐจ์ ๋ฒกํฐ๋ก ๋ณํ
print()
print(temp.view(1,-1)) # 1x4 ํ๋ ฌ๋ก ๋ณํ
๐น ๋ฐ์ดํฐ ์ค๋น
โ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ : pandas ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ or ํ์ดํ ์น์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ
โ ์ด๋ฏธ์ง ๋ฐ์ดํฐ : ๋ถ์ฐ๋ ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ์ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ๋ฐฐ์น ๋จ์๋ก ๋ถํ ํ์ฌ ์ฒ๋ฆฌํ๋ค.
โ ํ ์คํธ ๋ฐ์ดํฐ : ์๋ฒ ๋ฉ ๊ณผ์ ์ ๊ฑฐ์ณ ์๋ก ๋ค๋ฅธ ๊ธธ์ด์ ์ํ์ค๋ฅผ ๋ฐฐ์น ๋จ์๋ก ๋ถํ ํ์ฌ ์ฒ๋ฆฌํ๋ค.
โ Custom dataset ์ปค์คํ ๋ฐ์ดํฐ์ : ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ๋ค ๋ถ๋ฅด์ง ์๊ณ ์กฐ๊ธ์ฉ ๋๋์ด ๋ถ๋ฌ์ ์ฌ์ฉํ๋ ๋ฐฉ์
- torch.utils.data.Dataset → ์ด๋ฅผ ์์๋ฐ์ ๋ฉ์๋๋ค์ ์ค๋ฒ๋ผ์ด๋ ํ์ฌ ์ปค์คํ ๋ฐ์ดํฐ์ ์ ๋ง๋ค ์ ์๋ค.
- torch.utils.data.DataLoader → ํ์ต์ ์ฌ์ฉ๋ ๋ฐ์ดํฐ ์ ์ฒด๋ฅผ ๋ณด๊ดํ๋ค๊ฐ ๋ชจ๋ธ ํ์ต์ ํ ๋ ๋ฐฐ์นํฌ๊ธฐ ๋งํผ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด ์ฌ์ฉํ๋ค. ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์๋ผ๋๋ ๊ฒ์ ์๋๊ณ , ๋ด๋ถ์ ์ผ๋ก ๋ฐ๋ณต์์ ํฌํจ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐ์น ํฌ๊ธฐ ๋งํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ค.
- ๋ฏธ๋ ๋ฐฐ์น ํ์ต, ๋ฐ์ดํฐ ์ ํ(shuffle), ๋ณ๋ ฌ ์ฒ๋ฆฌ๊น์ง ๊ฐ๋จํ ์ํ๊ฐ๋ฅ
import pandas as pd
import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
class CustomDataset(Dataset) :
# csv_file ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ๋ฐ์ดํฐ์
์ ๋ถ๋ฌ์จ๋ค.
def __init__(self, csv_file) :
self.label = pd.read_csv(csv_file)
# ์ ์ฒด ๋ฐ์ดํฐ์
์ ํฌ๊ธฐ๋ฅผ ๋ฐํ
def __len__(self) :
return len(self.label)
# ์ ์ฒด x ์ y ๋ฐ์ดํฐ ์ค์ ํด๋น idx ๋ฒ์งธ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
def __getitem__(self,idx) :
sample = torch.tensor(self.label.iloc[idx, 0:3]).int()
label = torch.tensor(self.label.iloc[idx,3]).int()
return sample, label
tensor_dataset = CustomDataset('../covtype.csv')
dataset = DataLoader(tensor_dataset, batch_size = 4, shuffle = True)
# ๋ฐ์ดํฐ์
์ torch.utils.data.DataLoader ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋ค.
โ MNIST ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
- torchvision : ํ์ดํ ์น์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ์ ๋ค์ด ๋ชจ์ฌ์๋ ํจํค์ง๋ก ImageNet, MNIST ๋ฅผ ํฌํจํ ์ ๋ช ํ ๋ฐ์ดํฐ์ ๋ค์ ์ ๊ณตํ๊ณ ์๋ค.
import torchvision.transforms as transforms
mnist_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,),(1.0,)) # ํ๊ท ์ด 0.5, ํ์คํธ์ฐจ๊ฐ 1์ด ๋๋๋ก ๋ฐ์ดํฐ ๋ถํฌ๋ฅผ ์กฐ์
])
from torchvision.datasets import MNIST
import requests
download_root = '/content/sample_data/mnist_dataset'
train_dataset = MNIST(download_root, transform = mnist_transform , train=True, download=True)
valid_dataset = MNIST(download_root, transform = mnist_transform , train=False, download=True)
test_dataset = MNIST(download_root, transform = mnist_transform , train=False, download=True)
๐น ๋ชจ๋ธ์ ์
ํ์ดํ ์น ๊ตฌํ์ฒด๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก Class ๋ผ๋ ๊ฐ๋ ์ ์ ์ฉํ๋ค.
โ ๋ชจ๋ธ๊ณผ ๋ชจ๋์ ์ฐจ์ด
- ๊ณ์ธต Layer : ๋ชจ๋์ ๊ตฌ์ฑํ๋ ํ ๊ฐ์ ๊ณ์ธต์ผ๋ก convolutional layer, linear layer ๋ฑ์ด ์๋ค.
- ๋ชจ๋ module : ํ ๊ฐ ์ด์์ ๊ณ์ธต์ด ๋ชจ์ฌ์ ๊ตฌ์ฑ๋ ๊ฒ์ผ๋ก ๋ชจ๋์ด ๋ชจ์ฌ์ ์๋ก์ด ๋ชจ๋์ ๋ง๋ค ์๋ ์๋ค.
- ๋ชจ๋ธ model : ์ต์ข ์ ์ผ๋ก ์ํ๋ ๋คํธ์ํฌ๋ก ํ ๊ฐ์ ๋ชจ๋์ด ๋ชจ๋ธ์ด ๋ ์๋ ์๋ค.
A. ๋จ์ ์ ๊ฒฝ๋ง์ ์ ์ํ๋ ๋ฐฉ๋ฒ
- nn.Module ์ ์์๋ฐ์ง ์๋ ๋งค์ฐ ๋จ์ํ ๋ชจ๋ธ์ ๋ง๋ค ๋ ์ฌ์ฉํ๋ค.
- ๊ตฌํ์ด ์ฝ๊ณ ๋จ์ํ๋ค.
# ๋์ ์ ๊ฒฝ๋ง ์ ์
import torch.nn as nn
model = nn.Linear(in_features = 1, out_features = 1, bias = True)
B. nn.Module() ์ ์์ํ์ฌ ์ ์ํ๋ ๋ฐฉ๋ฒ
- __init__() : ๋ชจ๋ธ์์ ์ฌ์ฉ๋ ๋ชจ๋ (nn.Linear , nn.Conv2d) , ํ์ฑํ ํจ์ ๋ฑ์ ์ ์
- forward() : ๋ชจ๋ธ์์ ์คํ๋์ด์ผ ํ๋ ์ฐ์ฐ์ ์ ์
import torch
import torch.nn as nn
class MLP(nn.Module) : # ๋ชจ๋ ์์
def __init__(self, inputs) :
super(MLP, self).__init__()
self.layer = Linear(inputs, 1) # ๊ณ์ธต ์ ์
self.activation = Sigmoid() # ํ์ฑํ ํจ์ ์ ์
def forward(self, X) :
X = self.layer(X)
X = self.activation(X)
return X
• ์ ํํ๊ท ๋ชจ๋ธ ์์ฑ ์์
class LinearRegressionModel(nn.Module) :
def __init__(self) :
super().__init__()
self.linear = nn.Linear(1,1)
def forward(self, x) :
return self.linear(x)
C. nn.Sequential ์ ๊ฒฝ๋ง์ ์ ์ํ๋ ๋ฐฉ๋ฒ
- nn.Sequential : ์ด๋ฅผ ์ฌ์ฉํ๋ฉด __init__() ์์ ์ฌ์ฉํ ๋คํธ์ํฌ ๋ชจ๋ธ๋ค์ ์ ์ํด ์ค ๋ฟ ์๋๋ผ forward() ํจ์์์๋ ๋ชจ๋ธ์์ ์คํ๋์ด์ผ ํ ๊ณ์ฐ์ ์ข ๋ ๊ฐ๋ ์ฑ ๋ฐ์ด๋๊ฒ ์ฝ๋๋ก ์์ฑํ ์ ์๋ค.
- layer ๋ฅผ ์ฌ๋ฌ๊ฐ ์ ์ํ ์ ์๊ณ , sequential ๊ฐ์ฒด๋ ๊ทธ ์์ ํฌํจ๋ ๊ฐ ๋ชจ๋์ ์์ฐจ์ ์ผ๋ก ์คํํด ์ค๋ค.
- nn.Sequential ์ ๋ชจ๋ธ์ ๊ณ์ธต์ด ๋ณต์กํ ์๋ก ํจ๊ณผ๊ฐ ๋ฐ์ด๋๋ค.
import torch.nn as nn
class MLP(nn.Module) :
def __init__(self) :
super(MLP, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(in_channels = 3, out_channels = 64, kernel_size = 5),
nn.ReLU(inplace = True),
nn.MaxPool2d(2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(in_channels = 64, out_channels = 30, kernel_size = 5),
nn.ReLU(inplace=True),
nn.MaxPool2d(2)
)
self.layer3 = nn.Sequential(
nn.Linear(in_features = 30*5*5, out_features = 10, bias = True),
nn.ReLU(inplace=True)
)
def forward(self,x) :
x = self.layer1(x)
x = self.layer2(x)
x = x.view(x.shape[0],-1)
x = self.layer3(x)
return x
model = MLP() # ๋ชจ๋ธ์ ๋ํ ๊ฐ์ฒด ์์ฑ
print("printing children \n ---------------------")
print(list(model.children()))
print("\n\nprinting Modules\n-------------------------")
print(list(model.modules()))
โ model.modules() : ๋ชจ๋ธ์ ๋คํธ์ํฌ์ ๋ํ ๋ชจ๋ ๋ ธ๋๋ค์ ๋ฐํ
โ model.children() : ๊ฐ์ ์์ค level ์ ํ์ ๋ ธ๋๋ฅผ ๋ฐํ
D. ํจ์๋ก ์ ๊ฒฝ๋ง์ ์ ์ํ๋ ๋ฐฉ๋ฒ
โ Sequential ์ด์ฉ๊ณผ ๋์ผํ์ง๋ง, ํจ์๋ก ์ ์ธํ ๊ฒฝ์ฐ ๋ณ์์ ์ ์ฅํด๋์ ๊ณ์ธต๋ค์ ์ฌ์ฌ์ฉ ํ ์ ์๋ ์ฅ์ ์ด ์๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ธ์ด ๋ณต์กํด์ง๋ ๋จ์ ๋ ์๋ค. ๋ณต์กํ ๋ชจ๋ธ์ ํจ์๋ฅผ ์ด์ฉํ๋ ๊ฒ๋ณด๋ค nn.Module ์ ์์๋ฐ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํธ๋ฆฌํ๋ค.
def MLP(in_features = 1, hidden_features = 20, out_features = 1) :
hidden = nn.Linear(in_features = in_features, out_features = hidden_features, bias = True)
activation = nn.ReLU()
output = nn.Linear(in_features = hidden_features, out_features = out_features, bias = True)
net = nn.Sequential(hidden, activation, output)
return net
๐น ๋ชจ๋ธ ํ๋ผ๋ฏธํฐ ์ ์
๐จ ์์คํจ์
โ ํ์ตํ๋ ๋์ ์ถ๋ ฅ๊ณผ ์ค์ ๊ฐ ์ฌ์ด์ ์ค์ฐจ๋ฅผ ์ธก์ ํ์ฌ ๋ชจ๋ธ์ ์ ํ์ฑ์ ์ธก์ ํ๋ค.
โ BCELoss : ์ด์ง ๋ถ๋ฅ๋ฅผ ์ํด ์ฌ์ฉ
โ CrossEntropyLoss : ๋ค์ค ํด๋์ค ๋ถ๋ฅ๋ฅผ ์ํด ์ฌ์ฉ
โ MSELoss : ํ๊ท ๋ชจ๋ธ์์ ์ฌ์ฉ
๐ ์์ค ํจ์์ ๊ฐ์ ์ต์ํ ํ๋ ๊ฐ์ค์น์ ๋ฐ์ด์ด์ค๋ฅผ ์ฐพ๋ ๊ฒ์ด ํ์ต์ ๋ชฉํ ๐
๐จ ์ตํฐ๋ง์ด์
โ ์์คํจ์๋ฅผ ๋ฐํ์ผ๋ก ๋ชจ๋ธ์ ์ ๋ฐ์ดํธ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๋ค.
โ step() ๋ฉ์๋๋ฅผ ํตํด ์ ๋ฌ๋ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฐ์ดํธ ํ๋ค.
โ ํ๋ผ๋ฏธํฐ๋ณ๋ก ๋ค๋ฅธ ๊ธฐ์ค (ex. ํ์ต๋ฅ ) ์ ์ ์ฉ์ํฌ ์ ์๋ค.
โ torch.optim.Optimizer(params, defaults) : ์ตํฐ๋ง์ด์ ์ ๊ธฐ๋ณธ ํด๋์ค
โ zero_grad() : ํ๋ผ๋ฏธํฐ์ gradient ๋ฅผ 0 ์ผ๋ก ๋ง๋๋ ๋ฉ์๋
โ torch.optim.lr_scheduler : ์ํฌํฌ์ ๋ฐ๋ผ ํ์ต๋ฅ ์ ์กฐ์ ํ ์ ์๋ค.
โ ์ข ๋ฅ
- optim.Adadelta , optim.Adagrad, optim.Adam, optim.SparseAdam, optim.Adamax
- optim.ASGD, optim.LBFGS
- optim.RMSProp, optimRprop, optim.SGD
๐จ ํ์ต ์ค์ผ์ฅด๋ฌ learning rate scheduler
โ ์ง์ ํ ํ์์ ์ํฌํฌ๋ฅผ ์ง๋ ๋๋ง๋ค ํ์ต๋ฅ ์ ๊ฐ์ (decay) ์์ผ์ค๋ค.
โ ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ต ์ด๊ธฐ์๋ ๋น ๋ฅธ ํ์ต์ ์งํํ๋ค๊ฐ global minimum ๊ทผ์ฒ์ ์ค๋ฉด ํ์ต๋ฅ ์ ์ค์ฌ ์ต์ ์ ์ ์ฐพ์๊ฐ ์ ์๋๋ก ํด์ค๋ค.
- optim.lr_scheduler.LambdaLR : ๋๋ค ํจ์๋ฅผ ์ด์ฉํด ํจ์์ ๊ฒฐ๊ณผ๋ฅผ ํ์ต๋ฅ ๋ก ์ค์
- optim.lr_scheduler.StepLR : ํน์ ๋จ๊ณ๋ง๋ค ํ์ต๋ฅ ์ ๊ฐ๋ง ๋น์จ๋งํผ ๊ฐ์์ํจ๋ค.
- optim.lr_scheduler.MultiStepLR : stepLR ๊ณผ ๋น์ทํ์ง๋ง ํน์ ๋จ๊ณ๊ฐ ์๋ ์ง์ ๋ ์ํฌํฌ์๋ง ๊ฐ๋ง ๋น์จ๋ก ๊ฐ์์ํจ๋ค.
- optim.lr_scheduler.ExponentialLR : ์ํฌํฌ๋ง๋ค ์ด์ ํ์ต๋ฅ ์ ๊ฐ๋ง๋งํผ ๊ณฑํ๋ค.
- optim.lr_scheduler.CosineAnnealingLR : ํ์ต๋ฅ ์ ์ฝ์ฌ์ธ ํจ์์ ํํ์ฒ๋ผ ๋ณํ์ํจ๋ค. ํ์ต๋ฅ ์ด ์ปค์ง๊ธฐ๋ ์์์ง๊ธฐ๋ ํ๋ค.
- optim.lr_scheduler.ReduceLROnPlateau : ํ์ต์ด ์๋๊ณ ์๋์ง ์๋์ง์ ๋ฐ๋ผ ๋์ ์ผ๋ก ํ์ต๋ฅ ์ ๋ณํ์ํฌ ์ ์๋ค.
๐จ ์งํ metrics
โ ํ๋ จ๊ณผ ํ ์คํธ ๋จ๊ณ๋ฅผ ๋ชจ๋ํฐ๋ง ํ๋ค.
๐จ ์ต์์ Minimum
โ Global minimum : ์ค์ฐจ๊ฐ ๊ฐ์ฅ ์์ ๋์ ๊ฐ์ ์๋ฏธํ๋ฉฐ, ์ฐ๋ฆฌ๊ฐ ์ต์ข ์ ์ผ๋ก ์ฐพ๊ณ ์ ํ๋๊ฒ (์ต์ ์ )
โ local minimum : ์ ์ญ ์ต์์ ์ ์ฐพ์๊ฐ๋ ๊ณผ์ ์์ ๋ง๋๋ ๊ตฌ๋ฉ ๊ฐ์ ๊ณณ์ผ๋ก ์ตํฐ๋ง์ด์ ๊ฐ ์ง์ญ ์ต์์ ์์ ํ์ต์ ๋ฉ์ถ๋ฉด ์ต์๊ฐ์ ๊ฐ๋ ์ค์ฐจ๋ฅผ ์ฐพ์ ์ ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
# ๋ชจ๋ธ ํ๋ผ๋ฏธํฐ ์ ์ ์์ ์ฝ๋
from torch.optim import optimizer
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01, momentum = 0.9)
scheduler = torch.optim.lr_scheduler.LamdaLR(optimizer = optimizer,
lr_lambda = lambda epoch : 0.95**epoch)
for epoch in range(1, 100+1) : # ์ํฌํฌ ์๋งํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ณตํ์ฌ ์ฒ๋ฆฌ
for x, y in dataloader : # ๋ฐฐ์น ํฌ๊ธฐ๋งํผ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ํ์ต ์งํ
optimizer.zero_grad()
loss_fn(model(x), y).backward()
optimizer.step()
scheduler.step()
๐น ๋ชจ๋ธํ๋ จ
๐จ ํ์ต
โ ๋ชจ๋ธ์ ํ์ต์ํจ๋ค๋ ๊ฒ์ y = wx + b ๋ผ๋ ํจ์์์ w ์ b ์ ์ ์ ํ ๊ฐ์ ์ฐพ๋๋ค๋ ๊ฒ์ ์๋ฏธ์ด๋ค.
โ w ์ b ์ ์์์ ๊ฐ์ ์ ์ฉํ์ฌ ์์ํด ์ค์ฐจ๊ฐ ์ค์ด๋ค์ด ์ ์ญ ์ต์์ ์ ์ด๋ฅผ๋๊น์ง ํ๋ผ๋ฏธํฐ๋ฅผ ๊ณ์ ์์ ํด ๋์๊ฐ๋ค.
๋ฅ๋ฌ๋ ํ์ต์ ์ฐจ | ํ์ดํ ์น ํ์ต ์ ์ฐจ |
๋ชจ๋ธ, ์์คํจ์, ์ตํฐ๋ง์ด์ ์ ์ | • ๋ชจ๋ธ, ์์คํจ์, ์ตํฐ๋ง์ด์ ์ ์ • optimizer.zero_grad() : ์ ๋ฐฉํฅ ํ์ต, ๊ธฐ์ธ๊ธฐ ์ด๊ธฐํ |
์ ๋ฐฉํฅ ํ์ต (์ ๋ ฅ → ์ถ๋ ฅ ๊ณ์ฐ) | output = model(input) : ์ถ๋ ฅ ๊ณ์ฐ |
์์ค ํจ์๋ก ์ถ๋ ฅ๊ณผ ์ ๋ต์ ์ฐจ์ด (์ค์ฐจ) ๊ณ์ฐ | loss = loss_fn(output, target) : ์ค์ฐจ ๊ณ์ฐ |
์ญ์ ํ ํ์ต (๊ธฐ์ธ๊ธฐ ๊ณ์ฐ) | loss.backward() : ์ญ์ ํ ํ์ต |
๊ธฐ์ธ๊ธฐ ์ ๋ฐ์ดํธ | optimizer.step() : ๊ธฐ์ธ๊ธฐ ์ ๋ฐ์ดํธ |
โ loss.backward( ) : ํ์ดํ ์น์์ ๊ธฐ์ธ๊ธฐ ๊ฐ์ ๊ณ์ฐํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ฒ์ธ๋ฐ, ์ด๋ ์๋ก์ด ๊ธฐ์ธ๊ธฐ๊ฐ์ด ์ด์ ๊ธฐ์ธ๊ธฐ ๊ฐ์ ๋์ ํ์ฌ ๊ณ์ฐ๋๋ฏ๋ก, RNN ๊ฐ์ ๋ชจ๋ธ์ ๊ตฌํํ ๋์๋ ํ์ํ์ง๋ง, ๊ทธ๋ ์ง ์์ ๋ฅ๋ฌ๋ ์ํคํ ์ณ์์๋ ๋ถํ์ํ๋ค. ๋ฐ๋ผ์ ๊ธฐ์ธ๊ธฐ ๊ฐ์ ๋์ ๊ณ์ฐ์ด ํ์ํ์ง ์์ ๋์๋ ์ ๋ ฅ ๊ฐ์ ๋ชจ๋ธ์ ์ ์ฉํ๊ธฐ ์ ์ optimizer.zero_grad() ๋ฅผ ํธ์ถํ์ฌ ๋ฏธ๋ถ๊ฐ (๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํ๋ ๊ณผ์ ์์ ๋ฏธ๋ถ์ ์ฌ์ฉ) ์ด ๋์ ๋์ง ์๊ฒ ์ด๊ธฐํ ํด์ฃผ์ด์ผ ํ๋ค.
โ ๋ชจ๋ธ ํ๋ จ ์ฝ๋
for epoch in range(100) :
yhat = model(x_train)
loss = criterion(yhat, y_train) # criterion = torch.nn.MSELoss()
optimizer.zero_grad() # ์ค์ฐจ๊ฐ ์ค์ฒฉ์ ์ผ๋ก ์์ด์ง ์๋๋ก ์ด๊ธฐํ
loss.backward() # ์ญ์ ํ ํ์ต
optimizer.step() # ๊ธฐ์ธ๊ธฐ ์
๋ฐ์ดํธ
๐น ๋ชจ๋ธํ๊ฐ
๐จ evaluation
โ ์ฃผ์ด์ง ํ ์คํธ ๋ฐ์ดํฐ์ ์ ์ฌ์ฉํด ๋ชจ๋ธ์ ํ๊ฐ
โ torchmetrics ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
๐จ ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ชจ๋ธ์ ํ๊ฐํ๋ ์ฝ๋
โ torchmetrics.functional.accuracy( )
# ํจํค์ง ์ค์น : pip install torchmetrics
# ๋ชจ๋ธ์ ํ๊ฐํ๋ ์ฝ๋ : ํจ์๋ฅผ ์ด์ฉํ ์ฝ๋
import torch
import torchmetrics
preds = torch.randn(10,5).softmax(dim = -1) # ์์ธก๊ฐ : softmax()
target = torch.randint(5, (10,)) # ์ค์ ๊ฐ
acc = torchmetrics.functional.accuracy(preds, target) # โญ๋ชจ๋ธ ํ๊ฐ
๐จ ๋ชจ๋์ ์ด์ฉํ์ฌ ๋ชจ๋ธ์ ํ๊ฐํ๋ ์ฝ๋
โ torchmetrics.Accuracy()
# ๋ชจ๋ธ์ ํ๊ฐํ๋ ์ฝ๋ : ๋ชจ๋์ ์ด์ฉํ ์ฝ๋
metric = torchmetrics.Accuracy() # ๋ชจ๋ธ ํ๊ฐ ์ด๊ธฐํ
n_batches = 10
for i in range(n_batches) :
preds = torch.randn(10,5).softmax(dim = -1)
target = torch.randint(5, (10,))
acc = metric(preds, target) # โญ
print(f'{i} ๋ฒ์งธ ๋ฐฐ์น์์์ ์ ํ๋ : {acc}') # ํ์ฌ ๋ฐฐ์น์์์ ๋ชจ๋ธ ํ๊ฐ
############################
acc = metric.compute()
print(f'์ ์ฒด ๋ฐ์ดํฐ์ ๋ํ ์ ํ๋ : {acc}') # ๋ชจ๋ ๋ฐฐ์น์์์ ๋ชจ๋ธ ํ๊ฐ
โ ์ฌ์ดํท๋ฐ์์ ์ ๊ณตํ๋ metrics ๋ชจ๋์ ์ฌ์ฉํ ์๋ ์๋ค → confusion_matrix , accuracy_score, classification_report
๐น ํ๋ จ๊ณผ์ ๋ชจ๋ํฐ๋ง
๐จ ๋ชจ๋ํฐ๋ง
โ ํ์ต์ด ์งํ๋๋ ๊ณผ์ ์์ ๊ฐ ํ๋ผ๋ฏธํฐ ๊ฐ๋ค์ด ์ด๋ป๊ฒ ๋ณํํ๋์ง ์ดํด๋ณด๋ ๊ฒ
โ ํ ์๋ณด๋ : ํ์ต์ ์ฌ์ฉ๋๋ ๊ฐ์ข ํ๋ผ๋ฏธํฐ๊ฐ์ด ์ด๋ป๊ฒ ๋ณํํ๋์ง ์์ฝ๊ฒ ์๊ฐํํ์ฌ ๋ณผ ์ ์์ + ์ฑ๋ฅ์ ์ถ์ ํ๊ฑฐ๋ ํ๊ฐํ๋ ์ฉ๋๋ก ์ฌ์ฉ
1. ํ ์๋ณด๋ ์ค์ Set up
2. ํ ์๋ณด๋์ ๊ธฐ๋ก write
3. ํ ์๋ณด๋๋ฅผ ์ฌ์ฉํด ๋ชจ๋ธ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณธ๋ค.
pip install tensorboard
import torch
from torch.utils.tensorboard import SummaryWriter #โญ
writer = SummaryWriter('../chap02/tensorboard') # ๐ ๋ชจ๋ํฐ๋ง์ ํ์ํ ๊ฐ๋ค์ด ์ ์ฅ๋ ์์น
for epoch in range(num_epochs) :
model.train() # ํ์ต ๋ชจ๋๋ก ์ ํ (dropout=True)
batch_loss = 0.0
for i, (x,y) in enumerate(dataloader) :
x, y = x.to(device).float(), y.to(device).float()
outputs = model(x)
loss = criterion(outputs, y)
writer.add_scalar('Loss', loss, epoch) # ๐ ์ค์นผ๋ผ ๊ฐ (์ค์ฐจ) ์ ๊ธฐ๋ก
optimizer.zero_grad()
loss.backward()
optimizer.step()
writer.close() # SummaryWriter ๊ฐ ๋์ด์ ํ์ํ์ง ์์ผ๋ฉด close() ํธ์ถ
tensorboard -- logdir = ../chap02/tensorboard --port=6006
# ์์ ๋ช
๋ น์ ์
๋ ฅํ๋ฉด ํ
์๋ณด๋๋ฅผ ์คํํ ์ ์๊ฒ ๋๊ณ ์น ๋ธ๋ผ์ฐ์ ์
http://localhost:6006 ์ ์
๋ ฅํ๋ฉด ์๋์ ๊ฐ์ ์นํ์ด์ง๊ฐ ๋ฌ๋ค.
๐จ model.train()
โ ํ๋ จ ๋ฐ์ดํฐ์ ์ ์ฌ์ฉ, ๋ชจ๋ธ ํ๋ จ์ด ์งํ๋ ๊ฒ์์ ์๋ฆผ
โ dropout ์ด ํ์ฑํ๋จ
โ model.train ๊ณผ model.eval ์ ์ ์ธํด์ผ ๋ชจ๋ธ์ ์ ํ๋๋ฅผ ๋์ผ ์ ์๋ค.
๐จ model.eval()
โ ๋ชจ๋ธ์ ํ๊ฐํ ๋ ๋ชจ๋ ๋ ธ๋๋ฅผ ์ฌ์ฉํ๊ฒ ๋ค๋ ์๋ฏธ
โ ๊ฒ์ฆ๊ณผ ํ ์คํธ์ ์ ์ฌ์ฉํ๋ค.
# model.eval()
model.eval() # ๊ฒ์ฆ ๋ชจ๋๋ก ์ ํ (dropout = False) โญ
with torch.no_grad() :
valid_loss = 0
for x,y in valid_dataloader :
outputs = model(x)
loss = F.cross_entropy(outputs, y.long(),squeeze())
valid_loss += float(loss)
y_hat += [outputs]
valid_loss = valid_loss/len(valid_loss)
→ ๊ฒ์ฆ ๊ณผ์ ์๋ ์ญ์ ํ๊ฐ ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ with torch.no_grad() ๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์ธ๊ธฐ ๊ฐ์ ์ ์ฅํ์ง ์๋๋ก ํ๋ค. (๋ฉ๋ชจ๋ฆฌ, ์ฐ์ฐ ์๊ฐ ์ค์ด๊ธฐ)
โ python with ์
โ ์์์ ํ๋ํ๊ณ , ์ฌ์ฉํ๊ณ , ๋ฐ๋ฉํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ค.
โ ํ์ด์ฌ์์ open() ํจ์๋ฅผ ํตํด ํ์ผ์ ์ด๋ฉด ๊ผญ close() ๋ฅผ ํด์ฃผ์ด์ผ ํ๋๋ฐ, with ๊ตฌ๋ฌธ์ ์ฐ๋ฉด close() ๋ฅผ ์๋์ผ๋ก ํธ์ถํด์ฃผ๊ธฐ ๋๋ฌธ์ close ๋ฌธ์ ์ฐ์ง ์์๋ ๋๋ ์ฅ์ ์ด ์๋ค.
๐น ์ฝ๋ ๋ง๋ณด๊ธฐ
๐จ ๋ถ๋ฅ ๋ฌธ์
โ car_evaluation dataset : output ์ ์ฐจ์ ์ํ์ ๊ดํ ๋ฒ์ฃผํ ๊ฐ์ผ๋ก 4๊ฐ์ ๋ฒ์ฃผ๋ฅผ ๊ฐ๋๋ค.
(1) ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# ๋ฐ์ดํฐ ํธ์ถ
dataset = pd.read_csv('/content/car_evaluation.csv')
dataset.head()
→ ๋จ์ด๋ฅผ ๋ฒกํฐ๋ก ๋ฐ๊พธ์ด์ฃผ๋ ์๋ฒ ๋ฉ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
(2) ๋ฐ์ดํฐ ๋ถํฌ ์๊ฐํ
# target ๋ถํฌ ์๊ฐํ
fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 8
fig_size[1] = 6
plt.rcParams["figure.figsize"] = fig_size
dataset.output.value_counts().plot(kind = 'pie', autopct = '%0.05f%%',
colors = ['lightblue', 'lightgreen', 'orange','pink'],
explode = (0.05,0.05,0.05,0.05))
(3) ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
๋ฒ์ฃผํ ๋ณ์์ ๋ํด ๋ฒ์ฃผ ํ๋ณํ astype('category') → ๋ํ์ด ๋ฐฐ์ด (numpy array) → Tensor
# ์ ์ฒ๋ฆฌ : ๋ฒ์ฃผํ ํ์
์ผ๋ก ๋ฐ๊พธ๊ธฐ
categorical_columns = ['price', 'maint', 'doors', 'persons', 'lug_capacity', 'safety']
for category in categorical_columns :
dataset[category] = dataset[category].astype('category') # ๐ ๋ฒ์ฃผํ์ผ๋ก ํ๋ณํ
# ๐ ๋ฒ์ฃผํ ๋ฐ์ดํฐ (๋จ์ด) ๋ฅผ ์ซ์ (๋ํ์ด ๋ฐฐ์ด)๋ก ๋ณํ : cat.codes
price = dataset['price'].cat.codes.values
maint = dataset['maint'].cat.codes.values
doors = dataset['doors'].cat.codes.values
persons = dataset['persons'].cat.codes.values
lug_capacity = dataset['lug_capacity'].cat.codes.values
safety = dataset['safety'].cat.codes.values
print(price)
print(price.shape)
categorical_data = np.stack([price, maint, doors, persons, lug_capacity, safety], axis=1)
# (1728,1) --> axis=1 --> (1728,6)
categorical_data[:10] # 10๊ฐ์ ํ๋ง ์ถ๋ ฅํด๋ณธ๋ค.
โ np.concatenate ์ np.stack ์ ์ฐจ์ด
: stack ์ ์ง์ ํ axis ๋ฅผ ์์ ํ ์๋ก์ด axis ๋ก ์๊ฐํ์ฌ ์ฐ๊ฒฐํ๋ฏ๋ก ๋ฐ๋์ ๋ ๋ํ์ด ๋ฐฐ์ด์ ์ฐจ์์ด ๋์ผํด์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
โป stack ์ฐธ๊ณ : https://everyday-image-processing.tistory.com/87
→ axis ์ถ์ ์ง์ ํ๋ ์์น๋๋ก ์ฐจ์์ด 1๋ก ์ฆ๊ฐํ ๊ฒ์ ํ์ธํด๋ณผ ์ ์๋ค.
โ ๋ฐฐ์ด์ ํ ์๋ก ๋ณํ : torch.tensor( )
# ๋ฐฐ์ด์ ํ
์๋ก ๋ณํ
categorical_data = torch.tensor(categorical_data, dtype = torch.int64)
categorical_data[:10]
โ target ๋ณ์์ ๋ํด์๋ ํ ์๋ก ๋ณํ : get_dummies ๋ฅผ ์ฌ์ฉํ์ฌ ๋ํ์ด ๋ฐฐ์ด๋ก ๋ณํํ ํ, 1์ฐจ์ ํ ์๋ก ๋ณํํ๋ค.
# target ์นผ๋ผ๋ ํ
์๋ก ๋ณํ
outputs = pd.get_dummies(dataset.output)
outputs = outputs.values
outputs = torch.tensor(outputs).flatten() # 1์ฐจ์ ํ
์๋ก ๋ณํ
print(categorical_data.shape)
print(outputs.shape)
โ ravel(), reshape(), flatten() ์ ํ ์์ ์ฐจ์์ ๋ฐ๊ฟ ๋ ์ฌ์ฉํ๋ค.
(4) ์๋ ์๋ฒ ๋ฉ
โ ์ ์ฌํ ๋จ์ด๋ผ๋ฆฌ ์ ์ฌํ๊ฒ ์ธ์ฝ๋ฉ๋๋๋ก ํํํ๋ ๋ฐฉ๋ฒ
โ ๋์ ์ฐจ์์ ์๋ฒ ๋ฉ์ผ์๋ก ๋จ์ด ๊ฐ์ ์ธ๋ถ ๊ด๊ณ๋ฅผ ์ ํ์ ํ ์ ์๊ฒ ๋๋ค.
โ ๋จ์ผ ์ซ์๋ก ๋ณํ๋ ๋ํ์ด ๋ฐฐ์ด์ N ์ฐจ์์ผ๋ก ๋ณ๊ฒฝํ๋ค.
โ ์๋ฒ ๋ฉ ํฌ๊ธฐ (๋ฒกํฐ ์ฐจ์) ์ ๋ํ ์ ํํ ๊ท์น์ ์์ผ๋, ์นผ๋ผ์ ๊ณ ์ ๊ฐ ์ (๋ฒ์ฃผ ๊ฐ์) ๋ฅผ 2๋ก ๋๋๋ ๊ฒ์ ๋ง์ด ์ฌ์ฉํ๋ค.
# ์๋ ์๋ฒ ๋ฉ ์ฐจ์ ์ ์
## ๋ฒ์ฃผ ๊ฐ์ (๊ณ ์ ๊ฐ ๊ฐ์)
categorical_column_sizes = [len(dataset[column].cat.categories) for column in categorical_columns]
## ์๋ฒ ๋ฉ ํฌ๊ธฐ = (๊ณ ์ ๊ฐ ์, ์ฐจ์์ ํฌ๊ธฐ)
categorical_embedding_sizes = [(col_size, min(50, (col_size+1)//2)) for col_size in categorical_column_sizes]
print(categorical_embedding_sizes)
(5) ๋ฐ์ดํฐ์ ๋ถ๋ฆฌ
# ๋ฐ์ดํฐ์
๋ถ๋ฆฌ
total_records = 1728
test_records = int(total_records*0.2) # ์ ์ฒด ๋ฐ์ดํฐ ์ค 20%๋ฅผ ํ
์คํธ ์ฉ๋๋ก ์ฌ์ฉ
categorical_train_data = categorical_data[:total_records - test_records]
categorical_test_data = categorical_data[total_records - test_records : total_records]
train_outputs = outputs[:total_records - test_records]
test_outputs = outputs[total_records - test_records : total_records]
(6) ๋ชจ๋ธ ๋คํธ์ํฌ ์์ฑ
# ๋ชจ๋ธ ๋คํธ์ํฌ ์์ฑ
class Model(nn.Module) : # 1๏ธโฃ
def __init__(self, embedding_size, output_size, layers, p = 0.4) : # 2๏ธโฃ
super().__init__() # 3๏ธโฃ
self.all_embeddings = nn.ModuleList(
[nn.Embedding(ni,nf) for ni,nf in embedding_size])
self.embedding_dropout = nn.Dropout(p)
all_layers = []
num_categorical_cols = sum((nf for ni, nf in embedding_size))
input_size = num_categorical_cols # ์
๋ ฅ์ธต์ ํฌ๊ธฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ฒ์ฃผํ ์นผ๋ผ์ ๊ฐ์๋ฅผ ์ ์ฅ
for i in layers : # 4๏ธโฃ
all_layers.append(nn.Linear(input_size, i))
all_layers.append(nn.ReLU(inplace=True))
all_layers.append(nn.BatchNorm1d(i))
all_layers.append(nn.Dropout(p))
input_size = i
all_layers.append(nn.Linear(layers[-1], output_size))
self.layers = nn.Sequential(*all_layers)
# ์ ๊ฒฝ๋ง์ ๋ชจ๋ ๊ณ์ธต์ด ์์ฐจ์ ์ผ๋ก ์คํ๋๋๋ก ๋ชจ๋ ๊ณ์ธต์ ๋ํ ๋ชฉ๋ก์ Sequential ํด๋์ค๋ก ์ ๋ฌ
def forward(self, x_categorical): # 5๏ธโฃ
embeddings = []
for i,e in enumerate(self.all_embeddings):
embeddings.append(e(x_categorical[:,i]))
x = torch.cat(embeddings, 1)
x = self.embedding_dropout(x)
x = self.layers(x)
return x
โ class ํํ๋ก ๊ตฌํ๋๋ ๋ชจ๋ธ์ nn.Module ์ ์์๋ฐ๋๋ค.
โก __init__ : ๋ชจ๋ธ์์ ์ฌ์ฉ๋ ํ๋ผ๋ฏธํฐ์ ์ ๊ฒฝ๋ง์ ์ด๊ธฐํํ๊ธฐ ์ํ ์ฉ๋๋ก ์ฌ์ฉ๋๋ฉฐ, ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ์๋์ผ๋ก ํธ์ถ๋๋ค.
- self : ์ฒซ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก, ์์ฑ๋๋ ๊ฐ์ฒด ์๊ธฐ ์์ ์ ์๋ฏธํ๋ค.
- embedding_size : ๋ฒ์ฃผํ ์นผ๋ผ์ ์๋ฒ ๋ฉ ํฌ๊ธฐ
- output_size : ์ถ๋ ฅ์ธต์ ํฌ๊ธฐ
- layers : ๋ชจ๋ ๊ณ์ธต์ ๋ํ ๋ชฉ๋ก
- p : ๋๋กญ์์ ๋น์จ (๊ธฐ๋ณธ๊ฐ์ 0.5)
โข super().__init__() : ๋ถ๋ชจ ํด๋์ค์ ์ ๊ทผํ ๋ ์ฌ์ฉํ๋ฉฐ super ์์๋ self ๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค.
โฃ ๋ชจ๋ธ์ ๋คํธ์ํฌ๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํด for ๋ฌธ์ ์ฌ์ฉํ์ฌ ๊ฐ ๊ณ์ธต์ all_layers ๋ชฉ๋ก์ ์ถ๊ฐํ๋ค.
โค forward() : ํ์ต ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅ๋ฐ์ ์ฐ์ฐ์ ์งํํ๋ค.
(7) ๊ฐ์ฒด ์์ฑ
โ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ ํ๋ผ๋ฏธํฐ ๊ฐ์ ์ ๋ ฅํ๋ค.
# ๋ชจ๋ธ ๊ฐ์ฒด ์์ฑ
model = Model(categorical_embedding_sizes, 4, [200,100,50], p =0.4)
# (๋ฒ์ฃผํ ์นผ๋ผ์ ์๋ฒ ๋ฉ ํฌ๊ธฐ, ์ถ๋ ฅํฌ๊ธฐ, ์๋์ธต์ ๋ด๋ฐ, ๋๋กญ์์)
# [200,100,50] : ๋ค๋ฅธ ํฌ๊ธฐ๋ก ์ง์ ํด์ ํ
์คํธ ํด๋ ๊ด์ฐฎ์
(8) ์์คํจ์, ์ตํฐ๋ง์ด์ ์ ์, ์์ ํ ๋น
โ ๋ถ๋ฅ ๋ฌธ์ ์ด๊ธฐ ๋๋ฌธ์ ์์คํจ์๋ ํฌ๋ก์ค ์ํธ๋กํผ๋ฅผ ์ฌ์ฉํ๊ณ , ์ตํฐ๋ง์ด์ ๋ ์๋ด์ ์ฌ์ฉํ๋ค.
loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
โ ํ์ดํ ์น๋ GPU ์ ์ต์ ํ๋ ๋ฅ๋ฌ๋ ํ๋ ์์ํฌ์ด๋ฏ๋ก GPU ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ฉด ์์์ ํ ๋นํด์ค๋ค.
# GPU / CPU ์ฌ์ฉ ์ค์
if torch.cuda.is_available():
device = torch.device('cuda')
else:
device = torch.device('cpu')
(9) ๋ชจ๋ธ ํ์ต
# ๋ชจ๋ธ ํ์ต
epochs = 500
aggregated_losses = []
train_outputs = train_outputs.to(device=device, dtype=torch.int64)
for i in range(epochs):# ๊ฐ ๋ฐ๋ณต๋ง๋ค ์์คํจ์๊ฐ ์ค์ฐจ๋ฅผ ๊ณ์ฐํ๋ค.
i += 1
y_pred = model(categorical_train_data).to(device)
single_loss = loss_function(y_pred, train_outputs)
aggregated_losses.append(single_loss) # ๋ฐ๋ณตํ ๋๋ง๋ค ์ค์ฐจ๋ฅผ ์ถ๊ฐ
if i%25 == 1:
print(f'epoch: {i:3} loss: {single_loss.item():10.8f}')
optimizer.zero_grad()
single_loss.backward() # ๊ฐ์ค์น ์
๋ฐ์ดํธ
optimizer.step() # ๊ธฐ์ธ๊ธฐ ์
๋ฐ์ดํธ
print(f'epoch: {i:3} loss: {single_loss.item():10.10f}') # 25 ์ํฌํฌ๋ง๋ค ์ค์ฐจ ์ถ๋ ฅ
(10) ํ ์คํธ ๋ฐ์ดํฐ์ ์ผ๋ก ์์ธก
# ์์ธก
test_outputs = test_outputs.to(device = device, dtype = torch.int64)
with torch.no_grad() :
y_val = model(categorical_test_data)
loss = loss_function(y_val, test_outputs)
print(f'Loss : {loss:.8f}')
print(y_val[:5]) # 5๊ฐ์ ๊ฐ์ ์ถซ๋ ฅ
# ๋ชจ๋ธ ๋คํธ์ํฌ์์ output size = 4 ๋ก ์ง์ ํ๊ธฐ ๋๋ฌธ์, ๊ฐ ํ์ ํ๋์ output ์ ๋ํ ๋ค ๊ฐ์ ๋ด๋ฐ ๊ฐ์ ๋ณด์ฌ์ค
→ ๊ธฐ์กด target ๊ฐ์ด ๋ฒ์ฃผ๊ฐ 4๊ฐ๋ก ์ด๋ฃจ์ด์ง ๊ฐ์ด์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ธ ๋คํธ์ํฌ์์๋ output size ๋ฅผ 4๋ก ์ง์ ํ๊ณ , ๊ฐ ๋ชฉ๋ก์์ ๊ฐ์ฅ ํฐ ๊ฐ์ ํด๋นํ๋ ์ธ๋ฑ์ค ์์น๊ฐ ํด๋น ๋ฒ์ฃผ๋ก ์์ธก๋๋ ๊ฐ์ด๋ค.
โป argmax
- axis=1 : ๊ฐ ๊ฐ๋ก์ถ ์์๋ค๋ผ๋ฆฌ ๋น๊ตํด์ ์ต๋๊ฐ์ ์์น(์ธ๋ฑ์ค) ๋ฅผ ๋ฐํ
- axis=0 : ๊ฐ ์ธ๋ก์ถ ์์๋ค๋ผ๋ฆฌ ๋น๊ตํด์ ์ต๋๊ฐ์ ์์น(์ธ๋ฑ์ค) ๋ฅผ ๋ฐํ
- axis ๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ๋ชจ๋ ์์๋ฅผ ์์๋๋ก 1์ฐจ์ array ๋ก ๊ฐ์ฃผํ์ ๋ ์ต๋๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๋ฐํํ๋ค.
(11) ๋ชจ๋ธ์ฑ๋ฅ ํ๊ฐ
import warnings
warnings.filterwarnings('ignore')
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
test_outputs=test_outputs.cpu().numpy()
print(confusion_matrix(test_outputs,y_val))
print(classification_report(test_outputs,y_val))
print(accuracy_score(test_outputs, y_val))
→ ํ๋ผ๋ฏธํฐ (ํ๋ จ/ํ ์คํธ ๋ฐ์ดํฐ์ ๋ถํ , ์๋์ธต ๊ฐ์ ๋ฐ ํฌ๊ธฐ ๋ฑ) ์ ๋ณ๊ฒฝํ๋ฉด์ ๋ ๋์ ์ฑ๋ฅ ์ฐพ์๋ณด๊ธฐ
'1๏ธโฃ AIโขDS > ๐ Deep learning' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[๋ฅ๋ฌ๋ ํ์ดํ ์น ๊ต๊ณผ์] 5์ฅ ํฉ์ฑ๊ณฑ ์ ๊ฒฝ๋ง โ (0) | 2022.10.06 |
---|---|
[๋ฅ๋ฌ๋ ํ์ดํ ์น ๊ต๊ณผ์] 4์ฅ ๋ฅ๋ฌ๋ ์์ (1) | 2022.10.04 |
[๋ฅ๋ฌ๋ ํ์ดํ ์น ๊ต๊ณผ์] 1์ฅ ๋จธ์ ๋ฌ๋๊ณผ ๋ฅ๋ฌ๋ (0) | 2022.09.22 |
[Pytorch ๋ฅ๋ฌ๋ ์ ๋ฌธ] ํ์ดํ ์น ๊ธฐ์ด (0) | 2022.09.14 |
[์ธ๊ณต์ง๋ฅ] ๋ฅ๋ฌ๋ ๋ชจ๋ธ ๊ฒฝ๋ํ (0) | 2022.06.21 |
๋๊ธ