티스토리 뷰

반응형

핵심 요약

"사람은 이미지를 보지만, AI는 숫자를 본다"는 말이 있습니다.
합성곱 신경망(CNN, Convolutional Neural Network)이미지를 숫자 행렬로 변환하여 필터(커널)로 훑으며 엣지, 텍스처, 패턴을 자동 추출합니다.
3x3 필터 하나가 수백만 픽셀 이미지에서 수직선을 99% 정확도로 감지하고, 풀링(Pooling)은 이미지 크기를 4분의 1로 압축하면서도 핵심 정보는 유지합니다.
2012년 AlexNet이 ImageNet에서 84% 정확도로 우승하며 CNN 시대를 열었고, 현재는 얼굴 인식(99.9%), 자율주행, 의료 영상 진단까지 인간 수준을 넘어섰습니다.
합성곱 연산부터 Max Pooling, 실제 응용까지 CNN의 모든 것을 완벽하게 설명합니다.


📍 목차

  1. 합성곱 신경망(CNN) 구조
  2. 합성곱 연산과 필터의 개념
  3. 풀링(Pooling) 레이어의 역할
  4. CNN의 실제 응용: 이미지 인식, 얼굴 인식, 자율주행
  5. 실전 CNN 설계 가이드

1. 합성곱 신경망(CNN) 구조

1-1. CNN이란?

합성곱 신경망(Convolutional Neural Network, CNN)이미지 데이터를 효과적으로 처리하기 위해 설계된 특수한 신경망입니다.

핵심 질문:

"왜 일반 신경망(MLP)으로는 이미지 처리가 어려울까?"

문제: 파라미터 폭발

이미지 크기 픽셀 수 MLP 은닉층 (100 뉴런) 파라미터 수
28×28 (MNIST) 784 784 → 100 78,400개
224×224 (ImageNet) 150,528 150,528 → 100 15,052,800개
1920×1080 (Full HD) 2,073,600 2,073,600 → 100 207,360,000개

결과: 메모리 부족, 학습 불가능

해결책: CNN - 지역적 연결 + 파라미터 공유

1-2. CNN의 전체 구조

기본 구조:

입력 이미지
  ↓
[합성곱층 1] → [활성화(ReLU)] → [풀링층 1]
  ↓
[합성곱층 2] → [활성화(ReLU)] → [풀링층 2]
  ↓
[합성곱층 3] → [활성화(ReLU)] → [풀링층 3]
  ↓
[Flatten: 1차원 변환]
  ↓
[완전연결층(FC)]
  ↓
[출력층 (Softmax)]
  ↓
분류 결과

대표 CNN 아키텍처: LeNet-5 (1998)

입력: 32×32 이미지
  ↓
Conv1: 6개 필터 (5×5) → 28×28×6
  ↓
Pooling1: Max Pooling (2×2) → 14×14×6
  ↓
Conv2: 16개 필터 (5×5) → 10×10×16
  ↓
Pooling2: Max Pooling (2×2) → 5×5×16
  ↓
Flatten: 5×5×16 = 400
  ↓
FC1: 120 뉴런
  ↓
FC2: 84 뉴런
  ↓
Output: 10 클래스 (0~9 숫자)

1-3. CNN vs MLP 비교

항목 MLP (Fully Connected) CNN (Convolutional)
연결 방식 모든 뉴런 연결 지역적 연결
파라미터 매우 많음 적음 (공유)
공간 정보 무시 (1D 벡터) 유지 (2D/3D)
이미지 처리 비효율적 최적화
학습 속도 느림 빠름
적합 데이터 표 형식 이미지, 비디오

파라미터 비교 (28×28 이미지):

# MLP
input_size = 28 * 28 = 784
hidden_size = 100
params = 784 * 100 = 78,400개

# CNN
filter_size = 3 * 3 = 9
num_filters = 32
params = 9 * 32 = 288개  # 272배 적음!

2. 합성곱 연산과 필터의 개념

2-1. 합성곱 연산이란?

