14장 영상 분류 사전 학습 모델 활용하기 2 (ResNet, VGG-19)

  • “부록3 매트플롯립 입문”에서 한글 폰트를 올바르게 출력하기 위한 설치 방법을 설명했다. 설치 방법은 다음과 같다.
!sudo apt-get install -y fonts-nanum* | tail -n 1
!sudo fc-cache -fv
!rm -rf ~/.cache/matplotlib
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 4.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin: 
Processing triggers for fontconfig (2.12.6-0ubuntu2) ...
/usr/share/fonts: caching, new cache contents: 0 fonts, 1 dirs
/usr/share/fonts/truetype: caching, new cache contents: 0 fonts, 3 dirs
/usr/share/fonts/truetype/humor-sans: caching, new cache contents: 1 fonts, 0 dirs
/usr/share/fonts/truetype/liberation: caching, new cache contents: 16 fonts, 0 dirs
/usr/share/fonts/truetype/nanum: caching, new cache contents: 31 fonts, 0 dirs
/usr/local/share/fonts: caching, new cache contents: 0 fonts, 0 dirs
/root/.local/share/fonts: skipping, no such directory
/root/.fonts: skipping, no such directory
/var/cache/fontconfig: cleaning cache directory
/root/.cache/fontconfig: not cleaning non-existent cache directory
/root/.fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded
# 필요 라이브러리 설치
 
!pip install torchviz | tail -n 1
!pip install torchinfo | tail -n 1
Successfully installed torchviz-0.0.2
Successfully installed torchinfo-1.6.5
  • 모든 설치가 끝나면 한글 폰트를 바르게 출력하기 위해 [런타임] -> **[런타임 다시시작]**을 클릭한 다음, 아래 셀부터 코드를 실행해 주십시오.
# 라이브러리 임포트
 
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display
 
# 폰트 관련 용도
import matplotlib.font_manager as fm
 
# Colab, Linux
# 나눔 고딕 폰트의 경로 명시
path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'
font_name = fm.FontProperties(fname=path, size=10).get_name()
 
# Window 
# font_name = "NanumBarunGothic"
 
# Mac
# font_name = "AppleGothic"
# 파이토치 관련 라이브러리
 
import torch
import torch.nn as nn
import torch.optim as optim
from torchinfo import summary
from torchviz import make_dot
from torchvision import models, transforms, datasets
from torch.utils.data import DataLoader
# warning 표시 끄기
import warnings
warnings.simplefilter('ignore')
 
# 기본 폰트 설정
plt.rcParams['font.family'] = font_name  # window font
 
# 기본 폰트 사이즈 변경
plt.rcParams['font.size'] = 14
 
# 기본 그래프 사이즈 변경
plt.rcParams['figure.figsize'] = (6,6)
 
# 기본 그리드 표시
# 필요에 따라 설정할 때는, plt.grid()
plt.rcParams['axes.grid'] = True
plt.rcParams["grid.linestyle"] = ":"
 
# 마이너스 기호 정상 출력
plt.rcParams['axes.unicode_minus'] = False
 
# 넘파이 부동소수점 자릿수 표시
np.set_printoptions(suppress=True, precision=4)
# GPU 디바이스 할당
 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
cuda:0

공통 함수 불러오기

# 공통 함수 다운로드
!git clone https://github.com/wikibook/pythonlibs.git
 
# 공통 함수 불러오기
from pythonlibs.torch_lib1 import *
 
 
# 공통 함수 확인
print(README)
Common Library for PyTorch
Author: M. Akaishi

데이터 준비

# 분류 클래스명 정의
 
classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
 
# 분류 클래스 수는 10
n_output = len(classes)
# Transforms 정의
 
# 학습 데이터용 : 정규화에 반전과 RandomErasing 추가
transform_train = transforms.Compose([
  transforms.Resize(112),
  transforms.RandomHorizontalFlip(p=0.5), 
  transforms.ToTensor(),
  transforms.Normalize(0.5, 0.5), 
  transforms.RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False)
])
 
# 검증 데이터용 : 정규화만 실시
transform = transforms.Compose([
  transforms.Resize(112),
  transforms.ToTensor(),
  transforms.Normalize(0.5, 0.5)
])
# 데이터 취득용 함수 dataset
data_root = './data'
 
train_set = datasets.CIFAR10(
    root = data_root, 
    train = True,
    download = True, 
    transform = transform_train)
 
# 검증 데이터셋
test_set = datasets.CIFAR10(
    root = data_root, 
    train = False, 
    download = True, 
    transform = transform)
Files already downloaded and verified
Files already downloaded and verified
# 배치 사이즈 지정
batch_size = 50
 
# 데이터로더
 
# 훈련용 데이터로더
# 훈련용이므로 셔플을 True로 설정함
train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True)
 
# 검증용 데이터로더
# 검증용은 셔플이 필요하지 않음
test_loader = DataLoader(test_set,  batch_size=batch_size, shuffle=False) 

ResNet18 불러오기

모델 불러오기

#  라이브러리 임포트
from torchvision import models
 
 
# 사전 학습 모델 불러오기
weights = models.ResNet18_Weights.IMAGENET1K_V1
net = models.resnet18(weights = weights)
# pretraind = True로 학습을 마친 파라미터를 동시에 불러오기
# net = models.resnet18(pretrained = True)

모델 구조 확인

# 모델 개요 표시 1
 
