logo

합성곱 신경망

다층 신경망에서 이미지 처리

  • 이미지는 높이, 너비, 채널을 가진 (H,W,C) 형태
  • 이미지 분류용 다층 신경망은 보통 Flatten으로 이미지를 길이 H×W×C인 벡터로 변환
  • Flatten은 픽셀값과 순서를 삭제하지 않지만 높이·너비 축을 하나의 축으로 펼침
  • Dense 레이어는 지역적으로 가까운 픽셀을 따로 구분하지 않고 모든 입력을 각 뉴런에 연결
  • 입력 크기와 출력 뉴런 수가 커질수록 (H×W×C)×U+U개의 파라미터가 필요

Dense 레이어의 전체 연결과 합성곱 레이어의 지역 연결 비교

합성곱 신경망 Convolutional Neural Network

  • 합성곱 신경망(CNN)은 작은 지역 패치에 필터를 반복 적용해 특징을 추출
  • 필터(filter) 또는 커널(kernel)은 데이터에서 학습하는 가중치
  • 같은 필터를 이미지의 여러 위치에서 공유하므로 지역 패턴을 효율적으로 탐색
  • 필터 하나는 하나의 피처 맵을 생성하며, 필터 수는 출력 채널 수와 같음
  • 수용 영역(receptive field): 특정 뉴런의 값에 영향을 주는 원본 입력 영역
  • 피처 맵(feature map): 필터가 각 위치에서 계산한 합성곱 출력

필터가 입력의 지역 패치에 적용되어 피처 맵을 만드는 과정

부분 특징에서 전체 특징으로

  • 얕은 레이어는 선, 방향, 모서리 같은 낮은 수준의 특징을 추출
  • 다음 레이어는 앞에서 찾은 특징을 조합해 눈, 코, 입처럼 더 큰 패턴을 표현
  • 깊은 레이어는 부분 특징을 다시 조합해 얼굴이나 사물 전체에 가까운 특징을 표현
  • 실제로 학습되는 특징은 데이터와 학습 목표에 따라 달라짐

선과 모서리에서 사물의 부분과 전체로 이어지는 CNN 특징 계층

풀링 pooling

  • 풀링은 피처 맵의 지역 값을 요약해 공간 크기를 줄이는 다운샘플링
  • 학습하는 가중치가 없으며 합성곱 레이어 수를 자동으로 줄이지 않음
  • 공간 크기가 줄어 이후 레이어의 연산량과 Dense 레이어의 파라미터 수를 줄일 수 있음
  • 세부 위치 정보가 손실되므로 위치가 중요한 작업에서는 성능에 영향을 줄 수 있음
  • 최대 풀링(max pooling)은 지역의 최댓값을 선택
  • 평균 풀링(average pooling)은 지역의 평균값을 계산

풀링을 반복 적용해 피처 맵의 공간 크기를 줄이는 과정

CNN의 기본 구조

  • 특징 추출 부분: 합성곱, 활성화 함수, 필요에 따른 풀링
  • 분류 부분: Flatten 또는 전역 풀링으로 특징을 모은 뒤 Dense 레이어로 예측
  • Flatten은 한 가지 연결 방법이며 모든 CNN에 필수인 것은 아님

합성곱 기반 특징 추출 부분과 Dense 기반 분류 부분

Keras 실습

데이터 준비

노트북과 같은 Torch 백엔드와 난수 초기값을 사용.

import os
os.environ["KERAS_BACKEND"] = "torch"

import keras
import numpy as np

keras.utils.set_random_seed(812)  # 실행 결과 재현용 난수 초기값

Fashion MNIST를 불러오면 훈련 이미지에는 채널 축이 없는 (60000, 28, 28) 형태가 저장됨.

(x_train, y_train), (x_test, y_test) = (
    keras.datasets.fashion_mnist.load_data()
)
  • CNN에 입력되는 이미지는 채널 축이 필요.
  • MNIST 데이터는 (N, 28, 28) 형식이므로 마지막에 채널 차원을 추가하여 (N, 28, 28, 1)로 만듦
  • 컬러 이미지의 경우 (N, H, W, 3)이므로 채널 축이 이미 존재.
x_train_cnn = np.expand_dims(x_train, axis=-1)  # 채널 축 추가
x_test_cnn = np.expand_dims(x_test, axis=-1)