합성곱(Convolution)작은 필터(커널)로 이미지를 훑으며 특징을 추출하는 연산입니다.

수식:
[
(I * K)(i, j) = \sum_{m}\sum_{n} I(i+m, j+n) \cdot K(m, n)
]

  • (I): 입력 이미지
  • (K): 필터(커널)
  • (*): 합성곱 연산
  • ((i, j)): 출력 위치

2-2. 필터(커널)의 역할

필터(Filter) 또는 커널(Kernel)이미지에서 특정 패턴을 감지하는 작은 행렬입니다.

예시: 수직 엣지 감지 필터 (3×3)

필터 K:
[-1  0  1]
[-1  0  1]
[-1  0  1]

적용 과정:

입력 이미지 (5×5):
[0 0 0 1 1]
[0 0 0 1 1]
[0 0 0 1 1]
[0 0 0 1 1]
[0 0 0 1 1]

↓ (필터 적용)

특징 맵 (3×3):
[0  4  0]
[0  4  0]
[0  4  0]

해석: 수직선(경계)이 감지됨!

2-3. 합성곱 연산 상세

단계별 계산:

1단계: 필터 배치

이미지:          필터:
[1 2 3]         [0 1 0]
[4 5 6]    ×    [1 0 1]
[7 8 9]         [0 1 0]

2단계: 원소별 곱셈 + 합산

1×0 + 2×1 + 3×0 +
4×1 + 5×0 + 6×1 +
7×0 + 8×1 + 9×0 = 2+4+6+8 = 20

3단계: 필터 이동 (Stride)

Stride = 1:
위치 (0,0) → (0,1) → (0,2) → (1,0) → ...

Python 구현:

import numpy as np

def convolution_2d(image, kernel):
    """2D 합성곱 연산"""
    i_h, i_w = image.shape
    k_h, k_w = kernel.shape

    # 출력 크기 계산
    o_h = i_h - k_h + 1
    o_w = i_w - k_w + 1

    output = np.zeros((o_h, o_w))

    # 합성곱 연산
    for i in range(o_h):
        for j in range(o_w):
            # 이미지 일부 추출
            region = image[i:i+k_h, j:j+k_w]
            # 원소별 곱셈 후 합산
            output[i, j] = np.sum(region * kernel)

    return output

# 예시
image = np.array([
    [1, 2, 3, 0, 1],
    [4, 5, 6, 2, 3],
    [7, 8, 9, 4, 5],
    [1, 2, 3, 6, 7],
    [4, 5, 6, 8, 9]
])

# 수직 엣지 필터
kernel = np.array([
    [-1, 0, 1],
    [-1, 0, 1],
    [-1, 0, 1]
])

feature_map = convolution_2d(image, kernel)
print("특징 맵:\n", feature_map)

2-4. Stride와 Padding

Stride (보폭)

Stride: 필터가 이동하는 간격

Stride 이동 출력 크기
1 1칸씩 큰 출력
2 2칸씩 작은 출력
3 3칸씩 매우 작은 출력

출력 크기 공식:
[
\text{Output Size} = \frac{n - f}{s} + 1
]

  • (n): 입력 크기
  • (f): 필터 크기
  • (s): Stride

예시:

# 입력: 5×5, 필터: 3×3, Stride=1
output_size = (5 - 3) / 1 + 1 = 3

# Stride=2
output_size = (5 - 3) / 2 + 1 = 2

Padding (패딩)

Padding: 입력 이미지 주변에 값(보통 0)을 추가

목적:

  1. 출력 크기 유지
  2. 가장자리 정보 보존

종류:

Padding 설명 출력 크기
Valid 패딩 없음 작아짐
Same 패딩 추가 입력과 동일

예시:

원본 (3×3):          Padding=1 추가 (5×5):
[1 2 3]             [0 0 0 0 0]
[4 5 6]      →      [0 1 2 3 0]
[7 8 9]             [0 4 5 6 0]
                    [0 7 8 9 0]
                    [0 0 0 0 0]

