Pytorch의 Neural Network
Pytorch에서 신경망 구현하기 2020-04-04

Neural Network in Pytorch

딥 러닝 프레임워크인 Pytorch에선 신경망 구축을 위한 API를 제공합니다. 이는 torch.nn 패키지를 import 하여 사용 가능합니다.

import torch
import torch.nn as nn
import torch.nn.functional as F

이번 시간의 목차는 다음과 같습니다.

  • 신경망 클래스 선언하기
  • 신경망 클래스의 멤버 변수, 멤버 함수 만들기
  • 신경망 학습시키기
  • 신경망 파라미터 확인하기

신경망 클래스 선언하기

신경망 클래스를 선언하는 방법은 nn.Module상속받음으로써 가능합니다. 이는 신경망 클래스의 기본이 되는 클래스 입니다. 사용 방법은 다음과 같습니다.

class DNN(nn.Module):
  def __init__(self):
    super(DNN, self).__init__()

  def forward(self, x):
    return x

super(클래스명, self).__init__()은 무조건 클래스 생성자에 입력 해 주어야 합니다.

신경망 클래스의 멤버 변수, 멤버 함수 만들기

신경망 클래스의 멤버 변수, 멤버 함수를 선언 하기 전에, 어떻게 신경망을 설계를 할 것인지 먼저 정해야 합니다.

  • 가중치의 크기는 어느 정도로 할 것인지?
  • 신경망을 몇 층으로 설계 할 것인지?
  • Dropout은 몇 퍼센트로 할 것인지?
  • 어떤 방식을 사용 하는 신경망인지? (CNN, RNN 등)
  • 기타 등등...

이에 따라서 신경망 클래스멤버 변수를 어떻게 설정 할 것인지는 천지차이로 달라 질 수 있습니다.

상황 설정

일단 털, 날개의 유무를 통해 종을 분류하는 신경망을 만든다고 가정 해 보겠습니다. 그렇다면 input의 size는 (n, 2) 가 될 것입니다. 그리고 종의 종류가 3개라고 가정 하면, 최종 outputsoftmax 함수를 사용하여 분류된 세가지 값 중에 하나 일 것입니다. 또한, 은닉층을 한 개 놓는다고 가정하고, 활성화 함수로는 ReLU를 사용 하겠습니다. 그리고 Dropout을 이용하여, Overfitting 현상을 막아 보겠습니다. 대충 과정을 요약하면 이렇게 되겠군요.

input -> affine1 -> ReLU -> dropout -> affine2 -> softmax

한 번 구현해 볼까요?

class DNN(nn.Module):
  def __init__(self):
    super(DNN, self).__init__()	# 필수
    self.w1 = nn.Linear(2, 20)	# Linear한 1차원 값의 행렬곱을 할 때 사용 한다.
    self.w2 = nn.Linear(20, 3)  # y = xA + b, bias 값을 가지고 있다.bias 비활성화를 원하면 bias=False를 파라미터에 입력 하면 된다.
    self.relu = nn.ReLU()	# ReLU 활성화 함수
    self.softmax = nn.Softmax(dim=0)	# Softmax 함수
    self.dropout = nn.Dropout(0.5)	# Dropout을 위함
    
  def forward(self, x):	# 값을 도출하는 함수
    y = self.w1(x) + self.bias1
    y = self.relu(y)
    y = self.dropout(y)
    y = self.w2(y) + self.bias2
    y = self.softmax(y)
    return y

신경망 학습 시키기

이제 학습을 시킬 차례입니다. 순서는 다음과 같습니다.

  • 신경망 객체 선언
  • loss function 설정
  • Optimizer 설정
  • 역전파를 통한 반복 학습
model = DNN() # 객체 선언
criterion = torch.nn.CrossEntropyLoss()  # loss function 설정
optim = torch.optim.Adam(model.parameters(), lr=0.01) # Optimizer 설정

x_data = torch.Tensor([
    [0, 0],
    [1, 0],
    [1, 1],
    [0, 0],
    [0, 0],
    [0, 1]
])

y_data = torch.LongTensor([
    0,  # etc
    1,  # mammal
    2,  # birds
    0,
    0,
    2
])

