: Feature Map으로 표현된 정보를 축약(down sampling) 하는 역할
Parameter를 사용하지 않고 정보를 압축할 수 있다는 장점이 있다.
(convolution과 달리 parameter 찾아내는 연산과정이 없는 것이 장점)
또한 Pooling은 비선형성을 강화하고,
Feature map의 크기를 줄여서 연산 성능을 향상시킬 수 있다.
Q. Max Pooling, Average Pooling, Sum Pooling은 각 Feature map을 어떻게 연산하는지 설명해 봅시다.
Max Pooling : 가장 큰 값을 추출
Average Pooling : 평균 값을 추출
Sum Pooling : 그 영역의 값을 모두 더한 값 추출
이 때, 겹치지 않게 커널이 움직인다.
Q. 전형적인 CNN 구조에 대해 다시 한번 설명해 볼까요? 3차원의 Input image가 CNN(Convolution Neural Network) 구조에 들어가면 어떠한 연산을 거치게 되는지 설명해 봅시다.
3차원의 Input image가 들어오게 되면 Convolution 연산을 하게 되고 그다음에 오늘 배울 Pooling 연산을 하게 됩니다. 반복해서 Convolution 연산과 Pooling 연산을 하게 되고 어느 순간 FC라고 표현하는 Fully Connected layer를 만나게 됩니다. 마지막으로는 최종적으로 내가 수행하고 싶은 classification을 진행하게 됩니다.
Q. Convolution Neural Network를 구성하고 있는 가장 핵심적인 연산 Convolution 연산과 Pooling 연산이 다 적용된 CNN은 어떻게 구성되어 있고 어떤 특징을 가지고 있는지 설명해 봅시다.
Input(3Dimention)을 R,G,B의 3개의 channel을 kernel로 overiding 하며
Convolution + ReLu(activation funtion) + Pooling 하면서
downsizing + upsizing 반복하며
패턴을 찾아낸 후에 (Feature Extraction)
가로세로가 줄어든 여러 개의 Feature Map이 생성되면
이를 Flatten Layer(1Dimention의 Vector) 를 여러 개를 쌓아서
Task (MLP 즉, FC(Fully Conndected Layer) 를 수행하여
원하는 Output을 나오게 하여
최종적으로 Classification 수행한다.
CNN은 크게 Feature Extraction과 Classification 영역으로 구성됩니다.
연속적인 CNN 연산(Convolution + Pooling)을 순차적으로 수행하면서
일련의 Feature Map을 생성합니다.
CNN 연산을 통해 순차적으로 생성된 Feature map의 크기(높이x너비)는 줄어들지만
채널(깊이)은 증가합니다.
최근에는 더 복잡하고 다양한 Feature 정보를 반영하기 위해,
CNN 깊이를 증가시키는 방향으로 점차 발전하고 있습니다.
tf.keras 라이브러리를 이용해서 CNN 구조를 구현해봅시다.
2D convolutional layer는
tf.keras.layers.Conv2D 객체를 생성하여 구현할 수 있습니다.
Conv2D 객체의 자료형은 keras.engine.keras_tensor.KerasTensor입니다.
모델을 생성할 때, tf.keras.layers.Input 레이어를 맨 처음에 정의해야 합니다.
여기서는 (28, 28, 1) 크기의 데이터를 입력받는 input layer를 생성했습니다.
input_layer.shape 결과에서 처음 보이는 None은
데이터셋의 batch size에 해당됩니다.
x라는 레이어 객체는 output 채널이 4개인 convolutional layer이므로
x.shape의 결과는 (None, 28, 28, 4)가 됩니다.
중요한 점은, 레이어를 생성할 때 output = Conv2D(params)(input) 형태로 input과 output 변수를 넣고, 이전 레이어의 output을 다음 레이어의 input으로 설정함으로써 레이어들이 서로 연결되도록 해야 한다는 것입니다.
import tensorflow as tf
# 가로 28, 세로 28, 채널 수 1의 input 데이터를 받는 input layer 생성하기
input_layer = tf.keras.layers.Input(shape=(28, 28, 1))
# 커널의 가로 세로 사이즈는 3이고, 채널 수는 4, zero-padding을 넣고,
# stride는 1로 한 Conv2D layer
x = tf.keras.layers.Conv2D(filters=4, kernel_size=3, strides=1, padding='same', activation='relu')(input_layer)
print(type(x))
print(x)
print(input_layer.shape)
print(x.shape)
패딩을 사용했기 때문에 input과 동일한 가로 세로 사이즈를 가지고 있고,
채널 수를 4로 했기 때문에 feature map의 채널 수도 4입니다.
이번에는 pooling layer가 포함된 CNN 모델을 만들어봅시다.
(27, 27, 1) 크기의 입력을 받는 input_tensor와 Conv2D 레이어 x1,
그리고 pooling layer에 해당하는 MaxPooling2D 레이어 x2로 구성되어 있습니다.
# Q. 가로 27, 세로 27, 채널 수 1의 input 데이터를 받는 input layer 생성
input_tensor = tf.keras.layers.Input(shape=(27, 27, 1))
# Q. 커널의 가로 세로 사이즈는 2이고, 채널 수는 6, zero-padding을 넣고,
# stride는 2인 Conv2D layer x1을 생성해 보세요. (활성화 함수 : relu)
x1 = tf.keras.layers.Conv2D(filters=6, kernel_size=2, strides=2, padding='same', activation='relu')(input_layer)
print(type(x1))
print(x1)
# 가로 세로 사이즈가 2인 영역에서 최대값을 뽑는 Maxpooling을 적용
x2 = tf.keras.layers.MaxPooling2D(2)(x1)
print(x1)
print(x2)
레이어 객체를 쭉 정의한 다음,
tf.keras.Model 함수에 input과 output을 연결해서 모델 객체를 생성합니다.
model.summary() 함수를 이용하면 완성된 모델의 구조를 한번에 살펴볼 수 있습니다.
input_layer = tf.keras.layers.Input(shape=(7, 7, 5))
convlayer1 = tf.keras.layers.Conv2D(filters=4, kernel_size=3, strides=1, padding='same')(input_layer)
convlayer2 = tf.keras.layers.Conv2D(filters=8, kernel_size=3, strides=1, padding='valid')(convlayer1)
pooling = tf.keras.layers.MaxPooling2D(2)(convlayer2)
model = tf.keras.Model(inputs=input_layer, outputs=pooling)
model.summary()
다음 코드를 실행하면 오류가 발생합니다.
input_layer = tf.keras.layers.Input(shape=(13, 13, 5))
convlayer1 = tf.keras.layers.Conv2D(filters=8, kernel_size=5, strides=2, padding='valid')(input_layer)
convlayer2 = tf.keras.layers.Conv2D(filters=16, kernel_size=5, strides=2, padding='valid')(convlayer1)
pooling = tf.keras.layers.MaxPooling2D(2)(convlayer2)
model = tf.keras.Model(inputs=input_layer, outputs=pooling)
model.summary()
Q. 위의 코드는 왜 오류가 났을까요? 각 Layer로부터의 연산 결과를 손으로 계산하신 것을 근거로 설명해 보세요.
두 번째 Conv2D 레이어의 output convlayer2의 크기가 작아서 pooling 연산을 수행할 공간이 부족하기 때문입니다.
첫 번째 Conv2D 레이어의 output convlayer1의 크기는 5x5이고, 두 번째 Conv2D 레이어의 output convlayer2의 크기는 1x1입니다. 1x1를 pooling 연산을 하기에는 공간이 부족합니다.
CNN 모델을 이미지 분류에 사용하려면,
Conv2D 레이어의 output인 3차원 feature map에 flatten을 적용한 다음,
fully connected layer(Dense)를 연결해야 합니다.
input_tensor = tf.keras.layers.Input(shape=(28, 28, 1))
x = tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=1, padding='same', activation='relu')(input_tensor)
x = tf.keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu')(x)
x = tf.keras.layers.MaxPooling2D(2)(x)
# 3차원으로 되어있는 Feature map 결과를 Fully Connected 연결하기 위해서는 Flatten()을 적용해야 합니다.
x = tf.keras.layers.Flatten()(x)
# Flatten 된 결과를 100의 노드를 가진 Fuly Connected Layer와 연결
x = tf.keras.layers.Dense(100, activation='relu')(x)
output = tf.keras.layers.Dense(10, activation='softmax')(x)
Pooling을 통해 Parameter 연산 없이 Feature map의 차원을 축소할 수 있다는 장점이 있습니다. 차원을 축소 즉, down sampling을 해준다고 표현할 수도 있습니다.
CNN 구조는 크게 특징을 찾아내는 feature extraction과 실제적으로 이미지 분류를 하는 classification 영역으로 나뉩니다.
또한, CNN 구조의 깊이를 증가시키면 다양하고 복잡한 feature를 찾아낼 수 있습니다.