딥러닝 파이토치 강좌, 합성곱 신경망 맛보기

딥러닝은 최근 몇 년 동안 인공지능 및 머신러닝 분야에서 우세한 방법론으로 자리 잡았습니다. 오늘은 그 중에서도 합성곱 신경망(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} %')

결론

이제 우리는 간단한 합성곱 신경망을 파이토치를 사용하여 구성하고, 실제 데이터셋을 통해 학습시키고 평가하는 과정을 경험했습니다. 이 강좌를 통해 딥러닝의 기본적인 구조와 파이썬을 활용한 실습을 이해하는 데 도움이 되셨기를 바랍니다. 앞으로 더 복잡한 모델과 다양한 데이터셋을 다루는 데에도 도전해보십시오!

참고자료