print(net)
# net.layer1[0].bn1
ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer2): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer3): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer4): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=1000, bias=True)
)
# 모델 개요 표시 2
net = net.to(device)
summary(net,(100,3,112,112))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
ResNet                                   [100, 1000]               --
├─Conv2d: 1-1                            [100, 64, 56, 56]         9,408
├─BatchNorm2d: 1-2                       [100, 64, 56, 56]         128
├─ReLU: 1-3                              [100, 64, 56, 56]         --
├─MaxPool2d: 1-4                         [100, 64, 28, 28]         --
├─Sequential: 1-5                        [100, 64, 28, 28]         --
│    └─BasicBlock: 2-1                   [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-1                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-2             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-3                    [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-4                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-5             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-6                    [100, 64, 28, 28]         --
│    └─BasicBlock: 2-2                   [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-7                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-8             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-9                    [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-10                 [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-11            [100, 64, 28, 28]         128
│    │    └─ReLU: 3-12                   [100, 64, 28, 28]         --
├─Sequential: 1-6                        [100, 128, 14, 14]        --
│    └─BasicBlock: 2-3                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-13                 [100, 128, 14, 14]        73,728
│    │    └─BatchNorm2d: 3-14            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-15                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-16                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-17            [100, 128, 14, 14]        256
│    │    └─Sequential: 3-18             [100, 128, 14, 14]        8,448
│    │    └─ReLU: 3-19                   [100, 128, 14, 14]        --
│    └─BasicBlock: 2-4                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-20                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-21            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-22                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-23                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-24            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-25                   [100, 128, 14, 14]        --
├─Sequential: 1-7                        [100, 256, 7, 7]          --
│    └─BasicBlock: 2-5                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-26                 [100, 256, 7, 7]          294,912
│    │    └─BatchNorm2d: 3-27            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-28                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-29                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-30            [100, 256, 7, 7]          512
│    │    └─Sequential: 3-31             [100, 256, 7, 7]          33,280
│    │    └─ReLU: 3-32                   [100, 256, 7, 7]          --
│    └─BasicBlock: 2-6                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-33                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-34            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-35                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-36                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-37            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-38                   [100, 256, 7, 7]          --
├─Sequential: 1-8                        [100, 512, 4, 4]          --
│    └─BasicBlock: 2-7                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-39                 [100, 512, 4, 4]          1,179,648
│    │    └─BatchNorm2d: 3-40            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-41                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-42                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-43            [100, 512, 4, 4]          1,024
│    │    └─Sequential: 3-44             [100, 512, 4, 4]          132,096
│    │    └─ReLU: 3-45                   [100, 512, 4, 4]          --
│    └─BasicBlock: 2-8                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-46                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-47            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-48                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-49                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-50            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-51                   [100, 512, 4, 4]          --
├─AdaptiveAvgPool2d: 1-9                 [100, 512, 1, 1]          --
├─Linear: 1-10                           [100, 1000]               513,000
==========================================================================================
Total params: 11,689,512
Trainable params: 11,689,512
Non-trainable params: 0
Total mult-adds (G): 48.54
==========================================================================================
Input size (MB): 15.05
Forward/backward pass size (MB): 1009.64
Params size (MB): 46.76
Estimated Total Size (MB): 1071.46
==========================================================================================
print(net.fc)
print(net.fc.in_features)
print(net.fc.out_features)
Linear(in_features=512, out_features=1000, bias=True)
512
1000

최종 레이어 함수 교체하기

# 난수 고정
torch_seed()
 
# 최종 레이어 함수의 입력 차원수 확인
fc_in_features = net.fc.in_features
 
# 최종 레이어 함수 교체
net.fc = nn.Linear(fc_in_features, n_output)
# 모델 개요 표시 1
print(net)
ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer2): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer3): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer4): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=10, bias=True)
)
# 모델 개요 표시 2
 
