안녕하세요! ai-1team 다섯 번째 주자입니다. 벌써 한 해가 다 지나가고 새해가 되었네요. 다들 새해 복 많이 받으시고 AI 스터디의 끝이 보이니 다들 조금만 더 힙냅시다! ^^
오늘의 주제는 CNN(Convolutional Neural Network)입니다.
CNN의 개요

위의 그림과 같이, Convolutional Neural Networks의 기본적인 아이디어는 고양이 실험에서 시작되었습니다. 고양이에게 어떤 그림을 보여주었더니 이 그림을 읽어들이는 뉴런들이 동시에 동작하는 것이 아니라 어떤 형태의 그림, 어떤 부분의 그림에 대해서만 부분적으로 반응한다는 것을 알게 되었다고 합니다. 즉, 입력을 나누어 받는 것인데 이것에 착안하여 만들어 낸 것이 CNN이 되겠습니다.
Convolution Layer

입력받을 왼쪽의 이미지가 있다고 가정합시다. 이미지의 크기가 32x32이고 이 예시에서는 컬러이기 때문에 RGB형태의 3가지 색상을 나타내므로 32x32x3 형태의 이미지가 됩니다. (여기서 색상을 나타낸 3은 채널(channel)이라고 하는데 흑백인 경우에는 gray scale이 1로 설정될 수 있습니다.) 위에서 설명한 고양이 실험에서 한 것처럼 전체의 이미지를 하나의 입력으로 받는 것이 아니라 이미지의 일부분만 처리하고 싶기 때문에 필터(filter)라는 개념을 사용할 수 있습니다.
위 그림으로 설명을 해보면, 주어진 필터는 5x5 사이즈에 색깔은 동일하게 처리하므로 채널은 그대로 3입니다. 여기에서 Convolution Layer에서의 중요한 특징 하나를 알 수 있는데 Conv Layer에 입력으로 들어오는 채널 값이 filter의 채널과 같다는 점 기억해주세요! 다시 돌아와서, 5x5필터를 사용하게 되면 32x32 짜리 크기의 이미지 중 5x5만큼 받아들이게 됩니다. 받아들인 값을 x라고 했을 때 x를 입력받아서 한 개의 값으로 뽑아니는 것이 filter가 하는 일이 됩니다.
filter가 어떻게 값을 뽑아내는지 자세히 알아볼까요? 우리는 AI 스터디를 초반에 Linear Regression을 열심히 배웠었는데요, 여기서 Wx+b 식을 사용하게 됩니다. 이 식을 사용하여 한 개의 값으로 만들어 낼 수 있습니다. 필터에는 5x5x3개 만큼의 값이 있지만 설명을 위해 다섯 개의 값(x1, x2, x3, x4, x5)가 있다고 가정하겠습니다. Linear Regression을 했던 것처럼 w1x1 + w2x2 + w3x3 + x4w4 + w5x5 + b 를 통해 y라는 하나의 값을 만들어 지는 거죠. 또한 ReLU함수를 사용하고 싶다면 ReLU(Wx+b)를 계산하여 렐루 층을 만들 수도 있습니다.
이렇게 filter를 사용하여 값을 내는 법을 알았으니 전체 이미지에 대해 어떻게 처리하는지도 알아보겠습니다. 전체 이미지를 읽어들이기 위해서는 똑같은 filter를 가지고 다른 부분의 이미지도 봐야하는데요, 그러기 위해서는 필터를 좌우 그리고 위아래로 움직이면서 확인해야 합니다. 그러면 우리는 몇 개의 값을 모을 수 있을까요? 값의 개수를 알아야 우리가 CNN을 구성할 때 실제로 weight의 개수도 정하고 이 값들로 어떻게 설계를 할 수 있을 지 정해지기 때문에 중요하다고 합니다.

7x7의 이미지와 3x3의 필터를 예로 들어보겠습니다. 필터를 한 칸씩 움직이면 좌우와 위아래 각각으로 5번씩 움직일 수 있으므로 5x5개의 출력을 갖게 됩니다. 우리가 필터를 움직인 칸 수를 stride라고 합니다. stride의 크기가 1이라는 것은 필터를 한 칸씩 움직였다는 거고, stride의 크기가 2이라는 것은 필터를 두 칸씩 움직였다는게 되겠죠.
이러한 Output size를 간단한 공식으로도 계산할 수 있는데요, Output size = (N - F) / stride + 1
를 통해 쉽게 계산할 수 있습니다.
위의 그림처럼 N = 7, F = 3 인 경우,
stride 1 => (7 - 3) / 1 + 1 = 5
stride 2 => (7 - 3) / 2 + 1 = 3
stride 3 => (7 - 3) / 3 + 1 = 2.33가 되는데, stride가 3인 경우는 Output size가 정수가 아니므로 stride가 될 수 없다는 점 주의해주세요!
그런데 가만보면, 7x7 사이즈의 이미지를 입력했는데 filter를 거치면 5x5, 3x3, ... 처럼 사이즈가 줄어드는 것을 확인할 수 있습니다. 이렇게 사이즈가 줄어든다는 것은 우리가 이미지에 대한 정보를 잃어버린다는 것인데요, 따라서 우리는 이미지에 패딩(Padding)이라는 개념을 사용하여 이러한 문제점을 해결할 수 있습니다.
Padding

