5. 파이토치(PyTorch) 튜토리얼 - 신경망 모델 구성하기

Yeonghyeon·2022년 7월 30일
0
post-custom-banner

본 포스팅은 파이토치(PYTORCH) 한국어 튜토리얼을 참고하여 공부하고 정리한 글임을 밝힙니다.


신경망 모델 구성하기

  • 신경망: 연산을 수행하는 lyaerd와 module로 구성
  • torch.nn: 신경망을 구성하는데 필요한 모든 구성 요소 제공
  • PyTorch의 모든 모듈은 nn.Module의 하위 클래스(subclass)

FashionMNIST 데이터셋의 이미지 분류 신경망 구성

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

학습을 위한 장치 얻기

  • torch.cuda를 사용하여 GPU에서 모델 학습
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

Out:

Using cuda device

클래스 정의하기

  • 신경망 모델을 nn.Module의 하위클래스로 정의
  • __init__에서 신경망 계층 초기화
  • nn.Module을 상속받은 모든 클래스는 forward 메소드에 입력 데이터에 대한 연산 구현
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의 인스턴스를 생성하고 이를 device로 이동한 뒤, 구조(structure) 출력
model = NeuralNetwork().to(device)
print(model)

Out:

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)
  )
)
  • 모델 사용을 위해 입력 데이터를 전달 ➡️ 백그라운드 연산들과 함께 모델의 forward 실행

    • 이때 model.forward() 직접 호출 ❌
  • 모델 입력 호출 시 각 분류(class)에 대한 raw 예측값이 있는 10-차원 텐서가 반환되고, 이를 nn.Softmax 모듈의 인스턴스를 통과시켜 예측 확률을 얻음

X = torch.rand(1, 28, 28, device=device) # 3차원 랜덤 텐서
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")

Out:

tensor([2], device='cuda:0')

모델 계층(Layer)

  • FashionMNIST 모델의 계층
  • 28x28 크기의 이미지 3개로 구성된 미니배치를 가져와, 신경망을 통과할 때 어떤 일이 발생하는지
input_image = torch.rand(3, 28, 28)
print(input_image.size())

Out:

torch.Size([3, 28, 28])

nn.Flatten

  • nn.Flatten 계층 초기화하여 각 28x28의 2D 이미지를 784 픽셀 값을 갖는 연속된 배열로 변환 (dim=0의 미니배치 차원 유지)
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())

Out:

torch.Size([3, 784])

nn.Linear

  • nn.Linear는 가중치(weight)와 편향(bias)을 사용하여 입력에 선형변환(linear transformation)을 적용하는 모듈
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())

Out:

torch.Size([3, 20])

nn.ReLU

= 비선형 활성화: 모델 입력과 출력 사이에 복잡한 관계(mapping) 만들어 선형 변환 후 적용되어 비선형성(nonlinearity) 도입

  • nn.ReLU 말고도 비선형성을 가진 다른 활성화도 도입 가능
print(f"Before ReLU: {hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {hidden1}")

Out:

Before ReLU: tensor([[ 0.0049,  0.2853,  0.1693, -0.2735, -0.0701,  0.0343, -0.6752, -0.2479,
         -0.0830,  0.0630, -0.4482,  0.1797,  0.2182, -0.0486,  0.4651,  0.1920,
         -0.0647,  1.2193, -0.2621, -0.4581],
        [-0.2920,  0.0676,  0.0520,  0.1891, -0.0580, -0.3115, -0.2957, -0.3636,
         -0.1154, -0.1232, -0.4627,  0.2641, -0.0069,  0.0628,  0.3546,  0.5656,
         -0.2520,  0.8359, -0.1429, -0.4318],
        [-0.0435, -0.2776,  0.2480,  0.2754, -0.0964,  0.0246, -0.3559,  0.1068,
         -0.3989,  0.0987, -0.4338, -0.0148,  0.1941, -0.1593,  0.2892,  0.5237,
         -0.1785,  1.1747, -0.1691, -0.2251]], grad_fn=<AddmmBackward0>)


After ReLU: tensor([[0.0049, 0.2853, 0.1693, 0.0000, 0.0000, 0.0343, 0.0000, 0.0000, 0.0000,
         0.0630, 0.0000, 0.1797, 0.2182, 0.0000, 0.4651, 0.1920, 0.0000, 1.2193,
         0.0000, 0.0000],
        [0.0000, 0.0676, 0.0520, 0.1891, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
         0.0000, 0.0000, 0.2641, 0.0000, 0.0628, 0.3546, 0.5656, 0.0000, 0.8359,
         0.0000, 0.0000],
        [0.0000, 0.0000, 0.2480, 0.2754, 0.0000, 0.0246, 0.0000, 0.1068, 0.0000,
         0.0987, 0.0000, 0.0000, 0.1941, 0.0000, 0.2892, 0.5237, 0.0000, 1.1747,
         0.0000, 0.0000]], grad_fn=<ReluBackward0>)

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)

nn.Softmax

  • 신경망의 마지막 선형 계층은 nn.Softmax 모듈에 전달될 ([-infty, infty] 범위의 원시 값(raw value)인) logtis를 반환
  • logits는 모델의 각 class에 대한 예측 확률을 나타내도록 [0,1] 범위로 비례하여 조정(scale)됨
  • dim 매개변수: 갑의 합이 1이 되는 차원 나타냄
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)

모델 매개변수

  • 신경망 내부의 많은 게층들은 매개변수화(parameterize) 됨

    • 즉, 학습 중에 최적화되는 가중치와 편향과 연관지어짐
  • nn.Module을 상속하면 모델 객체 내부의 모든 필드들이 자동으로 추적되며, 모델의 parameters()named_parameters() 메소드로 모든 매개변수 접근 가능

  • 예제) 매개변수의 크기와 값 출력

print(f"Model structure: {model}\n\n")

for name, param in model.named_parameters():
    print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
post-custom-banner

0개의 댓글