본문 바로가기

파이토치

파이토치 합성곱 신경망(CNN) (1)

1. nn.Module을 이용해 모델 생성

■ 합성곱 신경망은 이미지에 대한 특징을 추출(학습)한 다음, 추론을 위해 평탄화한 후 출력층에 데이터를 넣게 된다.

■ CNN에는  합성곱(Conv) 계층과 풀링(Pooling) 계층이 존재한다. '합성곱 계층 - 활성화 함수 계층 - (풀링 계층)' 흐름으로 연결되며, 풀링 계층을 생략하기도 한다.

합성곱 신경망(CNN) (1)

 

합성곱 신경망(CNN) (1)

1. 합성곱 신경망(Convolutional Neural Network, CNN)■ 합성곱 신경망CNN은 컨브넷(convnet)이라고도 부르며 이미지 인식, 음성 등 다양한 곳에 사용된다. 특히 이미지 인식 분야에서 활용도가 높다.■ 인접

hyeon-jae.tistory.com

■ 파이토치는 예를 들어 데이터가 2차원 이미지 데이터이면 합성곱 계층은 nn.Conv2d, 최대 풀링 계층은 nn.MaxPool2d를 사용하고, 추론을 위한 FCN 구조의 계층은 nn.Linear를 사용한다.

■ 예를 들어 CIFAR-10 데이터 셋을 사용해서 nn.ModuleI로 CNN 모델을 설계해 보자.

- CIFAR-10 데이터 셋은 비행기, 자동차, 트럭, 고양이, 개, 말, 새, 개구리 등 10개의 클래스로 구성돼 있으며, 학습 데이터 셋은 각 클래스별 5,000장 이미지, 검증 데이터 셋은 각 클래스별 1,000장의 이미지로 이뤄져 있다.

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms, datasets

BATCH_SIZE = 32
train_dataset = datasets.CIFAR10(root = "../data/CIFAR_10",
                                  train = True,
                                  download = True,
                                  transform = transforms.ToTensor())

test_dataset = datasets.CIFAR10(root = "../data/CIFAR_10",
                                train = False,
                                transform = transforms.ToTensor())

train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
                                            batch_size = BATCH_SIZE,
                                            shuffle = True)

test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
                                          batch_size = BATCH_SIZE,
                                          shuffle = False)
for (X_train, y_train) in train_loader:
    print('X_train:', X_train.size(), 'type:', X_train.type())
    print('y_train:', y_train.size(), 'type:', y_train.type())
    break
    
```#결과#```
X_train: torch.Size([32, 3, 32, 32]) type: torch.FloatTensor
y_train: torch.Size([32]) type: torch.LongTensor
````````````

- x_train의 형상을 보면, 1개의 미니배치에 32 x 32 크기의 이미지 32개로 이뤄진 것을 확인할 수 있다.

- 이때, 채널의 수가 3이므로 이미지는 red, green, blue 즉, RGB 색상으로 이뤄진 컬러 이미지임을 확인할 수 있다.

- 즉, 32 x 32 크기의 컬러 이미지 32개로 이뤄진 것이다.

- 32개의 이미지 데이터 각각에 대해 레이블 값이 1개가 존재하므로, y_train은 32개의 값을 가진다.

■ 만약, MLP를 설계한다면 입력 데이터를 1차원 벡터로 펼쳐서 사용해야 하기 때문에 첫 번째 완전연결 층의 입력은 32 x 32 x 3 = 3,072 개의 차원을 갖는 벡터가 된다.

이렇게 1차원 벡터로 진행할 경우 이미지의 공간 정보가 무시된다. 특히, 채널 수가 1인 흑백 이미지보다 채널 수가 3으로 다양한 색을 나타내는 컬러 이미지의 공간 정보 손실이 더 클 수밖에 없다. 그러므로 MLP 모델보다는 CNN 모델을 사용하는 것이 바람직하다.