패딩은 이미지의 가장자리에 0이라는 가상의 값을 붙여 넣는 것을 의미합니다. 이렇게 함으로써 그림이 급격하게 작아지는 것을 방지할 수 있고, 그림의 모서리는 모서리 부분이라고 네트워크에 알려줄 수 있다고 합니다.
위의 예시처럼 7x7짜리 입력에 3x3짜리 필터를 사용하고 stride의 값을 1로 설정하면 Output size = (9 - 3) / 1 + 1 = 7이 되므로 결과값이 7x7로 크기가 유지됨을 알 수 있습니다.
Swiping the entire image

방금 공부한 Padding은 잠시 넣어두고, Padding은 고려하지 않은 상태에서 주어진 이미지에 대해 6개의 필터를 사용하여 값을 내면 오른쪽 그림과 같이 activation maps가 되는 것을 알 수 있습니다. activation maps는 (28, 28, 6)의 값을 갖게 되는데, 28은 N = 32, F = 5, stride = 1일 때 Output size = (32 - 5) / 1 + 1 = 28인 것이고, 6은 필터의 개수로서 깊이를 의미하게 됩니다. 여기서 conv layer의 두 번째 중요한 특징이 있는데요, output picture map의 채널 수는 conv filter의 개수와 같다는 것입니다. 꼭 기억해주세요!
Computation
그러면 실제로 연산이 어떻게 이루어지는지 궁금하실 것 같습니다. 먼저, Input의 channel 값을 편의상 1로 가정하면 filter과 Output feature map의 channel도 자연스레 1이 됩니다. 아래의 그림처럼 5x5 image가 3x3 filter를 통해 어떻게 계산되는지 알아보도록 하겠습니다.

먼저, 위에서 이미 배웠으므로 Output size = (5 - 3) / 1 + 1 = 3임을 쉽게 알 수 있습니다. 그리고나서, Input feature map에서의 맨 왼쪽 위에 있는 3x3크기의 조각을 filter에 대응시켜 계산을 합니다. 그러면 1x1 + 1x0 + 1x1 + 0x0 + 1x1 + 1x0 + 0x1 + 0x0 + 1x1 = 4가 되어 Output feature map으로 넘어가는 것을 확인할 수 있습니다.

channel의 값이 1이므로 한 칸씩 이동하며 계산하면 오른쪽과 같은 Convolved Feature을 완성할 수 있습니다.
Convolution Layers

앞서 배운 Swiping the entire image를 여러 번 시행할 수 있는데요, 입력받은 32x32x3 image를 conv layer과 ReLU layer를 사용하여 적용할 수 있습니다. 그림에서 주어진 예시대로 계산해보면 32x32x3 image를 5x5x3 filter를 사용하여 (28, 28, 6)의 값을 갖는 activation maps를 만들 수 있고, 이것을 다시 5x5x6 filter를 사용하여 계산하면 (24, 24, 10)의 값을 갖는 activation maps를 만들 수 있다는 것 쉽게 아실 수 있겠죠?
Pooling layer (sampling)

Pooling이란 간단하게 설명하자면 sampling이라고 할 수 있습니다. 우리가 입력받은 이미지로 convolutional layer를 만들 수가 있고 이 conv layer의 깊이는 몇 개의 filter를 사용하는 지에 따라 결정된다고 했었죠. 아무튼 이 conv layer에서 한 layer을 뽑아내고 resize를 하는데, 모든 layer에 대해 이 과정을 수행한 뒤 다시 쌓아서 그 다음 단계로 넘기는 것을 Pooling이라고 합니다.
Max Pooling

4x4의 이미지가 있다고 가정하고 2x2 필터와 stride가 2라고 가정하겠습니다. 그러면 2x2의 output을 갖게 됩니다. 우리는 각 filter에 대해 어떤 값으로 정해야할 지 고민해야 하는데, 평균낸 값을 고를 수도 있고, 가장 작은 값, 또는 가장 큰 값을 고를 수 있습니다. 이 다양한 방법 중 가장 많이 사용되는 방법은 가장 큰 값을 고르는 것으로 Max Pooling이라고 합니다.
우리가 sampling이라고 하는 이유는 전체의 값들 중에 한개만 뽑기 때문인데요, 이러한 과정을 Pooling이라고 합니다. Pooling의 결과는 filter의 사이즈와 stride의 값에 따라 달라지게 됩니다.
이상으로 5주차 스터디 포스팅 정리를 마치도록 하겠습니다.
감사합니다!
'AI' 카테고리의 다른 글
[ai-1team] 6. Recurrent Neural Network (0) | 2021.01.08 |
---|---|
[ai-2team]1. Linear Regression, minimize cost (0) | 2021.01.07 |
[AI-3Team] 다변수 선형 회기(Multi Variable Linear Regression) (0) | 2020.12.29 |
[AI-3Team] Logistic Regression (0) | 2020.12.27 |
[ai-1team] 4. 딥 네트워크 학습 및 코드 실습 (0) | 2020.12.22 |