본문 바로가기
Study Log/Software Engineering

PyTorch 공부 (부제: Simplified MobileNet 구현)

by HZie 2022. 12. 5.

듣고 있는 강의의 과제를 어찌저찌 하긴 했는데 도저히 이해가 잘 가지 않아서 파이토치로 모델 만들기를 연습해보기로 했다.

하려는 것은 친구가 듣는 수업의 과제로 나온 것 구현하기

모바일넷을 약간 변형한 것인데 구조는 다음 그림과 같다.

모바일넷 변형 버전

아래는 내가 일반적인 모바일넷 구조를 다른 사람이 구현한 코드를 보고 이해한 후 참고하면서 위의 구조를 구현한 코드이다.

# 모델 구성
import torch.nn as nn
from torchsummary import summary

# Depthwise Seperable Convolutions with Depthwise and Pointwise layers followed by batchnorm and ReLU
# 모바일넷에서 정의한 Depthwise SeperableConv2d 구현
class SeperableConv2d(nn.Module):
  def __init__(self, in_channels, out_channels, stride):
    super(SeperableConv2d, self).__init__()

    self.depthwise = nn.Sequential(
        # in_channels에 out_channels를 덮어씌워서 pointwise에서 덮어씌워진 in_channels 사용
        # 3 x 3 Depthwise Conv이기 때문에 kernel_size = 3
        nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1, stride=stride),
        nn.BatchNorm2d(in_channels), # Conv2d에서의 결과값은 in_channels에 저장되어있으므로 BatchNorm2d에는 in_channels가 들어감
        nn.ReLU(inplace=False)
    )

    self.pointwise = nn.Sequential(
        nn.Conv2d(in_channels, out_channels, kernel_size = 1, stride = 1),
        nn.BatchNorm2d(out_channels), # Conv2d의 결과인 out_channles를 입력
        nn.ReLU(inplace=False)
    )
  
  def forward(self, x):
    x = self.depthwise(x)
    x = self.pointwise(x)
    return x

class MobileNet_Simplified(nn.Module):
  def __init__(self, in_channels, num_classes=10):
    super(MobileNet_Simplified, self).__init__()
    # Layer 정의
    self.model = nn.Sequential(
        nn.Conv2d(3, 32, kernel_size = 3, stride=2, padding=1), # O = (I-K+2P)/S + 1에 넣어서 계산하면 0.5가 나와서 일단 패딩을 1로 함
        SeperableConv2d(32, 64, stride=1),
        SeperableConv2d(64, 128, stride=2),
        SeperableConv2d(128, 128, stride=1),
        SeperableConv2d(128, 256, stride=2),
        SeperableConv2d(256, 256, stride=1),
        nn.AdaptiveAvgPool2d(1)
    )
    self.fc = nn.Linear(256, num_classes)

  def forward(self, x):
    x = self.model(x)
    x = x.view(x.size(0), -1)
    x = self.fc(x)
    return x

##### MAIN #####
# model check
model = MobileNet_Simplified(3)
summary(model, input_size=(3,32,32), device='cpu')

 

  • nn.Sequential - forward()함수에서 구현될 순전파를 Layer형태로 작성
  • nn.Conv2d - 2차원 배열에서 Convolutional 연산을 위한 Layer
    • in_channels: 필수로 입력. 입력 채널 수 (흑백: 1, RGB: 1)
    • out_channels: 필수 입력. 출력 채널 수
    • kernel_size: 필수 입력.
    • stride=1: 디폴트 1. 슬라이딩 윈도우 스텝 (= 몇 칸씩 이동할지)
    • padding=0: 디폴트 0. 패딩 사이즈
    • dilation=1: 디폴트 1.
    • groups=1: 디폴트 1.
    • bias=True: 디폴트 True
    • padding_mode='zeros': 디폴트 'zeros'.
  • nn.BatchNorm2d - 배치 정규화. gradient descent에 따른 weight 반응이 같아지므로 학습에 유리
    • num_features: 필수로 입력. 입력 채널 수
    • 나머지 파라미터는 default로 두어도 무방
  • nn.ReLU - ReLU 사용을 위한 함수
    • inplace=False: 디폴트 False. True인 경우 inplace연산 수행 ( = 결과값을 새로운 변수에 저장하는 대신 기존의 데이터를 대체하여 저장)
  • nn.AdaptiveAvgPool2d - 지정된 output_size로 변환하도록 average pooling 수행
    • output_size

References

- Pytorch 공식 문서: https://pytorch.org

- Pytorch: torch.nn.Sequantial & Pytorch: torch.nn.Conv2d: https://velog.io/@danbibibi/PyTorch-torch.nn.-Conv2d

- Pytorch Conv2d 함수 다루기: https://gaussian37.github.io/dl-pytorch-conv2d/

- 아래는 코드 구현 시 참고한 블로그

https://minimin2.tistory.com/42

https://ysbsb.github.io/cnn/2020/02/20/MobileNet.html

댓글