Pytorch Tutorials
- -
1. tensor
๐ธ ๋๋คํ ๊ฐ์ ๊ฐ์ง๋ ํ ์ ์์ฑ
- torch.rand() : 0๊ณผ 1 ์ฌ์ด์ ์ซ์๋ฅผ ๊ท ๋ฑํ๊ฒ ์์ฑ
- torch.rand_like() : ์ฌ์ด์ฆ๋ฅผ ํํ๋ก ์ ๋ ฅํ์ง ์๊ณ ๊ธฐ์กด์ ํ ์๋ก ์ ์
- torch.randn() : ํ๊ท ์ด 0์ด๊ณ ํ์คํธ์ฐจ๊ฐ 1์ธ ๊ฐ์ฐ์์ ์ ๊ท๋ถํฌ๋ฅผ ์ด์ฉํด ์์ฑ
- torch.randn_like() : ์ฌ์ด์ฆ๋ฅผ ํํ๋ก ์ ๋ ฅํ์ง ์๊ณ ๊ธฐ์กด์ ํ ์๋ก ์ ์
- torch.randint() : ์ฃผ์ด์ง ๋ฒ์ ๋ด์ ์ ์๋ฅผ ๊ท ๋ฑํ๊ฒ ์์ฑ, ์๋ฃํ์ torch.float32
- torch.randint_like() : ์ฌ์ด์ฆ๋ฅผ ํํ๋ก ์ ๋ ฅํ์ง ์๊ณ ๊ธฐ์กด์ ํ ์๋ก ์ ์
- torch.randperm() : ์ฃผ์ด์ง ๋ฒ์ ๋ด์ ์ ์๋ฅผ ๋๋คํ๊ฒ ์์ฑ
๐ธ ํน์ ํ ๊ฐ์ ๊ฐ์ง๋ ํ ์ ์์ฑ
- torch.arange() : ์ฃผ์ด์ง ๋ฒ์ ๋ด์ ์ ์๋ฅผ ์์๋๋ก ์์ฑ
- torch.ones() : ์ฃผ์ด์ง ์ฌ์ด์ฆ์ 1๋ก ์ด๋ฃจ์ด์ง ํ ์ ์์ฑ
- torch.zeros() : ์ฃผ์ด์ง ์ฌ์ด์ฆ์ 0์ผ๋ก ์ด๋ฃจ์ด์ง ํ ์ ์์ฑ
- torch.ones_like() : ์ฌ์ด์ฆ๋ฅผ ํํ๋ก ์ ๋ ฅํ์ง ์๊ณ ๊ธฐ์กด์ ํ ์๋ก ์ ์
- torch.zeros_like() : ์ฌ์ด์ฆ๋ฅผ ํํ๋ก ์ ๋ ฅํ์ง ์๊ณ ๊ธฐ์กด์ ํ ์๋ก ์ ์
- torch.linspace() : ์์์ ๊ณผ ๋์ ์ ์ฃผ์ด์ง ๊ฐฏ์๋งํผ ๊ท ๋ฑํ๊ฒ ๋๋ ๊ฐ๊ฒฉ์ ์ ํ๋ฒกํฐ๋ก ์ถ๋ ฅ
- torch.logspace() : ์์์ ๊ณผ ๋์ ์ ์ฃผ์ด์ง ๊ฐฏ์๋งํผ ๋ก๊ทธ๊ฐ๊ฒฉ์ผ๋ก ๋๋ ๊ฐ๊ฒฉ์ ์ ํ๋ฒกํฐ๋ก ์ถ๋ ฅ
2. Dataset๊ณผ DataLoader
2.1 Dataset
PyTorch๋ torch.utils.data.DataLoader ์ torch.utils.data.Dataset ์ ๋ ๊ฐ์ง ๋ฐ์ดํฐ ๊ธฐ๋ณธ ์์๋ฅผ ์ ๊ณตํ์ฌ ๋ฏธ๋ฆฌ ์ค๋นํด๋(pre-loaded) ๋ฐ์ดํฐ์
๋ฟ๋ง ์๋๋ผ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
Dataset ์ ์ํ๊ณผ ์ ๋ต(label)์ ์ ์ฅํ๊ณ ,
DataLoader ๋ Dataset ์ ์ํ์ ์ฝ๊ฒ ์ ๊ทผํ ์ ์๋๋ก ์ํ ๊ฐ๋ฅํ ๊ฐ์ฒด(iterable)๋ก ๊ฐ์๋๋ค.
2.1.1 ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ถํฐ Dataset ๋ก๋
import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda
import matplotlib.pyplot as plt
torchvision์ datasets, models, transforms๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
- torchvision.datasets์๋ MNIST, Fashion-MNIST๋ฑ ๋ค์ํ ๋ฐ์ดํฐ์
์ ๊ณต
- torchvision.models์๋ Alesnet, VGG, ResNet๋ฑ์ ๋ชจ๋ธ ์ ๊ณต
- torchvision.transforms๋ ๋ค์ํ ์ด๋ฏธ์ง ๋ณํ ๊ธฐ๋ฅ๋ค์ ์ ๊ณต
- torchvision.transform.ToTensor์ PIL Image๋ NumPy ndarray ๋ฅผ FloatTensor ๋ก ๋ณํํ๊ณ , ์ด๋ฏธ์ง์ ํฝ์
์ ํฌ๊ธฐ(intensity) ๊ฐ์ [0., 1.] ๋ฒ์๋ก ๋น๋กํ์ฌ ์กฐ์ (scale)
- from torchvision.transforms.Lambda๋ ์ฌ์ฉ์ ์ ์ ๋๋ค(lambda) ํจ์๋ฅผ ์ ์ฉํ๋ค.
training_data = datasets.FashionMNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
)
test_data = datasets.FashionMNIST(
root="data",
train=False,
download=True,
transform=ToTensor()
)
๋ค์ ๋งค๊ฐ๋ณ์๋ค์ ์ฌ์ฉํ์ฌ FashionMNIST ๋ฐ์ดํฐ์
์ ๋ถ๋ฌ์ค๋ ๊ณผ์ ์ด๋ค.
root ๋ ํ์ต/ํ
์คํธ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ ๊ฒฝ๋ก๋ฅผ ์ง์
train ์ ํ์ต์ฉ ๋๋ ํ
์คํธ์ฉ ๋ฐ์ดํฐ์
์ฌ๋ถ๋ฅผ ์ง์
download=True ๋ root์ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ ์ธํฐ๋ท์์ ๋ค์ด๋ก๋
transform ๊ณผ target_transform ์ ํน์ง(feature)๊ณผ ์ ๋ต(label) ๋ณํ(transform)์ ์ง์
Lambda์ lambda๋ ์ฌ๊ธฐ์์๋ ์ ์๋ฅผ ์-ํซ์ผ๋ก ๋ถํธํ๋ ํ
์๋ก ๋ฐ๊พธ๋ ํจ์๋ฅผ ์ ์ํ๋ค. ์ด ํจ์๋ ๋จผ์ (๋ฐ์ดํฐ์
์ ๋ต์ ๊ฐ์์ธ) ํฌ๊ธฐ 10์ง๋ฆฌ ์ ํ
์(zero tensor)๋ฅผ ๋ง๋ค๊ณ , scatter_ ๋ฅผ ํธ์ถํ์ฌ ์ฃผ์ด์ง ์ ๋ต y ์ ํด๋นํ๋ ์ธ๋ฑ์ค์ value=1 ์ ํ ๋นํ๋ค.
2.1.2 Dataset์ ์ํํ์ฌ ์๊ฐํ
Dataset ์ ๋ฆฌ์คํธ(list)์ฒ๋ผ ์ง์ ์ ๊ทผ(index)ํ ์ ์๋ค.
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, cols*rows+1):
sample_idx = torch.randint(len(training_data), size=(1,)).item()
img, label = training_data[sample_idx]
figure.add_subplot(rows, cols, i)
plt.title(labels_map[label])
plt.imshow(img.squeeze(), cmap='gray')
plt.show()
2.2 ํ์ผ์์ ์ฌ์ฉ์ ์ ์ Dataset ์์ฑ
์ฌ์ฉ์ ์ ์ Dataset ํด๋์ค๋ ๋ฐ๋์ 3๊ฐ ํจ์๋ฅผ ๊ตฌํํด์ผ ํ๋ค
: __init__, __len__, and __getitem__
from torch.utils.data import Dataset
import os
import pandas as pd
from torchvision.io import read_image
class CustomImageDataset(Dataset):
def __init__(self, annotation_file, img_dir, trnasform=None, target_transform=None):
self.img_labels = pd.read_csv(annotation_file, names=['file_name', 'label'])
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])
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_transfrom(label)
sample = {"image": image, "label": label}
return sample
- __init__
__init__ ํจ์๋ Dataset ๊ฐ์ฒด๊ฐ ์์ฑ(instantiate)๋ ๋ ํ ๋ฒ๋ง ์คํ๋๋ค.
์ฌ๊ธฐ์๋ ์ด๋ฏธ์ง์ ์ฃผ์ ํ์ผ(annotation_file)์ด ํฌํจ๋ ๋๋ ํ ๋ฆฌ์ ๋ณํ(transform)์ ์ด๊ธฐํํ๋ค.
MNIST๋ฅผ ํ์ผ์์ ๋ถ๋ฌ์ฌ ๊ฒฝ์ฐ MNIST.csv๋ ๋ค์๊ณผ ๊ฐ๋ค.
tshirt1.jpg, 0
tshirt2.jpg, 0
......
ankleboot999.jpg, 9
def __len__(self):
return len(self.img_labels)
- __len__
__len__ ํจ์๋ ๋ฐ์ดํฐ์ ์ ์ํ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
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_transfrom(label)
sample = {"image": image, "label": label}
return sample
- __getitem__
__getitem__ ํจ์๋ ์ฃผ์ด์ง ์ธ๋ฑ์ค idx ์ ํด๋นํ๋ ์ํ์ ๋ฐ์ดํฐ์ ์์ ๋ถ๋ฌ์ค๊ณ ๋ฐํํ๋ค.
์ธ๋ฑ์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก, ๋์คํฌ์์ ์ด๋ฏธ์ง์ ์์น๋ฅผ ์๋ณํ๊ณ ,
read_image ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํ ์๋ก ๋ณํํ๊ณ ,
self.img_labels ์ csv ๋ฐ์ดํฐ๋ก๋ถํฐ ํด๋นํ๋ ์ ๋ต(label)์ ๊ฐ์ ธ์ค๊ณ ,
(ํด๋นํ๋ ๊ฒฝ์ฐ) ๋ณํ(transform) ํจ์๋ค์ ํธ์ถํ ๋ค,
ํ ์ ์ด๋ฏธ์ง์ ๋ผ๋ฒจ์ Python ์ฌ์ (dict)ํ์ผ๋ก ๋ฐํํ๋ค.
2.2.1 ์์
์ํ ๋ฐ์ดํฐ
train_images = np.random.randint(256, size=(20,32,32,3))
train_labels = np.random.randint(2, size=(20,1))
## tensor๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ ์ ์ ๋ณดํต ์ ์ฒ๋ฆฌ ๋ชจ๋์ ๋ถ๋ฌ์ ์ ์ฒ๋ฆฌ ์งํ
# import preprocessing
# train_images, train_labels = preprocessing(train_images, train_labels)
print(train_images,shape, train_labels.shape)
>>> (20, 32, 32, 3) (20, 1)
custom dataset
class CustomDataset(Dataset):
def __init__(self, x_data, y_data, transform=None):
self.x_data = x_data
self.y_data = y_data
self.transform = transform
self.len = len(y_data)
def __getitem__(self, index):
sample = self.x_data[index], self.y_data[index]
if self.transform:
sample = self.transform(sample)
return sample
def __len__(self):
return self.len
transform์ ๋ํด custom class๋ฅผ ๋ง๋ค๊ธฐ
class ToTensor:
def __call__(self, sample):
inputs, labels = sample
inputs = torch.FloatTensor(inputs)
inputs = inputs.permute(2,0,1)
return inputs, torch.LongTensor(labels)
class LinearTensor:
def __init__(self, slope, bias=0):
self.slope = slope
self.bias = bias
def __call__(self, sample):
inputs, labels = sample
inputs = self.slope * inputs + self.bias
return inputs, labels
๋ง๋ class ์ฌ์ฉํ๊ธฐ
trans = tr.Compose([ToTensor(), LinearTensor(2,5)])
dataset = CustomDataset(train_images, train_labels, transform=trans)
train_loader = DataLoader(datset, batch_size, shuffle=True)
custom class์ธ ToTensor()๊ฐ ์๋ torchvision์ tr.ToTensor()์ ์ฐ๊ณ ์ถ์ ๊ฒฝ์ฐ
class MyTransform:
def __call__(self, sample):
inputs, labels = sample
inputs = torch.FloatTensor(inputs)
inputs = inputs.permute(2,0,1)
labels = torch.FloatTensor(labels)
transf = tr.Compose([tr.ToPILImabe(), tr.Resize(128), tr.ToTensor(), tr.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))]
final_output = transf(inputs)
return final_output, labels
2.3 ๊ฐ์ ํด๋์ค ๋ณ ํด๋ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ ๋
./class/cat ./class/lion ๊ฐ์ด ํด๋๊ฐ ๋์ด ์์ ๋
torchvision.datasets.ImageFolder ๋ฐ์ดํฐ ์ ์ฒด๋ฅผ ๋ถ๋ฌ์ค๋ฉด์ ๋ ์ด๋ธ๋ ์๋์ผ๋ก ๋งค๊ฒจ์ง๋ฉด์ ์ ์ฒ๋ฆฌ๊น์ง ๊ฐ๋ฅํ๋ค.
transf = tr.Compose([tr.Resize(16), tr.ToTensor()])
train_data = torchvision.datasets.ImageFolder(root='./class', transform=transf)
train_dataloader = DataLoader(train_data, batch_size=10, shuffle=True, num_workers=2)
3. DataLoader
3.1 DataLodaer๋ก ํ์ต์ฉ ๋ฐ์ดํฐ ์ค๋น
Dataset์ ๋ฐ์ดํฐ์ ์ feature์ ๊ฐ์ ธ์ค๊ณ ํ๋์ ์ํ์ label์ ์ง์ ํ๋ ์ผ์ ํ ๋ฒ์ ํ๋ค.
๋ณดํต ๋ชจ๋ธ์ ํ์ตํ ๋, ์ผ๋ฐ์ ์ผ๋ก ์ํ๋ค์ “๋ฏธ๋๋ฐฐ์น(minibatch)”๋ก ์ ๋ฌํ๊ณ , ๋งค ์ํญ(epoch)๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์์ด์ ๊ณผ์ ํฉ(overfit)์ ๋ง๊ณ , Python์ multiprocessing ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ๊ฒ์ ์๋๋ฅผ ๋์ด๋ ค๊ณ ํ๋ค.
DataLoader ๋ ๊ฐ๋จํ API๋ก ์ด๋ฌํ ๋ณต์กํ ๊ณผ์ ๋ค์ ์ถ์ํํ ์ํ ๊ฐ๋ฅํ ๊ฐ์ฒด(iterable)์ด๋ค.
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)
3.2 DataLoader์ ํตํด ์ํ
DataLoader ์ ๋ฐ์ดํฐ์
์ ๋ถ๋ฌ์จ ๋ค์๋ ํ์์ ๋ฐ๋ผ ๋ฐ์ดํฐ์
์ ์ํ(iterate)ํ ์ ์๋ค.
์๋์ ๊ฐ ์ํ(iter)๋ (๊ฐ๊ฐ batch_size=64 ์ ํน์ง(feature)๊ณผ ์ ๋ต(label)์ ํฌํจํ๋) train_features ์ train_labels ์ ๋ฌถ์(batch)์ ๋ฐํํ๋ค.
shuffle=True ๋ก ์ง์ ํ์ผ๋ฏ๋ก, ๋ชจ๋ ๋ฐฐ์น๋ฅผ ์ํํ ๋ค ๋ฐ์ดํฐ๊ฐ ์์ธ๋ค.
ํ์ด์ฌ ๋ด์ฅํจ์ next( ), iter( )
iter(ํธ์ถ๊ฐ๋ฅํ๊ฐ์ฒด, ๋ฐ๋ณต์๋๋ผ๊ฐ)
next(๋ฐ๋ณต๊ฐ๋ฅํ๊ฐ์ฒด, ๊ธฐ๋ณธ๊ฐ)>> it = iter(range(3)) >> next(it, 10) 0 >> next(it, 10) 1 >> next(it, 10) 2 >> next(it, 10) 10
train_features, train_labels = next(iter(train_dataloader))
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
print(f"Label: {label}")
img = train_features[0].squeeze()
label = train_labels[0]
plt.imshow(img, cmap="gray")
plt.show()
print(f"Label: {label}")
Feature batch shape: torch.Size([64, 1, 28, 28])
Labels batch shape: torch.Size([64])
Label : tensor([0., 0., 0., 0., 0., 0., 0., 1., 0., 0.])
4. ํ์ต ํ๊ฒฝ ์ค์
torch.cuda ๋ฅผ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด CPU๋ฅผ ๊ณ์ ์ฌ์ฉํ๋ค.
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f'Using {device} device')
5. ์ ๊ฒฝ๋ง ๋ชจ๋ธ ๊ตฌ์ถ
์ ๊ฒฝ๋ง ๋ชจ๋ธ์ ์ฐ์ฐ์ ์ํํ๋ ๊ณ์ธต(layer)/๋ชจ๋(module)๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
torch.nn๋ ์ ๊ฒฝ๋ง์ ๊ตฌ์ฑํ๋๋ฐ ํ์ํ ๋ชจ๋ ๊ตฌ์ฑ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
PyTorch์ ๋ชจ๋ ๋ชจ๋์ nn.Module ์ ํ์ ํด๋์ค(subclass)์ด๋ค.
5.1 ์ ๊ฒฝ๋ง ๋ชจ๋ธ ํด๋์ค ์ ์
์ ๊ฒฝ๋ง ๋ชจ๋ธ์ nn.Module ์ ํ์ํด๋์ค๋ก ์ ์ํ๊ณ ,
init ์์ ์ ๊ฒฝ๋ง ๊ณ์ธต๋ค์ ์ด๊ธฐํํ๋ค.
nn.Module ์ ์์๋ฐ์ ๋ชจ๋ ํด๋์ค๋ forward ๋ฉ์๋์ ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ์ฐ์ฐ๋ค์ ๊ตฌํํ๋ค.
from torch import nn
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
NeuralNetwork ์ ์ธ์คํด์ค(instance)๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ device ๋ก ์ด๋์ํจ๋ค.
model = NeuralNetwork().to(device)
print(model)
NeuralNetwork( (flatten): Flatten(start_dim=1, end_dim=-1) (linear_relu_stack): Sequential( (0): Linear(in_features=784, out_features=512, bias=True) (1): ReLU() (2): Linear(in_features=512, out_features=512, bias=True) (3): ReLU() (4): Linear(in_features=512, out_features=10, bias=True) ) )
๋ชจ๋ธ์ ์
๋ ฅ์ ํธ์ถํ๋ฉด ๊ฐ ๋ถ๋ฅ(class)์ ๋ํ ์์(raw) ์์ธก๊ฐ์ด ์๋ 10-์ฐจ์ ํ
์๊ฐ ๋ฐํ๋๋ค.
์์ ์์ธก๊ฐ์ nn.Softmax ๋ชจ๋์ ์ธ์คํด์ค์ ํต๊ณผ์์ผ ์์ธก ํ๋ฅ ์ ์ป๋๋ค.
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")
>>> Predicted class: tensor([6])
5.1.1 Layer
Layer๋ค์์ ์ด๋ค ์ผ์ด ๋ฐ์ํ๋์ง ํ์ธํด ๋ณด๊ธฐ ์ํด 28X28ํฌ๊ธฐ์ ์ด๋ฏธ์ง 3๊ฐ๋ก ๊ตฌ์ฑ๋ ๋ฏธ๋๋ฐฐ์น๋ฅผ ์ด์ฉํ๊ฒ ๋ค.
input_image = torch.rand(3,28,28)
print(input_image.size())
>>> torch.Size([3, 28, 28])
5.1.2 nn.Flatten
Flatten์ ๊ณ์ธต์ ์ด๊ธฐํํ์ฌ ๊ฐ 28x28์ 2D ์ด๋ฏธ์ง๋ฅผ 784 ํฝ์ ๊ฐ์ ๊ฐ๋ ์ฐ์๋ ๋ฐฐ์ด๋ก ๋ณํํ๋ค. (dim=0์ ๋ฏธ๋๋ฐฐ์น ์ฐจ์์ ์ ์ง)
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())
>>> torch.Size([3, 784])
5.1.3 nn.Linear
Linear์ weight์ bias๋ฅผ ์ด์ฉํด ์ ๋ ฅ์ ์ ํ ๋ณํ์ ์ ์ฉํ๋ ๋ชจ๋์ด๋ค.
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())
>>> torch.Size([3, 20])
5.1.4 nn.ReLU
Activation function์ ์ ํ ์ํ์ ๋น์ ํ์ฑ์ ๋์ ํ์ฌ ์ ๊ฒฝ๋ง์ด ๋ค์ํ ํ์์ ํ์ตํ ์ ์๋๋ก ํ๋ค.
hidden1 = nn.ReLU()(hidden1)
5.1.5 nn.Sequential
nn.Sequential ์ ์์๋ฅผ ๊ฐ๋ ๋ชจ๋์ ์ปจํ
์ด๋์ด๋ค.
sequential container๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ seq_modules ์ ๊ฐ์ ์ ๊ฒฝ๋ง์ ๋น ๋ฅด๊ฒ ๋ง๋ค ์ ์๋ค.
seq_modules = nn.Sequential(
flatten,
layer1,
nn.ReLU(),
nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)
5.1.6 nn.Softmax
์ ๊ฒฝ๋ง์ ๋ง์ง๋ง ์ ํ ๊ณ์ธต์ [-infty, infty] ๋ฒ์์ ๊ฐ(raw value)์ธ logits๋ฅผ ๋ฐํํ๋ค.
nn.Softmax ๋ชจ๋์ logits๋ ๋ชจ๋ธ์ ๊ฐ ๋ถ๋ฅ(class)์ ๋ํ ์์ธก ํ๋ฅ ์ ๋ํ๋ด๋๋ก [0, 1] ๋ฒ์๋ก ๋น๋กํ์ฌ ์กฐ์ ํ๋ค.
dim ๋งค๊ฐ๋ณ์๋ ๊ฐ์ ํฉ์ด 1์ด ๋๋ ์ฐจ์์ ๋ํ๋ธ๋ค.
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)
logits
>>> tensor([[-0.1024, -0.0443, -0.0061, -0.0646, 0.0962, -0.0137, 0.0917, -0.1101,
-0.0819, 0.0465]], grad_fn=<AddmmBackward0>)
pred_probab
>>> tensor([[0.0917, 0.0972, 0.1010, 0.0953, 0.1119, 0.1003, 0.1114, 0.0910, 0.0936,
0.1065]], grad_fn=<SoftmaxBackward0>)
6. Autograd
์ ๊ฒฝ๋ง์ ํต์ฌ์ backpropagation์ด๋ค.
forward propagation์ ๋ค์๊ณผ ๊ฐ์ด ์งํ๋๋ค.
์ ์ ๊ฒฝ๋ง์์ Weight์ bias๊ฐ ์ต์ ํ๋ฅผ ํด์ผํ๋ ๋งค๊ฐ๋ณ์์ด๋ค.
backpropagation์ Weight์ bias๋ฅผ Loss์ ๋ํ weight์ bias์ derivative๋ฅผ ์ด์ฉํด updateํด ๋๊ฐ๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๊ฒ ํ๊ธฐ ์ํด์๋ ๋ณ์๋ค์ ๋ํ loss์ derivative๋ฅผ ๊ณ์ฐํ๊ณ chain rule์ ์ด์ฉํด ์ต์ข ์ ์ผ๋ก ∂loss/∂w์ ∂loss/∂b๋ฅผ ๊ตฌํด์ผ ํ๋ค.
Pytorch์์๋ ์ด๋ฌํ gradient์ ๊ณ์ฐ์ ์๋ ์ง์ํ๋ torch.autograd๊ฐ ์กด์ฌํ๋ค.
์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ ์ฝ๋์ backpropagation ๋ถ๋ถ์์ ํ์ธํ ์ ์๋ค.
7. ๋ชจ๋ธ Hyperparameter ์ต์ ํ, ํ์ต, ๊ฒ์ฆ, ํ ์คํธ
๋ชจ๋ธ๊ณผ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋ ํ์๋, ๋ฐ์ดํฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ต์ ํํ์ฌ ๋ชจ๋ธ์ ํ์ตํ๊ณ , ๊ฒ์ฆํ๊ณ , ํ
์คํธํ ์ฐจ๋ก์ด๋ค.
๋ชจ๋ธ์ ํ์ตํ๋ ๊ณผ์ ์ ๊ฐ epoch๋ง๋ค output์ ์์ธกํ๊ณ , predict์ ์ ๋ต ์ฌ์ด์ ์ค๋ฅ(์์ค(loss))๋ฅผ ๊ณ์ฐํ๊ณ , ๋งค๊ฐ๋ณ์์ ๋ํ ์ค๋ฅ์ ๋ํจ์(derivative)๋ฅผ ์์งํ ๋ค, ๊ฒฝ์ฌํ๊ฐ๋ฒ์ ์ฌ์ฉํ์ฌ ์ด ํ๋ผ๋ฏธํฐ๋ค์ ์ต์ ํ(optimize)ํ๋ ๊ฒ์ด๋ค.
7.1 Hyperparameter
Hyperparameter๋ ๋ชจ๋ธ ์ต์ ํ ๊ณผ์ ์ ์ ์ดํ ์ ์๋ ์กฐ์ ๊ฐ๋ฅํ ๋งค๊ฐ๋ณ์์ด๋ค.
์๋ก ๋ค๋ฅธ ํ์ดํผํ๋ผ๋งคํฐ ๊ฐ์ ๋ชจ๋ธ ํ์ต๊ณผ ์๋ ด์จ(convergence rate)์ ์ํฅ์ ๋ฏธ์น ์ ์๋ค.
epoch - ๋ฐ์ดํฐ์
์ ๋ฐ๋ณตํ๋ ํ์
batch size - ๋งค๊ฐ๋ณ์๊ฐ ๊ฐฑ์ ๋๊ธฐ ์ ์ ๊ฒฝ๋ง์ ํตํด ์ ํ๋ ๋ฐ์ดํฐ ์ํ์ ์
learning rate - ๊ฐ ๋ฐฐ์น/์ํญ์์ ๋ชจ๋ธ์ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ ํ๋ ๋น์จ. ๊ฐ์ด ์์์๋ก ํ์ต ์๋๊ฐ ๋๋ ค์ง๊ณ , ๊ฐ์ด ํฌ๋ฉด ํ์ต ์ค ์์ธกํ ์ ์๋ ๋์์ด ๋ฐ์ํ ์ ์๋ค.
7.2 Loss Function
predict์ ์ค์ ๊ฐ ์ฌ์ด์ ์ค์ฐจ๋ฅผ ์ธก์ ํ๋ฉฐ, ํ์ต ์ค์ ์ด ๊ฐ์ ์ต์ํํ๊ณ ์ ํ๋ค.
์ฃผ์ด์ง ๋ฐ์ดํฐ ์ํ์ ์
๋ ฅ์ผ๋ก ๊ณ์ฐํ ์์ธก๊ณผ ์ ๋ต(label)์ ๋น๊ตํ์ฌ ์์ค(loss)์ ๊ณ์ฐํ๋ค.
์ผ๋ฐ์ ์ธ ์์คํจ์์๋ ํ๊ท ๋ฌธ์ ์ ์ฌ์ฉํ๋ nn.MSELoss(ํ๊ท ์ ๊ณฑ ์ค์ฐจ(MSE; Mean Square Error))๋ ๋ถ๋ฅ(classification)์ ์ฌ์ฉํ๋ nn.LogSoftmax์ nn.CrossEntropyLoss ๋ฑ์ด ์๋ค.
7.3 Optimizer
๊ฐ ํ์ต ๋จ๊ณ์์ ๋ชจ๋ธ์ ์ค๋ฅ๋ฅผ ์ค์ด๊ธฐ ์ํด ๋ชจ๋ธ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ ํ๋ ๊ณผ์ ์ด๋ค.
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
ํ์ต ๋จ๊ณ(loop)์์ ์ต์ ํ๋ ์ธ๋จ๊ณ๋ก ์ด๋ค์ง๋ค.
- optimizer.zero_grad()๋ฅผ ํธ์ถํ์ฌ ๋ชจ๋ธ ๋งค๊ฐ๋ณ์์ ๋ณํ๋๋ฅผ ์ฌ์ค์ ํ๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก gradient๋ ๋ํด์ง๊ธฐ(add up) ๋๋ฌธ์ ์ค๋ณต ๊ณ์ฐ์ ๋ง๊ธฐ ์ํด ๋ฐ๋ณตํ ๋๋ง๋ค ๋ช ์์ ์ผ๋ก 0์ผ๋ก ์ค์ ํ๋ค.
- loss.backwards()๋ฅผ ํธ์ถํ์ฌ prediction loss๋ฅผ backpropagateํ๋ค. PyTorch๋ ๊ฐ ๋งค๊ฐ๋ณ์์ ๋ํ ์์ค์ ๋ณํ๋๋ฅผ ์ ์ฅํ๋ค.
- ๋ณํ๋๋ฅผ ๊ณ์ฐํ ๋ค์๋ optimizer.step()์ ํธ์ถํ์ฌ backpropagation ๋จ๊ณ์์ ์์ง๋ ๋ณํ๋๋ก ๋งค๊ฐ๋ณ์๋ฅผ ์กฐ์ ํฉ๋๋ค.
7.4 train_loop / test_loop
def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
for batch, (X, y) in enumerate(dataloader):
# forward propagation
pred = model(X)
loss = loss_fn(pred, y)
# backpropagation
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
loss, current = loss.item(), batch * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
def test_loop(dataloader, model, loss_fn):
size = len(dataloader.dataset)
num_batches = len(dataloader)
test_loss, correct = 0, 0
with torch.no_grad():
for X, y in dataloader:
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
learning_rate = 1e-3
batch_size = 64
epochs = 5
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
for i in range(epochs):
print(f"Epoch {i+1}\n----------------")
train_loop(train_dataloader, model, loss_fn, optimizer)
test_loop(test_dataloader, model, loss_fn)
print("Done")
>>> Epoch 1
----------------
loss: 2.143001 [ 0/60000]
loss: 2.136818 [ 6400/60000]
loss: 2.114318 [12800/60000]
loss: 2.030327 [19200/60000]
loss: 2.062488 [25600/60000]
loss: 2.009769 [32000/60000]
loss: 1.964789 [38400/60000]
loss: 1.966160 [44800/60000]
loss: 1.953037 [51200/60000]
loss: 1.913669 [57600/60000]
Test Error:
Accuracy: 53.5%, Avg loss: 1.870262
8. ๋ชจ๋ธ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ค๊ธฐ
import torch
import torchvision.models as models
8.1 ๋ชจ๋ธ ๊ฐ์ค์น ์ ์ฅ/๋ถ๋ฌ์ค๊ธฐ
PyTorch ๋ชจ๋ธ์ ํ์ตํ ๋งค๊ฐ๋ณ์๋ฅผ state_dict๋ผ๊ณ ๋ถ๋ฆฌ๋ ๋ด๋ถ ์ํ ์ฌ์ (internal state dictionary)์ torch.save๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์ ์ฅ ํ ์ ์๋ค.
vgg๋ชจ๋ธ ๊ฐ์ค์น ์ ์ฅ
model = models.vgg16(pretrained=True)
torch.save(model.state_dict(), 'model_weights.pth')
๋ชจ๋ธ ๊ฐ์ค์น ๋ถ๋ฌ์ค๊ธฐ
model = models.vgg16() # ๊ธฐ๋ณธ ๊ฐ์ค์น๋ฅผ ๋ถ๋ฌ์ค์ง ์์ผ๋ฏ๋ก pretrained=True๋ฅผ ์ง์ ํ์ง ์์.
model.load_state_dict(torch.load('model_weights.pth'))
model.eval()
8.2 ๋ชจ๋ธ ๊ตฌ์กฐ๊น์ง ์ ์ฅ/๋ถ๋ฌ์ค๊ธฐ
์ ์ฅ
torch.save(model, 'model.pth')
๋ถ๋ฌ์ค๊ธฐ
model = torch.load('model.pth')
'๋ฅ๋ฌ๋' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ์ฑํ ํจ์(Activation function) (0) | 2022.05.15 |
---|---|
[Feature Engineering]- Text Representation_Ngram (0) | 2022.05.05 |
[Feature Engineering]- Text Representation_BoW (0) | 2022.05.02 |
[Feature Engineering]- Interaction Feature(๊ฒฐํฉ ํผ์ณ) (0) | 2022.05.01 |
[Feature Engineering]- Categorical Feature (0) | 2022.04.28 |