일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- TensorFlow
- c++
- pytorch
- MFC 프로그래밍
- 딥러닝
- 가우시안 필터링
- c언어
- 컴퓨터 비전
- pytorch zero to all
- 케라스 정리
- 모두의 딥러닝 예제
- 파이토치 김성훈 교수님 강의 정리
- 파이토치
- 파이토치 강의 정리
- 영상처리
- 골빈해커
- c++공부
- 딥러닝 공부
- C언어 공부
- tensorflow 예제
- 모두의 딥러닝
- object detection
- c언어 정리
- 해리스 코너 검출
- Pytorch Lecture
- 딥러닝 스터디
- 김성훈 교수님 PyTorch
- 팀프로젝트
- 미디언 필터링
- matlab 영상처리
- Today
- Total
ComputerVision Jack
PyTorch Lecture 11 : Advanced CNN 본문
Advanced CNN
저번시간 교수님께서 강의해주신 CNN 모델의 architecture입니다.
하지만 여기서 우리는 의문점이 생깁니다. 이미지에서 Kernel을 통해 feature를 추출할 경우, kernel size를 1 x 1 or 3 x 3, 5 x 5으로 선택해야하기 때문입니다.
교수님은 여기서 Inception Module을 설명해주셨습니다.
즉, 모든 연산을 다 집어 넣으면서 basic은 1 x 1로 시작하는 방식입니다.
Why 1 x 1 convolution?
1 x 1 convolution을 토대로 3 x 3, 5 x 5, pooling까지 확장해 나아갑니다. 그럼 왜 1 x 1 convolution을 진행할까요?
1 x 1 convolution의 경우 이미지의 손실이 발생하지 않습니다. 하지만 dimensional dot product를 통해 이미지의 depth를 감소시킬 수 있습니다.
예를 들어 (64 x 56 x 56) 인경우 1 x 1 conv with 1 filters 진행하면 (1 x 56 x 56) 입니다. 즉 64인 depth가 1depth로 감소된 것을 확인할 수 있습니다. 이러한 1 x 1 convolution을 진행하는 이유는 operations 측면에서 시간과 비용이 감소되기 때문입니다.
그럼 basic을 1 x 1 로 모든 연산을 다 고려하는 Inception Module을 코딩으로 구현해보겠습니다.
[11.toy_inception_mnist.py]
from __future__ import print_function
import argparse
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
# 해당 실습에 필요한 라이브러리를 import 합니다.
batch_size = 64
# batch size 는 64로 정합니다.
train_dataset = datasets.MNIST(root='./data/', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./data/', train=False, transform=transforms.ToTensor())\
# 학습과 테스트에 필요한 mnist 데이터 셋을 다운로드합니다.
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)
# 해당 mnist 데이터셋을 위한 DataLoader를 제작합니다.
class InceptionA(nn.Module):
def __init__(self, in_channels):
super(InceptionA, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
self.branch3x3dbl_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch3x3dbl_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
self.branch3x3dbl_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_1(x)
branch5x5 = self.branch5x5_2(branch5x5)
branch3x3dbl = self.branch3x3dbl_1(x)
branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs = [branch1x1, branch5x5, branch3x3dbl, branch_pool]
return torch.cat(outputs, 1)
# 해당 Inception Module architecture 로 inception class를 구현합니다.
레이어와 층을 준비하고, forward 연산을 진행한 후, 리스트로 결과를 담아 concat을 사용하여 넘겨줍니다.
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(88, 20, kernel_size=5)
self.incept1 = InceptionA(in_channels=10)
self.incept2 = InceptionA(in_channels=20)
self.mp = nn.MaxPool2d(2)
self.fc = nn.Linear(1408, 10)
def forward(self, x):
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))
x = self.incept1(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.incept2(x)
x = x.view(in_size, -1) # flatten the tensor
x = self.fc(x)
return F.log_softmax(x)
# 해당 inception module을 사용하여 network를 구성합니다. 전 시간에 배운 cnn 구성에 inception 처리를 추가했다고 생각하면 됩니다.
model = Net()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
# 해당 모델에 대한 객체를 생성하고, 최적화를 준비합니다.
def train(epoch):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = Variable(data), Variable(target)
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
if batch_idx % 10 == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
# 학습을 진행합니다. 여기서 깃허브의 코드를 그대로 코렙에 치시면 오류가 발생합니다. 해당 오류는 0차원 텐서의 잘못된 인덱스라고 표기되어있습니다.
error : invalid index of a 0 - dim tensor. Use 'tensor.item() ' in Python or~~
따라서 loss.data[0] 에대한 부분을 loss.item()으로 수정하여 실행하면 됩니다.
def test():
model.eval()
test_loss = 0
correct = 0
for data, target in test_loader:
data, target = Variable(data, volatile=True), Variable(target)
output = model(data)
# sum up batch loss
test_loss += F.nll_loss(output, target, size_average=False).data
# get the index of the max log-probability
pred = output.data.max(1, keepdim=True)[1]
correct += pred.eq(target.data.view_as(pred)).cpu().sum()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
# 해당 학습된 모델에 대해 test를 적용할 함수를 생성합니다.
여기도 data[0] 으로 되어 있는 코드를 data로 수정해야 오류없이 동작합니다.
for epoch in range(1, 10):
train(epoch)
test()
# 학습을 실행하면 됩니다.
'DeepLearning > Pytorch_ZeroToAll' 카테고리의 다른 글
PyTorch Lecture 10 : Basic CNN (0) | 2020.10.26 |
---|---|
PyTorch Lecture 09 : softmax Classifier (0) | 2020.10.23 |
PyTorch Lecture 08 : DataLoader (0) | 2020.10.21 |
PyTorch Lecture 07 : Wide and Deep (0) | 2020.10.20 |
PyTorch Lecture 06 : Logistic Regression (0) | 2020.10.12 |