딥러닝 파이토치 강좌, 합성곱 & 역합성곱 네트워크

딥러닝 기술은 컴퓨터 비전, 자연어 처리 및 다양한 분야에서 혁신적인 성과를 이루고 있습니다. 이 강좌에서는 파이토치(PyTorch)를 사용하여 합성곱 신경망(Convolutional Neural Network, CNN)과 역합성곱 신경망(Deconvolutional Neural Network 또는 Transpose Convolutional Network)에 대해 심도 있게 살펴보겠습니다.

1. 합성곱 신경망(CNN) 소개

합성곱 신경망(CNN)은 주로 이미지 인식 및 처리에서 우수한 성능을 보이는 딥러닝 기술입니다. CNN은 입력 이미지를 처리하기 위해 특수화된 계층인 합성곱 계층(convolutional layer)을 사용합니다. 이 계층은 이미지의 공간적 구조를 활용하여 특징을 추출합니다.

1.1 합성곱 계층의 작동 원리

합성곱 계층은 필터(또는 커널)를 사용해 입력 이미지와의 합성곱 연산을 수행합니다. 필터는 이미지의 특정 특징을 감지하는 작은 행렬로, 이러한 필터가 여러 개 사용되어 다양한 특징을 추출하게 됩니다. 일반적으로 필터는 학습 과정에서 업데이트됩니다.

1.2 합성곱 연산

합성곱 연산은 입력 이미지에 필터를 슬라이딩하면서 계산됩니다. 다음과 같은 수식으로 표현됩니다:

Convolution Operation

여기서 \(Y\)는 출력, \(X\)는 입력 이미지, \(K\)는 필터, \(M\)과 \(N\)은 필터의 크기입니다.

1.3 활성화 함수

합성곱 연산 뒤에는 비선형성을 추가하기 위해 활성화 함수가 적용됩니다. 주로 ReLU(Rectified Linear Unit) 함수가 사용됩니다:

ReLU Function

2. 파이토치에서 CNN 구현

이제 파이토치를 사용하여 CNN을 구현하는 방법을 알아보겠습니다. 아래는 기본적인 CNN 구조의 예입니다.

2.1 데이터셋 준비

우리는 MNIST 데이터셋을 사용할 것입니다. MNIST는 손글씨 숫자 이미지로 구성된 데이터셋으로, 기본적인 이미지 처리 모델을 테스트하기에 적합합니다.


import torch
import torchvision
import torchvision.transforms as transforms

# 데이터 전처리
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5,), (0.5,))])

# MNIST 데이터셋 다운로드
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)
    

2.2 CNN 모델 정의

CNN 구조를 정의하는 코드는 다음과 같습니다. 여기서는 합성곱 계층, 긴밀한 연결 계층(fully connected layer), 그리고 활성화 함수를 포함합니다.


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, stride=1, padding=1)  # 첫 번째 합성곱 레이어
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)  # 맥스 풀링 레이어
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)  # 두 번째 합성곱 레이어
        self.fc1 = nn.Linear(64 * 7 * 7, 128)  # 첫 번째 완전 연결 레이어
        self.fc2 = nn.Linear(128, 10)  # 두 번째 완전 연결 레이어

    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 * 7 * 7)  # 텐서의 형태 변환
        x = F.relu(self.fc1(x))  # 완전 연결 -> 활성화
        x = self.fc2(x)  # 출력층
        return x
    

2.3 모델 학습

모델을 학습시키기 위해 손실 함수와 옵티마이저를 정의하겠습니다.


import torch.optim as optim

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CNN().to(device)
criterion = nn.CrossEntropyLoss()  # 손실 함수
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  # SGD 옵티마이저

# 모델 학습
for epoch in range(10):  # 10 epochs
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data[0].to(device), data[1].to(device)
        
        # 기울기 초기화
        optimizer.zero_grad()
        
        # 순전파 + 역전파 + 최적화
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        
        running_loss += loss.item()
        if i % 100 == 99:    # 매 100 배치마다 출력
            print(f'[Epoch {epoch + 1}, Batch {i + 1}] loss: {running_loss / 100:.3f}')
            running_loss = 0.0
    print("Epoch finished")
    

2.4 모델 평가

학습이 완료된 모델을 평가하고 정확도를 측정하겠습니다.


correct = 0
total = 0

with torch.no_grad():
    for data in testloader:
        images, labels = data[0].to(device), data[1].to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Accuracy of the network on the 10000 test images: {100 * correct / total:.2f}%')
    

3. 역합성곱 신경망(Deconvolutional Neural Network) 소개

역합성곱 신경망 또는 Transpose Convolutional Network는 합성곱 신경망(CNN)에서 특징을 추출한 후, 이를 통해 이미지를 재구성하는 구조입니다. 주로 이미지 생성 작업, 특히 생성적 적대 신경망(GAN)과 같은 분야에서 사용됩니다.

3.1 역합성곱 계층의 작동 원리

역합성곱 계층은 CNN의 일반적인 합성곱 기능을 반대로 수행합니다. 그러니까 저해상도 이미지를 더 높은 해상도로 변환하는 데 사용됩니다. 이러한 계층은 “Transpose Convolution” 또는 “Deconvolution”으로도 알려져 있습니다. 이는 필터의 공간적 선형 변환을 적용하는 방식입니다.

3.2 역합성곱 예제

파이토치에서 역합성곱 신경망을 구현하는 예제를 살펴보겠습니다.


class DeconvNetwork(nn.Module):
    def __init__(self):
        super(DeconvNetwork, self).__init__()
        self.deconv1 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1)  # 첫 번째 역합성곱 레이어
        self.deconv2 = nn.ConvTranspose2d(32, 1, kernel_size=3, stride=2, padding=1)  # 두 번째 역합성곱 레이어

    def forward(self, x):
        x = F.relu(self.deconv1(x))  # 활성화
        x = torch.sigmoid(self.deconv2(x))  # 출력층
        return x
    

3.3 역합성곱 네트워크를 통한 이미지 재구성

이렇게 정의한 모델을 사용해 이미지 재구성의 기초적인 구조를 확인할 수 있습니다. 이는 GAN 또는 Autoencoder와 같은 솔루션에 적용될 수 있습니다.


deconv_model = DeconvNetwork().to(device)

# 이미지를 배열에 추가
image = torch.randn(1, 64, 7, 7).to(device)  # 임의의 텐서
reconstructed_image = deconv_model(image)
print(reconstructed_image.shape)  # (1, 1, 28, 28)로 재구성이 가능함
    

4. 결론

본 강좌에서는 딥러닝의 두 핵심 기술인 합성곱 신경망(CNN)과 역합성곱 신경망(Deconvolutional Network)에 대해 알아보았습니다. 파이토치 프레임워크를 활용하여 이론과 실습을 통해 CNN 구조를 구축하고 학습시키는 방법, 그리고 역합성곱 네트워크의 기초적인 작동 원리에 대해 설명했습니다. 이러한 기술들은 현재 많은 최신 딥러닝 모델의 기초가 되고 있으며, 지속적으로 발전하고 있습니다.

여러분의 딥러닝 여정에 도움이 되길 바라며, 언제든지 더 깊이 있는 연구와 탐구를 통해 자신의 모델을 발전시켜 나가시길 바랍니다!