- CIFAR-10 이미지 데이터는 32 x 32 x 3으로 32 x 32 크기의 2차원 이미지 3개가 겹쳐 이미지를 형성하므로 28 x 28 크기의 2차원 이미지 1개로 구성된 FashionMNIST 이미지 데이터보다 1차원으로 펼쳤을 때 이미지의 특징을 잃어버리는 것에 더욱 민감할 수밖에 없다. 그러므로 다음과 같은 CNN 모델을 사용하는 것이 바람직하다.

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels = 3, out_channels = 8, 
                               kernel_size = 3, stride=1, padding = 1)
        self.conv2 = nn.Conv2d(8, 16, 3, 1, 1)
        self.pool = nn.MaxPool2d(kernel_size = 2, stride = 2)
        
        self.fc1 = nn.Linear(8 * 8 * 16, 64)
        self.fc2 = nn.Linear(64, 32)
        self.fc3 = nn.Linear(32, 10)
        
        self.bh2d_1 = nn.BatchNorm2d(num_features = 8)
        self.bh2d_2 = nn.BatchNorm2d(16)
        
        self.bh1d_1 = nn.BatchNorm1d(64)
        self.bh1d_2 = nn.BatchNorm1d(32)
        
    def forward(self, x):
        x = self.conv1(x)
        x = self.bh2d_1(x)
        x = F.relu(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.bh2d_2(x)
        x = F.relu(x)
        x = self.pool(x)
        
        x = x.view(-1, 8 * 8 * 16) # 평탄화
        x = self.fc1(x)
        x = self.bh1d_1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = self.bh1d_2(x)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.log_softmax(x)
        return x

nn.Conv2d 메서드를 이용해 컨볼루션 연산을 하는 필터(커널)를 정의한다.

(1) in_channels

- 이때, 채널 수는 입력 이미지의 채널 수와 동일하게 맞춰야 한다. 이 예에서는 입력 이미지는 컬러 이미지라서 채널 수는 3이다. (red, green, blue channel)

- 그러므로, 3개 채널의 픽셀에 대해 동시에 컨볼루션 연산을 진행하기 위해 첫 번째 컨볼루션 계층의 in_channels = 3으로 설정한다. in_channels에는 입력 채널의 개수를 지정한다.

(2) out_channels

- nn.Conv2d의 out_channels은 출력 채널의 개수, 즉 컨볼루션 연산을 진행하는 필터(커널)의 개수이다.

- 여기서 지정한 필터 개수만큼 output의 depth(채널 수)가 정해진다. 필터 개수만큼 앞뒤로 쌓아 피처 맵을 형성하기 때문이다. 이 예에서는 in_channels = 8로 지정했기 때문에 첫 번째 컨볼루션 결과는 depth가 8인 피처맵이 생성된다.

- 필터의 개수가 많을수록 이미지에서 더 복잡한 특징을 학습(추출)할 수 있지만, 모델의 파라미터 개수가 증가한다.

(3) kernel_size, stride, padding

- kernel_size는 컨볼루션 필터의 크기를 설정하는 부분이다. 

- 예를 들어 3 x 3 필터를 사용하고 싶으면 kernel_size = 3 또는 kernel_size = (3, 3)으로 필터의 크기를 지정할 수 있다.

- stride는 필터의 이동 간격, padding은 출력 피처 맵의 크기를 보존하기 위해 입력 데이터의 가장자리에 추가되는 패딩의 크기를 설정하는 부분이다.

- padding = 1로 지정하면 가장자리의 왼쪽, 오른쪽, 위, 아래쪽에 층을 하나 더 만들고, 그 안에는 0을 채운다. 

- 패딩을 지정하지 않는다면, 필터가 이미지 위를 돌아다니면서 겹치는 영역(컨볼루션 연산을 하는 부분)이 구석 부분보다 중앙 부분이 자주 겹치므로, 이미지 구석 부분에 대한 특징 추출이 중앙 부분보다 덜할 수밖에 없다.

- 패딩을 지정하면 이미지 구석(모서리) 부분과 중앙 부분이 컨볼루션 연산되는 횟수를 동일하게 맞출 수 있다.

(4) bias = True

- bias = True는 기본값으로 컨볼루션 연산 이후 bias 값을 더해줄 것인지를 선택하는 옵션이다.

- 만약, Conv2d 레이어 직후에 BatchNorm2d 레이어가 있는 경우 컨볼루션 레이어의 편향은 필요하지 않아 bias = False로 설정해도 된다.

- BatchNorm 레이어에서 평균을 빼기 때문에 bias의 효과가 상쇄된다. 

https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html#disable-bias-for-convolutions-directly-followed-by-a-batch-norm

 

Performance Tuning Guide — PyTorch Tutorials 2.5.0+cu124 documentation

Note Click here to download the full example code Performance Tuning Guide Author: Szymon Migacz Performance Tuning Guide is a set of optimizations and best practices which can accelerate training and inference of deep learning models in PyTorch. Presented

pytorch.org

- 이 예에서는 bias = True로 설정하였다.

■ 첫 번째 Conv2d 함수는 2차원의 입력 이미지 데이터를 컨볼루션 연산하는 필터의 속성을 정의한 것이다. 이제, 두 번째 Conv2d 함수에는 첫 번째 Conv2d 함수의 결과로 나온 피처 맵과 컨볼루션 연산을 진행하는 필터의 속성을 정의한다.

- 두 번째 Conv2d 함수의 in_channels은 첫 번째 컨볼루션 결과, 출력 채널 개수 8이 두 번째 Conv2d의 입장에서는 입력 채널 개수 8이므로 in_channels = 8으로 지정한다.

- 이 예에서는 out_channels = 16으로 지정했다. 그러므로 두 번째 컨볼루션 연산 결과는 depth가 16인 피처 맵이 생성된다.

■ 컨볼루션 연산을 통해 피처 맵이 생성됐을 때, 최대 풀링을 이용해 2차원 피처 맵의 크기를 줄이면서, 피처 맵에서 가장 큰 피처 맵의 값만 사용할 수 있다.

- 이 예에서 사용한 최대 풀링의 크기는 2 x 2이다. 

- 2 x 2 필터가 피처 맵을 지정한 stride 값만큼 이동하면서 2 x 2 = 4개의 값 중 최댓값 1개만 선택하므로 나머지 3개의 값은 버려진다.

컨볼루션 연산 과정이 모두 끝나면, FCN 분류기를 통해 이미지를 분류하기 위해 생성된 최종 피처 맵을 1차원으로 펼쳐 여러 층의 완전연결 계층에 통과시킨다.

■ 컨볼루션 연산을 하는 이유는 이미지 내 주변 픽셀과의 조합을 통해서 이미지의 특징을 추출(학습)하기 위해서이다.

여러 번의 컨볼루션 연산을 통해 산출된 피처 맵은 이미지의 지역 정보를 반영한 결괏값이다.

즉, 피처 맵을 1차원으로 펼쳐도 이미 지역 정보가 반영되어 있으므로, 지역 정보를 전혀 반영하지 못하는 기존 MLP의 문제점을 해결할 수 있다.

■ 이 예에서 최종 피처 맵의 크기는 8 x 8 x 16이므로, view 함수를 통해 이 피처 맵을 1차원으로 평탄화시킨다.

- 최종 피처 맵의 크기가 8 x 8 x 16이 된 이유는

- 먼저, 입력 이미지의 크기 (H, W) = (32, 32)이고, 첫 번째 Conv의 필터 크기는 3 x 3, stride = 1, padding = 1이므로 출력 크기는 OH = (32 + 2 - 3)/1 + 1 = 32, OW = (32 + 2 - 3)/1 + 1 = 32로 32 x 32이며, 출력 채널의 개수를 8로 지정했으므로 첫 번째 컨볼루션 연산으로 생성되는 피처 맵은 32 x 32 x 8이다.

- 그다음, 풀링의 필터 크기는 2 x 2, stride = 2이므로 OH = (32 + 0 - 2)/2 + 1 = 16, OW = (32 + 0 - 2)/2 + 1 = 16이므로 피처 맵의 크기는 다운 샘플링되어 16 x 16 x 8이 된다.

- 따라서 두 번째 합성곱의 입력 채널의 수 in_channels = 8로 설정해야 한다.

- 두 번째 Conv의 필터 크기는 3 x 3, stride = 1, padding = 1이므로 OH = (16 + 2 - 3)/1 + 1 = 16, OW = (16 + 2 - 3)/1 + 1 = 16으로 출력 크기는 16 x 16이 되며, 출력 채널의 개수를 16으로 설정했으므로 두 번째 컨볼루션 연산으로 생성되는 피처 맵의 크기는 16 x 16 x 16이 된다.

- 그다음, 풀링의 필터 크기는 2 x 2, stride = 2이므로 OH = (16 + 0 - 2)/2 + 1 = 8, OW = (16 + 0 - 2)/2 + 1 = 8이므로 피처 맵의 크기는 다운 샘플링되어 8 x 8 x 16이 된다.

- 최종 산출된 피처 맵을 평탄화시키면 첫 번째 완전연결 계층의 노드 수는 8 x 8 x 16 = 1024개가 된다.

■ 순전파 과정을 정의한 forward 함수를 보면, CNN 부분의 흐름은 '합성곱 계층 - 활성화 함수 계층 - (풀링 계층)'으로 흐르고, FCN 부분의 흐름은 '어파인 계층 - (활성화 함수 계층) -.... - 어파인 계층 - 출력층'으로 흘러간다.

- 데이터 셋의 클래스의 개수는 10개이므로 마지막 완전연결 계층의 output의 크기는 10으로 지정해야 한다. 

def initialize_weights(m):
    if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
        nn.init.kaiming_uniform_(m.weight.data, nonlinearity='relu')

- 활성화 함수로 비선형 함수인 relu를 사용하므로, 가중치 초깃값은 He 초깃값을 사용한다. 이때, 위와 같이 가중치 데이터가 있는 Conv2d와 Linear에 He 초깃값을 적용한다.

model = CNN().to(DEVICE)
model.apply(initialize_weights) # He 초깃값 적용
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss()

cf) Conv2d의 가중치 값은 .weight를 통해 확인할 수 있다.