CNN 구성

  • 첫 번째 합성곱은 padding="same"으로 28×28 공간 크기를 유지하며 피처 맵 32개를 생성
  • 첫 번째 2×2 최대 풀링은 공간 크기를 14×14로 축소
  • 두 번째 합성곱은 12×12 피처 맵 64개를 생성
  • 두 번째 풀링은 공간 크기를 6×6으로 축소
  • Flatten은 6×6×64 피처 맵을 길이 2,304인 분류용 벡터로 변환
  • 마지막 Dense 레이어는 10개 클래스의 로짓 출력
keras.utils.set_random_seed(812)  # 모델 가중치 초기값 재현

cnn_model = keras.models.Sequential([
    keras.Input(shape=(28, 28, 1)),  # 28×28 흑백 이미지
    keras.layers.Rescaling(1/255),  # 픽셀값을 0~1로 변환
    # 공간 크기를 유지하며 지역 특징 32개 추출
    keras.layers.Conv2D(
        32, (3, 3), padding="same", activation="relu"
    ),
    # 높이와 너비를 각각 절반으로 축소
    keras.layers.MaxPooling2D((2, 2)),
    # 더 깊은 지역 특징 64개 추출
    keras.layers.Conv2D(64, (3, 3), activation="relu"),
    keras.layers.MaxPooling2D((2, 2)),
    keras.layers.Flatten(),
    keras.layers.Dense(10),  # 10개 클래스의 로짓
])

cnn_model.compile(
    # 실습에서 사용할 고정 학습률
    optimizer=keras.optimizers.SGD(learning_rate=0.001),
    loss=keras.losses.SparseCategoricalCrossentropy(
        from_logits=True  # 마지막 Dense가 로짓을 출력
    ),
    metrics=["accuracy"],
)

각 레이어의 출력 형태와 전체 파라미터 수를 확인.

for layer in cnn_model.layers:
    print(layer.__class__.__name__, tuple(layer.output.shape))

cnn_model.count_params()
실행 결과
Rescaling (None, 28, 28, 1)
Conv2D (None, 28, 28, 32)
MaxPooling2D (None, 14, 14, 32)
Conv2D (None, 12, 12, 64)
MaxPooling2D (None, 6, 6, 64)
Flatten (None, 2304)
Dense (None, 10)
41866

첫 합성곱은 공간 크기를 유지하고, 두 번의 풀링 뒤에는 6×6×64가 됨.

모델 훈련

  • 최대 5에포크 훈련
  • 한 배치에는 이미지 64개 사용
  • 훈련 데이터의 20%를 검증 데이터로 사용
  • SGD 학습률은 0.001로 지정
cnn_history = cnn_model.fit(
    x_train_cnn,
    y_train,
    epochs=5,  # 짧은 실습을 위한 반복 횟수
    batch_size=64,  # 한 번에 처리할 이미지 수
    validation_split=0.2,  # 훈련 데이터의 20%로 검증
    verbose=0,  # 마지막 지표만 확인
)
cnn_history.history["accuracy"][-1]  # 훈련 정확도
실행 결과
0.6410416960716248
cnn_history.history["val_accuracy"][-1]  # 검증 정확도
실행 결과
0.659500002861023
cnn_history.history["val_loss"][-1]  # 검증 손실
실행 결과
1.0048625469207764
  • 5번째 에포크의 훈련 정확도는 0.6410, 검증 정확도는 0.6595
  • 검증 손실은 1.0049
  • 실행 장치와 라이브러리 버전에 따라 구체적인 값은 달라질 수 있음

테스트 데이터 평가

cnn_test_loss, cnn_test_accuracy = cnn_model.evaluate(
    x_test_cnn, y_test, verbose=0  # 진행 막대 숨김
)

cnn_test_accuracy  # 테스트 정확도
실행 결과
0.6417999863624573
  • 테스트 정확도는 약 64.18%

퀴즈

문제 1 / 7맞음: 0힌트: 0틀림: 0채점중: 0남음: 7

이미지 분류에서 Dense 중심 구조와 비교한 합성곱 레이어의 핵심 장점으로 가장 알맞은 것은 무엇입니까?

  • 작은 지역에 같은 필터를 반복 적용하여 공간 패턴을 효율적으로 찾는다
  • 이미지를 먼저 펼친 뒤 서로 가까웠던 픽셀만 골라 Dense 레이어에 연결한다
  • 이미지의 각 위치에 서로 다른 필터를 적용하여 위치별 패턴만 따로 학습한다
  • 원본 픽셀을 클래스 확률로 직접 바꾸므로 별도의 분류 레이어가 필요 없다

퀴즈를 풀려면 대화형 기능을 불러와야 합니다.

Previous
조기 종료와 모델 체크포인트