๐ ํ์ดํ ์น
- 2017๋
์ด์ ๊ณต๊ฐ๋ ๋ฅ๋ฌ๋ ํ๋ ์์ํฌ
- ๊ฐ๋ฐ์๋ค๊ณผ ์ฐ๊ตฌ์๋ค์ด ์ฝ๊ฒ GPU๋ฅผ ํ์ฉํ์ฌ ์ธ๊ณต ์ ๊ฒฝ๋ง ๋ชจ๋ธ์ ๋ง๋ค๊ณ ํ์ต์ํฌ ์ ์๊ฒ ๋์์ค
- ํ์ด์ค๋ถ์ ์ธ๊ณต์ง๋ฅ ์ฐ๊ตฌํ(AI Research) ๋ฉค๋ฒ๋ค์ด ์ฃผ๋ก ๊ด๋ฆฌ
- ํ์ดํ ์น ํฌ๋ผ: ๋
์์ ์ผ๋ก ์ด์, ์ฌ๋๋ค์ด ์ง๋ฌธ์ ์ฌ๋ฆฌ๋ฉด ํ๋ ์์ํฌ ๊ฐ๋ฐ์๋ฅผ ๋น๋กฏํ ๋ง์ ์ฌ๋์ด ๋ต์ ํด์ฃผ๋ ํ๋ฐํ ๊ต๋ฅ๊ฐ ์ผ์ด๋๊ณ ์์
- ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ์ ์ํ ์ฐ์ฐ ๊ทธ๋ํ๋ฅผ ์ญ ๋ฐ๋ผ์ ๋ฏธ๋ถํ ๋, ํ์ดํ ์น์์๋ backward() ํจ์ ํธ์ถ์ ํตํด ์๋์ผ๋ก ๊ณ์ฐํ ์ ์๋ค.
- ๋ด๋ถ์ ์ผ๋ก CUDA, cuDNN์ด๋ผ๋ API๋ฅผ ํตํด GPU๋ฅผ ํตํ ์ฐ์ฐ์ด ๊ฐ๋ฅํ๊ฒ ํจ -> ์ฐ์ฐ ์๋๊ฐ CPU์ ๋นํด 15๋ฐฐ ์ด์ ๋น ๋ฆ
- CUDA: ์๋น๋์๊ฐ GPU๋ฅผ ํตํ ์ฐ์ฐ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋ API ๋ชจ๋ธ
- cuDNN: CUDA๋ฅผ ์ด์ฉํด ๋ฅ๋ฌ๋ ์ฐ์ฐ์ ๊ฐ์ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๐ ํ์ดํ ์น์์์ ๊ฒฝ์ฌํ๊ฐ๋ฒ
๐ ํ
์(Tensor)
- ํ
์ = ๋ค์ฐจ์ ๋ฐฐ์ด(multidimensional array)
- ํ์ดํ ์น์์ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ์ ๊ธฐ๋ณธ ๋จ์
๐ ํ
์ ์์ฑ
- Shape์ด 2x3์ธ tensor์์ฑ, tensor ์ ์์์๋ ์์์ ๋์๊ฐ ๋ค์ด๊ฐ
import torch
X = torch.Tensor(2,3)
- Tensor๋ฅผ ์์ฑํ๋ฉด์ ์ํ๋ ๊ฐ์ผ๋ก ์ด๊ธฐํํ๋ ๊ฒฝ์ฐ
X = torch.tensor([[1,2,3], [4,5,6]])
๐ backward()
- ํ์ดํ ์น์์ ์๋ ๋ฏธ๋ถ์ ์ํํ๊ธฐ ์ํ ๋ฉ์๋๋ก, ์ญ์ ํ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ฌ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ์ฌ์ฉ. ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ํ์ดํ ์น๋ ์ฐ์ฐ ๊ทธ๋ํ๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ ๊ฐ leaf node์ ๋ํ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐ
๐ ๋จ์ํ ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ
# ๋จผ์ ํ์ดํ ์น๋ฅผ ๋ถ๋ฌ์จ๋ค.
import torch
# x๋ฅผ [2.0, 3.0]์ ๊ฐ์ ๊ฐ์ง ํ
์๋ก ์ด๊ธฐํํด์ฃผ๊ณ ๊ธฐ์ธ๊ธฐ ๊ณ์ฐ์ True๋ก ์ผ๋๋๋ค.
# z = 2x^2+3
x = torch.tensor(data=[2.0, 3.0], requires_grad=True)
y = x**2
z = 2*y + 3
# ๋ชฉํ๊ฐ์ ์ง์
target = torch.tensor([3.0, 4.0])
# z์ ๋ชฉํ๊ฐ์ ์ ๋๊ฐ ์ฐจ์ด๋ฅผ ๊ณ์ฐ
# backward๋ ์ค์นผ๋ผ ๊ฐ์ ๋ํด์ ๋์ํ๊ธฐ ๋๋ฌธ์ ๊ธธ์ด 2์ง๋ฆฌ ํ
์์ธ loss๋ฅผ torch.sum์ ํตํด ํ๋์ ์ซ์๋ก ๋ฐ๊ฟ์ค๋ค.
loss = torch.sum(torch.abs(z - target))
# ์ค์นผ๋ผ ๊ฐ์ด ๋ loss์ ๋ํด backward๋ฅผ ์ ์ฉ
loss.backward()
# ์ฌ๊ธฐ์ y์ z๋ ๊ธฐ์ธ๊ธฐ๊ฐ None์ผ๋ก ๋์ค๋๋ฐ ์ด๋ x, y, z์ค์ x๋ง์ด leaf node์ด๊ธฐ ๋๋ฌธ
print(x.grad, y.grad, z.grad)
- leaf node๋ ๊ณ์ฐ ๊ทธ๋ํ์์์ ๋ ์ง์ , ์ฆ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ๋ ๊ธฐ์ค์ด ๋๋ ํ
์๋ฅผ ์๋ฏธ. ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐํ ๋ ํ์ดํ ์น๋ leaf node์ ๋ํด์๋ง ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ณ์ฐ. backward()๋ฅผ ํธ์ถํ ํ์๋ leaf node์ธ x์ ๋ํด์๋ง .grad์์ฑ์ ๊ธฐ์ธ๊ธฐ๊ฐ ์ ์ฅ๋์ด ์๋ค.
๐ ์ ํํ๊ท๋ถ์ ๋ชจ๋ธ ๋ง๋ค๊ธฐ
1๏ธโฃ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ
# ๋ํ์ด์ ํ์ดํ ์น๋ฅผ ๋ถ๋ฌ์จ๋ค
import numpy as np
import torch
# Neural Network์ ์ฝ์๋ก ์ธ๊ณต์ ๊ฒฝ๋ง ์ฐ์ฐ๋ค์ด ๋ค์ด๊ฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (ex. Linear, Convolution, RNN ๋ฑ๋ฑ)
import torch.nn as nn
# ๋ชจ๋ธ์ ์ต์ ํ ํ๋๋ฐ ํ์ํ ์ต์ ํ ํจ์๋ค์ด ๋ค์ด๊ฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (ex. SGD, ADAM, LBFGS ๋ฑ๋ฑ)
import torch.optim as optim
# ํ
์๋ฅผ ์ด๊ธฐํํ๋ ํจ์๋ค์ด ๋ค์ด๊ฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (ex. uniform, normal, xavier ๋ฑ๋ฑ)
import torch.nn.init as init
# ๋ฐ์ดํฐ๋ ํ์ต ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด ์ฌ์ฉ
import matplotlib.pyplot as plt
2๏ธโฃ ๋ฐ์ดํฐ ์์ฑ
# ๋ฐ์ดํฐ์ ๊ฐ์๋ 1000๊ฐ, ํ์ต ํ์๋ 500ํ๋ก ์ง์
# ์ด๋ ์์๋ก ์ง์ ํ ์์น
num_data = 1000
num_epoch = 500
# ๋ฐ์ดํฐ์ ์ถ๊ฐํ ๋
ธ์ด์ฆ๋ฅผ ์ ๊ท๋ถํฌ๋ฅผ ๋ฐ๋ฅด๊ฒ ๋ง๋ค์ด์ค๋ค.
# ์ด๋ ํ๊ท ์ ๋ํดํธ๋ก 0, ํธ์ฐจ๋ 0.2๋ก ์์๋ก ์ง์
noise = init.normal_(torch.FloatTensor(num_data, 1), std=0.2)
# x๋ -10์์ 10์ผ๋ก uniform ํ๊ฒ ์์ฑ
# ์ด๋ ๊ฒ ๋๋ฉด x๋ 1000x1ํํ๋ฅผ ๊ฐ์ง๊ณ -10์์ 10 ์ฌ์ด์ ๊ฐ๋ค์ uniform ํ๊ฒ ๊ฐ๊ฒ ๋๋ค
x = init.uniform_(torch.Tensor(num_data, 1), -10, 10)
# ์ฐ์ฐ ๊ทธ๋ํ๋ฅผ ์ ์
y = 2*x+3
# y์ ๋
ธ์ด์ฆ๋ฅผ ๋ํด y_noise ๊ฐ์ ๋ง๋ค์ด์ค๋ค
# ํ์ต๋ y_noise๋ฅผ ๋ชฉํ๊ฐ์ผ๋ก ์ฌ์ฉ
# ์ด์ : ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ๋ ์ฌ๋ฌ ์ธก์ ๊ณผ์ ์์ ๋
ธ์ด์ฆ๊ฐ ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ
y_noise = y+noise
3๏ธโฃ ๋ฐ์ดํฐ ์๊ฐํ
# figure์ ํฌ๊ธฐ๋ฅผ ์ง์
plt.figure(figsize=(10,10))
# x์ถ์๋ x๋ฅผ ์ฌ์ฉํ๊ณ y์ถ์๋ y_noise๋ฅผ ์ฌ์ฉํด scatter plot ํด์ค
# ์ด ๋ ์ ์ ํฌ๊ธฐ๋ 7, ์ ์ ์์์ ํ์
plt.scatter(x.numpy(), y_noise.numpy(), s=7, c="gray")
# figure์ x,y์ถ ๋ฒ์๋ฅผ ์ง์
plt.axis([-12, 12, -25, 25])
# figure ์ถ๋ ฅ
plt.show()
4๏ธโฃ ๋ชจ๋ธ, ์์คํจ์, ์ต์ ํํจ์ ์ค์
# ์ ํ ๋ชจ๋ธ ์์ฑ
# ์
๋ ฅ์ผ๋ก ๋ค์ด์ค๋ x๊ฐ 1000x1์ ํํ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ , ์ฌ๊ธฐ์ ํน์ฑ์ ๊ฐ์๋ 1์ด๊ธฐ ๋๋ฌธ์ ์์ 1์ด ๋ค์ด๊ฐ๊ฒ ๋๋ค. Linear(1, ?)
# ์ถ๋ ฅ์ผ๋ก ๊ธฐ๋ํ๋ ๊ฐ ๋ํ 1000x1์ ํํ์ด๊ธฐ ๋๋ฌธ์ ํน์ฑ์ ๊ฐ์๊ฐ 1๊ฐ. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ค์ 1์ด ๋ค์ด๊ฐ๊ฒ ๋๋ค. Linear(?, 1)
model = nn.Linear(1, 1)
# ์์ค ํจ์ ์ง์
# ์์๋ก L1 ์์ค์ ์ง์ (Mean Absolute Error Loss)
loss_func = nn.L1Loss()
# ์ต์ ํ ํจ์ ์ ์ง
# ์ด๋ ์ธ์๋ก ํ์ต์ ๋์์ด ๋๋ ๋ชจ๋ธ์ ๋ณ์(model.parameters())๋ฅผ ์ ๋ฌํ๋ค.
# ํ์ต๋ฅ ์ 0.01๋ก ์์๋ก ์ง์
optimizer = optim.SGD(model.parameters(),lr=0.01)
5๏ธโฃ ๋ชจ๋ธ ํ์ต ๋ฐ ์ค๊ฐ ํ์ธ
# ์์ค์ด ์ด๋ป๊ฒ ๋ณํ๋์ง ํ์ธํ๊ธฐ ์ํด loss_arr๋ฅผ ๋ง๋ค์ด ๊ธฐ๋ก
loss_arr = []
# ๋ชฉํ๊ฐ์ y_noise๋ก ์ง์
label = y_noise
# 500์ผ๋ก ์ง์ ํ๋ ํ์ต ํ์๋งํผ ๋ฐ๋ณต
for i in range(num_epoch):
# ์ด์ ํ์ต์ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ง์ฐ๊ณ , ์ต์ ํ ํจ์ ์ด๊ธฐํ
# ๊ธฐ์ธ๊ธฐ๋ฅผ ์ง์ฐ์ง ์์ผ๋ฉด ๊ธฐ์กด์ ์
๋ฐ์ดํธ ๋๋ฌธ์ ํ์ต์ด ์ ์ด๋ฃจ์ด์ง์ง ์์.
optimizer.zero_grad()
# ์
๋ ฅ๊ฐ x๋ฅผ ๋ชจ๋ธ์ ๋ฃ์ด ๊ฒฐ๊ณผ๊ฐ์ ์ป๋๋ค.
output = model(x)
# ๊ฒฐ๊ณผ๊ฐ๊ณผ ๋ชฉํ๊ฐ์ ์ฐจ์ด๋ฅผ L1 ์์ค ํจ์๋ก ๊ตฌํด์ค๋ค.
loss = loss_func(output, label)
# ์์ค์ ๋ํ ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํ๋ค.
loss.backward()
# ๊ตฌํ ๊ธฐ์ธ๊ธฐ๋ฅผ ์ด์ฉํด ๋ชจ๋ธ์ ๋ณ์๋ฅผ ์
๋ฐ์ดํธ
optimizer.step()
# 10๋ฒ ๋ง๋ค ๋ชจ๋ธ์ ๋ณ์๊ฐ ์ด๋ป๊ฒ ๋ณํ๊ณ ์๋์ง ์ถ๋ ฅ.
if i % 10 == 0:
# ํ์ฌ ์ฐ์ฐ ๊ทธ๋ํ์ ์ํด์๋ x, output ๊ฐ์ detach๋ฅผ ํตํด ๋ถ๋ฆฌํ๊ณ , ํ
์๋ฅผ ๋ํ์ด ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ plt.scatter์ ์ ๋ฌ
plt.scatter(x.detach().numpy(), output.detach().numpy())
plt.axis([-10, -10, -30, -30])
plt.show()
print(loss.data)
# ์์ค์ loss_arr์ ์ถ๊ฐ
loss_arr.append(loss.detach().numpy())
6๏ธโฃ ํ์ต ํ ๋ฐ์ดํฐ์ ๋ชจ๋ธ ๊ฒฐ๊ณผ๊ฐ ํ์ธ
# ํ์ต ํ ๋ฐ์ดํฐ์ ๋ชจ๋ธ ๊ฒฐ๊ณผ๊ฐ ํ์ธ
plt.figure(figsize=(15, 15))
plt.scatter(x.numpy(), y_noise.numpy(), s = 5, c = "gray")
plt.scatter(x.detach().numpy(), output.detach().numpy(), s = 5, c = "red")
plt.axis([-10, 10, -30, 30])
plt.show()
# ์์ค ๊ทธ๋ํ
# matplotlib์ plot ํจ์๋ฅผ ์ด์ฉํด ์์ค์ด ์ด๋ป๊ฒ ์ค์ด๊ฐ๋์ง ํ์ธ
plt.plot(loss_arr)
plt.show()
7๏ธโฃ ํ์ต ํ ๋ชจ๋ธ ๋ณ์ ๊ฐ ํ์ธ
# ํ์ต ํ ๋ชจ๋ธ ๋ณ์ ๊ฐ ํ์ธ
# ํ์ฌ ๋ชจ๋ธ์ weight ์ bias๋ฅผ ๋ณ์๋ก ๊ฐ์ง๊ณ ์๋๋ฐ ๊ทธ ๊ฐ๋ค์ด ํ์ต ํ ์ค์ ๋ช์ธ์ง ์์น์ ์ผ๋ก ํ์ธํด๋ณธ๋ค.
param_list = list(model.parameters())
print("Weight: ", param_list[0].item(), "\nBias: ", param_list[1].item())