꾸준함이 중요한 Lion2me의 기술블로그

CNN에 대해서

25 Sep 2021
ML

CNN에 대해서

CNN은 Convolutional Neural Network의 약자입니다. 한글로는 합성곱 신경망이라고 말 할 수 있겠네요.

CNN은 무엇인가?

Convolution Layer가 포함되어 있는 Neural Net을 우리는 CNN이라고 부릅니다.

그러면 우리는 Convolution Layer가 무엇인지 알아봐야겠네요.

Convolution Layer란?

Convolution Layer는 고양이가 보는 것마다 자극받는 뇌의 위치가 다른 것을 보고 영감을 받아 만들어진 각기 다른 필터를 통해 같은 이미지를 다르게 표현하는 방식입니다. 여기서 표현이란 새로운 특징으로 만들어내는 것이며, 이것을 우리는 Activation Map이라고 합니다.

실생활에 비유하자면, 다양한 색안경을 낀 사람들에게 한 사진을 보여주었을 때 보이는 시각을 다음 레이어에게 전달하는 학습을 한다고 생각하면 될 것 같네요. 각 색안경은 다른 이미지를 만들어내고, 그 이미지들에서 특징을 추출하면 대상에 대한 다양한 시각에서의 특징을 얻어 낼 수 있을테니까요.

여기서 우리가 주의깊게 볼 사항은 색안경필터입니다.

그럼 필터를 통해 데이터를 바라보는 과정에 대해서 알아보겠습니다.

Convolution 과정

우선 5x5의 크기를 가진 데이터가 있다고 생각해보겠습니다. 그리고 3x3의 크기를 가진 Filter를 하나 만들어보겠습니다.

그리고 데이터를 Filter의 크기로 쪼개어 각 위치의 값을 곱한 뒤 합산해주면 우리가 원하는 필터를 통과 한 값이 등장하게 됩니다.

이 과정을 전체 데이터에 적용시켜주면 우리는 데이터를 필터를 통과 시켜서 새롭게 표현 한 Activation Map을 얻을 수 있습니다.

전반적인 과정을 눈으로 확인했으니 조금 더 정확하게 살펴보겠습니다.

먼저 데이터의 크기는 5x5였습니다. 하지만 조금 더 깊게 표현해서 하나의 데이터를 다음과 같이 표현하겠습니다.

너비와 높이가 5이면서 채널 수가 1개인 데이터 1개라고 표현하겠습니다. 이미지를 표현 할 때 사용하는 Width, Height, Channel를 이용했습니다. 여기서 채널이란 곧 RGB/HSV와 같은 색상을 나타는 수로 주로 사용됩니다.

마찬가지로 Filter를 표현하면 너비와 높이가 3이면서 채널 수가 1개인 필터 1개라고 표현하겠습니다. 하지만 필터의 갯수는 곧 채널로 표현 할 수 있기 때문에 갯수는 생각하지 않겠습니다.

그러면 우리는 한 칸씩만 움직 일 수 있나요?

아닙니다. 우리에게는 Stride가 있습니다. 학습 할 때 필터를 얼마나 이동시킬 것 인지를 나타내는 Stride는 기본적으로 1을 사용하고 있지만, 데이터의 크기에 영향을 주는 파라미터이기 때문에 다른 방식으로 사용되기도 합니다.

Stride가 1이라면 한 칸씩 이동하는 방식이며 2라면 두 칸씩 움직이며 필터를 통과시킵니다. 그리고 Filter의 크기와 Stride의 크기로 인해 데이터는 압축되게 됩니다. 다음의 공식은 Output의 크기를 나타내고 있습니다.

\[OutputSize(Width,Height) = (((Width_{D} - Width_{C})/stride) + 1 , ((Height_{D} - Height_{C})/stride )+ 1)\]

무언가 이상한 점이 있다?!

필터를 통과할 때 마다 데이터가 작아지는 것을 알 수 있습니다. 우리는 그 데이터를 원본 데이터의 특징이 될 수 있는 요소를 담고 있다고 생각하기 때문에 끄덕이며 Activation Map을 사용하여 모델을 만들면 됩니다.

근데 이상한 점이 있습니다.

날카로운 학생은 “각 모서리에 있는 데이터는 1번만 학습되지 않아요?” 라는 질문이 들어 올 수 있습니다. 왜냐하면 필터의 크기에 따라서 학습되면 데이터의 한 부분은 필터의 Width/Stride번 만큼 학습이 됩니다만, 가장 첫 번째에 위치한 데이터는 딱 한번 학습 한 뒤에 필터는 떠나가버립니다.

이런 이유로 학습이 진행되면서 필터에 크기에 따라서 점점 다음 레이어에 도달하는 Activation Map이 점점 작아지면서 데이터 유실이 발생합니다.

그러면 어떻게 첫번째 요소를 Width/Stride번 만큼 학습 할 수 있을까요? 결과적으로 데이터의 유실을 막을 수 있는 방법이 있을까요?

여기서 Padding이 등장합니다.

Padding

Padding은 데이터에 아무 의미가 없는 값을 추가해서 학습하는 과정에서 다음 레이어에 전달되는 데이터의 크기를 유지하기 위해 사용하는 기법입니다.

예를 들면 이전 예제를 보면 5x5의 데이터를 3x3 필터를 통과시켰을 때 우리는 3x3의 정보를 다음 레이어에게 넘겨주었습니다. 하지만 입력 데이터를 다음과 같이 넓히면 어떨까요?

[그림]

데이터의 크기가 7x7가 되었고 필터는 3x3입니다. Stride가 1이라는 가정하에 다음 레이어에 전달 할 Activation Map의 크기를 알아보면 다음과 같습니다.

\[Size = (7-3)/1 + 1 = 5\]

즉 입력 데이터와 동일한 크기의 5x5 Activation Map이 다음 레이어에게 전달되게 됩니다. 일반적으로 Padding을 사용 할 때는 입력 된 데이터의 크기가 결과로 나올 수 있도록 하는 것이 일반적입니다.

Pooling

그렇다면 무조건 Activation Map은 크기가 고정적인 것이 좋을까요? 그렇지는 않습니다.

우리가 Padding을 사용 한 이유는 데이터의 유실을 대비하기 위함이 큽니다.

학습을 진행 할 때 특히나 이미지와 같이 높은 차원의 데이터를 분석할 때는 중요한 특징을 찾아주는 것이 중요합니다.

2048*2048의 픽셀 크기를 가진 이미지를 24개의 레이어를 통해 100만 장 학습하는 일이 생긴다면, 섬뜩한 연산 횟수가 발생 할 것을 우리는 알고 있습니다.

그러면 Activation Map을 만드는 과정에서 특징만을 추출하는 방법을 사용 할 수 있지 않을까요? 이 생각에서 Pooling이 만들어졌습니다.

MaxPooling / MinPooling / MeanPooling 은 각각 해당 Pooling 필터를 통과하면서 발생하는 최대값, 최솟값, 평균(때로는 중앙)값으로 결과를 만드는 필터링 방식입니다.

하지만, stride(필터의 이동거리)만을 이용해서 굳이 Pooling을 사용하지 않고 크기를 줄이는 방법도 좋은 성과를 낸다고 합니다.