Same Padding 계산:
[
\text{Padding} = \frac{f - 1}{2}
]

TensorFlow/Keras 구현:

from tensorflow.keras.layers import Conv2D

# Valid Padding (패딩 없음)
conv_valid = Conv2D(filters=32, kernel_size=3, padding='valid')

# Same Padding (출력 크기 유지)
conv_same = Conv2D(filters=32, kernel_size=3, padding='same')

2-5. 다양한 필터 예시

1️⃣ 수평 엣지 감지

[[-1 -1 -1]
 [ 0  0  0]
 [ 1  1  1]]

2️⃣ 블러 필터 (평균)

[[1/9 1/9 1/9]
 [1/9 1/9 1/9]
 [1/9 1/9 1/9]]

3️⃣ 샤프닝 필터

[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]

핵심: CNN은 이런 필터를 사람이 설계하지 않고, 데이터로부터 자동 학습합니다!


3. 풀링(Pooling) 레이어의 역할

3-1. 풀링이란?

풀링(Pooling)특징 맵의 크기를 줄이는 다운샘플링 기법입니다.

목적:

  1. 파라미터 감소 → 계산 효율 증가
  2. 과적합 방지
  3. 평행이동 불변성 확보

3-2. Max Pooling

Max Pooling: 영역에서 최댓값만 선택

예시: 2×2 Max Pooling

입력 (4×4):          출력 (2×2):
[1  3  2  4]
[5  6  1  2]    →   [6  4]
[9  7  3  0]        [9  5]
[4  2  1  5]

계산 과정:

영역 1:  [1 3]  → Max = 6
         [5 6]

영역 2:  [2 4]  → Max = 4
         [1 2]

영역 3:  [9 7]  → Max = 9
         [4 2]

영역 4:  [3 0]  → Max = 5
         [1 5]

특징:

  • 주요 특징 강조
  • 노이즈 제거
  • 위치 불변성

3-3. Average Pooling

Average Pooling: 영역의 평균값 계산

입력 (4×4):          출력 (2×2):
[1  3  2  4]
[5  6  1  2]    →   [3.75  2.25]
[9  7  3  0]        [5.50  2.25]
[4  2  1  5]

계산:

영역 1: (1+3+5+6)/4 = 3.75
영역 2: (2+4+1+2)/4 = 2.25
영역 3: (9+7+4+2)/4 = 5.50
영역 4: (3+0+1+5)/4 = 2.25

3-4. Max Pooling vs Average Pooling

항목 Max Pooling Average Pooling
연산 최댓값 선택 평균값 계산
특징 강조 ⭐⭐⭐⭐⭐ ⭐⭐
노이즈 제거 ⭐⭐⭐⭐ ⭐⭐⭐
정보 손실 높음 낮음
사용 빈도 매우 높음 (90%) 낮음 (10%)
적합한 경우 엣지, 텍스처 강조 부드러운 변화

Python 구현:

import numpy as np

def max_pooling_2d(feature_map, pool_size=2):
    """2D Max Pooling"""
    f_h, f_w = feature_map.shape
    p_h = p_w = pool_size

    o_h = f_h // p_h
    o_w = f_w // p_w

    output = np.zeros((o_h, o_w))

    for i in range(o_h):
        for j in range(o_w):
            # 풀링 영역
            region = feature_map[
                i*p_h:(i+1)*p_h,
                j*p_w:(j+1)*p_w
            ]
            # 최댓값
            output[i, j] = np.max(region)

    return output

# 예시
feature_map = np.array([
    [1, 3, 2, 4],
    [5, 6, 1, 2],
    [9, 7, 3, 0],
    [4, 2, 1, 5]
])

pooled = max_pooling_2d(feature_map, pool_size=2)
print("Max Pooling 결과:\n", pooled)

TensorFlow/Keras 구현:

from tensorflow.keras.layers import MaxPooling2D, AveragePooling2D

# Max Pooling (2×2, stride=2)
max_pool = MaxPooling2D(pool_size=2, strides=2)