layer = nn.Conv2d(1,2,2,1).to(torch.device('cpu'))
layer
```#결과#```
Conv2d(1, 2, kernel_size=(2, 2), stride=(1, 1))
````````````

weight = layer.weight # Conv2d의 weight 값

describe_tensor(weight)
```#결과#```
형상: torch.Size([2, 1, 2, 2])
값: Parameter containing:
tensor([[[[ 0.3494, -0.1288],
          [ 0.2530,  0.3442]]],


        [[[ 0.3413,  0.0840],
          [-0.3290,  0.2409]]]], requires_grad=True)
dtype: torch.float32
````````````

cf) 이 weight 값은 detach( ) 함수를 통해 꺼내줘야 numpy( ) 변환이 가능하다.

weight = weight.detach()
weight
```#결과#```
tensor([[[[-0.4485,  0.1075],
          [ 0.1829, -0.1226]]],


        [[[ 0.4412, -0.1767],
          [ 0.1863,  0.4597]]]])
````````````

weight = weight.numpy() # 넘파이 변환
weight.shape
```#결과#```
(2, 1, 2, 2)
````````````

weight
```#결과#```
array([[[[ 0.34938955, -0.12882715],
         [ 0.25297606,  0.3441702 ]]],


       [[[ 0.3413334 ,  0.08397621],
         [-0.32903033,  0.2409085 ]]]], dtype=float32)
