듣고 있는 강의의 과제를 어찌저찌 하긴 했는데 도저히 이해가 잘 가지 않아서 파이토치로 모델 만들기를 연습해보기로 했다.
하려는 것은 친구가 듣는 수업의 과제로 나온 것 구현하기
모바일넷을 약간 변형한 것인데 구조는 다음 그림과 같다.
아래는 내가 일반적인 모바일넷 구조를 다른 사람이 구현한 코드를 보고 이해한 후 참고하면서 위의 구조를 구현한 코드이다.
# 모델 구성
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/
- 아래는 코드 구현 시 참고한 블로그
'Study Log > Software Engineering' 카테고리의 다른 글
[삽질기록] Conda ResolvePackageNotFound 에러 (feat. environment.yml) (1) | 2023.02.08 |
---|---|
02. Supervised Learning of Behaviors (0) | 2022.11.22 |
01. OT (0) | 2022.11.15 |
pm2와 관련된 것들 (0) | 2022.10.12 |
[삽질기록] RDS 연결 안됨 (0) | 2022.10.11 |
댓글