내가 하고싶은 건 다 하는 공간

혼자 만들면서 공부하는 딥러닝 1-2 합성곱 신경망(CNN) 모델 이해하기: 합성곱층 Conv2D 본문

인공지능

혼자 만들면서 공부하는 딥러닝 1-2 합성곱 신경망(CNN) 모델 이해하기: 합성곱층 Conv2D

하고파 2025. 7. 5. 16:48

패딩 Padding

합성곱 연산을 통해 얻어진 결과에서 가장자리에 빈 공간을 추가합니다. 패딩을 이용하면 이미지 가장자리 부분의 픽셀이 충분히 처리될 수 있습니다.

ⓒ https://amber-chaeeunk.tistory.com/24

패딩을 하지 않았다면 빨간색으로 표시된 1이 한 번만 연산될텐데, 패딩을 통해 4번 연산됩니다. 즉, 연산이 더 많이 일어나지만 가장자리 정보를 보존할 수 있습니다. 또한 출력 크기가 일정하게 유지된다는 특징이 있습니다. 위 사진에서는 입력과 출력 데이터가 모두 4*4의 크기로 동일합니다.

패딩을 하면 세임 패딩 Same Padding, 패딩을 안 하면 밸리드 패딩 Valid Padding이라고 합니다. 패딩을 하면 입력과 출력의 크기가 같으므로(same) 세임 패딩이다~ 이렇게 이해했습니다.

 

스트라이드 Strides

합성곱 연산을 수행할 때 몇 칸씩 이동하면서 수행할지를 나타냅니다. 인간의 보폭으로 비유하면 딱 좋겠네요.스트라이드가 1이면 합성곱 연산 대상 범위를 한 칸씩 이동하고, 2이면 두 칸씩 이동합니다.

보통 스트라이드 = 1을 선택합니다. 스트라이드가 클수록 겅중겅중(?) 뛰어다니기 때문에 정보가 생략되고, 스트라이드가 작을수록 정밀하게 분석합니다.

 

Conv2D 클래스

2차원 합성곱을 수행합니다. 필수 매개변수로는 1) 필터 개수 2) 필터 1개의 크기 - 2개입니다.

* 필터 = 커널 = 입력에 곱해지는 가중치 
import keras
from keras import layers

conv1 = layers.Conv2D(filters=10, kernel_size=(3, 3))

이 외에도 스트라이드, 패딩, 활성화 함수, (높이, 너비, 채널 수) 등을 지정하는 매개변수들이 있습니다. 별도로 설정하지 않으면 스트라이드 기본값은 1로 들어갑니다.

tf.keras.layers.Conv2D(
    filters,               # 출력 채널 수 (즉, 필터 개수)
    kernel_size,           # 필터 크기 (예: 3, (3,3))
    strides=(1, 1),        # 필터 이동 간격
    padding='valid',       # 'same' or 'valid'
    activation=None,       # 예: 'relu'
    input_shape=None       # 첫 층이라면 필요
)

 

합성곱층 만들기 실습

넘파이를 사용해 임의의 28*28*1 크기의 흑백 이미지 10개를 랜덤으로 생성해서 합성곱층 만들기 실습을 진행합니다.

*채널수가 1이면 흑백 이미지, 채널수가 3이면 컬러 이미지(RGB; R, G, B 총 3개의 채널)
import numpy as numpy
x = np.random.normal(size = (10, 28, 28, 1))
conv_out = conv1(x)
print(conv_out.shape) # (10, 26, 26, 10)

이전에 3*3 크기의 커널을 지정해주었기 때문에 그 커널을 이용한 합성곱 연산을 진행하면 (10: 배치의 차원, 26: 높이, 26: 너비, 10: 특성 맵의 깊이, 즉 필터의 개수) 크기의 데이터가 반환됩니다.

* 배치 Batch: 데이터의 묶음 단위

ⓒ 혼자 만들면서 공부하는 딥러닝 책

전체적인 흐름을 그림으로 그리면 다음과 같습니다. 합성곱층이 거듭될수록 많은 필터를 사용해서 특성 맵의 깊이가 점점 더 깊어집니다. 또한 패딩을 사용하지 않으면 차원이 줄어듭니다(=가로/세로 크기가 줄어듭니다). 즉, 특성맵의 하나의 원소가 많은 정보를 담게 됩니다. 

 

스트라이드, 패딩 등의 추가 조건을 넣어서 어떤 변화가 있는지 살펴보겠습니다.

 

1. 스트라이드 Stride = 2로 설정

stride의 기본값이 1인데, 이걸 2로 바꿔주려면 Conv2D 클래스 내에서 매개변수를 지정해줘야 합니다. 참고로 stride가 아니라 strides 입니다(자꾸 헷갈리네요). strides = (2, 2)라고 했지만 strides = 2처럼 정수 하나로 지정할 수 있습니다. 

conv2 = layers.Conv2D(filters=10, kernel_size=(3, 3), strides=(2, 2))
print(conv2(x).shape) # (10, 13, 13, 10)

그러면 차원의 크기가 28*28에서 13*13으로, 크기가 확 줄었습니다.

 

2. 패딩

가장자리에 0을 넣어서 패딩을 추가합니다.

conv3 = layers.Conv2D(filters=10, kernel_size=(3, 3), padding='same')
print(conv3(x).shape) # (10, 28, 28, 10)

패딩을 해줬기 때문에 차원의 크기가 그대로 유지됩니다.

 

3. 스트라이드 = 2 & 패딩 

둘 다 해주면 차원이 14*14가 되네요.

conv3 = layers.Conv2D(filters=10, kernel_size=(3, 3), strides=(2, 2), padding='same')
print(conv3(x).shape) # (10, 14, 14, 10)

 

정리하면 아래와 같습니다. 풀링, 스트라이드를 하면 차원의 크기가 변합니다.

  배치의 차원 차원 특성 맵의 깊이 = 필터의 개수
원래 흑백 이미지 10(이미지 10개) 28*28 1
기본 합성곱 연산(필터 10개, 필터 크기 3*3) 10 26*26 10
스트라이드 = 2 10 13*13 10
패딩 10 28*28 10
스트라이드 = 2 & 패딩 10 14*14 10

 

참고

 

딥러닝) CNN 구조 , 합성곱 계층 , padding , stride , 배치 처리

이번 포스팅에서 다룰 합성곱 신경망(Convolutional neural network , CNN)은 이미지 및 음성 인식에서 주로 사용된다. 1. CNN 구조 이전 포스팅까지 다루었던 기본 신경망은 인접하는 Layer의 모든 neuron들이

amber-chaeeunk.tistory.com