컨볼루션 신경망(CNN) 이해 및 구현

1. 컨볼루션이란?

컨볼루션은 이미지와 필터(고정된 가중치 집합) 간의 내적 연산을 의미합니다. 각 픽셀에 해당하는 값을 곱하고 이를 모두 더하는 방식으로 특성을 추출합니다.

2. CNN 구성 요소

(1) 컨볼루션 레이어

  • 기능: 입력 데이터에서 중요한 특징을 추출.
  • 매개변수: 필터 크기(예: 3x3, 5x5), 스트라이드(픽셀 이동 단위), 패딩(데이터 손실 방지를 위해 추가).

(2) 풀링 레이어

  • 기능: 데이터 차원 축소 및 계산량 감소.
  • 종류: 최대값 풀링(최댓값 선택), 평균 풀링(평균값 선택).

(3) 활성화 함수

  • 기능: 비선형성을 도입하여 복잡한 패턴 학습 가능.
  • 유형: ReLU(음수는 0, 양수는 그대로 출력), Sigmoid(0~1 사이 값 출력), Softmax(분류 문제를 위한 확률 분포 변환).

(4) 완전 연결 레이어

  • 기능: 앞서 추출된 특징들을 종합하여 최종 분류 또는 회귀 수행.

3. CNN 구조

입력층 → 컨볼루션층 → 풀링층 → 완전 연결층 → 출력층 순으로 구성됩니다.

4. 코드 예제

(1) 데이터 전처리


import torch
from torchvision import transforms
from PIL import Image

class CustomDataset(torch.utils.data.Dataset):
    def __init__(self, file_path, transform=None):
        self.file_path = file_path
        self.transform = transform
        with open(file_path, 'r') as f:
            lines = [line.strip().split(' ') for line in f]
            self.images, self.labels = zip(*lines)

    def __len__(self):
        return len(self.images)

    def __getitem__(self, idx):
        image = Image.open(self.images[idx])
        label = int(self.labels[idx])

        if self.transform:
            image = self.transform(image)

        return image, torch.tensor(label)

transform = transforms.Compose([
    transforms.Resize((128, 128)),
    transforms.ToTensor()
])

dataset = CustomDataset('./data.txt', transform=transform)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)

(2) 모델 정의


import torch.nn as nn
import torch.nn.functional as F

class CNNModel(nn.Module):
    def __init__(self):
        super(CNNModel, self).__init__()
        self.feature_extractor = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        
        self.classifier = nn.Sequential(
            nn.Linear(64 * 32 * 32, 128),
            nn.ReLU(),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = self.feature_extractor(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = CNNModel().to(device)
print(model)

(3) 학습 및 평가 함수


def train_model(dataloader, model, loss_fn, optimizer):
    model.train()
    for images, labels in dataloader:
        images, labels = images.to(device), labels.to(device)
        
        outputs = model(images)
        loss = loss_fn(outputs, labels)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

def evaluate_model(dataloader, model, loss_fn):
    model.eval()
    total_loss, correct = 0, 0
    
    with torch.no_grad():
        for images, labels in dataloader:
            images, labels = images.to(device), labels.to(device)
            
            outputs = model(images)
            total_loss += loss_fn(outputs, labels).item()
            _, preds = torch.max(outputs, 1)
            correct += (preds == labels).sum().item()
    
    avg_loss = total_loss / len(dataloader)
    accuracy = correct / len(dataloader.dataset)
    print(f"Accuracy: {accuracy:.4f}, Avg Loss: {avg_loss:.4f}")

(4) 실행


loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

epochs = 10
for epoch in range(epochs):
    print(f"Epoch {epoch+1}/{epochs}")
    train_model(dataloader, model, loss_fn, optimizer)
    evaluate_model(dataloader, model, loss_fn)

태그: deep-learning PyTorch CNN

7월 8일 21:24에 게시됨