Convolutional Neural Network

3 minute read

CNN

사진은 각 픽셀 별 R, G, B의 값을 나타내는
세 개의 이차원 행렬로 나타낼 수 있다.
즉 사진은 3차원의 텐서로 나타낼 수 있다.
예를 들어 4k 사진은
(3, 3840, 2160)의 커다란 텐서이다.

여기서 이 첫번째 성분을 채널이라고 한다.
여기서는 채널이 3이지만 3이 아닐 수도 있다.

이 텐서를 1차원의 벡터인
(1, 3 x 3840 x 2160)로 길게 늘려서 (평탄화, flatten)
신경망과 softmax 함수를 이용해
사진 분류 작업에 이용할 수도 있다. (image classification task)

간단한 사진이라면 이 모델에서 어느정도 정확성을 얻을 수 있지만
실제로는 적용할 수가 없다.

Why CNN?

사람은 얼굴을 인식할 때 왜 얼굴이라고 인식하냐 물으면
“눈 두 개에 코 하나, 입 하나 달려있으니까?”
라는 답 밖에 내지 못한다.

이렇듯 사람의 인식은 굉장히 추상적이다.
눈이나 코가 무엇인지는 정확히 정의할 수 있지만
이걸 왜 눈으로 봤는지, 코로 봤는지에 대해 설명하기는 어렵다.

그래도 눈은 왜 눈으로 보이냐면, 대충 눈썹 같이 생긴 것에
중간에 눈동자처럼 동그란 것이 있기 때문이라고 설명할 수 있다.
같은 원리로 실제 눈이 아니라 타원 모양 하나에 중간에 원 하나 그려도
우리는 눈이라고 인식할 수 있다.

즉 사람은 사진을 볼 때 모양을 중점으로 파악하고,
이에 더불어 색이나 재질로도 물체를 인식할 수 있다.

물체만을 인식하는 것이 아닌, 물체가 여러개라던가 상황을 설명하라 한다면
사물과 사물 간의 거리 차, 그림자 등의 상으로 파악할 수 있다.

결론적으로 어떤 사진을 인식한다고 하였을 때
그 사진이 무엇인가에 대한 답을 내리기 위해서는
그 사진의 모양, 색, 물체 사이의 거리(원근감), 주변 그림자 등이 그 근거가 되는데
기존 방식으로 사진을 나타내면서 그 텐서를 1차원으로 다 일렬로 늘어놓게 되면
사진의 이러한 특성들이 모두 사라지게 된다.

이때 CNN, 합성곱 신경망을 이용하여
사진의 텐서를 망가뜨리지 않고
사진의 각 영역별 특성을 컴퓨터에게 학습시킬 수 있다.

CNN 의 기본 원리

CNN은 Convolutional Neural Network,
한국어로 합성곱 신경망이라고 번역된다.

CNN에서 input되는 사진은
기존 일반 신경망에서 학습할 때와 다르게
3차원 텐서 그대로 입력이 된다.

대신 특별한 순서를 거치게 된다.

Conv 계층은 입력받은 사진의 크기를
특성을 반영해 줄인다.
기본적으로 사진 텐서를 필터(혹은 커널)를 거쳐
사진의 특성을 반영한 특징 맵(feature map)을 출력한다.
이후 이 특징 맵은 활성화 함수를 거쳐 활성화 맵 (activation map)이 되고
이 활성화 맵은 풀링 계층 (pooling)을 거치게 된다.

즉 일반 신경망이 다음과 같다면
입력 -> Affine -> 활성화 -> Affine -> 활성화 … Affine -> Softmax -> 출력

CNN의 순서는 다음과 같다.
입력 -> Conv -> 활성화 -> Pooling -> Conv -> 활성화 -> Pooling … 활성화 -> Softmax -> 출력

Conv 계층

Conv 계층은 사진 텐서의 특징을
필터(커널)을 통해 뽑아내는 작업을 한다.

conv

