[케라스] 컨볼루션 신경망(CNN)의 레이어
21 Feb 2020
Reading time ~6 minutes
김태영님의 블록과 함께 하는 파이썬 딥러닝 케라스
를 공부하며 옮겨온 내용입니다.
이번 포스팅에서는 컨볼루션 신경망(Convolution Neuron Network)
에서 사용되는 레이어들에 대해서 정리해보겠습니다.
컨볼루션(Convolution) 레이어
필터를 통해 입력값의 특징을 뽑아주는 레이어로 이미지처리에 많이 사용되고 있습니다.
그 중에 많이 사용되는 Conv2D
레이어는 아래와 같이 사용합니다.
Conv2D(32, (5, 5), padding = 'valid', input_shape = (28, 28, 1), activation = 'relu')
Conv2D레이어의 입력 인자
- 첫번째 인자(
filters
): 컨볼루션 필터의 수를 설정합니다. - 두번째 인자(
kernel_size
): 컨볼루션 커널의 행, 열 수를 설정합니다. padding
: 경계 처리 방법을 정의합니다.valid
: 유효한 영역만 출력이 되어, 출력 이미지 사이즈는 입력 사이즈보다 작습니다.same
: 출력 이미지 사이즈가 입력 이미지 사이즈와 동일합니다.
input_shape
: 샘플 수를 제외한 입력 형태를 정의합니다. 첫 레이어에서만 정의하면 됩니다.- (행, 열, 채널수) 로 정의되며 흑백 이미지의 경우 1, 컬러(RGB)인 경우 3으로 채널을 설정합니다.
activation
: 활성화함수를 설정합니다.linear
: 디폴트 값으로 입력값과 가중치로 계산된 결과 값이 그대로 출력으로 나옵니다sigmoid
: 시그모이드 함수로 이진분류에서 출력층에 주로 쓰입니다softmax
: 소프드맥스 함수로 다중클래스 분류문제에서 출력층에 주로 쓰입니다.relu
: Rectified Linear Unit 함수로 은닉층에서 주로 쓰입니다.
입출력형태 잠시 생략
입력이미지의 너비 3픽셀, 높이 3픽셀, 채널수가 1이고, 필터 크기가 2 x 2 인 컨볼루션 레이어를 표시하면 다음과 같습니다.
Conv2D(1, (2, 2), padding = 'valid', input_shape = (3, 3, 1))
이를 블록으로 나타내면 아래와 같습니다.
필터는 가중치(w0, w1, w2, w3)를 의미합니다. 하나의 필터가 입력 이미지를 순회하면서 적용된 결과 값을 모으면 출력 이미지가 생성됩니다.
- 이 때, 하나의 필터로 입력 이미지를 순회하기 때문에 적용되는 가중치는 모두 동일합니다. 이 특징은 학습해야할 가중치 수를 줄여줍니다.
- 출력에 영향을 미치는 영역이 제한되어 있습니다. 레고 블록 그림에서 y0에 영향을 미치는 입력은 x0, x1, x3, x4 입니다. 이런 방식은 지역적인 특징을 잘 뽑아내며 이미지 인식에 잘 적용됩니다. 가령, 코를 볼 때는 코를 보고, 눈을 볼 때는 눈 주변만 보며 학습합니다.
컨볼루션 레이어 가중치의 수
Dense 레이어와 비교하여 컨볼루션 레이어의 특징을 알아보겠습니다. 이미지도 결국 픽셀의 집합이기 때문에 입력 뉴런의 값이 9개(3 x 3), 출력 뉴런이 (2 x 2)인 Dense 레이어로 표현할 수 있습니다.
Dense(4, input_dim = 9)
이를 블록으로 나타내면 아래와 같습니다.
가중치는 녹색블록으로 표시되어 있습니다. 총 9개 입력값에 대해 가중치가 각각 4개가 있어 총 36개의 가중치가 있습니다.
그리고 아래는 컨볼루션 레이어를 블록으로 나타낸 그림입니다.
필터가 입력값의 일부구역에만 적용되어 출력 뉴련에 영향을 미치는 입력 뉴런이 제한적입니다. 때문에 앞의 Dense 레이어보다 가중치가 많이 줄어든 것을 볼 수 있습니다. 그리고 녹색 블록 상단에 표시된 빨강, 파랑, 노랑, 분홍은 동일한 가중치 값이므로 사용된 가중치 값은 필터의 크기인 총 4개 입니다.
경계 처리 방법(padding)
컨볼루션 레이어의 padding
파라미터를 조절하여 입력값의 경계를 처리하는 방법을 설정할 수 있습니다.
valid
: 입력이미지의 영역에 맞게 필터를 적용하여 출력 이미지의 크기가 입력 이미지의 크기보다 작아집니다.same
: 출력 이미지와 입력 이미지 사이즈가 동일하도록 입력 이미지 경계에 빈 영역(검은 블록)을 추가하여 필터를 적용합니다. 그 결과, 출력 이미지의 크기는 입력 이미지의 크기와 동일해집니다. 이 방법은 입력 이미지의 경계를 학습시키는 효과가 있습니다.
필터 수
필터의 수에 대해 알아보겠습니다. 입력 이미지의 크기가 3 x 3이고, 필터의 크기가 2 x 2인 컨볼루션 레이어는 아래와 같이 나타낼 수 있습니다.
Conv2D(1, (2, 2), padding = 'same', input_shape = (3, 3, 1))
여기서 필터의 개수를 3개를 사용하면 아래와 같이 나타낼 수 있습니다.
Conv2D(3, (2, 2), padding = 'same', input_shape = (3, 3, 1))
필터를 1개를 사용했을 때와 비교하면, 3개를 사용했을 때 출력 이미지의 수도 3개로 늘어났습니다. 총 가중치의 수도 3 x 2 x 2 로 12개가 됩니다. 필터마다 고유한 특징을 뽑아 고유한 출력 이미지로 만들기 때문에 필터의 출력 값들을 더해서 하나의 이미지를 만들거나 그렇게 하지 않습니다. 이를 블록으로 간단히 표현하면 아래와 같이 나타낼 수 있습니다.
위 그림은 다음을 의미합니다.
- 입력 이미지 : 3 x 3의 크기
- 크기가 2 x 2인 필터가 3개 → 가중치는 총 12개
- 출력 이미지 : 크기가 3 x 3이고 개수(채널)는 3개
이번에는 입력 이미지의 채널이 여러 개인 경우를 보겠습니다. 입력 이미지의 크기가 3 x 3이고 채널이 3개, 2 x 2인 필터를 1개일 때의 컨볼루션 레이어는 아래와 같습니다.
Conv2D(1, (2, 2), padding = 'same', input_shape = (3, 3, 3))
그림 상으로 보면 필터의 개수가 3개인 것 같지만, 노란색 블록은 각 입력 이미지에 할당되어 계산되고, 파란색 블록에 해당하는 출력 이미지 하나를 만들어 냅니다. 필터의 개수는 1개이지만, 입력이미지의 채널이 3개 이므로, 가중치는 2 x 2 x 3 = 12개입니다. 이를 보다 간단히 나타내면 아래와 같습니다.
위 그림은 다음을 의미합니다.
- 입력 이미지 : 크기가 3 x 3, 채널은 3개
- 크기가 2 x 2 인 필터라 1개, 채널마다 커널이 할당되어 총 가중치는 12개입니다.
- 출력 이미지 : 크기가 3 x 3, 채널은 1개
이번엔 입력 이미지의 크기가 3 x 3이고 채널이 3개, 2 x 2인 필터가 2개인 경우를 보겠습니다.
Conv2D(2, (2, 2), padding = 'same', input_shape = (3, 3, 3))
필터가 2개였기 때문에, 출력이미지도 2개로 나오며 이를 더 간단히 표현하면 아래와 같습니다.
위 그림은 다음을 의미합니다.
- 입력 이미지 : 크기가 3 x 3, 채널은 3개
- 크기가 2 x 2 인 필터라 2개, 채널마다 커널이 할당되어 총 가중치는 3 x 2 x 2 x 2 = 24개입니다.
- 출력 이미지 : 크기가 3 x 3, 채널은 2개
맥스풀링(Max Pooling) 레이어
맥스풀링 레이어는 컨볼루션 레이어의 출력 이미지에서 주요한 값들만 뽑아 크기가 작은 출력 이미지를 만들어 줍니다. 이를 통해 지역적인 작은 변화가 영향을 미치지 않게 해줍니다.
MaxPooling2D(pool_size = (2,2))
pool_size
파라미터는 출력될 이미지의 수직, 수평 축소 비율을 지정합니다. (2, 2)이면 출력 이미지의 크기는 입력 이미지의 크기를 반으로 줄여줍니다.
가령, 입력 이미지의 크기가 4 x 4이고, pool_size
를 (2, 2)로 했을 때 블록으로 나타내면 아래와 같습니다. 녹색 블럭은 입력 이미지를 나타내고, 노란색 블록은 풀 크기에 따라 나눈 경계를 표시합니다. 나뉜 부분에서 가장 큰 값을 선택하여 파란 블록으로 만들면 그것이 출력 이미지가 됩니다.
맥스풀링 레이어는 이미지의 작은 변화가 특징을 추출할 때 크게 영향을 미치지 않도록 합니다. 이미지 내 세 개의 특징이 있다고 가정하겠습니다. 이 때, 아래 그림에서 첫 번째 그림에서 두 번째 그림은 오른쪽으로 조금 이동, 세 번째 그림은 살짝 비틀어져있고, 네 번째 그림은 확대되어 있습니다. 얼굴 인식 문제에서의 경우, 맥스풀링 레이어는 사람 마다 눈, 코, 입의 위치가 조금씩 다른데 이런 차이로 인해 사람의 얼굴을 인식하지 못하는 문제를 줄여줍니다.
플래튼(Flatten) 레이어
CNN에서 컨볼루션 레이어나 맥스풀링 레이어를 반복적으로 거치면 주요 특징이 추출되고, 추출된 주요 특징들은 전결합층(덴스 레이어)에 전달되어 학습됩니다. 컨볼루션 레이어나 맥스풀링 레이어는 2차원 자료를 주로 다루지만 전결합층에 전달하기 위해서는 1차원 자료로 변환해야 합니다. 이 때 플래튼 레이어(Flatten Layer)
를 사용합니다.
Flatten()
플레튼 레이어는 이전 레이어의 출력 정보를 이용하여 입력 정보를 자동으로 설정합니다. 그리고 출력 형태는 입력형태에 따라 자동으로 설정하기 때문에, 파라미터를 별도로 지정해주지 않아도 됩니다.
크기가 3 x 3인 이미지를 1차원으로 변경했을 때, 이를 도식화하면 다음과 같습니다.
### CNN 모델 만들어보기
손으로 삼각형, 사각형, 원을 손으로 그린 이미지가 있고, 이미지 크기가 8 x 8 이라고 가정하겠습니다. 삼각형, 사각형, 원 3개의 클래스를 분류하는 문제이므로 출력 벡터도 3개여야 합니다.
- 컨볼루션 레이어 : (입력 이미지) 크기 8 x 8, 채널 1개 / (필터) 크기 3 x 3, 2개 / (경계) same / (활성화함수) relu
- 맥스풀링 레이어 : 풀 크기 2 x 2
- 컨볼루션 레이어 : (입력 이미지) 크기 4 x 4, 채널 2개 / (필터) 크기 2 x 2, 3개 / (경계) same / (활성화함수) relu
- 맥스풀링 레이어 : 풀 크기 2 x 2
- 플래튼 레이어
- 덴스 레이어 : (입력 뉴런 수) 12개 / (출력 뉴런 수) 8개 / (활성화함수) relu
- 덴스 레이어 : (입력 뉴런 수) 8개 / (출력 뉴런 수) 3개 / (활성화함수) softmax
위의 레이어들을 조합하여 CNN 모델의 전체 모양을 나타내면 아래와 같습니다.
이제 위의 블록으로 나타낸 CNN 모델을 케라스 코드로 구현해 보겠습니다.
# 사용할 패키지 불러오기
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.utils import np_utils
# CNN 모델 만들기
model = Sequential()
model.add(Conv2D(2, (3, 3), input_shape = (8, 8, 1), padding = 'same', activation= 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Conv2D(3, (2, 2), padding = 'same', activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Flatten())
model.add(Dense(8, activation = 'relu'))
model.add(Dense(3, activation = 'softmax'))
# 모델의 시각화
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
%matplotlib inline
SVG(model_to_dot(model, show_shapes = True).create(prog = 'dot', format = 'svg'))
Reference
- 블록과 함께 하는 파이썬 딥러닝 케라스 (김태영 저)