🤖 AI/ML

컨볼루션

Convolution

이미지 처리에서 필터를 적용하는 연산. CNN의 핵심 구성 요소로 특징 추출에 사용.

📖 상세 설명

컨볼루션(Convolution)은 입력 데이터에 필터(커널)를 슬라이딩하며 적용하여 특징을 추출하는 수학적 연산입니다. 딥러닝에서는 CNN(Convolutional Neural Network)의 핵심 연산으로, 이미지의 에지, 텍스처, 패턴 등 계층적 특징을 자동으로 학습합니다.

컨볼루션 연산은 신호 처리 분야에서 오래전부터 사용되었지만, 딥러닝에서의 혁신은 1989년 Yann LeCun의 LeNet에서 시작되었습니다. 2012년 AlexNet이 ImageNet 대회에서 압도적 성능을 보이며 딥러닝 혁명을 촉발했고, 이후 VGGNet, ResNet, EfficientNet 등 다양한 CNN 아키텍처가 발전했습니다. 현재는 Vision Transformer(ViT)와 경쟁하지만, 여전히 효율성과 해석 가능성 측면에서 CNN이 선호되는 영역이 많습니다.

컨볼루션의 핵심 원리는 파라미터 공유와 지역 연결성입니다. 동일한 필터가 이미지 전체를 스캔하므로 파라미터 수가 대폭 감소하고, 학습된 필터는 위치에 관계없이 동일한 패턴을 탐지합니다(평행 이동 불변성). 필터 크기(예: 3x3, 5x5), 스트라이드(이동 간격), 패딩, 채널 수가 주요 하이퍼파라미터입니다. 다층 컨볼루션을 통해 저수준(에지)에서 고수준(물체) 특징까지 계층적으로 추출됩니다.

실무에서 컨볼루션은 이미지 분류, 객체 탐지, 시맨틱 분할, 의료 영상 분석 등 컴퓨터 비전의 기반 기술입니다. 2025년 현재 ConvNeXt, EfficientNetV2 같은 현대적 CNN은 ViT와 비슷한 성능을 더 적은 데이터와 연산으로 달성합니다. 1D 컨볼루션은 시계열, 음성 처리에, Graph Convolution은 분자 구조, 소셜 네트워크 분석에 활용됩니다.

💻 코드 예제

PyTorch를 활용한 CNN 이미지 분류 구현:

# CNN 이미지 분류 모델 (PyTorch)
import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleCNN(nn.Module):
    """
    CIFAR-10 분류를 위한 CNN 모델
    입력: 32x32x3 이미지
    """
    def __init__(self, num_classes=10):
        super().__init__()

        # Conv Block 1: 3 -> 32 채널
        self.conv1 = nn.Conv2d(
            in_channels=3,
            out_channels=32,
            kernel_size=3,      # 3x3 필터
            padding=1,          # same padding
            stride=1
        )
        self.bn1 = nn.BatchNorm2d(32)

        # Conv Block 2: 32 -> 64 채널
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(64)

        # Conv Block 3: 64 -> 128 채널
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.bn3 = nn.BatchNorm2d(128)

        # Pooling
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)

        # Fully Connected Layers
        # 32 -> 16 -> 8 -> 4 (3번의 pooling 후)
        self.fc1 = nn.Linear(128 * 4 * 4, 256)
        self.fc2 = nn.Linear(256, num_classes)

        self.dropout = nn.Dropout(0.5)

    def forward(self, x):
        # Block 1: Conv -> BN -> ReLU -> Pool
        x = self.pool(F.relu(self.bn1(self.conv1(x))))  # 32x32 -> 16x16

        # Block 2
        x = self.pool(F.relu(self.bn2(self.conv2(x))))  # 16x16 -> 8x8

        # Block 3
        x = self.pool(F.relu(self.bn3(self.conv3(x))))  # 8x8 -> 4x4

        # Flatten
        x = x.view(x.size(0), -1)  # (batch, 128*4*4)

        # FC Layers
        x = self.dropout(F.relu(self.fc1(x)))
        x = self.fc2(x)

        return x

# 모델 생성 및 구조 확인
model = SimpleCNN(num_classes=10)
print(model)

# 입력 테스트
dummy_input = torch.randn(1, 3, 32, 32)
output = model(dummy_input)
print(f"\n입력: {dummy_input.shape} -> 출력: {output.shape}")

