ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 혼공머신 CH 08 합성곱 신경망 (CNN)
    Study/머신러닝 딥러닝 2025. 9. 28. 16:31


     

    합성곱 신경망(CNN)의 이론 및 실습: 이미지 분류와 시각화 정복하기

     

    목차

     

    들어가며: CNN의 핵심 구성 요소 이해와 실전 구현

     

    1. 합성곱 신경망(CNN)의 기본 구성 요소 (이론)
      1-1. 밀집층과 합성곱층의 차이 
      1-2. 커널(Kernel)과 필터(Filter), 그리고 특성 맵(Feature Map) 
      1-3. 패딩(Padding)과 풀링층(Pooling Layer)의 역할
    2. 실습: Fashion MNIST 분류 모델 구축 (코드 구현)
      2-1. 데이터 준비 및 CNN 모델 구조 설계 
      2-2. 모델 훈련 및 성능 평가
    3. 심화: CNN의 작동 원리 시각화 
      3-1. 학습된 가중치(필터) 시각화: 필터는 무엇을 배웠는가? 
      3-2. 특성 맵(Feature Map) 시각화: 이미지는 어떻게 변환되는가? 

    마치며: 이론과 실습으로 완성하는 CNN 이해

     


    들어가며: CNN의 핵심 구성 요소 이해와 실전 구현

     

    이번 글은 이미지 처리에서 뛰어난 성능을 보이는 합성곱 신경망(Convolutional Neural Network, CNN)의 핵심을 총정리한 완성본입니다. 우리는 CNN의 이론적 배경을 확실히 다지고, Fashion MNIST 데이터셋을 사용한 실제 이미지 분류 모델 구축 과정을 상세히 살펴봅니다.

    특히, 단순히 모델을 만드는 것을 넘어, 학습된 필터(가중치) 특성 맵(Feature Map)을 시각화하여 CNN이 이미지를 어떻게 '이해'하고 '처리'하는지 그 내부 동작 원리까지 깊이 있게 파헤쳐 보겠습니다. 이 글을 통해 CNN의 이론과 실습 능력을 동시에 향상시킬 수 있을 겁니다.

     


    1. 합성곱 신경망(CNN)의 기본 구성 요소 

    CNN은 이미지의 공간적 정보를 효과적으로 처리하기 위해 기존의 밀집층 기반 신경망과 다른 특별한 구조를 사용합니다.

    1-1. 밀집층과 합성곱층의 차이

     

    • 밀집층 (Dense Layer): 입력의 모든 특성값에 가중치를 곱하여 출력을 만듭니다. 이미지의 공간 정보를 무시하고 1차원으로 펼쳐서 처리합니다.
    • 합성곱층 (Convolutional Layer): 입력의 일부 특성값에만 가중치를 곱하는 가중치 뭉치(필터)가 입력 위를 슬라이딩(Sliding)
      하며 이동하며 계산합니다. 이 방식은 주변 픽셀과의 관계를 유지하여 특징을 추출하는 데 효과적입니다.

    1-2. 커널(Kernel)과 필터(Filter), 그리고 특성 맵(Feature Map)

     

    • 커널/필터: 합성곱층의 가중치 뭉치를 커널 또는 필터라고 하며, 이미지에서 특정 패턴을 감지하는 역할을 학습합니다. 여러 필터를 사용하면 다양한 특징을 동시에 추출할 수 있습니다.
    • 특성 맵 (Feature Map): 합성곱 연산의 출력 결과로, 필터가 이미지에서 어떤 특징을 어디서 발견했는지를 보여주는 지도와 같습니다. 필터의 개수가 특성 맵의 깊이(채널)를 결정합니다.

    1-3. 패딩(Padding)과 풀링층(Pooling Layer)의 역할

     

    • 패딩 (padding='same'): 입력 이미지 가장자리에 0 값을 채워 넣어, 합성곱 연산 후에도 출력 특성 맵의 크기를 입력과 동일하게 유지하도록 돕습니다.
    • 풀링층 (MaxPooling2D): 특성 맵의 크기(너비와 높이)를 줄이는 다운샘플링을 수행합니다. 주로 최대 풀링을 사용하며, 모델의 연산량을 줄이고 과대적합을 방지하는 효과가 있습니다. 풀링층은 학습할 가중치가 없습니다.

     

     


    2. 실습: Fashion MNIST 분류 모델 구축 (코드 구현)

    2-1. 데이터 준비 및 CNN 모델 구조 설계

     

    Fashion MNIST 데이터셋을 사용하여 CNN 모델을 구축합니다. 흑백 이미지(28x28)를 CNN 입력 형태인 (28, 28, 1)로 변환하고 255로 나누어 정규화(Scaling)하는 전처리 작업을 수행합니다.

    import keras
    import tensorflow as tf
    from sklearn.model_selection import train_test_split
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 재현성을 위한 랜덤 시드 설정
    keras.utils.set_random_seed(42)
    tf.random.set_seed(42)
    tf.config.experimental.enable_op_determinism()
    
    # Fashion MNIST 데이터 로드 및 전처리
    (train_input, train_target), (test_input, test_target) = \
        keras.datasets.fashion_mnist.load_data()
    
    # 픽셀 값을 0~1로 정규화하고, 이미지 차원을 (28, 28, 1)로 변환
    train_scaled = train_input.reshape(-1, 28, 28, 1) / 255.0
    
    # 훈련 세트와 검증 세트로 분리
    train_scaled, val_scaled, train_target, val_target = train_test_split(
        train_scaled, train_target, test_size=0.2, random_state=42)
    
    # CNN 모델 정의 (Sequential API)
    model = keras.Sequential()
    model.add(keras.layers.Input(shape=(28,28,1)))
    
    # 첫 번째 합성곱 + 풀링 층
    model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu',
                                  padding='same')) # 3x3 커널 32개, relu, padding='same'
    model.add(keras.layers.MaxPooling2D(2)) # 2x2 풀링, 크기가 절반으로 감소 (28x28 -> 14x14)
    
    # 두 번째 합성곱 + 풀링 층
    model.add(keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu',
                                  padding='same')) # 3x3 커널 64개, relu, padding='same'
    model.add(keras.layers.MaxPooling2D(2)) # 2x2 풀링, 크기가 다시 절반으로 감소 (14x14 -> 7x7)
    
    # 밀집층을 위한 준비 및 Dropout
    model.add(keras.layers.Flatten()) # 다차원 특성 맵을 1차원으로 펼침 (7*7*64=3136)
    model.add(keras.layers.Dense(100, activation='relu')) # 은닉층 (ReLU 활성화 함수)
    model.add(keras.layers.Dropout(0.4)) # 과대적합 방지를 위한 40% 드롭아웃
    model.add(keras.layers.Dense(10, activation='softmax')) # 출력층 (Softmax, 10개 클래스)
    

     

     

    CNN 모델 구조 요약:

     

    Layer (type) Output Shape Param # 설명
    Input (28, 28, 1) 0 흑백 이미지 입력 (28x28, 1채널)
    Conv2D (None, 28, 28, 32) 320 3x3 커널 32개, relu, padding='same'.
    MaxPooling2D (None, 14, 14, 32) 0 2x2 풀링, 크기가 절반으로 감소.
    Conv2D (None, 14, 14, 64) 18,496 3x3 커널 64개, relu, padding='same'.
    MaxPooling2D (None, 7, 7, 64) 0 2x2 풀링, 크기가 다시 절반으로 감소.
    Flatten (None, 3136) 0 다차원 특성 맵을 1차원으로 펼침
    Dense (None, 100) 313,700 은닉층 (ReLU 활성화 함수)
    Dropout (None, 100) 0 과대적합 방지를 위한 40% 드롭아웃
    Dense (None, 10) 1,010 출력층 (Softmax 활성화 함수, 10개 클래스)
    총 파라미터 수   333,526  
     
     


    2-2. 모델 훈련 및 성능 평가

     

    모델은 adam 옵티마이저 sparse_categorical_crossentropy 손실 함수를 사용하여 컴파일하고, ModelCheckpoint EarlyStopping 콜백을 적용하여 훈련합니다.

    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'], jit_compile=False) 
    # 최적의 검증 손실을 달성한 모델 저장
    checkpoint_cb = keras.callbacks.ModelCheckpoint('best-cnn-model.keras',
                                                    save_best_only=True)
    # 검증 손실이 2번 연속 개선되지 않으면 훈련을 중지
    early_stopping_cb = keras.callbacks.EarlyStopping(patience=2,
                                                      restore_best_weights=True)
    
    history = model.fit(train_scaled, train_target, epochs=20,
                        validation_data=(val_scaled, val_target),
                        callbacks=[checkpoint_cb, early_stopping_cb])
    
    # 테스트 세트 평가
    test_scaled = test_input.reshape(-1, 28, 28, 1) / 255.0
    model.evaluate(test_scaled, test_target)
    

     

    주요 결과:

    • 훈련 결과 (총 6 Epochs 후 조기 종료): 훈련 정확도 약 91.5% 이상, 검증 손실 최저점 0.2303 (Epoch 6)
    • 최종 성능 평가 (테스트 세트): 손실(Loss) 0.2553, 정확도(Accuracy) 0.9096 (약 91.0%)
     


    3. 심화: CNN의 작동 원리 시각화

    3-1. 학습된 가중치(필터) 시각화: 필터는 무엇을 배웠는가?

     

     

    훈련된 모델의 첫 번째 Conv2D 층의 가중치(필터)를 시각화하여, 모델이 이미지에서 어떤 기본적인 특징을 감지하도록 학습했는지 확인합니다.

    # 훈련된 모델 로드 (best-cnn-model.keras 파일이 존재한다고 가정)
    # model = keras.models.load_model('best-cnn-model.keras')
    conv = model.layers[0] 
    conv_weights = conv.weights[0].numpy()
    
    # 학습된 32개 필터 시각화
    fig, axs = plt.subplots(2, 16, figsize=(15,2))
    for i in range(2):
        for j in range(16):
            # 3x3 필터가 어떤 패턴을 학습했는지 시각화
            axs[i, j].imshow(conv_weights[:,:,0,i*16 + j], vmin=-0.5, vmax=0.5)
            axs[i, j].axis('off')
    plt.show()
    

     

    분석:

    • 훈련 전 가중치: 무작위로 초기화되어 아무런 의미 있는 패턴이 보이지 않습니다.
    • 훈련 후 가중치: 3x3 크기의 필터들이 수직선, 수평선, 대각선, 명암 대비 등 이미지의 가장 기본적인 특징을 감지하는 패턴으로 학습된 것을 확인할 수 있습니다. 이는 CNN이 낮은 층에서부터 기본적인 선과 윤곽을 추출하는 것부터 시작함을 보여줍니다.

    3-2. 특성 맵(Feature Map) 시각화: 이미지는 어떻게 변환되는가?

     

    함수형 API를 사용하여 첫 번째 및 두 번째 합성곱 층의 출력을 얻는 새로운 모델을 생성하고, 입력 이미지가 각 층에서 어떻게 변환되는지를 시각화합니다.

    # 검증 세트의 첫 번째 샘플을 입력으로 준비
    ankle_boot = val_scaled[0:1] 
    
    # 1. 첫 번째 Conv2D 층의 출력을 얻는 모델 생성 및 예측
    conv_acti = keras.Model(model.inputs[0], model.layers[0].output)
    feature_maps_conv1 = conv_acti.predict(ankle_boot)
    print("첫 번째 Conv2D 층 출력 형태:", feature_maps_conv1.shape)
    # 
    
    # 2. 두 번째 Conv2D 층의 출력을 얻는 모델 생성 및 예측
    conv2_acti = keras.Model(model.inputs, model.layers[2].output)
    feature_maps_conv2 = conv2_acti.predict(ankle_boot)
    print("두 번째 Conv2D 층 출력 형태:", feature_maps_conv2.shape)
    # 
    


    분석:

    • 첫 번째 Conv2D 층 (32개 채널): 각 맵은 필터에 따라 신발의 외곽선이나 수직선 등 기본적인 특징을 다르게 추출하며, relu 활성화 함수로 인해 배경이 어둡고 활성화된 특징만 밝게 나타납니다.
    • 두 번째 Conv2D 층 (64개 채널): 맵의 크기가 에서 로 줄어든 출력에 대해 연산하며, 시각적으로 더 추상적이고 복잡한 특징을 포착하는 경향을 보여줍니다. (참고: 이 예시 이미지에 대해 모델은 '앵클 부츠'를 '가방'으로 예측하는 오류를 보였습니다.)
     


    마치며: 이론과 실습으로 완성하는 CNN 이해

    이번 종합 정리를 통해 CNN의 이론적 구성 요소와 실제 모델 구현, 그리고 그 작동 원리를 시각적으로 확인하는 과정을 모두 마쳤습니다. CNN은 낮은 층에서 기본적인 윤곽선을 학습하고, 높은 층으로 갈수록 이를 조합하여 복잡한 특징을 추출하는 계층적 특징 추출 과정을 거칩니다. 이러한 깊은 이해를 바탕으로 여러분의 딥러닝 모델 개발 능력이 한 단계 더 발전하길 응원합니다!

     

     


     

     

    코드 출처:

     

    https://github.com/rickiepark/hg-mldl2/blob/main/08-2.ipynb

     

    hg-mldl2/08-2.ipynb at main · rickiepark/hg-mldl2

    <혼자 공부하는 머신러닝+딥러닝(개정판)>(한빛미디어, 2025)의 코드 저장소입니다. Contribute to rickiepark/hg-mldl2 development by creating an account on GitHub.

    github.com

     

    https://github.com/rickiepark/hg-mldl2/blob/main/08-2.ipynb

     

    hg-mldl2/08-2.ipynb at main · rickiepark/hg-mldl2

    <혼자 공부하는 머신러닝+딥러닝(개정판)>(한빛미디어, 2025)의 코드 저장소입니다. Contribute to rickiepark/hg-mldl2 development by creating an account on GitHub.

    github.com

     

    내용 및 이미지 출처:

     

    https://www.youtube.com/watch?v=NUYgibJAHfA&list=PLVsNizTWUw7E2RxZ4aspcR9vNamXccmFE&index=21

     

    https://www.youtube.com/watch?v=F-K03UBWUVE&list=PLVsNizTWUw7E2RxZ4aspcR9vNamXccmFE&index=22

     

    https://www.youtube.com/watch?v=28beETw65Ec&list=PLVsNizTWUw7E2RxZ4aspcR9vNamXccmFE&index=23

     

Designed by Tistory.