for epoch in range(1000):
  output = model(x_data)	# model의 forward 함수 호출
  loss = criterion(output, y_data)	# loss function으로 값 계산

  optim.zero_grad()	# 변화도를 0으로 만듦
  loss.backward() # 역전파
  optim.step()	# 역전파로 알아낸 변화도를 model에 적용

  print("progress:", epoch, "loss=", loss.item())

for x in x_data:
  y_pred = model(x)	# 결과
  print(y_pred.max(dim=0)[1].item())	# Softmax로 나온 최고 값의 Item 반환

결과는 다음과 같습니다. 원래 분류값과 같습니다.

...
progress: 999 loss= 0.8048997521400452
0
1
2
0
0
2

신경망 파라미터 보기

nn.Module.parameters() 함수를 이용하여, 신경망 내 파라미터를 확인 할 수 있습니다. 이는 iterable한 객체를 반환 합니다. nn.Linear 같은 경우 Bias 값도 같이 가지고 있습니다.

In

for p in model.parameters():
  print(p)

Out

Parameter containing:
tensor([[ 1.7096, -1.7123],
        [-0.6805,  0.0985],
        [ 0.1440,  1.9562],
        [ 1.8654,  0.4950],
        [ 0.5621,  1.7321],
        [ 1.0138,  1.2981],
        [-0.5106, -0.3613],
        [-0.7362,  1.9065],
        [ 0.4817,  1.8496],
        [-0.2222,  0.3298],
        [-0.2911, -0.0461],
        [ 0.0025, -0.4711],
        [ 0.1412,  0.3408],
        [ 1.4825, -1.5597],
        [-0.3180,  1.9836],
        [-1.2678, -1.1919],
        [ 0.2207, -0.2972],
        [ 1.6377, -1.6504],
        [ 1.5434, -1.5627],
        [-0.6680,  0.4963]], requires_grad=True)
Parameter containing:
tensor([-0.0138, -0.3932, -0.1902, -0.0206, -0.0475, -0.0151, -0.3948,  0.5054,
        -0.0722, -0.4243, -0.0933, -0.6166, -0.6943, -0.0642,  0.0584,  1.1297,
        -0.6891, -0.0328, -0.0174, -0.5061], requires_grad=True)
Parameter containing:
tensor([[-4.4640e-01, -9.9519e-02, -1.4001e+00, -1.3389e+00, -1.5929e+00,
         -1.4062e+00, -1.8384e-01, -2.6385e-01, -8.5617e-01, -1.5454e-01,
          2.1536e-01, -1.6306e-01, -1.1615e-01, -1.0810e+00, -8.3832e-01,
          2.2192e-01, -1.3481e-01, -5.9061e-01, -1.2475e+00,  1.1666e-01],
        [ 1.2246e+00, -1.6060e-03, -5.1957e-01,  5.3110e-01, -1.5496e-01,
          6.3452e-02,  9.0574e-03, -2.1007e+00, -1.9217e-01,  1.7074e-01,
          2.0107e-01,  8.5908e-02, -6.8430e-02,  1.3706e+00, -1.3454e+00,
         -1.6898e+00, -7.8466e-02,  1.2772e+00,  1.5808e+00, -4.7245e-02],
        [-7.1529e-01,  2.0121e-01,  6.2016e-01,  3.4047e-01,  5.1581e-01,
          4.6319e-01, -7.1984e-02,  5.3509e-01,  4.9709e-01, -1.2095e-01,
          1.3305e-01, -1.1810e-01, -1.4068e-01, -2.6007e-01,  6.0926e-01,
         -9.6860e-01,  3.2639e-02, -5.9985e-01, -9.6767e-01, -8.5310e-02]],
       requires_grad=True)
Parameter containing:
tensor([ 0.0040, -0.0931, -0.2043], requires_grad=True)

마치며

여러 가지 Loss Function들은 해당 링크에서 확인 할 수 있고, 다른 Optimizer들은 해당 링크에서 확인 할 수 있습니다. 다음 시간에는 PytorchCNN 모델을 설계 하는 방법을 알아 보겠습니다.

Reference