이미지 처리에 앞서 CNN을 복습해 보자.
출처 : https://www.analyticsvidhya.com/blog/2022/01/convolutional-neural-network-an-overview/
여기까지 특징 추출, 보통 컨볼루션 + 풀링 레이어 2~3회 반복(예. VGG 컨볼루션 3 풀링 1 반복)
하나씩 상세히 알아보자
풀링 후 레이어 크기 변화 :
n : 입력 크기, p : 패딩 크기, f : 커널 크기, s : 스트라이드
filter 2x2일 때 : 특징 유지하면서 사이즈 줄이는 게 이런 거

filter 5x5

CNN 개념 정리를 이해가 잘 되도록 정리해 주신 포스팅을 찾았다.
https://di-bigdata-study.tistory.com/18
CNN 학습 결과가 잘 나오는 MNIST 데이터셋으로 실습을 진행해 보자.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import cv2
import matplotlib.pyplot as plt
# myCNN 클래스 정의
class myCNN(nn.Module):
def __init__(self):
super(myCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size = 5, padding = 2)
self.conv2 = nn.Conv2d(32, 64, kernel_size = 5, padding = 2)
self.conv3 = nn.Conv2d(64, 128, kernel_size = 5, padding = 2)
self.fc1 = nn.Linear(128*3*3, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = F.relu(F.max_pool2d(self.conv1(x), 2))
x = F.relu(F.max_pool2d(self.conv2(x), 2))
x = F.relu(F.max_pool2d(self.conv3(x), 2))
x = x.view(-1, 128*3*3)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, dim = 1)
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST('./data', train = True, download = True, transform = transform)
test_dataset = datasets.MNIST('./data', train = False, transform = transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size = 64, shuffle = True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size = 1000, shuffle = False)
model = myCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum = 0.5)
# 손실과 정확도를 저장하기 위한 리스트
train_losses = []
test_losses = []
test_accuracies = []
# 훈련 함수
def train(model, train_loader, optimizer, epoch):
model.train()
train_loss = 0
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
train_loss += loss.item()
loss.backward()
optimizer.step()
# 평균 훈련 손실 계산
train_loss /= len(train)
train_losses.append(train_loss)
print(f'Epoch {epoch}, Training loss: {train_loss:.4f}')
# 테스트 함수
def test(model, test_loader):
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
for data, target in test_loader:
output = model(data)
test_loss += criterion(output, target).item()
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
test_loss /= len(test_loader)
accuracy = 100. * correct / len(test_loader.dataset)
test_losses.append(test_loss)
test_accuracies.append(accuracy)
print(f'Test loss: {test_loss:.4f}, Accuracy: {accuracy:.2f}%')
# 훈련 및 테스트 실행
for epoch in range(1, 11):
train(model, train_loader, optimizer, epoch)
test(model, test_loader)
# 손실 및 정확도 시각화
fig, axs = plt.subplots(2,1,figsize=(10,10))
axs[0].plot(train_losses, label = 'Training Loss')
axs[0].plot(test_losses, label = 'Test Loss')
axs[0].set_xlabel('Epoch')
axs[0].set_ylabel('Loss')
axs[0].legend()
axs[0].set_title('Training and Test Loss')
axs[1].plot(test_accuracies, label='Test Accuracy', color='orange')
axs[1].set_xlabel('Epoch')
axs[1].set_ylabel('Accuracy (%)')
axs[1].legend()
axs[1].set_title('Test Accuracy')
plt.tight_layout()
plt.show()
