딥러닝은 최근 몇 년 동안 인공지능 및 머신러닝 분야에서 우세한 방법론으로 자리 잡았습니다. 오늘은 그 중에서도 합성곱 신경망(Convolutional Neural Network, CNN)에 대해 살펴보겠습니다. CNN은 이미지 인식 및 처리에 특히 효과적이며, 여러 산업에서 광범위하게 사용됩니다.
합성곱 신경망이란?
합성곱 신경망은 바로 사진이나 비디오 같은 주어진 데이터의 시각적 패턴을 인식하는 데 특화된 신경망의 일종입니다. CNN은 기본적으로 합성곱 층, 풀링 층, 완전 연결 층으로 구성됩니다.
합성곱 층(Convolutional Layer)
합성곱 층은 입력 데이터에서 특징을 추출하는 역할을 합니다. 이 층은 작은 필터(커널)를 사용하여 입력 이미지의 특정 부분과 연산을 수행하여 출력을 생성합니다. 이렇게 생성된 특성 맵(feature map)은 입력 데이터의 유용한 정보만을 담고 있습니다.
풀링 층(Pooling Layer)
풀링 층은 특성 맵의 크기를 줄이는 데 사용됩니다. 이는 모델의 복잡성을 줄이고 연산량을 감소시켜 과적합을 방지하는 데 도움을 줍니다. 가장 일반적인 방법은 최대 풀링(max pooling)으로, 이 방법은 주어진 영역에서 가장 큰 값을 선택하여 특성 맵의 크기를 줄입니다.
완전 연결 층(Fully Connected Layer)
신경망의 마지막 부분에서는 완전 연결 층이 존재합니다. 이 층은 이전 층에서 얻은 정보들을 바탕으로 최종 예측을 하게 됩니다. 모든 뉴런이 이전 층과 연결되어 있는 구조이므로, 입력 데이터에 대한 복잡한 결정을 내릴 수 있습니다.
파이토치(PyTorch)로 CNN 구현하기
이제 파이토치를 사용하여 간단한 CNN 모델을 구현해보겠습니다. MNIST 데이터셋을 사용하여 손글씨 숫자를 분류하는 모델을 만들어 보겠습니다.
사전 준비
먼저 필요한 라이브러리를 설치하고 데이터셋을 다운로드하겠습니다. 다음은 필요한 라이브러리입니다:
pip install torch torchvision
데이터셋 준비
MNIST 데이터셋을 다운로드하고 불러옵니다. 아래 코드를 사용하여 학습 및 테스트 데이터셋을 준비할 수 있습니다.
import torch
import torchvision
import torchvision.transforms as transforms
# 데이터 변환 정의
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))]) # 평균과 표준편차를 사용한 정규화
# 학습 데이터셋
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
# 테스트 데이터셋
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)
모델 정의
이제 합성곱 신경망 모델을 정의해 봅시다. CNN 모델은 일반적으로 합성곱 층과 풀링 층을 조합한 구조로 설계됩니다.
import torch.nn as nn
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3) # 입력 채널 1, 출력 채널 32
self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 최대 풀링
self.conv2 = nn.Conv2d(32, 64, kernel_size=3) # 입력 채널 32, 출력 채널 64
self.fc1 = nn.Linear(64 * 6 * 6, 128) # 완전 연결 층, 64x6x6은 출력 크기
self.fc2 = nn.Linear(128, 10) # 최종 출력 10개(0~9)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x))) # 첫 번째 합성곱과 풀링
x = self.pool(F.relu(self.conv2(x))) # 두 번째 합성곱과 풀링
x = x.view(-1, 64 * 6 * 6) # 텐서 형태 변경
x = F.relu(self.fc1(x)) # 첫 번째 완전 연결 층
x = self.fc2(x) # 두 번째 완전 연결 층
return x
모델 학습
모델을 학습시키기 위해서는 손실 함수와 옵티마이저를 정의하고 데이터에 대해 반복적으로 학습을 진행해야 합니다.
# 모델 초기화
cnn = CNN()
criterion = nn.CrossEntropyLoss() # 손실 함수
optimizer = torch.optim.SGD(cnn.parameters(), lr=0.01) # 확률적 경사 하강법
# 모델 학습
for epoch in range(5): # 에폭 수
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad() # 기울기 초기화
outputs = cnn(inputs) # 예측
loss = criterion(outputs, labels) # 손실 계산
loss.backward() # 기울기 계산
optimizer.step() # 파라미터 업데이트
running_loss += loss.item()
print(f'Epoch {epoch + 1}, Loss: {running_loss / len(trainloader)}')
모델 평가
학습이 완료된 후, 테스트 데이터셋을 통해 모델의 성능을 평가합니다.
correct = 0
total = 0
with torch.no_grad(): # 기울기 계산 비활성화
for data in testloader:
images, labels = data
outputs = cnn(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy on the test set: {100 * correct / total} %')
결론
이제 우리는 간단한 합성곱 신경망을 파이토치를 사용하여 구성하고, 실제 데이터셋을 통해 학습시키고 평가하는 과정을 경험했습니다. 이 강좌를 통해 딥러닝의 기본적인 구조와 파이썬을 활용한 실습을 이해하는 데 도움이 되셨기를 바랍니다. 앞으로 더 복잡한 모델과 다양한 데이터셋을 다루는 데에도 도전해보십시오!