CNN
PyTorch에서 Convolutional Neural Network (CNN)을 사용하는 방법은 딥러닝에서 이미지 처리 문제를 해결하기 위한 핵심 기술입니다. CNN은 컨볼루션 레이어와 풀링 레이어를 조합하여 이미지의 공간적 특징을 학습합니다. 아래에 PyTorch에서 CNN을 사용한 기본적인 설명과 예제를 제공합니다.
CNN 기본 개념
- Convolution Layer:
- 입력 이미지에 필터(커널)를 적용하여 특징 맵을 생성.
-
이미지의 국소적 특징(모서리, 윤곽 등)을 학습.
-
Activation Function:
-
활성화 함수(ReLU 등)를 사용하여 비선형성을 도입.
-
Pooling Layer:
- 특징 맵의 크기를 줄이고 계산 비용을 감소.
-
MaxPooling, AveragePooling 등이 일반적.
-
Fully Connected Layer:
- 컨볼루션과 풀링 과정을 통해 추출된 특징을 기반으로 최종 분류 수행.
입력 채널
PyTorch의 nn.Conv2d 레이어에서 in_channels 매개변수는 입력 데이터의 채널 수를 나타냅니다. 이 값은 입력 데이터의 형식(예: 흑백 또는 컬러 이미지)에 따라 설정됩니다.
1. in_channels와 입력 데이터의 형식
in_channels는 입력 데이터의 **채널 수**를 지정합니다.
- 흑백 이미지:
- 흑백 이미지는 픽셀당 하나의 값(명도)을 가지므로 **1채널**로 간주됩니다.
- 따라서
in_channels=1로 설정합니다. -
흑백 이미지의 형태:
(batch_size, 1, height, width)
예:(64, 1, 28, 28)(MNIST 데이터셋) -
컬러 이미지:
- 컬러 이미지는 RGB(빨강, 초록, 파랑) 값으로 구성되므로 **3채널**로 간주됩니다.
- 따라서
in_channels=3으로 설정합니다. - 컬러 이미지의 형태:
(batch_size, 3, height, width)
예:(64, 3, 32, 32)(CIFAR-10 데이터셋)
2. Conv2d의 입력 구조
nn.Conv2d의 입력은 4차원 텐서여야 하며, 다음과 같은 구조를 가집니다:
(batch_size, in_channels, height, width)
batch_size: 한 번에 처리할 데이터의 개수.in_channels: 입력 데이터의 채널 수.height, width: 입력 데이터의 세로 및 가로 크기.
3. 입력 데이터가 2차원인 경우
만약 입력 데이터가 **2차원 이미지(흑백)**라면, 채널 정보가 누락된 형태일 수 있습니다. 이를 처리하려면 채널 차원을 추가해야 합니다.
예를 들어:
# 입력 데이터 형태: (batch_size, height, width)
input_2d = torch.rand(64, 28, 28) # 64개의 흑백 이미지
# 채널 차원을 추가하여 Conv2d에 맞게 변환: (batch_size, in_channels, height, width)
input_2d = input_2d.unsqueeze(1) # (64, 1, 28, 28)
4. 컬러 이미지의 경우
컬러 이미지는 채널 정보가 이미 포함되어 있으므로 in_channels=3으로 설정합니다.
예를 들어, CIFAR-10 데이터셋:
# CIFAR-10 이미지는 3채널 RGB
input_rgb = torch.rand(64, 3, 32, 32) # 64개의 컬러 이미지
conv = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1)
output = conv(input_rgb) # 출력: (64, 32, 32, 32)
5. 요약
- 흑백 이미지:
in_channels=1(데이터 형태:(batch_size, 1, height, width)) - 컬러 이미지:
in_channels=3(데이터 형태:(batch_size, 3, height, width))
만약 데이터의 차원이 맞지 않는다면 unsqueeze나 데이터 전처리 과정을 통해 채널 차원을 추가하거나 조정해야 합니다.
PyTorch에서 CNN 구현
아래는 PyTorch를 사용하여 CNN을 설계하고 MNIST 데이터셋에 적용하는 예제입니다.
1. 라이브러리 임포트
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
2. 데이터 준비
# 데이터 변환: Tensor 변환 및 정규화
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
# 데이터셋 로드
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
# 데이터 로더 생성
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
3. CNN 모델 정의
CNN 모델은 nn.Module을 상속받아 정의하며, 여러 계층을 조합하여 설계합니다.
class CNNModel(nn.Module):
def __init__(self):
super(CNNModel, self).__init__()
# Convolutional layers
self.conv_layers = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1), # 1채널 입력 -> 32채널 출력
nn.ReLU(), # 활성화 함수
nn.MaxPool2d(kernel_size=2, stride=2), # 크기 감소 (28x28 -> 14x14)
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1), # 32채널 입력 -> 64채널 출력
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2) # 크기 감소 (14x14 -> 7x7)
)
# Fully connected layers
self.fc_layers = nn.Sequential(
nn.Flatten(), # 64x7x7 -> 3136
nn.Linear(64 * 7 * 7, 128), # Fully connected layer
nn.ReLU(),
nn.Linear(128, 10) # 출력 10 (클래스 개수)
)
def forward(self, x):
x = self.conv_layers(x) # Convolutional layers 통과
x = self.fc_layers(x) # Fully connected layers 통과
return x
# 모델 초기화
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = CNNModel().to(device)
4. 손실 함수 및 최적화 기법
# 손실 함수: CrossEntropyLoss
criterion = nn.CrossEntropyLoss()
# 옵티마이저: Adam
optimizer = optim.Adam(model.parameters(), lr=0.001)
5. 학습 루프
epochs = 5
for epoch in range(epochs):
model.train() # 학습 모드
running_loss = 0.0
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
# Forward pass
outputs = model(images)
loss = criterion(outputs, labels)
# Backward pass and optimization
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}")
6. 모델 평가
테스트 데이터셋에서 모델의 성능을 평가합니다.
model.eval() # 평가 모드
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"Test Accuracy: {100 * correct / total:.2f}%")
7. 모델의 주요 하이퍼파라미터
- Conv2d Parameters:
in_channels: 입력 채널 수 (흑백 이미지=1, 컬러 이미지=3).out_channels: 출력 채널 수 (필터 수).kernel_size: 필터 크기 (보통 3x3 또는 5x5 사용).stride: 필터 이동 간격 (기본값=1).-
padding: 입력에 추가되는 픽셀 (엣지 보존용). -
MaxPool2d Parameters:
kernel_size: 풀링 영역 크기.-
stride: 풀링 이동 간격 (기본값=kernel_size). -
Linear Parameters:
- 입력 및 출력 노드의 개수.
8. 확장: 더 복잡한 CNN
복잡한 데이터셋(CIFAR-10, ImageNet 등)을 처리하려면 더 많은 컨볼루션 레이어와 드롭아웃(dropout)을 추가하거나, ResNet, VGG와 같은 사전 학습된 모델을 사용할 수 있습니다.
9. 결과
위 코드로 MNIST 데이터셋을 학습하면 약 **98% 이상의 테스트 정확도**를 얻을 수 있습니다. CNN은 이미지 처리에서 뛰어난 성능을 발휘하며, PyTorch를 사용하면 간단히 구현할 수 있습니다. Jetson Orin Nano와 같은 디바이스에서 CNN을 효율적으로 실행하면 엣지 컴퓨팅 환경에서도 강력한 AI 모델을 활용할 수 있습니다.