net = net.to(device)
summary(net,(100, 3, 224, 224))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
ResNet                                   [100, 10]                 --
├─Conv2d: 1-1                            [100, 64, 112, 112]       9,408
├─BatchNorm2d: 1-2                       [100, 64, 112, 112]       128
├─ReLU: 1-3                              [100, 64, 112, 112]       --
├─MaxPool2d: 1-4                         [100, 64, 56, 56]         --
├─Sequential: 1-5                        [100, 64, 56, 56]         --
│    └─BasicBlock: 2-1                   [100, 64, 56, 56]         --
│    │    └─Conv2d: 3-1                  [100, 64, 56, 56]         36,864
│    │    └─BatchNorm2d: 3-2             [100, 64, 56, 56]         128
│    │    └─ReLU: 3-3                    [100, 64, 56, 56]         --
│    │    └─Conv2d: 3-4                  [100, 64, 56, 56]         36,864
│    │    └─BatchNorm2d: 3-5             [100, 64, 56, 56]         128
│    │    └─ReLU: 3-6                    [100, 64, 56, 56]         --
│    └─BasicBlock: 2-2                   [100, 64, 56, 56]         --
│    │    └─Conv2d: 3-7                  [100, 64, 56, 56]         36,864
│    │    └─BatchNorm2d: 3-8             [100, 64, 56, 56]         128
│    │    └─ReLU: 3-9                    [100, 64, 56, 56]         --
│    │    └─Conv2d: 3-10                 [100, 64, 56, 56]         36,864
│    │    └─BatchNorm2d: 3-11            [100, 64, 56, 56]         128
│    │    └─ReLU: 3-12                   [100, 64, 56, 56]         --
├─Sequential: 1-6                        [100, 128, 28, 28]        --
│    └─BasicBlock: 2-3                   [100, 128, 28, 28]        --
│    │    └─Conv2d: 3-13                 [100, 128, 28, 28]        73,728
│    │    └─BatchNorm2d: 3-14            [100, 128, 28, 28]        256
│    │    └─ReLU: 3-15                   [100, 128, 28, 28]        --
│    │    └─Conv2d: 3-16                 [100, 128, 28, 28]        147,456
│    │    └─BatchNorm2d: 3-17            [100, 128, 28, 28]        256
│    │    └─Sequential: 3-18             [100, 128, 28, 28]        8,448
│    │    └─ReLU: 3-19                   [100, 128, 28, 28]        --
│    └─BasicBlock: 2-4                   [100, 128, 28, 28]        --
│    │    └─Conv2d: 3-20                 [100, 128, 28, 28]        147,456
│    │    └─BatchNorm2d: 3-21            [100, 128, 28, 28]        256
│    │    └─ReLU: 3-22                   [100, 128, 28, 28]        --
│    │    └─Conv2d: 3-23                 [100, 128, 28, 28]        147,456
│    │    └─BatchNorm2d: 3-24            [100, 128, 28, 28]        256
│    │    └─ReLU: 3-25                   [100, 128, 28, 28]        --
├─Sequential: 1-7                        [100, 256, 14, 14]        --
│    └─BasicBlock: 2-5                   [100, 256, 14, 14]        --
│    │    └─Conv2d: 3-26                 [100, 256, 14, 14]        294,912
│    │    └─BatchNorm2d: 3-27            [100, 256, 14, 14]        512
│    │    └─ReLU: 3-28                   [100, 256, 14, 14]        --
│    │    └─Conv2d: 3-29                 [100, 256, 14, 14]        589,824
│    │    └─BatchNorm2d: 3-30            [100, 256, 14, 14]        512
│    │    └─Sequential: 3-31             [100, 256, 14, 14]        33,280
│    │    └─ReLU: 3-32                   [100, 256, 14, 14]        --
│    └─BasicBlock: 2-6                   [100, 256, 14, 14]        --
│    │    └─Conv2d: 3-33                 [100, 256, 14, 14]        589,824
│    │    └─BatchNorm2d: 3-34            [100, 256, 14, 14]        512
│    │    └─ReLU: 3-35                   [100, 256, 14, 14]        --
│    │    └─Conv2d: 3-36                 [100, 256, 14, 14]        589,824
│    │    └─BatchNorm2d: 3-37            [100, 256, 14, 14]        512
│    │    └─ReLU: 3-38                   [100, 256, 14, 14]        --
├─Sequential: 1-8                        [100, 512, 7, 7]          --
│    └─BasicBlock: 2-7                   [100, 512, 7, 7]          --
│    │    └─Conv2d: 3-39                 [100, 512, 7, 7]          1,179,648
│    │    └─BatchNorm2d: 3-40            [100, 512, 7, 7]          1,024
│    │    └─ReLU: 3-41                   [100, 512, 7, 7]          --
│    │    └─Conv2d: 3-42                 [100, 512, 7, 7]          2,359,296
│    │    └─BatchNorm2d: 3-43            [100, 512, 7, 7]          1,024
│    │    └─Sequential: 3-44             [100, 512, 7, 7]          132,096
│    │    └─ReLU: 3-45                   [100, 512, 7, 7]          --
│    └─BasicBlock: 2-8                   [100, 512, 7, 7]          --
│    │    └─Conv2d: 3-46                 [100, 512, 7, 7]          2,359,296
│    │    └─BatchNorm2d: 3-47            [100, 512, 7, 7]          1,024
│    │    └─ReLU: 3-48                   [100, 512, 7, 7]          --
│    │    └─Conv2d: 3-49                 [100, 512, 7, 7]          2,359,296
│    │    └─BatchNorm2d: 3-50            [100, 512, 7, 7]          1,024
│    │    └─ReLU: 3-51                   [100, 512, 7, 7]          --
├─AdaptiveAvgPool2d: 1-9                 [100, 512, 1, 1]          --
├─Linear: 1-10                           [100, 10]                 5,130
==========================================================================================
Total params: 11,181,642
Trainable params: 11,181,642
Non-trainable params: 0
Total mult-adds (G): 181.36
==========================================================================================
Input size (MB): 60.21
Forward/backward pass size (MB): 3973.95
Params size (MB): 44.73
Estimated Total Size (MB): 4078.89
==========================================================================================
# 손실 계산 그래프 시각화
 
criterion = nn.CrossEntropyLoss()
loss = eval_loss(test_loader, device, net, criterion)
g = make_dot(loss, params=dict(net.named_parameters()))
display(g)

svg

