์ด๋ฒ ๊ธ์์๋ 30๋ถ ๋ง์ ๋จธ์ ๋ฌ๋ ํ๊ฒฝ์ ์ค์ ํ๊ณ , ์ด๋ฏธ์ง ์ธ์์ ์ํ ์ ๊ฒฝ๋ง์ ๋ง๋ ๋ค, ๋์ผํ ๋คํธ์ํฌ๋ฅผ ๊ทธ๋ํฝ ํ๋ก์ธ์(GPU)์์ ์คํํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋จผ์ ์ ๊ฒฝ๋ง์ด ๋ฌด์์ธ์ง ์ ์ํด ๋ณด๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ์ด๊ฒ์ ์๋ฌผํ์ ์ ๊ฒฝ ๋คํธ์ํฌ, ์ฆ ์ด์์๋ ์ ๊ธฐ์ฒด์ ์ ๊ฒฝ ์ธํฌ ๋คํธ์ํฌ์ ์กฐ์ง ๋ฐ ๊ธฐ๋ฅ ์๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋ ์ํ์ ๋ชจ๋ธ์ด์ ์ํํธ์จ์ด ๋๋ ํ๋์จ์ด ๊ตฌํ์ ๋๋ค. ์ด ๊ฐ๋ ์ ๋์์ ์ผ์ด๋๋ ๊ณผ์ ์ ์ฐ๊ตฌํ๊ณ ์ด๋ฌํ ๊ณผ์ ์ ๋ชจ๋ธ๋งํ๋ ค๊ณ ์๋ํ๋ ๋์ ๋ฐ์ํ์ต๋๋ค.
์ ๊ฒฝ๋ง์ ์ผ๋ฐ์ ์ธ ์๋ฏธ๋ก ํ๋ก๊ทธ๋๋ฐ๋๋ ๊ฒ์ด ์๋๋ผ ํ๋ จ๋ฉ๋๋ค. ํ์ต ๋ฅ๋ ฅ์ ๊ธฐ์กด ์๊ณ ๋ฆฌ์ฆ์ ๋นํด ์ ๊ฒฝ๋ง์ ์ฃผ์ ์ฅ์ ์ค ํ๋์ ๋๋ค. ๊ธฐ์ ์ ์ผ๋ก ํ์ต์ ๋ด๋ฐ ๊ฐ์ ์ฐ๊ฒฐ ๊ณ์๋ฅผ ์ฐพ๋ ๊ฒ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ํ๋ จ ๊ณผ์ ์์ ์ ๊ฒฝ๋ง์ ์ ๋ ฅ ๋ฐ์ดํฐ์ ์ถ๋ ฅ ๋ฐ์ดํฐ ๊ฐ์ ๋ณต์กํ ์ข ์์ฑ์ ์๋ณํ๊ณ ์ผ๋ฐํ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
๊ธฐ๊ณ ํ์ต์ ๊ด์ ์์ ๋ณผ ๋ ์ ๊ฒฝ๋ง์ ํจํด ์ธ์ ๋ฐฉ๋ฒ, ํ๋ณ ๋ถ์, ํด๋ฌ์คํฐ๋ง ๋ฐฉ๋ฒ ๋ฐ ๊ธฐํ ๋ฐฉ๋ฒ์ ํน๋ณํ ๊ฒฝ์ฐ์ ๋๋ค.
ะะฑะพััะดะพะฒะฐะฝะธะต
๋จผ์ ์ฅ๋น๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. Linux ์ด์ ์ฒด์ ๊ฐ ์ค์น๋ ์๋ฒ๊ฐ ํ์ํฉ๋๋ค. ๊ธฐ๊ณ ํ์ต ์์คํ
์ ์๋ํ๋ ๋ฐ ํ์ํ ์ฅ๋น๋ ๋งค์ฐ ๊ฐ๋ ฅํ๊ณ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋น์ฉ์ด ๋ง์ด ๋ญ๋๋ค. ์ข์ ๋จธ์ ์ ๊ฐ์ง๊ณ ์์ง ์์ ๋ถ๋ค์ ํด๋ผ์ฐ๋ ์ ๊ณต ์
์ฒด์ ์ ์์ ์ฃผ๋ชฉํ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. ํ์ํ ์๋ฒ๋ฅผ ๋น ๋ฅด๊ฒ ์๋ํ๊ณ , ์ฌ์ฉํ ์๊ฐ๋งํผ๋ง ๋น์ฉ์ ์ง๋ถํ๋ฉด ๋ฉ๋๋ค.
์ ๊ฒฝ๋ง์ ์์ฑํด์ผ ํ๋ ํ๋ก์ ํธ์์๋ ๋ฌ์์ ํด๋ผ์ฐ๋ ์ ๊ณต์
์ฒด ์ค ํ๋์ ์๋ฒ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ํ์ฌ๋ NVIDIA์ ๊ฐ๋ ฅํ Tesla V100 ๊ทธ๋ํฝ ํ๋ก์ธ์(GPU)๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๊ณ ํ์ต์ ์ํ ์๋์ฉ ํด๋ผ์ฐ๋ ์๋ฒ๋ฅผ ํน๋ณํ ์ ๊ณตํฉ๋๋ค. ๊ฐ๋จํ ๋งํด์, GPU๊ฐ ์๋ ์๋ฒ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ์ฐ์ ์ํด CPU(์ ์๋ ค์ง ์ค์ ์ฒ๋ฆฌ ์ฅ์น)๋ฅผ ์ฌ์ฉํ๋ ์ ์ฌํ ๋น์ฉ์ ์๋ฒ์ ๋นํด ์์ญ ๋ฐฐ ๋ ํจ์จ์ (๋น ๋ฅผ ์ ์์)์ด ๋ ์ ์์ต๋๋ค. ์ด๋ ๊ณ์ฐ์ ๋ ๋น ๋ฅด๊ฒ ๋์ฒํ๋ GPU ์ํคํ
์ฒ์ ๊ธฐ๋ฅ์ผ๋ก ์ธํด ๋ฌ์ฑ๋ฉ๋๋ค.
์๋ ์ค๋ช ๋ ์์ ๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๋ฉฐ์น ๋์ ๋ค์ ์๋ฒ๋ฅผ ๊ตฌ์ ํ์ต๋๋ค.
- SSD ๋์คํฌ 150GB
- RAM 32GB
- Tesla V100 16Gb ํ๋ก์ธ์, 4์ฝ์ด
์ฐ๋ฆฌ ์ปดํจํฐ์ Ubuntu 18.04๋ฅผ ์ค์นํ์ต๋๋ค.
ํ๊ฒฝ ์ค์
์ด์ ์๋ฒ ์์ ์ ํ์ํ ๋ชจ๋ ๊ฒ์ ์ค์นํด ๋ณด๊ฒ ์ต๋๋ค. ์ฐ๋ฆฌ ๊ธฐ์ฌ๋ ์ฃผ๋ก ์ด๋ณด์๋ฅผ ๋์์ผ๋กํ๋ฏ๋ก ์ด๋ณด์์๊ฒ ์ ์ฉํ ๋ช ๊ฐ์ง ์ฌํญ์ ๋ํด ์ด์ผ๊ธฐํ๊ฒ ์ต๋๋ค.
ํ๊ฒฝ์ ์ค์ ํ ๋ ๋ง์ ์์
์ด ๋ช
๋ น์ค์ ํตํด ์ํ๋ฉ๋๋ค. ๋๋ถ๋ถ์ ์ฌ์ฉ์๋ Windows๋ฅผ ์์
OS๋ก ์ฌ์ฉํฉ๋๋ค. ์ด OS์ ํ์ค ์ฝ์์๋ ๋ถ์กฑํ ์ ์ด ๋ง์ต๋๋ค. ๋ฐ๋ผ์ ํธ๋ฆฌํ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
ssh root@server-ip-or-hostname
server-ip-or-hostname ๋์ ์๋ฒ์ IP ์ฃผ์๋ DNS ์ด๋ฆ์ ์ง์ ํ์ญ์์ค. ๋ค์์ผ๋ก ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ๊ณ ์ฐ๊ฒฐ์ ์ฑ๊ณตํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฉ์์ง๊ฐ ๋ํ๋ฉ๋๋ค.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)
ML ๋ชจ๋ธ ๊ฐ๋ฐ์ ์ํ ์ฃผ์ ์ธ์ด๋ Python์
๋๋ค. Linux์์ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ํ๋ซํผ์
์๋ฒ์ ์ค์นํด ๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ ๋ก์ปฌ ํจํค์ง ๊ด๋ฆฌ์๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
sudo apt-get update
์ปฌ ์ค์น(๋ช ๋ น์ค ์ ํธ๋ฆฌํฐ):
sudo apt-get install curl
Anaconda ๋ฐฐํฌํ์ ์ต์ ๋ฒ์ ์ ๋ค์ด๋ก๋ํ์ธ์:
cd /tmp
curl โO https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
์ค์น๋ฅผ ์์ํด ๋ณด๊ฒ ์ต๋๋ค.
bash Anaconda3-2019.10-Linux-x86_64.sh
์ค์น ๊ณผ์ ์์ ๋ผ์ด์ผ์ค ๊ณ์ฝ์ ํ์ธํ๋ผ๋ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค. ์ฑ๊ณต์ ์ผ๋ก ์ค์น๋๋ฉด ๋ค์์ด ํ์๋ฉ๋๋ค.
Thank you for installing Anaconda3!
ํ์ฌ ML ๋ชจ๋ธ ๊ฐ๋ฐ์ ์ํด ๋ง์ ํ๋ ์์ํฌ๊ฐ ์์ฑ๋์์ผ๋ฉฐ, ์ฐ๋ฆฌ๋ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ ์๋๋ฅผ ๋์ด๊ณ ํ์ค ์์ ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ์์์๋ PyTorch๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ๊ฒ ์ต๋๋ค. ์ค์นํด ๋ด ์๋ค:
conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
์ด์ ML ์ ๋ฌธ๊ฐ๋ฅผ ์ํ ์ธ๊ธฐ ์๋ ๊ฐ๋ฐ ๋๊ตฌ์ธ Jupyter Notebook์ ์ถ์ํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์คํ ๊ฒฐ๊ณผ๋ฅผ ์ฆ์ ํ์ธํ ์ ์์ต๋๋ค. Jupyter Notebook์ Anaconda์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ด๋ฏธ ์๋ฒ์ ์ค์น๋์ด ์์ต๋๋ค. ๋ฐ์คํฌํ ์์คํ ์์ ์ฐ๊ฒฐํด์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด ๋จผ์ ํฌํธ 8080์ ์ง์ ํ๋ ์๋ฒ์์ Jupyter๋ฅผ ์์ํฉ๋๋ค.
jupyter notebook --no-browser --port=8080 --allow-root
๋ค์์ผ๋ก Cmder ์ฝ์(์์ ๋ฉ๋ด - ์ ์ฝ์ ๋ํ ์์)์์ ๋ค๋ฅธ ํญ์ ์ด๋ฉด SSH๋ฅผ ํตํด ํฌํธ 8080์ ํตํด ์๋ฒ์ ์ฐ๊ฒฐ๋ฉ๋๋ค.
ssh -L 8080:localhost:8080 root@server-ip-or-hostname
์ฒซ ๋ฒ์งธ ๋ช ๋ น์ ์ ๋ ฅํ๋ฉด ๋ธ๋ผ์ฐ์ ์์ Jupyter๋ฅผ ์ด ์ ์๋ ๋งํฌ๊ฐ ์ ๊ณต๋ฉ๋๋ค.
To access the notebook, open this file in a browser:
file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
Or copy and paste one of these URLs:
http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
or http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
localhost:8080์ ๋ํ ๋งํฌ๋ฅผ ์ฌ์ฉํด ๋ณด๊ฒ ์ต๋๋ค. ์ ์ฒด ๊ฒฝ๋ก๋ฅผ ๋ณต์ฌํ์ฌ PC ๋ก์ปฌ ๋ธ๋ผ์ฐ์ ์ ์ฃผ์ ํ์์ค์ ๋ถ์ฌ๋ฃ์ผ์ธ์. Jupyter Notebook์ด ์ด๋ฆฝ๋๋ค.
์ ๋ ธํธ๋ถ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. New - Notebook - Python 3.
์ฐ๋ฆฌ๊ฐ ์ค์นํ ๋ชจ๋ ๊ตฌ์ฑ ์์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค. ์์ PyTorch ์ฝ๋๋ฅผ Jupyter์ ์ ๋ ฅํ๊ณ ์คํ์ ์คํํด ๋ณด๊ฒ ์ต๋๋ค(์คํ ๋ฒํผ).
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค.
๋น์ทํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ฉด ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑ๋ ๊ฒ์ด๋ฉฐ ์ ๊ฒฝ๋ง ๊ฐ๋ฐ์ ์์ํ ์ ์์ต๋๋ค!
์ ๊ฒฝ๋ง ๋ง๋ค๊ธฐ
์ด๋ฏธ์ง ์ธ์์ ์ํ ์ ๊ฒฝ๋ง์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ๊ธฐ์ด๋ก ์ผ์
์ฐ๋ฆฌ๋ ๊ณต๊ฐ์ ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ CIFAR10 ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ๋ฅผ ํ๋ จํ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์๋ "๋นํ๊ธฐ", "์๋์ฐจ", "์", "๊ณ ์์ด", "์ฌ์ด", "๊ฐ", "๊ฐ๊ตฌ๋ฆฌ", "๋ง", "๋ฐฐ", "ํธ๋ญ" ํด๋์ค๊ฐ ์์ต๋๋ค. CIFAR10์ ์ด๋ฏธ์ง๋ 3x32x32, ์ฆ 3x32 ํฝ์ ์ 32์ฑ๋ ์ปฌ๋ฌ ์ด๋ฏธ์ง์ ๋๋ค.
์์
์์๋ ์ด๋ฏธ์ง ์์
์ ์ํด PyTorch์์ ๋ง๋ ํจํค์ง์ธ torchvision์ ์ฌ์ฉํฉ๋๋ค.
๋ค์ ๋จ๊ณ๋ฅผ ์์๋๋ก ์ํํ๊ฒ ์ต๋๋ค.
- ํ์ต ๋ฐ ํ ์คํธ ๋ฐ์ดํฐ ์ธํธ ๋ก๋ ๋ฐ ์ ๊ทํ
- ์ ๊ฒฝ๋ง ์ ์
- ํ๋ จ ๋ฐ์ดํฐ์ ๋ํ ๋คํธ์ํฌ ํ๋ จ
- ํ ์คํธ ๋ฐ์ดํฐ์ ๋ํ ๋คํธ์ํฌ ํ ์คํธ
- GPU๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ จ๊ณผ ํ ์คํธ๋ฅผ ๋ฐ๋ณตํ์
Jupyter Notebook์์ ์๋์ ๋ชจ๋ ์ฝ๋๋ฅผ ์คํํ๊ฒ ์ต๋๋ค.
CIFAR10 ๋ก๋ ๋ฐ ์ ๊ทํ
Jupyter์์ ๋ค์ ์ฝ๋๋ฅผ ๋ณต์ฌํ๊ณ ์คํํฉ๋๋ค.
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
๋๋ต์ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค.
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Extracting ./data/cifar-10-python.tar.gz to ./data
Files already downloaded and verified
ํ ์คํธ๋ฅผ ์ํด ์ฌ๋ฌ ํ๋ จ ์ด๋ฏธ์ง๋ฅผ ํ์ํด ๋ณด๊ฒ ์ต๋๋ค.
import matplotlib.pyplot as plt
import numpy as np
# functions to show an image
def imshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
์ ๊ฒฝ๋ง ์ ์
๋จผ์ ์ด๋ฏธ์ง ์ธ์์ ์ํ ์ ๊ฒฝ๋ง์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ๊ฐ๋จํ ์ง์ ๊ฐ ๋คํธ์ํฌ์ ๋๋ค. ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์ฌ๋ฌ ๋ ์ด์ด๋ฅผ ํ๋์ฉ ํต๊ณผํ ๋ค์ ์ต์ข ์ ์ผ๋ก ์ถ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
์ฐ๋ฆฌ ํ๊ฒฝ์์ ์ ์ฌํ ๋คํธ์ํฌ๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
๋ํ ์์ค ํจ์์ ์ต์ ํ ํ๋ก๊ทธ๋จ์ ์ ์ํฉ๋๋ค.
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
ํ๋ จ ๋ฐ์ดํฐ์ ๋ํ ๋คํธ์ํฌ ํ๋ จ
์ ๊ฒฝ๋ง ํ๋ จ์ ์์ํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์ฝ๋๋ฅผ ์คํํ ํ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ์ ์ ๊ธฐ๋ค๋ ค์ผ ํ๋ค๋ ์ ์ ์ ์ํ์ธ์. 5๋ถ ์ ๋ ๊ฑธ๋ ธ์ด์. ๋คํธ์ํฌ๋ฅผ ํ๋ จ์ํค๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
for epoch in range(2): # loop over the dataset multiple times
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
if i % 2000 == 1999: # print every 2000 mini-batches
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
๋ค์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
ํ๋ จ๋ ๋ชจ๋ธ์ ์ ์ฅํฉ๋๋ค.
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
ํ ์คํธ ๋ฐ์ดํฐ์ ๋ํ ๋คํธ์ํฌ ํ ์คํธ
์ฐ๋ฆฌ๋ ํ๋ จ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ๋ฅผ ํ๋ จํ์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ๋คํธ์ํฌ๊ฐ ์ ํ ํ์ตํ ๊ฒ์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ ๊ฒฝ๋ง์ด ์ถ๋ ฅํ๋ ํด๋์ค ๋ผ๋ฒจ์ ์์ธกํ๊ณ ๊ทธ๊ฒ์ด ์ฌ์ค์ธ์ง ํ
์คํธํจ์ผ๋ก์จ ์ด๋ฅผ ํ
์คํธํ ๊ฒ์
๋๋ค. ์์ธก์ด ์ ํํ๋ฉด ์ํ์ ์ฌ๋ฐ๋ฅธ ์์ธก ๋ชฉ๋ก์ ์ถ๊ฐํฉ๋๋ค.
ํ
์คํธ ์ธํธ์ ์ด๋ฏธ์ง๋ฅผ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
dataiter = iter(testloader)
images, labels = dataiter.next()
# print images
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
์ด์ ์ ๊ฒฝ๋ง์ ์ด ๊ทธ๋ฆผ์ ๋ฌด์์ด ์๋์ง ๋งํด๋ฌ๋ผ๊ณ ์์ฒญํด ๋ณด๊ฒ ์ต๋๋ค.
net = Net()
net.load_state_dict(torch.load(PATH))
outputs = net(images)
_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
for j in range(4)))
๊ฒฐ๊ณผ๋ ๊ฝค ์ข์ ๋ณด์
๋๋ค. ๋คํธ์ํฌ๋ ์ฌ์ง 4์ฅ ์ค 3์ฅ์ ์ ํํ๊ฒ ์๋ณํ์ต๋๋ค.
์ ์ฒด ๋ฐ์ดํฐ ์ธํธ์์ ๋คํธ์ํฌ๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (
100 * correct / total))
๋คํธ์ํฌ๊ฐ ๋ญ๊ฐ๋ฅผ ์๊ณ ์๋ํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๊ฐ ๋ฌด์์๋ก ํด๋์ค๋ฅผ ๊ฒฐ์ ํ๋ค๋ฉด ์ ํ๋๋ 10%๊ฐ ๋ ๊ฒ์
๋๋ค.
์ด์ ๋คํธ์ํฌ๊ฐ ์ด๋ค ํด๋์ค๋ฅผ ๋ ์ ์๋ณํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()
for i in range(4):
label = labels[i]
class_correct[label] += c[i].item()
class_total[label] += 1
for i in range(10):
print('Accuracy of %5s : %2d %%' % (
classes[i], 100 * class_correct[i] / class_total[i]))
๋คํธ์ํฌ๋ ์๋์ฐจ์ ์ ๋ฐ์ ์๋ณํ๋ ๋ฐ ๊ฐ์ฅ ์ข์ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค. ์ ํ๋๋ 71%์
๋๋ค.
๊ทธ๋์ ๋คํธ์ํฌ๊ฐ ์๋ํ๊ณ ์์ต๋๋ค. ์ด์ ์์ ์ ๊ทธ๋ํฝ ํ๋ก์ธ์(GPU)๋ก ์ ์กํ๊ณ ์ด๋ค ๋ณํ๊ฐ ์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
GPU์์ ์ ๊ฒฝ๋ง ํ๋ จ
๋จผ์ CUDA๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ๊ฒ ์ต๋๋ค. CUDA(Compute Unified Device Architecture)๋ GPU(๊ทธ๋ํฝ ์ฒ๋ฆฌ ์ฅ์น)์ ์ผ๋ฐ ์ปดํจํ ์ ์ํด NVIDIA๊ฐ ๊ฐ๋ฐํ ๋ณ๋ ฌ ์ปดํจํ ํ๋ซํผ์ ๋๋ค. CUDA๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ์๋ GPU์ ์ฑ๋ฅ์ ํ์ฉํ์ฌ ์ปดํจํ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๊ธฐ์ ์ผ๋ก ๊ฐ์ํํ ์ ์์ต๋๋ค. ์ด ํ๋ซํผ์ ์ฐ๋ฆฌ๊ฐ ๊ตฌ๋งคํ ์๋ฒ์ ์ด๋ฏธ ์ค์น๋์ด ์์ต๋๋ค.
๋จผ์ GPU๋ฅผ ์ต์ด์ ๊ฐ์์ cuda ์ฅ์น๋ก ์ ์ํด ๋ณด๊ฒ ์ต๋๋ค.
device = torch . device ( "cuda:0" if torch . cuda . is_available () else "cpu" )
# Assuming that we are on a CUDA machine, this should print a CUDA device:
print ( device )
๋คํธ์ํฌ๋ฅผ GPU๋ก ๋ณด๋ด๊ธฐ:
net.to(device)
๋ํ ๊ฐ ๋จ๊ณ์์ ์ ๋ ฅ๊ณผ ๋ชฉํ๋ฅผ GPU๋ก ๋ณด๋ด์ผ ํฉ๋๋ค.
inputs, labels = data[0].to(device), data[1].to(device)
GPU์์ ๋คํธ์ํฌ๋ฅผ ๋ค์ ํ๋ จ์์ผ ๋ณด๊ฒ ์ต๋๋ค.
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(2): # loop over the dataset multiple times
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data[0].to(device), data[1].to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
if i % 2000 == 1999: # print every 2000 mini-batches
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
์ด๋ฒ์ ๋คํธ์ํฌ ํ๋ จ์ ์ฝ 3๋ถ ์ ๋ ์งํ๋์์ต๋๋ค. ๊ธฐ์กด ํ๋ก์ธ์์์ ๋์ผํ ๋จ๊ณ๊ฐ 5๋ถ ๋์ ์ง์๋์๋ค๋ ์ ์ ๊ธฐ์ตํด ๋ณด๊ฒ ์ต๋๋ค. ์ฐจ์ด๋ ํฌ์ง ์์ต๋๋ค. ์ด๋ ๋คํธ์ํฌ๊ฐ ๊ทธ๋ค์ง ํฌ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ํ๋ จ์ ๋๊ท๋ชจ ๋ฐฐ์ด์ ์ฌ์ฉํ๋ฉด GPU ์๋์ ๊ธฐ์กด ํ๋ก์ธ์์ ์๋ ์ฐจ์ด๊ฐ ์ปค์ง๋๋ค.
๊ทธ๊ฒ ์ ๋ถ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ํด๋ธ ์ผ:
- GPU๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณด๊ณ GPU๊ฐ ์ค์น๋ ์๋ฒ๋ฅผ ์ ํํ์ต๋๋ค.
- ์ฐ๋ฆฌ๋ ์ ๊ฒฝ๋ง์ ์์ฑํ๊ธฐ ์ํ ์ํํธ์จ์ด ํ๊ฒฝ์ ์ค์ ํ์ต๋๋ค.
- ์ฐ๋ฆฌ๋ ์ด๋ฏธ์ง ์ธ์์ ์ํ ์ ๊ฒฝ๋ง์ ๋ง๋ค๊ณ ํ๋ จ์์ผฐ์ต๋๋ค.
- GPU๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ ํ๋ จ์ ๋ฐ๋ณตํ๊ณ ์๋๊ฐ ํฅ์๋์์ต๋๋ค.
๋๊ธ๋ก ์ง๋ฌธ์ ๋ต๋ณํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ถ์ฒ : habr.com