````````````

■ 생성한 모델이 어떤 계층으로 이뤄져 있는지 확인하고 싶으면 다음과 같이 생성한 모델에 children( )을 적용하면 된다.

print(list(model.children()))
```#결과#```
[Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), Conv2d(8, 16, kernel_size=(3, 3),
stride=(1, 1), padding=(1, 1)), MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode
=False), Linear(in_features=1024, out_features=64, bias=True), Linear(in_features=64, out_features=
32, bias=True), Linear(in_features=32, out_features=10, bias=True), BatchNorm2d(8, eps=1e-05, momen
tum=0.1, affine=True, track_running_stats=True), BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=Tr
ue, track_running_stats=True), BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_
stats=True), BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)]
````````````

■ 이 정보와 모델 구조를 동시에 확인하고 싶으면 생성한 모델에 modules( )를 적용하면 된다.

print(list(model.modules()))
```#결과#```
[CNN(
  (conv1): Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc1): Linear(in_features=1024, out_features=64, bias=True)
  (fc2): Linear(in_features=64, out_features=32, bias=True)
  (fc3): Linear(in_features=32, out_features=10, bias=True)
  (bh2d_1): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (bh2d_2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (bh1d_1): BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (bh1d_2): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
), Conv2d(3, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), Conv2d(8, 16, kernel_size=(3, 
3), stride=(1, 1), padding=(1, 1)), MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_
mode=False), Linear(in_features=1024, out_features=64, bias=True), Linear(in_features=64, out_featu
res=32, bias=True), Linear(in_features=32, out_features=10, bias=True), BatchNorm2d(8, eps=1e-05, m
omentum=0.1, affine=True, track_running_stats=True), BatchNorm2d(16, eps=1e-05, momentum=0.1, affin
e=True, track_running_stats=True), BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_runn
ing_stats=True), BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)]
````````````