# Average Pooling
avg_pool = AveragePooling2D(pool_size=2, strides=2)

3-5. 풀링의 효과

크기 감소:

입력: 224×224×64 특징 맵
  ↓ (2×2 Max Pooling)
출력: 112×112×64 (크기 1/4, 파라미터 1/4)

평행이동 불변성:

원본 이미지:         1픽셀 이동:
●●○○               ○●●○
●●○○      vs       ○●●○
○○○○               ○○○○
○○○○               ○○○○

Max Pooling 후:    Max Pooling 후:
[1  0]             [1  0]
[0  0]             [0  0]
→ 동일한 결과!

4. CNN의 실제 응용: 이미지 인식, 얼굴 인식, 자율주행

4-1. 이미지 분류 (ImageNet)

ImageNet 대회:

  • 데이터: 1,400만 이미지, 1,000 클래스
  • 과제: 고양이, 개, 자동차 등 분류

역사적 순간들:

연도 모델 층 수 Top-5 Error 혁신
2010 전통 ML - 28.2% 수작업 Feature
2012 AlexNet 8 16.4% CNN 최초 우승
2014 VGGNet 19 7.3% 깊은 네트워크
2015 ResNet 152 3.6% Skip Connection
2021 ViT 24 1.8% Transformer
인간 - - 5.1% CNN이 인간 넘어섬!

AlexNet 아키텍처 (2012):

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout

model = Sequential([
    # Conv1
    Conv2D(96, 11, strides=4, activation='relu', input_shape=(227, 227, 3)),
    MaxPooling2D(3, strides=2),

    # Conv2
    Conv2D(256, 5, padding='same', activation='relu'),
    MaxPooling2D(3, strides=2),

    # Conv3
    Conv2D(384, 3, padding='same', activation='relu'),

    # Conv4
    Conv2D(384, 3, padding='same', activation='relu'),

    # Conv5
    Conv2D(256, 3, padding='same', activation='relu'),
    MaxPooling2D(3, strides=2),

    # FC
    Flatten(),
    Dense(4096, activation='relu'),
    Dropout(0.5),
    Dense(4096, activation='relu'),
    Dropout(0.5),
    Dense(1000, activation='softmax')  # 1000 클래스
])

model.summary()

4-2. 얼굴 인식

FaceNet (Google, 2015):

  • 정확도: 99.63% (인간: 97.5%)
  • 응용: 스마트폰 잠금 해제, 출입 통제

작동 원리:

입력 얼굴 이미지
  ↓
[CNN] → 128차원 임베딩 벡터
  ↓
거리 계산 (Euclidean Distance)
  ↓
동일인 여부 판단 (임계값 비교)

Triplet Loss:

Anchor (기준)    Positive (동일인)    Negative (타인)
    A    ────────    P               N

목표: d(A, P) < d(A, N)

실전 예제:

from tensorflow.keras.applications import VGG16
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D

# 사전 학습 VGG16 사용
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))

# 커스텀 헤드
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(128, activation='relu')(x)  # 128차원 임베딩
output = Dense(1, activation='sigmoid')(x)  # 동일인 여부

model = Model(inputs=base_model.input, outputs=output)

# 학습
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

4-3. 객체 탐지 (Object Detection)

YOLO (You Only Look Once):

  • 속도: 45 FPS (실시간)
  • 정확도: 80% mAP

작동 방식:

입력 이미지
  ↓
[CNN] → 그리드 분할 (7×7)
  ↓
각 그리드마다:
  - 객체 유무 (Confidence)
  - 경계 상자 (Bounding Box)
  - 클래스 확률
  ↓
NMS (Non-Maximum Suppression)
  ↓
최종 탐지 결과

예시 출력:

[
  {'class': 'person', 'confidence': 0.98, 'box': [120, 50, 300, 400]},
  {'class': 'car', 'confidence': 0.95, 'box': [400, 200, 600, 350]},
  {'class': 'dog', 'confidence': 0.87, 'box': [50, 300, 200, 450]}
]