왼쪽과 같은 사진이 있다고 하자.
이때 이 사진은 R, G, B 따윈 없고 흑(0)과 백(1)만으로 표시되는 아주 간단한 사진이다.

오른쪽의 파란 행렬은 필터이다.
그리고 왼쪽의 사진에 이 필터를 씌우면 오른쪽과 같은 결과가 나온다.

필터를 씌우는 방법은, 일단 사진의 크기가 7x7이고 필터가 3x3이니
사진에서 왼쪽 위부터 3x3 부분만 본다.
그리고 그 위치에 해당되는 값과 필터의 값들을 서로 곱한다.
일반적인 행렬의 곱 연산이 아닌, 같은 성분끼리 곱을 한 다음 나오는 9개의 값을 모두 더한다.
그리고 바로 옆 칸으로 가서 다시 3x3부분을 보고, 곱하고를 반복한다.

이렇게 하면 5x5의 행렬이 나오게 된다.

conv_explained

그러나 문제점이 하나 있는데,
바로 이렇게 되면 필시 출력 시의 크기가 줄어들게 된다.
필터는 사진의 크기보다 작기 때문에(3x3),
출력 시의 크기(5x5)는 원본 사진의 사이즈(7x7)보다 작을 수 밖에 없다.

이때 패딩이라는 것이 등장한다.
패딩(padding)은 사진 주위에 0으로 만들어진 벽을 둘러싸는 것이다.

padding

이렇게 패딩으로 둘러싸게 되면 원본 사진의 크기를 잃지 않을 수 있다.
위 예는 1 짜리 padding을 둘렀으며, 원본은 3x3의 크기, 필터는 2x2의 크기지만
출력은 4x4이다.
padding이 커지면 출력의 크기는 커진다.

또한 이렇게 필터를 적용할 때 굳이 바로 옆 칸으로 안 가고
두 칸, 세 칸 옆으로 가서 계산해도 되는데,
이때 이 옆으로 가는 거리를 stride 라고 한다.
역시 stride 가 몇이냐에 따라서 출력의 크기도 달라진다.
stride가 크면 출력의 크기도 줄어든다.

즉 사진을 입력 받았을 때,
사진, 필터, 패딩, 스트라이드, 출력의 크기를 I, F, P, S, O 라고 했을 때
output
와 같은 식이 성립한다.

그리고 이 출력은 다시 다음 계층의 입력값이 된다.

Pooling 계층

풀링 계층은 사진의 특성을 최대화하거나
평균을 구하기 위하여 쓰인다.

풀링 계층은 앞의 Conv 계층, 그리고 활성화 함수를 거치고 난 후의
activation map을
nxn의 크기로 슬라이딩 해가며(n<=activation map의 크기)
그 안에서의 값 하나를 골라내는 작업인데
이때 무엇을 고르는지에 따라
max pooling (최대값을 고름)
average pooling (평균을 고름)으로 나뉘게 된다.

pooling

3차원 합성곱

여기까지는 2차원의 합성곱이었지만
3차원에서는 약간 달라진다.

왜냐하면 3차원의 입력값이 (앞에서는 사진이라고 했지만 이제부터 입력이라 설명)
필터를 거치게 되면 2차원으로 바뀌기 때문이다.

conv3d
(이때 필터의 차원도 3개여야 하며, 셋의 크기도 동일해야 함)

따라서 3차원에서의 합성곱 연산을 할 때에는
차원이 여러 개가 필요하다. (출력의 차원이 1이 아니라면)
내가 출력 데이터의 채널이 3이었으면 한다면
3차원의 필터가 3개가 필요하다.

좋은 소식은, 풀링 계층은

  1. 학습해야 할 매개변수가 없고
  2. 채널 수가 변하지 않으며
  3. 입력 변화에 영향을 적게 받는다.

이렇게 필터를 거치는 이미지는
기존의 1차원 벡터와 달리
cnn_filter
이렇게 엣지와 모양, 재질 따위를 학습할 수 있다.