■ 텐서플로의 summary( ) 함수처럼 파이토치도 torchsummary의 summary( ) 함수를 통해서 모델 구조를 요약해서 확인할 수 있다. 단, 입력 이미지의 (C, H, W) 정보를 넣어줘야 한다.

from torchsummary import summary 

summary(model, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [-1, 8, 32, 32]             224
       BatchNorm2d-2            [-1, 8, 32, 32]              16
         MaxPool2d-3            [-1, 8, 16, 16]               0
            Conv2d-4           [-1, 16, 16, 16]           1,168
       BatchNorm2d-5           [-1, 16, 16, 16]              32
         MaxPool2d-6             [-1, 16, 8, 8]               0
            Linear-7                   [-1, 64]          65,600
       BatchNorm1d-8                   [-1, 64]             128
            Linear-9                   [-1, 32]           2,080
      BatchNorm1d-10                   [-1, 32]              64
           Linear-11                   [-1, 10]             330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.21
Params size (MB): 0.27
Estimated Total Size (MB): 0.49
----------------------------------------------------------------
````````````

■ CNN 결과와 MLP 결과를 비교하기 위해 다음과 같은 MLP 모델을 정의하자.

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(32 * 32 * 3, 512)
        self.fc2 = nn.Linear(512, 256)
        self.fc3 = nn.Linear(256, 10)
        self.batch_norm1 = nn.BatchNorm1d(512) 
        self.batch_norm2 = nn.BatchNorm1d(256) #
        
    def forward(self, x):
        x = x.view(-1, 32 * 32 * 3)
        x = self.fc1(x)
        x = self.batch_norm1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = self.batch_norm2(x)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.log_softmax(x, dim = 1)
        return x 
        
def mlp_initialize_weights(m): 
    if isinstance(m, nn.Linear):
        nn.init.kaiming_uniform_(m.weight.data, nonlinearity='relu')
        
mlp_model = MLP().to(DEVICE)
mlp_model.apply(mlp_initialize_weights) 
optimizer = torch.optim.Adam(mlp_model.parameters(), lr = 0.001)
criterion = nn.CrossEntropyLoss().to(DEVICE)

MLP vs. CNN

- 두 모델 모두 빠르게 과적합하지만, MLP 모델의 정확도는 50% 정도에 그친 반면, 컨볼루션 연산이 추가된 CNN 모델의 정확도는 65% 정도로 향상된 것을 확인할 수 있다.

 

2. nn.Sequential을 이용해 모델 생성

■ 위에서 정의한 CNN 구조를 nn.Sequential을 이용해 동일하게 만들 수 있다.

다음과 같이 nn.Sequential 객체로 그 안에 각 모듈을 순차적으로 실행하는 구조로 만들 수 있다.

class CNN2(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 8, 3, 1, 1),
            nn.BatchNorm2d(8),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size = 2, stride = 2)
        )
        
        self.layer2 = nn.Sequential(
            nn.Conv2d(8, 16, 3, 1, 1),
            nn.BatchNorm2d(16),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size = 2, stride = 2)
        )
        
        self.layer3 = nn.Sequential(
            nn.Linear(8 * 8 * 16, 64),
            nn.BatchNorm1d(64),
            nn.ReLU(inplace=True),
            nn.Linear(64, 32),
            nn.BatchNorm1d(32),
            nn.ReLU(inplace=True),
            nn.Linear(32, 10),
        )        
    
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = x.view(x.shape[0],-1) # 평탄화
        x = self.layer3(x)
        x = F.log_softmax(x, dim = 1)
        return x