컨볼루션 연산의 시각적 이해:

# 컨볼루션 연산 시각화
import torch
import torch.nn.functional as F
import numpy as np

# 5x5 입력 이미지 (1채널)
input_image = torch.tensor([
    [1, 2, 3, 4, 5],
    [2, 3, 4, 5, 6],
    [3, 4, 5, 6, 7],
    [4, 5, 6, 7, 8],
    [5, 6, 7, 8, 9]
], dtype=torch.float32).unsqueeze(0).unsqueeze(0)  # (1, 1, 5, 5)

# 3x3 에지 탐지 필터 (소벨 필터)
sobel_x = torch.tensor([
    [-1, 0, 1],
    [-2, 0, 2],
    [-1, 0, 1]
], dtype=torch.float32).unsqueeze(0).unsqueeze(0)  # (1, 1, 3, 3)

# 컨볼루션 적용
output = F.conv2d(input_image, sobel_x, padding=1)

print("입력 이미지 (5x5):")
print(input_image.squeeze().numpy())

print("\n소벨 필터 (3x3):")
print(sobel_x.squeeze().numpy())

print("\n컨볼루션 결과:")
print(output.squeeze().numpy())

# 다양한 설정 비교
print("\n=== 컨볼루션 설정별 출력 크기 ===")
for padding in [0, 1]:
    for stride in [1, 2]:
        out = F.conv2d(input_image, sobel_x, padding=padding, stride=stride)
        print(f"padding={padding}, stride={stride} -> 출력 크기: {out.shape[-2:]})")

# 출력 크기 공식: (W - K + 2P) / S + 1
# W=5, K=3 -> padding=1, stride=1: (5-3+2)/1+1 = 5
# W=5, K=3 -> padding=0, stride=2: (5-3+0)/2+1 = 2

📊 CNN 아키텍처 비교

주요 CNN 아키텍처 성능 비교 (ImageNet 기준):

모델 년도 파라미터 Top-1 정확도 특징
AlexNet 2012 60M 57.1% 딥러닝 혁명의 시작
VGG-16 2014 138M 71.5% 3x3 필터 반복 사용
ResNet-50 2015 25M 76.1% Skip Connection 도입
EfficientNet-B7 2019 66M 84.4% 복합 스케일링
ConvNeXt-L 2022 198M 87.5% 현대화된 CNN

* Vision Transformer(ViT-L)는 86.4% 수준, ConvNeXt가 ViT와 경쟁 가능함을 입증

🗣️ 실무에서 이렇게 말하세요

💬 회의에서
"이미지 분류 태스크에는 EfficientNet-B3 정도면 충분합니다. B7까지 올리면 정확도는 1-2% 오르지만 추론 시간이 4배 늘어나요. 모바일 배포라면 MobileNetV3도 좋은 선택입니다."
💬 면접에서
"ResNet의 Skip Connection이 중요한 이유는 gradient vanishing 문제를 해결하기 때문입니다. 입력을 출력에 직접 더함으로써 gradient가 깊은 레이어까지 전파되고, 100층 이상의 네트워크 학습이 가능해졌습니다."
💬 기술 토론에서
"ViT가 대용량 데이터에서 강하지만, 중소규모 데이터에서는 CNN의 inductive bias(지역성, 평행이동 불변성)가 더 효율적이에요. ConvNeXt는 Transformer의 장점을 CNN에 적용해서 두 세계의 장점을 결합했죠."

⚠️ 흔한 실수 & 주의사항

무조건 깊은 네트워크 사용

태스크에 비해 너무 깊은 네트워크는 과적합되고 추론 시간이 늘어납니다. 데이터셋 크기와 복잡도에 맞는 아키텍처를 선택하세요. CIFAR-10에는 ResNet-18이면 충분합니다.

입력 크기 불일치

사전학습된 모델의 입력 크기(예: 224x224)와 실제 데이터 크기가 다르면 성능이 저하됩니다. 적절한 리사이징과 전처리(정규화 등)가 필수입니다.

올바른 접근법

ImageNet 사전학습 모델로 시작하여 전이학습하세요. 작은 데이터셋에서는 특징 추출(Feature Extraction)만, 큰 데이터셋에서는 전체 파인튜닝을 권장합니다. 데이터 증강(Augmentation)도 필수입니다.

🔗 관련 용어

📚 더 배우기