# 모델 개요 표시 1
print(net)
ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer2): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer3): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer4): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=10, bias=True)
)
# 모델 개요 표시 2
net = net.to(device)
summary(net,(100,3,112,112))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
ResNet                                   [100, 10]                 --
├─Conv2d: 1-1                            [100, 64, 56, 56]         9,408
├─BatchNorm2d: 1-2                       [100, 64, 56, 56]         128
├─ReLU: 1-3                              [100, 64, 56, 56]         --
├─MaxPool2d: 1-4                         [100, 64, 28, 28]         --
├─Sequential: 1-5                        [100, 64, 28, 28]         --
│    └─BasicBlock: 2-1                   [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-1                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-2             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-3                    [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-4                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-5             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-6                    [100, 64, 28, 28]         --
│    └─BasicBlock: 2-2                   [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-7                  [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-8             [100, 64, 28, 28]         128
│    │    └─ReLU: 3-9                    [100, 64, 28, 28]         --
│    │    └─Conv2d: 3-10                 [100, 64, 28, 28]         36,864
│    │    └─BatchNorm2d: 3-11            [100, 64, 28, 28]         128
│    │    └─ReLU: 3-12                   [100, 64, 28, 28]         --
├─Sequential: 1-6                        [100, 128, 14, 14]        --
│    └─BasicBlock: 2-3                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-13                 [100, 128, 14, 14]        73,728
│    │    └─BatchNorm2d: 3-14            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-15                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-16                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-17            [100, 128, 14, 14]        256
│    │    └─Sequential: 3-18             [100, 128, 14, 14]        8,448
│    │    └─ReLU: 3-19                   [100, 128, 14, 14]        --
│    └─BasicBlock: 2-4                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-20                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-21            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-22                   [100, 128, 14, 14]        --
│    │    └─Conv2d: 3-23                 [100, 128, 14, 14]        147,456
│    │    └─BatchNorm2d: 3-24            [100, 128, 14, 14]        256
│    │    └─ReLU: 3-25                   [100, 128, 14, 14]        --
├─Sequential: 1-7                        [100, 256, 7, 7]          --
│    └─BasicBlock: 2-5                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-26                 [100, 256, 7, 7]          294,912
│    │    └─BatchNorm2d: 3-27            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-28                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-29                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-30            [100, 256, 7, 7]          512
│    │    └─Sequential: 3-31             [100, 256, 7, 7]          33,280
│    │    └─ReLU: 3-32                   [100, 256, 7, 7]          --
│    └─BasicBlock: 2-6                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-33                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-34            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-35                   [100, 256, 7, 7]          --
│    │    └─Conv2d: 3-36                 [100, 256, 7, 7]          589,824
│    │    └─BatchNorm2d: 3-37            [100, 256, 7, 7]          512
│    │    └─ReLU: 3-38                   [100, 256, 7, 7]          --
├─Sequential: 1-8                        [100, 512, 4, 4]          --
│    └─BasicBlock: 2-7                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-39                 [100, 512, 4, 4]          1,179,648
│    │    └─BatchNorm2d: 3-40            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-41                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-42                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-43            [100, 512, 4, 4]          1,024
│    │    └─Sequential: 3-44             [100, 512, 4, 4]          132,096
│    │    └─ReLU: 3-45                   [100, 512, 4, 4]          --
│    └─BasicBlock: 2-8                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-46                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-47            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-48                   [100, 512, 4, 4]          --
│    │    └─Conv2d: 3-49                 [100, 512, 4, 4]          2,359,296
│    │    └─BatchNorm2d: 3-50            [100, 512, 4, 4]          1,024
│    │    └─ReLU: 3-51                   [100, 512, 4, 4]          --
├─AdaptiveAvgPool2d: 1-9                 [100, 512, 1, 1]          --
├─Linear: 1-10                           [100, 10]                 5,130
==========================================================================================
Total params: 11,181,642
Trainable params: 11,181,642
Non-trainable params: 0
Total mult-adds (G): 48.49
==========================================================================================
Input size (MB): 15.05
Forward/backward pass size (MB): 1008.85
Params size (MB): 44.73
Estimated Total Size (MB): 1068.63
==========================================================================================

학습과 결과 평가

초기 설정

# 난수 고정
torch_seed()
 
# 사전 학습 모델 불러오기
weights = models.ResNet18_Weights.IMAGENET1K_V1
net = models.resnet18(weights = weights)
 
# 최종 레이어 함수 입력 차원수 확인
fc_in_features = net.fc.in_features
 
# 최종 레이어 함수 교체
net.fc = nn.Linear(fc_in_features, n_output)
 
# GPU 사용
net = net.to(device)
 
# 학습률
lr = 0.001
 
# 손실 함수 정의
criterion = nn.CrossEntropyLoss()
 
# 최적화 함수 정의
optimizer = optim.SGD(net.parameters(), lr=lr, momentum=0.9)
 
# history 파일 초기화
history = np.zeros((0, 5))

학습

# 학습
num_epochs = 5
history = fit(net, optimizer, criterion, num_epochs, 
        train_loader, test_loader, device, history)
  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [1/5], loss: 0.60050 acc: 0.79544 val_loss: 0.30019, val_acc: 0.89720



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [2/5], loss: 0.32100 acc: 0.88816 val_loss: 0.23029, val_acc: 0.92010



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [3/5], loss: 0.25802 acc: 0.91102 val_loss: 0.19530, val_acc: 0.93400



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [4/5], loss: 0.21796 acc: 0.92298 val_loss: 0.17268, val_acc: 0.94230



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [5/5], loss: 0.19113 acc: 0.93398 val_loss: 0.17815, val_acc: 0.94070

학습 결과 평가

# 결과 요약
evaluate_history(history)
초기상태 : 손실 : 0.30019  정확도 : 0.89720
최종상태 : 손실 : 0.17815 정확도 : 0.94070



png

png

# 이미지와 정답, 예측 결과를 함께 표시
show_images_labels(test_loader, classes, net, device)
len(images) =  50



png

VGG-19-BN 활용하기

모델 불러오기

# 사전 학습 모델 불러오기
from torchvision import models
 
weights = models.VGG19_BN_Weights.DEFAULT
net = models.vgg19_bn(weights = weights)

모델 구조 확인

# 모델 개요 표시 1
print(net)
VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
    (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (5): ReLU(inplace=True)
    (6): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (7): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (9): ReLU(inplace=True)
    (10): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (12): ReLU(inplace=True)
    (13): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (14): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (16): ReLU(inplace=True)
    (17): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (19): ReLU(inplace=True)
    (20): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (21): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (22): ReLU(inplace=True)
    (23): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (24): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (25): ReLU(inplace=True)
    (26): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (27): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (28): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (29): ReLU(inplace=True)
    (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (31): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (32): ReLU(inplace=True)
    (33): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (34): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (35): ReLU(inplace=True)
    (36): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (37): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (38): ReLU(inplace=True)
    (39): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (40): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (41): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (42): ReLU(inplace=True)
    (43): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (44): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (45): ReLU(inplace=True)
    (46): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (47): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (48): ReLU(inplace=True)
    (49): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (50): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (51): ReLU(inplace=True)
    (52): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

최종 레이어 함수는classifier[6]임을 알 수 있다.

# 최종 레이어 함수 확인
print(net.classifier[6])
 
Linear(in_features=4096, out_features=1000, bias=True)

최종 레이어 함수 교체

# 난수 고정
torch_seed()
 
# 최종 레이어 함수 교체
in_features = net.classifier[6].in_features
net.classifier[6] = nn.Linear(in_features, n_output)
 
# features 마지막의 MaxPool2d 제거
net.features = net.features[:-1]
 
# AdaptiveAvgPool2d 제거
net.avgpool = nn.Identity()
# 모델 개요 표시 2
net = net.to(device)
summary(net,(100,3,112,112))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
VGG                                      [100, 10]                 --
├─Sequential: 1-1                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-1                       [100, 64, 112, 112]       1,792
│    └─BatchNorm2d: 2-2                  [100, 64, 112, 112]       128
│    └─ReLU: 2-3                         [100, 64, 112, 112]       --
│    └─Conv2d: 2-4                       [100, 64, 112, 112]       36,928
│    └─BatchNorm2d: 2-5                  [100, 64, 112, 112]       128
│    └─ReLU: 2-6                         [100, 64, 112, 112]       --
│    └─MaxPool2d: 2-7                    [100, 64, 56, 56]         --
│    └─Conv2d: 2-8                       [100, 128, 56, 56]        73,856
│    └─BatchNorm2d: 2-9                  [100, 128, 56, 56]        256
│    └─ReLU: 2-10                        [100, 128, 56, 56]        --
│    └─Conv2d: 2-11                      [100, 128, 56, 56]        147,584
│    └─BatchNorm2d: 2-12                 [100, 128, 56, 56]        256
│    └─ReLU: 2-13                        [100, 128, 56, 56]        --
│    └─MaxPool2d: 2-14                   [100, 128, 28, 28]        --
│    └─Conv2d: 2-15                      [100, 256, 28, 28]        295,168
│    └─BatchNorm2d: 2-16                 [100, 256, 28, 28]        512
│    └─ReLU: 2-17                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-18                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-19                 [100, 256, 28, 28]        512
│    └─ReLU: 2-20                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-21                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-22                 [100, 256, 28, 28]        512
│    └─ReLU: 2-23                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-24                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-25                 [100, 256, 28, 28]        512
│    └─ReLU: 2-26                        [100, 256, 28, 28]        --
│    └─MaxPool2d: 2-27                   [100, 256, 14, 14]        --
│    └─Conv2d: 2-28                      [100, 512, 14, 14]        1,180,160
│    └─BatchNorm2d: 2-29                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-30                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-31                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-32                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-33                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-34                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-35                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-36                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-37                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-38                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-39                        [100, 512, 14, 14]        --
│    └─MaxPool2d: 2-40                   [100, 512, 7, 7]          --
│    └─Conv2d: 2-41                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-42                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-43                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-44                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-45                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-46                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-47                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-48                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-49                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-50                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-51                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-52                        [100, 512, 7, 7]          --
├─Identity: 1-2                          [100, 512, 7, 7]          --
├─Sequential: 1-3                        [100, 10]                 --
│    └─Linear: 2-53                      [100, 4096]               102,764,544
│    └─ReLU: 2-54                        [100, 4096]               --
│    └─Dropout: 2-55                     [100, 4096]               --
│    └─Linear: 2-56                      [100, 4096]               16,781,312
│    └─ReLU: 2-57                        [100, 4096]               --
│    └─Dropout: 2-58                     [100, 4096]               --
│    └─Linear: 2-59                      [100, 10]                 40,970
==========================================================================================
Total params: 139,622,218
Trainable params: 139,622,218
Non-trainable params: 0
Total mult-adds (G): 500.04
==========================================================================================
Input size (MB): 15.05
Forward/backward pass size (MB): 5947.40
Params size (MB): 558.49
Estimated Total Size (MB): 6520.94
==========================================================================================
# 손실 계산 그래프 시각화
 
criterion = nn.CrossEntropyLoss()
loss = eval_loss(test_loader, device, net, criterion)
g = make_dot(loss, params=dict(net.named_parameters()))
display(g)

svg

초기 설정

# 난수 고정
torch_seed()
 
# 사전 학습 모델 불러오기
net = models.vgg19_bn(pretrained = True)
 
# 최종 레이어 함수 교체
in_features = net.classifier[6].in_features
net.classifier[6] = nn.Linear(in_features, n_output)
 
# features 마지막의 MaxPool2d 제거
net.features = net.features[:-1]
 
# AdaptiveAvgPool2d 제거
net.avgpool = nn.Identity()
 
# 모델을 GPU로 전송
net = net.to(device)
 
# 학습률
lr = 0.001
 
# 손실 함수 정의
criterion = nn.CrossEntropyLoss()
 
# 최적화 함수 정의
optimizer = optim.SGD(net.parameters(), lr=lr, momentum=0.9)
 
# history 초기화
history = np.zeros((0, 5))
 

학습

num_epochs = 5
history = fit(net, optimizer, criterion, num_epochs, 
          train_loader, test_loader, device, history)
  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [1/5], loss: 0.49669 acc: 0.83160 val_loss: 0.19144, val_acc: 0.93610



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [2/5], loss: 0.24048 acc: 0.91826 val_loss: 0.15483, val_acc: 0.94740



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [3/5], loss: 0.18289 acc: 0.93778 val_loss: 0.13438, val_acc: 0.95410



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [4/5], loss: 0.15228 acc: 0.94810 val_loss: 0.12692, val_acc: 0.95720



  0%|          | 0/1000 [00:00<?, ?it/s]


Epoch [5/5], loss: 0.13073 acc: 0.95556 val_loss: 0.12888, val_acc: 0.95750

결과 확인

# 결과 요약
evaluate_history(history)
초기상태 : 손실 : 0.19144  정확도 : 0.93610
최종상태 : 손실 : 0.12888 정확도 : 0.95750



png

png

# 이미지와 정답, 예측 결과를 함께 표시
show_images_labels(test_loader, classes, net, device)
len(images) =  50



png

CIFAR-10에 전이 학습을 적용한 경우 (parameters freezing)

# 사전 학습 모델 불러오기
weights = models.ResNet18_Weights.IMAGENET1K_V1
net = models.resnet18(weights = weights)
next(iter(net.parameters())).requires_grad
True
print(net)
ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer2): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer3): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer4): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=10, bias=True)
)
# 전이 학습
 
# 사전 학습 모델 불러오기
weights = models.ResNet18_Weights.IMAGENET1K_V1
net = models.resnet18(weights = weights)
 
# 모든 파라미터의 경사 계산을 OFF로 설정
for param in net.parameters():
    param.requires_grad = False
 
# 난수 고정
torch_seed()
 
# 최종 레이어 함수 교체
net.fc = nn.Linear(net.fc.in_features, n_output)
 
# GPU 사용
net = net.to(device)
 
# 학습률
lr = 0.001
 
# 손실 함수 정의
criterion = nn.CrossEntropyLoss()
 
# 최적화 함수 정의
# 파라미터 변경은 최종 레이어 함수로 한정
optimizer = optim.SGD(net.fc.parameters(), lr=lr, momentum=0.9)
 
# history 파일 초기화
history = np.zeros((0, 5))
# 학습
num_epochs = 5
history = fit(net, optimizer, criterion, num_epochs, 
        train_loader, test_loader, device, history)
  0%|          | 0/1000 [00:00<?, ?it/s]
# 결과 요약
evaluate_history(history)

범용적인 사전 학습 모델을 작성하는 법

모델 불러오기

# 사전 학습 모델 불러오기
from torchvision import models
 
weights = models.VGG19_BN_Weights.DEFAULT
net = models.vgg19_bn(weights = weights)

모델 개요 표시 1

print(net)
VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
    (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (5): ReLU(inplace=True)
    (6): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (7): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (9): ReLU(inplace=True)
    (10): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (12): ReLU(inplace=True)
    (13): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (14): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (16): ReLU(inplace=True)
    (17): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (19): ReLU(inplace=True)
    (20): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (21): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (22): ReLU(inplace=True)
    (23): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (24): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (25): ReLU(inplace=True)
    (26): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (27): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (28): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (29): ReLU(inplace=True)
    (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (31): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (32): ReLU(inplace=True)
    (33): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (34): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (35): ReLU(inplace=True)
    (36): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (37): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (38): ReLU(inplace=True)
    (39): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (40): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (41): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (42): ReLU(inplace=True)
    (43): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (44): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (45): ReLU(inplace=True)
    (46): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (47): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (48): ReLU(inplace=True)
    (49): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (50): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (51): ReLU(inplace=True)
    (52): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

중간 텐서 확인

# 원본 데이터 사이즈의 경우(배치사이즈 100)
net = net.to(device)
summary(net, (100, 3, 224, 224))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
VGG                                      [100, 1000]               --
├─Sequential: 1-1                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-1                       [100, 64, 224, 224]       1,792
│    └─BatchNorm2d: 2-2                  [100, 64, 224, 224]       128
│    └─ReLU: 2-3                         [100, 64, 224, 224]       --
│    └─Conv2d: 2-4                       [100, 64, 224, 224]       36,928
│    └─BatchNorm2d: 2-5                  [100, 64, 224, 224]       128
│    └─ReLU: 2-6                         [100, 64, 224, 224]       --
│    └─MaxPool2d: 2-7                    [100, 64, 112, 112]       --
│    └─Conv2d: 2-8                       [100, 128, 112, 112]      73,856
│    └─BatchNorm2d: 2-9                  [100, 128, 112, 112]      256
│    └─ReLU: 2-10                        [100, 128, 112, 112]      --
│    └─Conv2d: 2-11                      [100, 128, 112, 112]      147,584
│    └─BatchNorm2d: 2-12                 [100, 128, 112, 112]      256
│    └─ReLU: 2-13                        [100, 128, 112, 112]      --
│    └─MaxPool2d: 2-14                   [100, 128, 56, 56]        --
│    └─Conv2d: 2-15                      [100, 256, 56, 56]        295,168
│    └─BatchNorm2d: 2-16                 [100, 256, 56, 56]        512
│    └─ReLU: 2-17                        [100, 256, 56, 56]        --
│    └─Conv2d: 2-18                      [100, 256, 56, 56]        590,080
│    └─BatchNorm2d: 2-19                 [100, 256, 56, 56]        512
│    └─ReLU: 2-20                        [100, 256, 56, 56]        --
│    └─Conv2d: 2-21                      [100, 256, 56, 56]        590,080
│    └─BatchNorm2d: 2-22                 [100, 256, 56, 56]        512
│    └─ReLU: 2-23                        [100, 256, 56, 56]        --
│    └─Conv2d: 2-24                      [100, 256, 56, 56]        590,080
│    └─BatchNorm2d: 2-25                 [100, 256, 56, 56]        512
│    └─ReLU: 2-26                        [100, 256, 56, 56]        --
│    └─MaxPool2d: 2-27                   [100, 256, 28, 28]        --
│    └─Conv2d: 2-28                      [100, 512, 28, 28]        1,180,160
│    └─BatchNorm2d: 2-29                 [100, 512, 28, 28]        1,024
│    └─ReLU: 2-30                        [100, 512, 28, 28]        --
│    └─Conv2d: 2-31                      [100, 512, 28, 28]        2,359,808
│    └─BatchNorm2d: 2-32                 [100, 512, 28, 28]        1,024
│    └─ReLU: 2-33                        [100, 512, 28, 28]        --
│    └─Conv2d: 2-34                      [100, 512, 28, 28]        2,359,808
│    └─BatchNorm2d: 2-35                 [100, 512, 28, 28]        1,024
│    └─ReLU: 2-36                        [100, 512, 28, 28]        --
│    └─Conv2d: 2-37                      [100, 512, 28, 28]        2,359,808
│    └─BatchNorm2d: 2-38                 [100, 512, 28, 28]        1,024
│    └─ReLU: 2-39                        [100, 512, 28, 28]        --
│    └─MaxPool2d: 2-40                   [100, 512, 14, 14]        --
│    └─Conv2d: 2-41                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-42                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-43                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-44                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-45                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-46                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-47                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-48                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-49                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-50                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-51                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-52                        [100, 512, 14, 14]        --
│    └─MaxPool2d: 2-53                   [100, 512, 7, 7]          --
├─AdaptiveAvgPool2d: 1-2                 [100, 512, 7, 7]          --
├─Sequential: 1-3                        [100, 1000]               --
│    └─Linear: 2-54                      [100, 4096]               102,764,544
│    └─ReLU: 2-55                        [100, 4096]               --
│    └─Dropout: 2-56                     [100, 4096]               --
│    └─Linear: 2-57                      [100, 4096]               16,781,312
│    └─ReLU: 2-58                        [100, 4096]               --
│    └─Dropout: 2-59                     [100, 4096]               --
│    └─Linear: 2-60                      [100, 1000]               4,097,000
==========================================================================================
Total params: 143,678,248
Trainable params: 143,678,248
Non-trainable params: 0
Total mult-adds (T): 1.96
==========================================================================================
Input size (MB): 60.21
Forward/backward pass size (MB): 23770.71
Params size (MB): 574.71
Estimated Total Size (MB): 24405.63
==========================================================================================
# 실습용 데이터 사이즈의 경우(배치사이즈 100)
summary(net, (100, 3, 112, 112))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
VGG                                      [100, 1000]               --
├─Sequential: 1-1                        [100, 512, 3, 3]          --
│    └─Conv2d: 2-1                       [100, 64, 112, 112]       1,792
│    └─BatchNorm2d: 2-2                  [100, 64, 112, 112]       128
│    └─ReLU: 2-3                         [100, 64, 112, 112]       --
│    └─Conv2d: 2-4                       [100, 64, 112, 112]       36,928
│    └─BatchNorm2d: 2-5                  [100, 64, 112, 112]       128
│    └─ReLU: 2-6                         [100, 64, 112, 112]       --
│    └─MaxPool2d: 2-7                    [100, 64, 56, 56]         --
│    └─Conv2d: 2-8                       [100, 128, 56, 56]        73,856
│    └─BatchNorm2d: 2-9                  [100, 128, 56, 56]        256
│    └─ReLU: 2-10                        [100, 128, 56, 56]        --
│    └─Conv2d: 2-11                      [100, 128, 56, 56]        147,584
│    └─BatchNorm2d: 2-12                 [100, 128, 56, 56]        256
│    └─ReLU: 2-13                        [100, 128, 56, 56]        --
│    └─MaxPool2d: 2-14                   [100, 128, 28, 28]        --
│    └─Conv2d: 2-15                      [100, 256, 28, 28]        295,168
│    └─BatchNorm2d: 2-16                 [100, 256, 28, 28]        512
│    └─ReLU: 2-17                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-18                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-19                 [100, 256, 28, 28]        512
│    └─ReLU: 2-20                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-21                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-22                 [100, 256, 28, 28]        512
│    └─ReLU: 2-23                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-24                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-25                 [100, 256, 28, 28]        512
│    └─ReLU: 2-26                        [100, 256, 28, 28]        --
│    └─MaxPool2d: 2-27                   [100, 256, 14, 14]        --
│    └─Conv2d: 2-28                      [100, 512, 14, 14]        1,180,160
│    └─BatchNorm2d: 2-29                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-30                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-31                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-32                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-33                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-34                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-35                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-36                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-37                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-38                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-39                        [100, 512, 14, 14]        --
│    └─MaxPool2d: 2-40                   [100, 512, 7, 7]          --
│    └─Conv2d: 2-41                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-42                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-43                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-44                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-45                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-46                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-47                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-48                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-49                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-50                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-51                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-52                        [100, 512, 7, 7]          --
│    └─MaxPool2d: 2-53                   [100, 512, 3, 3]          --
├─AdaptiveAvgPool2d: 1-2                 [100, 512, 7, 7]          --
├─Sequential: 1-3                        [100, 1000]               --
│    └─Linear: 2-54                      [100, 4096]               102,764,544
│    └─ReLU: 2-55                        [100, 4096]               --
│    └─Dropout: 2-56                     [100, 4096]               --
│    └─Linear: 2-57                      [100, 4096]               16,781,312
│    └─ReLU: 2-58                        [100, 4096]               --
│    └─Dropout: 2-59                     [100, 4096]               --
│    └─Linear: 2-60                      [100, 1000]               4,097,000
==========================================================================================
Total params: 143,678,248
Trainable params: 143,678,248
Non-trainable params: 0
Total mult-adds (G): 500.45
==========================================================================================
Input size (MB): 15.05
Forward/backward pass size (MB): 5948.19
Params size (MB): 574.71
Estimated Total Size (MB): 6537.96
==========================================================================================

레이어 함수 교체하기

# 난수 고정
torch_seed()
 
# 최종 레이어 함수 교체
in_features = net.classifier[6].in_features
net.classifier[6] = nn.Linear(in_features, n_output)
# features의 마지막 요소(MaxPool2d)를 제거
net.features = net.features[:-1]
print(net.features)
Sequential(
  (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (2): ReLU(inplace=True)
  (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (5): ReLU(inplace=True)
  (6): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (7): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (8): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (9): ReLU(inplace=True)
  (10): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (12): ReLU(inplace=True)
  (13): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (14): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (15): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (16): ReLU(inplace=True)
  (17): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (19): ReLU(inplace=True)
  (20): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (21): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (22): ReLU(inplace=True)
  (23): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (24): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (25): ReLU(inplace=True)
  (26): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (27): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (28): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (29): ReLU(inplace=True)
  (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (31): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (32): ReLU(inplace=True)
  (33): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (34): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (35): ReLU(inplace=True)
  (36): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (37): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (38): ReLU(inplace=True)
  (39): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (40): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (41): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (42): ReLU(inplace=True)
  (43): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (44): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (45): ReLU(inplace=True)
  (46): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (47): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (48): ReLU(inplace=True)
  (49): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (50): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (51): ReLU(inplace=True)
)
# avgpool에 위치한AdaptiveAvgPool2d을 아무것도 하지 않는 함수(nn.Identity)로 치환
net.avgpool = nn.Identity()

결과 확인

print(net)
VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
    (3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (5): ReLU(inplace=True)
    (6): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (7): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (9): ReLU(inplace=True)
    (10): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (12): ReLU(inplace=True)
    (13): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (14): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (16): ReLU(inplace=True)
    (17): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (19): ReLU(inplace=True)
    (20): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (21): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (22): ReLU(inplace=True)
    (23): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (24): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (25): ReLU(inplace=True)
    (26): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (27): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (28): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (29): ReLU(inplace=True)
    (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (31): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (32): ReLU(inplace=True)
    (33): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (34): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (35): ReLU(inplace=True)
    (36): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (37): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (38): ReLU(inplace=True)
    (39): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (40): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (41): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (42): ReLU(inplace=True)
    (43): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (44): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (45): ReLU(inplace=True)
    (46): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (47): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (48): ReLU(inplace=True)
    (49): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (50): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (51): ReLU(inplace=True)
  )
  (avgpool): Identity()
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=10, bias=True)
  )
)
# 실습용 데이터 사이즈로 중간 텐서 확인(배치사이즈 100)
net = net.to(device)
summary(net,(100, 3, 112, 112))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
VGG                                      [100, 10]                 --
├─Sequential: 1-1                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-1                       [100, 64, 112, 112]       1,792
│    └─BatchNorm2d: 2-2                  [100, 64, 112, 112]       128
│    └─ReLU: 2-3                         [100, 64, 112, 112]       --
│    └─Conv2d: 2-4                       [100, 64, 112, 112]       36,928
│    └─BatchNorm2d: 2-5                  [100, 64, 112, 112]       128
│    └─ReLU: 2-6                         [100, 64, 112, 112]       --
│    └─MaxPool2d: 2-7                    [100, 64, 56, 56]         --
│    └─Conv2d: 2-8                       [100, 128, 56, 56]        73,856
│    └─BatchNorm2d: 2-9                  [100, 128, 56, 56]        256
│    └─ReLU: 2-10                        [100, 128, 56, 56]        --
│    └─Conv2d: 2-11                      [100, 128, 56, 56]        147,584
│    └─BatchNorm2d: 2-12                 [100, 128, 56, 56]        256
│    └─ReLU: 2-13                        [100, 128, 56, 56]        --
│    └─MaxPool2d: 2-14                   [100, 128, 28, 28]        --
│    └─Conv2d: 2-15                      [100, 256, 28, 28]        295,168
│    └─BatchNorm2d: 2-16                 [100, 256, 28, 28]        512
│    └─ReLU: 2-17                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-18                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-19                 [100, 256, 28, 28]        512
│    └─ReLU: 2-20                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-21                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-22                 [100, 256, 28, 28]        512
│    └─ReLU: 2-23                        [100, 256, 28, 28]        --
│    └─Conv2d: 2-24                      [100, 256, 28, 28]        590,080
│    └─BatchNorm2d: 2-25                 [100, 256, 28, 28]        512
│    └─ReLU: 2-26                        [100, 256, 28, 28]        --
│    └─MaxPool2d: 2-27                   [100, 256, 14, 14]        --
│    └─Conv2d: 2-28                      [100, 512, 14, 14]        1,180,160
│    └─BatchNorm2d: 2-29                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-30                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-31                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-32                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-33                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-34                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-35                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-36                        [100, 512, 14, 14]        --
│    └─Conv2d: 2-37                      [100, 512, 14, 14]        2,359,808
│    └─BatchNorm2d: 2-38                 [100, 512, 14, 14]        1,024
│    └─ReLU: 2-39                        [100, 512, 14, 14]        --
│    └─MaxPool2d: 2-40                   [100, 512, 7, 7]          --
│    └─Conv2d: 2-41                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-42                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-43                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-44                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-45                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-46                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-47                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-48                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-49                        [100, 512, 7, 7]          --
│    └─Conv2d: 2-50                      [100, 512, 7, 7]          2,359,808
│    └─BatchNorm2d: 2-51                 [100, 512, 7, 7]          1,024
│    └─ReLU: 2-52                        [100, 512, 7, 7]          --
├─Identity: 1-2                          [100, 512, 7, 7]          --
├─Sequential: 1-3                        [100, 10]                 --
│    └─Linear: 2-53                      [100, 4096]               102,764,544
│    └─ReLU: 2-54                        [100, 4096]               --
│    └─Dropout: 2-55                     [100, 4096]               --
│    └─Linear: 2-56                      [100, 4096]               16,781,312
│    └─ReLU: 2-57                        [100, 4096]               --
│    └─Dropout: 2-58                     [100, 4096]               --
│    └─Linear: 2-59                      [100, 10]                 40,970
==========================================================================================
Total params: 139,622,218
Trainable params: 139,622,218
Non-trainable params: 0
Total mult-adds (G): 500.04
==========================================================================================
Input size (MB): 15.05
Forward/backward pass size (MB): 5947.40
Params size (MB): 558.49
Estimated Total Size (MB): 6520.94
==========================================================================================