- nn.ReLU( )에는 inplace라는 인수가 있다. 이 inplace 인수를 사용하면 ReLU 함수의 연산을 in-place로 수행해서 연산 속도를 향상시킬 수 있다. 

- 단, inplace를 사용할 경우 원본 텐서가 직접 수정되기 때문에, 원본 텐서를 사용하는 다른 연산에 영향을 줄 수 있다.

model2 = CNN2().to(DEVICE)
summary(model2, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [-1, 8, 32, 32]             224
       BatchNorm2d-2            [-1, 8, 32, 32]              16
              ReLU-3            [-1, 8, 32, 32]               0
         MaxPool2d-4            [-1, 8, 16, 16]               0
            Conv2d-5           [-1, 16, 16, 16]           1,168
       BatchNorm2d-6           [-1, 16, 16, 16]              32
              ReLU-7           [-1, 16, 16, 16]               0
         MaxPool2d-8             [-1, 16, 8, 8]               0
            Linear-9                   [-1, 64]          65,600
      BatchNorm1d-10                   [-1, 64]             128
             ReLU-11                   [-1, 64]               0
           Linear-12                   [-1, 32]           2,080
      BatchNorm1d-13                   [-1, 32]              64
             ReLU-14                   [-1, 32]               0
           Linear-15                   [-1, 10]             330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.31
Params size (MB): 0.27
Estimated Total Size (MB): 0.58
----------------------------------------------------------------
````````````

 

3. 모델 저장 및 로드

https://tutorials.pytorch.kr/beginner/saving_loading_models.html

 

모델 저장하기 & 불러오기

Author: Matthew Inkawhich, 번역: 박정환, 김제필,. 이 문서에서는 PyTorch 모델을 저장하고 불러오는 다양한 방법을 제공합니다. 이 문서 전체를 다 읽는 것도 좋은 방법이지만, 필요한 사용 예의 코드만

tutorials.pytorch.kr

■ 파이토치 모델 저장 및 로드하는 방법으로 torch.save와 torch.load_state_dict가 있다.

■ torch.save와 torch.load는 pickle을 사용하며, torch.save는 지정한 경로에 모델의 state_dict( )을 저장한다. state_dict은 각 계층의 매개변수(가중치와 편향) 텐서를 매핑한 파이썬 딕셔너리 객체이다.

torch.load_state_dict는 지정한 경로에 있는 state_dict( )을 불러온다.

PATH = './fashion_mnist.pth'
torch.save(model2.state_dict(),PATH) # 저장

model3 = CNN2()
model3.load_state_dict(torch.load(PATH)) # 로드

model3 = model3.to(DEVICE)
summary(model3, input_size = (3, 32, 32))
```#결과#```
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [-1, 8, 32, 32]             224
       BatchNorm2d-2            [-1, 8, 32, 32]              16
              ReLU-3            [-1, 8, 32, 32]               0
         MaxPool2d-4            [-1, 8, 16, 16]               0
            Conv2d-5           [-1, 16, 16, 16]           1,168
       BatchNorm2d-6           [-1, 16, 16, 16]              32
              ReLU-7           [-1, 16, 16, 16]               0
         MaxPool2d-8             [-1, 16, 8, 8]               0
            Linear-9                   [-1, 64]          65,600
      BatchNorm1d-10                   [-1, 64]             128
             ReLU-11                   [-1, 64]               0
           Linear-12                   [-1, 32]           2,080
      BatchNorm1d-13                   [-1, 32]              64
             ReLU-14                   [-1, 32]               0
           Linear-15                   [-1, 10]             330
================================================================
Total params: 69,642
Trainable params: 69,642
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.31
Params size (MB): 0.27
Estimated Total Size (MB): 0.58
----------------------------------------------------------------
````````````

 

'파이토치' 카테고리의 다른 글

파이토치 합성곱 신경망(CNN) (2)  (2) 2024.12.06
torch.nn (2)  (0) 2024.12.04
torch.nn (1)  (0) 2024.12.04