뉴비에욤
PyTorch 튜토리얼 3 - 뉴럴 네트워크(신경망, Neural Networks) 본문
2017/07/13 - [Machine Learning/PyTorch] - 윈도우 10 PyTorch 환경 구성 - 설치
2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 1 - PyTorch란?
2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 2 - Autograd : 자동 미분
원문 : http://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#
* 17년도 07월에 초번 번역 후, 파이토치 최신 버전인 0.4.0에 맞추어 갱신 된 번역본
* 최근 갱신일 : 2018-05-02
목 차 ( 초보자 튜토리얼 )
A. 파이토치와 함께하는 딥러닝 : 60분만에 끝장내기!
3. 뉴럴 네트워크
- 네트워크 정의
- 손실 함수
- 역전파
- 가중치 갱신
뉴럴 네트워크 ( 신경망, Neural Networks )
뉴럴 네트워크는 torch.nn 패키지를 이용하여 생성할 수 있다.
이전 포스팅에서 autograd와, autograd를 이용하여 모델을 정의하고 미분을 수행하는 nn 패키지에 대하여 살펴보았다. nn.Module은 여러개의 레이어와 output를 리턴하는 forward(input) 메소드를 포함한다.
아래의 이미지는 디지털 이미지를 식별하는 뉴럴 네트워크이다.
그림 1. Convolutional Neural Network(컨볼루션 뉴럴 네트워크, ConvNet) 그림
위 네트워크는 가장 간단한 feed-forward 네트워크이다. 입력으로 사용된 데이터를 순차적으로 여러 레이어에 전달하고 마지막에 출력을 제공한다.
일반적인 뉴럴 네트워크의 학습 절차는 다음과 같다.
- 학습 가능한 파라미터나 weight(가중치)가 있는 뉴럴 네트워크를 정의 한다.
- 입력 데이터셋에 대한 반복 학습을 진행 한다.
- 네트워크를 통해 입력 값을 처리한다.
- loss(결과가 정확한 값을 기준으로 얼마나 멀리 떨어져 있는지 나타냄)를 계산한다.
- 손실(오차) 계산, = 출력(output)과 정답(targget)의 차이
- 그라디언트(기울기)를 네트워크의 파라미터로 역전파 시킨다.
- 다음과 같이 간단한 갱신 룰을 이용하여 네트워크의 weight를 갱신한다.
- weight = weight - learning_rate * gradient
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 1 input image channel, 6 output channels, 5x5 square convolution
# kernel
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# Max pooling over a (2, 2) window
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# If the size is a square you can only specify a single number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
size = x.size()[1:] # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
10
torch.Size([6, 1, 5, 5])
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
tensor([[-0.0089, -0.0514, 0.0059, 0.1412, -0.1543, 0.0494, -0.0966,
-0.1150, -0.0986, -0.1103]])
net.zero_grad()
out.backward(torch.randn(1, 10))
- torch.Tensor - backward()와 같은 autograd 연산을 지원하는 다차원 배열이며 텐서에 대한 그라디언트(기울기)를 가지고 있다.
- nn.Module - 뉴럴 네트워크 모듈로서 파라미터를 GPU로 옮기거나, 내보내기, 불러오기 등의 보조 작업을 이용하여 파라미터를 캡슐화 하는 편리한 방법이다.
- nn.Parameter - 텐서의 일종, Module에 속성을 할당 될 때 파라미터로 자동 등록 된다.
- autograd.Function - autograd 연산의 forward와 backward에 대한 정의를 구현한다. 모든 Tensor 연산은 최소한 하나의 Function 노드를 생성하는데, 이 노드는 Tensor를 생성하고 기록을 인코딩 하는 여러 함수들에 연결 된다.
- 뉴럴 네트워크의 정의
- 입력 처리 및 backward 호출
- loss 계산
- 네트워크 weights(가중치) 갱신
output = net(input)
target = torch.arange(1, 11) # a dummy target, for example
target = target.view(1, -1) # make it the same shape as output
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
tensor(39.2273)
input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
-> view -> linear -> relu -> linear -> relu -> linear
-> MSELoss
-> loss
print(loss.grad_fn) # MSELoss
print(loss.grad_fn.next_functions[0][0]) # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU
<MseLossBackward object at 0x7fb9f7338780>
<AddmmBackward object at 0x7fb9f73385c0>
<ExpandBackward object at 0x7fb9f73385c0>
net.zero_grad() # zeroes the gradient buffers of all parameters
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)
loss.backward()
print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)
conv1.bias.grad before backward
tensor([ 0., 0., 0., 0., 0., 0.])
conv1.bias.grad after backward
tensor([ 0.0501, 0.1040, -0.1200, 0.0833, 0.0081, 0.0120])
위와 같은 과정을 통해 우리는 손실 함수의 사용법을 살펴 보았다.
나중에 읽어보기
뉴럴 네트워크 패키지는 딥 뉴럴 네트워크의 빌딩 블록을 생성하는 다양한 모듈과 손실 함수들을 포함하고 있다. 이와 관련 된 전체 목록은 다음 링크를 참고하기 바란다.
http://pytorch.org/docs/nn
마지막으로 배워야 하는 항목
- 네트워크의 weights(가중치) 갱신
가중치 갱신 ( Update the weights )
실제로 사용되는 가장 간단한 갱신 룰은 Stochastic Gradient Descent(SGD)이며 다음과 같은 식을 가진다.
weight = weight - learning_rate * gradient
파이썬 코드를 통해 다음과 같이 구현할 수 있다.
- 소스
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data * learning_rate)
그러나 뉴럴 네트워크를 사용할 때 SGD, Nesterov-SGD, Adam, RMSProp 등과 같은 다양한 갱신 룰을 사용하고 싶을 수도 있다. 이러한 룰의 사용을 위해 PyTorch는 위와 같은 갱신 룰을 포함하는 torch.optim 패키지를 제공한다.
해당 패키지는 다음 코드와 같이 매우 간단하게 사용할 수 있다.
- 소스
import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # Does the update
역전파(backprop) 섹션에서 설명한 것처럼 그라디언트는 누적되기 때문에 optimizer.zero_grad()를 이용하여 그라디언트(기울기) 버퍼를 어떻게 수동으로 '0'으로 세팅하는지 살펴보기 바란다.
'Machine Learning > PyTorch' 카테고리의 다른 글
PyTorch 튜토리얼 5 - 데이터 병렬 처리 (1) | 2018.05.01 |
---|---|
PyTorch 튜토리얼 4 - 분류기(classifier) 학습 (1) | 2018.05.01 |
PyTorch 튜토리얼 2 - Autograd : 자동 미분 (3) | 2018.04.30 |
PyTorch 튜토리얼 1 - PyTorch란? (0) | 2018.04.30 |
PyTorch 튜토리얼 16 - 시퀀스 모델 및 장,단기 메모리 네트워크 (0) | 2017.07.25 |