4-4. 자율주행

Tesla Autopilot CNN 구조:

8개 카메라 입력
  ↓
[Multi-scale CNN]
  ├─ 차선 감지
  ├─ 차량 감지
  ├─ 보행자 감지
  ├─ 신호등 인식
  └─ 표지판 인식
  ↓
[Fusion Layer]
  ↓
[제어 시스템]
  ├─ 조향
  ├─ 가속
  └─ 제동

핵심 기술:

기술 설명 CNN 역할
Lane Detection 차선 인식 엣지 감지
Object Detection 차량/보행자 YOLO, Faster R-CNN
Semantic Segmentation 픽셀 단위 분류 FCN, U-Net
Depth Estimation 거리 측정 Stereo CNN

실시간 처리:

import cv2
from tensorflow.keras.models import load_model

# 사전 학습 모델 로드
model = load_model('lane_detection.h5')

# 웹캠/차량 카메라
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # 전처리
    img = cv2.resize(frame, (224, 224))
    img = img / 255.0
    img = np.expand_dims(img, axis=0)

    # 예측
    prediction = model.predict(img)

    # 시각화
    cv2.imshow('Lane Detection', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

4-5. 의료 영상 진단

폐암 탐지 (Google, 2019):

  • 정확도: 94.4% (의사: 88.9%)
  • 데이터: CT 스캔 이미지

작동 원리:

CT 스캔 이미지
  ↓
[3D CNN] (512×512×100 슬라이스)
  ↓
특징 추출:
  - 결절(nodule) 위치
  - 크기
  - 모양
  - 밀도
  ↓
[분류기]
  ├─ 양성 (0.05)
  └─ 악성 (0.95)
  ↓
CAM (Class Activation Map)
  - 의사에게 근거 제시

5. 실전 CNN 설계 가이드

5-1. CNN 설계 체크리스트

1단계: 데이터 확인

  • 이미지 크기: 224×224, 299×299 등
  • 채널: RGB (3), Grayscale (1)
  • 클래스 수: 2 (이진), 10, 1000 등

2단계: 아키텍처 선택

목적 추천 모델 크기 정확도
빠른 프로토타입 MobileNet 작음 중간
일반 분류 ResNet-50 중간 높음
최고 정확도 EfficientNet-B7 최고
실시간 처리 YOLO, MobileNet 작음 중간

3단계: 전이 학습 vs 처음부터

데이터 크기 방법 이유
< 1,000개 전이 학습 (Fine-tuning) 데이터 부족
1,000 ~ 10,000개 전이 학습 + 일부 학습 효율성
> 10,000개 처음부터 학습 가능 충분한 데이터

5-2. 전이 학습 실전 예제

CIFAR-10 분류 (10개 클래스)

from tensorflow.keras.applications import ResNet50
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.utils import to_categorical

# 데이터 로드
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train / 255.0
X_test = X_test / 255.0
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

# 사전 학습 ResNet50 (ImageNet)
base_model = ResNet50(
    weights='imagenet',
    include_top=False,  # 최상위 FC층 제외
    input_shape=(32, 32, 3)
)

# Base model 동결 (학습 안 함)
base_model.trainable = False

# 커스텀 헤드 추가
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
output = Dense(10, activation='softmax')(x)

model = Model(inputs=base_model.input, outputs=output)

# 컴파일
model.compile(
    optimizer='adam',
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

# 학습
history = model.fit(
    X_train, y_train,
    validation_data=(X_test, y_test),
    epochs=10,
    batch_size=64
)

# 평가
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f"Test Accuracy: {test_acc:.2%}")

5-3. 하이퍼파라미터 튜닝

필터 개수:

필터 개수 이유
Conv1 32~64 저수준 Feature
Conv2 64~128 중수준 Feature
Conv3 128~256 고수준 Feature
Conv4+ 256~512 추상적 Feature

필터 크기:

크기 장점 단점 사용
1×1 채널 조정, 빠름 공간 정보 없음 차원 축소
3×3 균형 좋음 - 기본 (90%)
5×5 넓은 수용 영역 느림 초기 층
7×7 매우 넓음 매우 느림 첫 번째 층만

배치 크기:

# GPU 메모리에 따라
batch_sizes = {
    '2GB': 16,
    '4GB': 32,
    '8GB': 64,
    '16GB': 128,
    '24GB': 256
}

5-4. 데이터 증강 (Data Augmentation)

과적합 방지 + 일반화 향상

from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 데이터 증강 설정
datagen = ImageDataGenerator(
    rotation_range=20,       # 20도 회전
    width_shift_range=0.2,   # 가로 20% 이동
    height_shift_range=0.2,  # 세로 20% 이동
    horizontal_flip=True,    # 좌우 반전
    zoom_range=0.2,          # 20% 확대/축소
    shear_range=0.2,         # 전단 변환
    fill_mode='nearest'      # 빈 공간 채우기
)

# 학습
model.fit(
    datagen.flow(X_train, y_train, batch_size=32),
    validation_data=(X_test, y_test),
    epochs=50
)

효과:

원본 데이터 증강 후 데이터 정확도 향상
1,000개 10,000개 (10배) +15%p

FAQ: 초보자가 자주 묻는 질문

Q1. CNN은 왜 이미지 처리에 특화되어 있나요?

A. 3가지 이유: (1) 지역적 연결 - 이미지는 인접 픽셀끼리 관련 높음, (2) 파라미터 공유 - 같은 필터를 전체 이미지에 적용 → 파라미터 272배 감소, (3) 계층적 특징 - 층마다 엣지 → 텍스처 → 객체 순으로 학습.

Q2. 필터는 어떻게 학습되나요?

A. 역전파 알고리즘으로 자동 학습됩니다. 처음엔 랜덤 값으로 시작 → 손실함수 계산 → 경사하강법으로 필터 값 업데이트 → 반복. 최종적으로 수직선, 곡선, 눈, 얼굴 등을 감지하는 필터가 자동으로 생성됩니다.

Q3. Max Pooling vs Average Pooling, 언제 뭘 쓰나요?

A. Max Pooling을 90% 이상 사용합니다. 이유: (1) 주요 특징 강조, (2) 노이즈 제거, (3) 더 좋은 성능. Average Pooling은 마지막 Global Pooling에서만 가끔 사용 (전체 평균).

Q4. 전이 학습은 왜 성능이 좋나요?

A. ImageNet 1,400만 이미지로 사전 학습된 모델은 이미 엣지, 텍스처, 패턴 감지 능력을 갖추고 있습니다. 이를 내 데이터(1,000개)에 Fine-tuning하면 처음부터 학습(10만 개 필요)보다 훨씬 적은 데이터로 높은 성능 달성.

Q5. CNN은 이미지 외에 다른 데이터에도 사용 가능한가요?

A. Yes! (1) 시계열 데이터: 1D CNN으로 주가, 심전도 분석, (2) 오디오: 스펙트로그램을 이미지로 변환, (3) 자연어: 문장을 2D 행렬로 표현, (4) 동영상: 3D CNN으로 행동 인식.


외부 참고 자료 (SEO 최적화)

CNN을 더 깊게 배우고 싶다면:


정리: 이 글에서 배운 것

CNN 구조: Conv → ReLU → Pooling → FC → Softmax
합성곱 연산: 필터로 이미지 훑기, 특징 맵 생성
필터: 엣지, 텍스처 자동 학습, 파라미터 공유
Max Pooling: 최댓값 선택, 크기 1/4, 특징 강조
응용: ImageNet 95%, 얼굴 인식 99.6%, 자율주행
전이 학습: ResNet-50 사전 학습 → Fine-tuning

다음 편에서는 "RNN과 LSTM - 시퀀스 데이터를 이해하는 AI"에 대해 자세히 알아봅니다. 특히 순환 신경망, 기울기 소실, LSTM 구조를 완벽 설명하겠습니다.

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/02   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
글 보관함