본문 바로가기

Deep Learning & Machine Learning/PyTorch

[PyTorch] tutorial, 4.신경망 모델 구성하기

FashionMNIST 데이터셋의 이미지들을 분류하는 신경망을 구성해보고자 한다.

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

 

학습을 위한 장치 얻기

device = (
    "cuda"
    if torch.cuda.is_available()
    else "mps"
    if torch.backends.mps.is_available()
    else "cpu"
)
print(f"Using {device} device")

 

클래스 정의하기

  • 신경망 모델을 nn.Module의 하위클래스로 정의하고, __init__ 에서 신경망 계층들을 초기화한다.
  • nn.Module 을 상속받은 모든 클래스는 forward 메소드에 입력 데이터에 대한 연산들을 구현한다.
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__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 의 인스턴스(instance)를 생성하고 이를 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()를 직접 호출하면 안된다.
  • 모델에 입력을 전달하여 호출하면 2차원 텐서를 반환한다.
    • 2차원 텐서의 dim=0은 각 분류(class)에 대한 raw 예측값 10개가, dim=1에는 각 출력의 개별 값들이 해당한다.
    • raw 예측값을 nn.Softmax 모듈의 인스턴스에 통과시켜 예측 확률을 얻는다.
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")

 

 

모델 계층(Layer)

  • 28 x 28 크기의 이미지 3개로 구성된 미니배치를 가져와, 신경망을 통과할 때 어떤 일이 발생하는지 알아보고자 한다.
input_image = torch.rand(3,28,28)
print(input_image.size())

 

Out:

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

 

nn.Flatten

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

 

Out:

torch.Size([3, 784])

 

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

  • 비선형 활성화(activation)는 모델의 입-출력 사이에 복잡한 관계(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.0251, -0.0921,  0.2688,  0.0091,  0.0885,  0.1725, -0.0981, -0.3290,
          0.1264, -0.2142,  0.0291,  0.0834,  0.3299,  0.1260,  0.3924, -0.1626,
         -0.3833, -0.3058, -0.0281, -0.1061],
        [ 0.0722, -0.0170,  0.2973, -0.1068, -0.0644,  0.0034, -0.4394, -0.5947,
         -0.2328, -0.3774,  0.3962,  0.0735,  0.5387, -0.0721,  0.0665, -0.0798,
          0.0287, -0.0591,  0.1872,  0.0013],
        [ 0.1833, -0.1361,  0.4334, -0.1708,  0.0088,  0.1179,  0.1551, -0.3565,
         -0.1464, -0.4036,  0.2725, -0.0768,  0.3906,  0.2656,  0.3837, -0.0969,
         -0.3594, -0.2714,  0.0758, -0.0043]], grad_fn=<AddmmBackward0>)


After ReLU: tensor([[0.0000, 0.0000, 0.2688, 0.0091, 0.0885, 0.1725, 0.0000, 0.0000, 0.1264,
         0.0000, 0.0291, 0.0834, 0.3299, 0.1260, 0.3924, 0.0000, 0.0000, 0.0000,
         0.0000, 0.0000],
        [0.0722, 0.0000, 0.2973, 0.0000, 0.0000, 0.0034, 0.0000, 0.0000, 0.0000,
         0.0000, 0.3962, 0.0735, 0.5387, 0.0000, 0.0665, 0.0000, 0.0287, 0.0000,
         0.1872, 0.0013],
        [0.1833, 0.0000, 0.4334, 0.0000, 0.0088, 0.1179, 0.1551, 0.0000, 0.0000,
         0.0000, 0.2725, 0.0000, 0.3906, 0.2656, 0.3837, 0.0000, 0.0000, 0.0000,
         0.0758, 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)인) logits 를 반환한다.
  • logits 는 모델의 각 분류(class)에 대한 예측 확률을 나타내도록 [0, 1] 범위로 비례하여 조정(scale) 된다.
  • dim 매개변수는 값의 합이 1이 되는 차원을 나타낸다.
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)

 

 

모델 매개변수

  • nn.Module 을 상속하면 모델 객체 내부의 모든 필드들이 자동으로 추적(track)되며, 모델의 parameters() 및 named_parameters() 메소드로 모든 매개변수에 접근할 수 있게 된다.
  • 아래의 코드에서는 각 매개변수들을 순회하며(iterate), 매개변수의 크기와 값을 출력한다.
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")

 

Out:

Model structure: 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)
  )
)


Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[ 0.0053,  0.0255,  0.0002,  ...,  0.0179,  0.0238,  0.0260],
        [ 0.0300,  0.0331,  0.0168,  ..., -0.0267, -0.0049,  0.0160]],
       grad_fn=<SliceBackward0>) 

Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([-0.0345, -0.0263], grad_fn=<SliceBackward0>) 

Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[ 0.0078, -0.0284, -0.0307,  ...,  0.0328,  0.0039,  0.0119],
        [ 0.0252, -0.0136, -0.0009,  ...,  0.0348, -0.0379,  0.0106]],
       grad_fn=<SliceBackward0>) 

Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([-0.0032,  0.0172], grad_fn=<SliceBackward0>) 

Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[-0.0141,  0.0060, -0.0353,  ..., -0.0312,  0.0311, -0.0356],
        [ 0.0357, -0.0232, -0.0379,  ...,  0.0124, -0.0329, -0.0377]],
       grad_fn=<SliceBackward0>) 

Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([0.0032, 0.0246], grad_fn=<SliceBackward0>)

 

https://tutorials.pytorch.kr/beginner/basics/buildmodel_tutorial.html

 

신경망 모델 구성하기

파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 신경망은 데이터에 대한 연

tutorials.pytorch.kr