[Deeplearning(Tensorflow)] 4. 합성곱 신경망의 구성 요소
본 포스팅은 “혼자 공부하는 머신러닝+딥러닝” 책 내용을 기반으로 작성되었습니다. 잘못된 내용이 있을 경우 지적해 주시면 감사드리겠습니다.
4-1. 합성곱
합성곱(Convolution)은 마치 입력 데이터에 마법의 도장을 찍어서 유용한 특성만 드러나게 하는 것이다. 인공 신경망은 처음에 가중치 $w_{1}$ ~ $w_{10}$ 과 절편 $b$를 랜덤하게 초기화한 다음 에포크를 반복하면서 경사 하강법 알고리즘을 사용하여 손실이 낮아지도록 최적의 가중치와 절편을 찾아간다.
합성곱은 이와 조금 다르게 입력 데이터 전체에 가중치를 적용하는 것이 아닌 일부에 가중치를 곱한다. 첫 번째 합성곱에 사용된 가중치 $w_{1}$ ~ $w_{3}$ 과 절편 $b$가 두 번째 합성곱에도 동일하게 사용된다. 이렇게 한 칸씩 아래로 이동하면서 출력을 만드는 것이 바로 합성곱이다. 합성곱 층의 뉴런에 있는 가중치 개수는 정하기 나름이다. 이 가중치는 마치 입력 데이터 위를 이동하면서 같은 도장으로 하나씩 찍는 것처럼 생각할 수 있다. 입력 위를 이동하면서 출력을 만드는 뉴런을 합성곱 신경망(Convolutional neural network)에서는 필터(Filter) 혹은 커널(Kernel) 라고 부른다.
합성곱의 장점은 2차원 입력에도 적용할 수 있다는 것이다. 필터의 커널 크기를 (3, 3)으로 가정하고 입력의 9개 원소와 커널의 9개 가중치를 곱한 후 절편을 더하여 1개의 출력을 만든다. 그 다음 필터가 오른쪽 한 칸 이동하여 합성곱을 또 수행한다. 입력의 너비 만큼 이동이 끝났으면 그 다음 아래로 한 칸 이동하여 다시 왼쪽에서부터 합성곱을 수행한다. 이처럼 입력과 가중치의 행과 열을 맞추어 곱하고 더하는게 전부이다. 합성곱 계산을 통해 얻은 출력은 특성 맵(Feature map)이라고 부른다.
밀집층에서 여러개의 뉴런을 사용했다. 합성곱 층에서도 여러 개의 필터를 사용한다. 만약 (2, 2) 특성맵이 출력된다 할 때, 3개의 필터를 사용한다면 (2, 2, 3) 크기의 3차원 배열이 출력된다. 이 때 합성곱 층에 있는 필터의 가중치(커널)는 모두 다르다.
정리하자면, 합성곱의 실제 계산은 밀집층과 동일하게 단순히 입력과 가중치를 곱하는 것이지만 2차원 형태를 유지하는 점이 다르다. 또한 입력보다 훨씬 작은 크기의 커널을 사용하고 입력 위를 이동하면서 2차원 특성 맵을 만든다. 이렇게 2차원 구조를 그대로 이용하므로 이미지 처리 분야에서 뛰어난 성능을 발휘한다.
4-2. 케라스 합성곱 층
from tensorflow import keras
keras.layers.Conv2D(10, kernel_size=(3, 3), activation='relu')
Conv2D 클래스의 첫 번째 매개변수는 필터의 개수이다. kernel_size 매개변수는 필터에 사용할 커널의 크기를 지정한다. 이 두 매개변수는 반드시 지정해야 하는 매개변수이다. 마지막으로 활성화 함수를 지정한다. 참고로 일반적인 특성 맵은 활성화 함수를 통과한 값을 의미한다. 커널의 크기는 하이퍼파라미터이므로 여러 가지 값을 시도해봐야 한다. 보통 (3, 3)이나 (5, 5)가 많이 쓰인다. 일반적으로 1개 이상의 합성곱 층을 쓴 인공 신경망을 합성곱 신경망이라고 부른다.
4-3. 패딩과 스트라이드
(4, 4) 크기의 입력에 (3, 3) 크기의 커널을 적용하면 (2, 2) 특성 맵이 만들어진다. 만약 출력의 크기를 입력과 동일하게 (4, 4)로 만들려면 어떻게 해야 할까? 입력과 동일한 크기의 출력을 만들려면 더 큰 입력을 만들어줘야 한다. 실제 입력 크기가 (4, 4)일 경우 (6, 6)으로 만들어 줘야 (3, 3) 크기의 커널로 합성곱 했을 때 (4, 4) 출력이 나온다. 이렇게 입력 주위를 가상의 원소로 채워 크기를 늘리는 방법을 패딩(Padding)라고 한다. 실제 입력값이 아니므로 패딩은 0을 채운다. 즉 (4, 4) 이미지 바깥 주변으로 한줄씩 0을 채워 (6, 6) 크기의 입력을 만든다. 패딩의 역할은 순전히 커널이 도장을 찍을 횟수를 늘려주는 것 외에는 없다. 실제 값은 0으로 채워져 있어 계산에 영향을 미치지는 않는다. 이렇게 입력과 특성 맵의 크기를 동일하게 만들기 위해 입력 주위에 0으로 패딩 하는 것을 세임 패딩(Same padding)라고 한다. 패딩 없이 순수한 입력 배열에서만 합성곱을 하여 특성 맵을 만드는 경우를 밸리드 패딩(Valid padding) 라고 한다. 밸리드 패딩은 특성 맵 크기가 줄어들 수밖에 없다.
패딩은 왜 하는 걸까? 만약 패딩없이 합성곱을 한다면 네 모서리 모퉁이에 있는 값들은 1번~2번 이상 커널과 계산되는 반면 다른 원소들은 3번~4번 계산된다. 즉, 모서리에 있는 중요한 정보가 특성 맵으로 잘 전달되지 않을 가능성이 있는 것이다. 반면 가운데 있는 정보는 두드러지게 표현된다. 적절한 패딩은 이처럼 이미지의 주변에 있는 정보를 잃어버리지 않도록 도와준다. 합성곱 신경망에서는 세임 패딩이 많이 사용된다. padding 매개변수로 패딩을 지정할 수 있다. 기본값은 valid 이며 세임 패딩을 사용하려면 same으로 지정한다.
keras.layers.Conv2D(10, kernel_size=(3, 3), activation='relu', padding='same')
지금까지 합성곱 연산을 위해 필터가 한칸씩 좌우, 위아래로 움직였다. 하지만 두 칸 이상씩 움직일 수도 있다. 이렇게 움직이면 특성맵의 크기는 더 작아질 것이다. 이런 이동의 크기를 스트라이드(Stride)라고 한다. 기본으로 스트라이드는 1이다. Conv2D 의 stride 매개변수 값을 통해 지정할 수 있다.
keras.layers.Conv2D(10, kernel_size=(3, 3), activation='relu', padding='same', strides=1)
strides 매개변수는 오른쪽으로 이동하는 크기와 아래쪽으로 이동하는 크기를 (1, 1)과 같이 튜플을 사용하여 각각 지정할 수 있다. 하지만 커널의 이동 크기를 가로, 세로 방향으로 다르게 지정하는 경우는 거의 없다. 1보다 큰 스트라이드를 사용하는 경우도 드물다.
4-4. 풀링
풀링(Pooling)은 합성곱 층에서 만든 특성 맵의 가로세로 크기를 줄이는 역할을 한다. 특성 맵의 개수가 줄어드는 것은 아니다. 풀링도 입력 위를 지나가면서 도장을 찍는다. 하지만 풀링에는 가중치가 없고 도장을 찍은 영역에서 가장 큰 값을 고르거나 평균값을 계산한다. 이를 각각 최대 풀링(Max pooling)과 평균 풀링(Average pooling)라고 부른다.
풀링은 합성곱 층과 뚜렷이 구분되어 풀링 층이라 불리운다. 예를 들어 (4, 4) 크기의 특성 맵에 (2, 2) 최대 풀링을 적용하면 절반으로 크기가 줄어든다. 만약 10개의 특성 맵이 있다면, 풀링을 거친 특성 맵도 10개가 된다. 눈여결 볼 점은 풀링 영역은 두 칸씩 이동한다는 것이다. 합성곱에서는 커널이 한 칸씩 이동하여 겹치는 부분이 있었다. 풀링에서는 겹치지 않고 이동한다. 따라서 풀링 크기가 (2, 2) 이면 가로세로 두 칸씩 이동한다. 즉 스트라이드가 2인 것이다. MaxPooling2D 클래스로 풀링을 수행할 수 있다.
keras.layers.MaxPooling2D(2)
풀링은 가중치가 없고 풀링 크기와 스트라이드가 같다. 패딩은 없다.
MaxPooling2D 첫 번째 매개변수로 풀링 크기를 지정한다. 대부분 풀링 크기는 2이다. 가로세로 방향 다르게 하려면 (2, 3) 같이 지정해주면 된다. 합성곱과 마찬가지로 풀링도 strides와 padding 매개변수를 제공한다. padding은 기본값을 valid로 하여 패딩을 하지 않는다. strides의 기본값은 풀링의 크기라 따로 지정할 필요가 없다.
keras.layers.MaxPooling2D(2, strides=2, padding='valid')
평균 풀링을 제공하는 클래스는 AveragePooling2D이다. 최대값 대신 평균을 계산하는것 외에는 MaxPooling2D와 동일하며, 제공하는 매개변수도 같다. 꼭 기억할 점은 풀링은 가로세로 방향으로만 진행하며, 특성 맵의 개수는 변하지 않고 그대로라는 것이다.
4-5. 합성곱 신경망의 전체 구조
정리해보자. 합성곱 층에서 사용할 커널의 크기는 (3, 3) 크기이고 세임 패딩이므로 1픽셀이 입력 데이터 주변에 추가된다. 그 다음 패딩이 추가된 입력에서 합성곱이 수행된다. 합성곱 필터가 3개라 하자. 각각 (3, 3) 크기의 가중치를 가지고 있고 필터마다 절편도 하나씩 있다. 각 필터의 가중치와 절편은 각기 다르다. 따로 언급이 없다면 합성곱의 스트라이드는 항상 1이다. 입력 크기가 (4, 4)일 경우 만들어지는 특성 맵의 크기도 (4, 4)가 된다. 3개의 필터가 사용됐으므로 (4, 4, 3) 크기의 특성 맵이 만들어진다. 합성곱 층에서도 활성화 함수를 적용한다. 보통 렐루 함수를 많이 사용한다.
풀링 층은 합성곱 층에서 만든 특성 맵의 가로세로 크기를 줄인다. 보통 (2, 2) 풀링을 사용해 절반으로 줄인다. 특성 맵 개수는 변하지 않으므로 (4, 4, 3)에서 (2, 2, 3)으로 특성 맵 개수는 유지된다. 풀링을 사용하는 이유는 합성곱에서 스트라이드를 크게 하여 특성 맵을 줄이는 것보다 풀링 층에서 크기를 줄이는 것이 경험적으로 더 나은 성능을 내기 때문이다. 합성곱 신경망은 이렇게 합성곱 층에서 특성 맵을 생성하고 풀링에서 크기를 줄이는 구조가 쌍을 이룬다.
풀링을 거친 특성 맵의 크기는 절반으로 줄었으므로 (2, 2, 3)이 된다. 밀집층인 출력층에 전달하려면 Flatten 클래스를 사용하여 3차원 배열을 1차원으로 펼쳐야 한다. 12개의 원소를 가진 1차원 배열이 출력층의 입력이 된다. 출력층에는 몇개의 뉴런을 두어 분류가 되도록 한다. 출력층에 계산된 값은 소프트맥스 활성화 함수를 거쳐 최종 예측 확률이 된다.
4-6. 컬러 이미지를 사용한 합성곱
컬러 이미지는 RGB 채널로 구성된다. 컴퓨터는 이를 3차원 배열로 표시한다. 하나의 컬러 이미지는 너비와 높이 차원 외에 깊이 차원이 있다. 흑백 이미지가 (4, 4) 크기라면 컬러 이미지는 (4, 4, 3)인 것이다. 마지막 3이 깊이 차원이다. 깊이가 있는 입력에서 합성곱을 수행하려면 도장도 깊이가 필요하다. 즉 필터 커널의 크기가 (3, 3)이 아니라 (3, 3, 3)이 되는 것이다. 커널 배열의 깊이는 항상 입력 깊이와 같다. 만약 (3, 3, 3) 영역에 합성곱을 한다면 27개 원소에 가중치를 곱하고 절편을 더한다 생각하면 된다. 여기서 중요한 것은 입력이나 필터의 차원이 몇개인지 상관없이 항상 출력은 하나라는 점이다. 즉 특성 맵에 있는 한 원소가 채워진다.
케라스의 합성곱 층은 항상 3차원 입력을 기대한다. 예를 들어 (28, 28) 크기의 2차원 배열이 입력이라면 (28, 28, 1) 크기의 3차원 배열로 변환한다. 원소 개수는 동일하면서 차원만 맞추는 것이다. 첫 번째 풀링 층을 통과한 특성 맵 크기가 (4, 4, 5)라 하자. 두 번째 합성곱 층에서 필터의 너비와 높이가 각각 3이라면 필터의 커널 크기는 (3, 3, 5)가 된다. 45개의 가중치를 곱하고 절편을 더한 합성곱의 결과는 1개의 출력을 만든다. (3, 3, 5) 필터를 10개 적용한다면 특성 맵의 크기는 (2, 2, 10)이 될 것이다. 이렇게 합성곱 신경망은 너비와 높이는 점점 줄고 깊이는 점점 깊어지는 것이 특징이다. 마지막 출력층 전에 특성 맵을 모두 펼쳐서 밀집층 입력으로 사용한다.
합성곱 신경망에서 필터는 이미지에 있는 어떤 특징을 찾는다고 생각할 수 있다. 처음에는 간단한 기본적인 특징을 찾고 층이 깊어질수록 다양하고 구체적인 특징을 감지할 수 있도록 필터의 개수를 늘린다. 또 어떤 특징이 이미지의 어느 위치에 놓이더라도 쉽게 감지할 수 있도록 너비와 높이 차원을 점점 줄여나간다.
Leave a comment