본문 바로가기

AI/Deep Learning

[DL] 합성곱 신경망(CNN; Convolutional Neural Network) 파헤치기

등장 배경 - 컴퓨터 비전 (computer vision)

  딥러닝의 컴퓨터 비전 분야에서는 어떤 영상에서의 장면이나 특징들을 이해(understanding)하는 컴퓨터를 프로그래밍하는 것이 목적이 된다. 즉, 사람의 시각 시스템이 하는 작업을 컴퓨터가 동일하게 수행하도록 연구하는 것이다.

 

딥러닝을 통한 사물 인식(object detection)

  사람이 눈으로 사물을 보고 무엇인지 인지하거나 장면을 이해하듯이, 컴퓨터로 하여금 사진 또는 동영상으로부터 특정 객체의 위치와 자세를 찾아내거나 장면을 인식하도록 만드는 작업이 필요하다. 사람은 사진 속의 사물을 매우 빠르고 정확하게, 그리고 직관적으로 이해할 수 있다. 그러나 컴퓨터가 사람처럼 사진을 인식하고 사물을 빠르고 정확하게 찾을 수 있게 만드는 것은 결코 쉽지 않다. 이를 딥러닝의 신경망 구조로 처리하고자 고안된 것이 합성곱 신경망(CNN; Convolutional Neural Network)이다.

  왜 합성곱 신경망은 이미지를 처리하는 데에 효과적일까? 가령 입력층과 출력층의 뉴런이 전부 연결된 Fully connected layer(Dense layer)는 1차원 데이터의 처리에만 한정된다. 하지만 이미지의 텐서는 (samples, height, width, channel) 크기의 4D텐서(3차원)로, 이를 1차원으로 변형시키면 데이터의 형상이 소실되는 단점이 있다. 수학에서의 합성곱 개념을 사용하면 3차원 데이터의 공간적인 정보를 유지한 채 다음 레이어로 보낼 수 있기 때문에, 이미지 인식에 있어 특히 CNN을 사용하게 되었다.

 

  CNN은 비전 분야에 다음과 같이 활용될 수 있다.

 

  • 영상에서 물체의 detection, segmentation
  • 같은 장면이나 물체에 대한 다른 관점 (view) 의 등록 (registration)
  • 연속 영상에서 물체를 추적
  • 어떤 장면을 3차원 모델로 mapping
  • 인간의 자세와 팔다리 움직임을 3차원으로 추정 (estimation)

 

합성곱 신경망의 기본 구조

  기존 신경망 구조에 합성곱 계층(사진에서의 Conv_1, Conv_2)과 풀링 계층(사진에서의 Max-Pooling)을 Fully connected 계층 이전에 추가하여 원본 이미지에 필터링 기법을 적용할 수 있다.

  다음 인공신경망 구조와 비교해보면 쉽게 와닿을 것이다.

 

신경망(NN)의 기본 구조
합성곱 신경망(CNN)의 기본 구조

 

이미지의 텐서?

  앞서 잠깐 이미지는 4D텐서로, (samples, height, width)로 표현되는 3D텐서의 마지막 axis에 channel이 추가된 형태를 띈다고 설명했다. channel이란 무엇인가? 이미지 픽셀 하나하나는 실수이다. 컬러 사진의 경우, 각 픽셀을 RGB(Red, Green, Blue) 3개의 실수로 표현한 3차원 데이터가 된다. 반면 흑백 사진은 흑백 명암만을 표현하기 때문에 2차원 데이터가 됨을 알 수 있다. 즉, 1개의 channel을 가진다. 

이 고양이 사진은 5x5의 크기를 가진 컬러 사진임을 알 수 있다(channel=3)

 

1. Conv layer (Conv2D 기반)

합성곱 연산

  합성곱(convolution)은 이미 수학적으로 정의된 개념이다. 딥러닝에서는 이 합성곱의 연산은 특성 맵(feature map)이라고 부르는 3D텐서에 적용되어 지역 패턴을 학습한다. 이 텐서는 2개의 공간 축(height와 width)과 채널 축으로 구성된다. 위에서 봤던 컬러 사진은 RGB 이미지이기 때문에 3개의 채널을 가지고, 채널 축의 차원이 3이 된다. 합성곱 연산은 입력 특성 맵에서 작은 패치(patch)들을 추출하고 이런 모든 패치에 같은 변환을 적용하여 출력 특성 맵(output feature map)을 만든다.

  출력 특성 맵을 만들기 위해 고려해야 할 파라미터가 몇 가지 있다. 대표적인 것들을 살펴보도록 하겠다.

 

Filter

  이미지의 특징을 찾아내기 위한 공용 파라미터(W)이다. kernel이라고도 한다.

 

 

위 그림에서 합성곱 연산을 수행하는 데 쓰는 filter의 크기가 (3,3)인 것을 알 수 있다. filter는 정사각행렬의 형태를 띄며, 지정된 간격으로 이동하면서 전체 입력 데ㅣ터와 합성곱하여 특성 맵을 만든다.

 

Stride

  위에서 filter가 '지정된 간격'으로 이동하면서 합성곱 연산을 수행한다고 하였는데, 이 '지정된 간격'은 무엇인가? stride 파라미터이다. 위의 그림에서는 한 칸씩 이동하고 있으니 stride=1이다.

 

이제 다음 그림을 보자.

 

처음 입력으로 들어온 이미지는 4x4 크기의 행렬이었는데, filter와 stride를 거쳐 얻은 특성 맵을 보면 2x2의 크기기 되었다. 합성곱 레이어를 거치면 항상 특성 맵은 입력 데이터의 크기보다 작아지는가?

 

Padding

  이렇게 합성곱 연산을 거칠수록 출력값의 크기가 계속 줄어드는 것을 방지하는 방법이 padding을 깔아주는 것이다. 입력 데이터의 외각에 지정된 픽셀만큼 특정 값으로 채워준다(보통은 0으로 채운다).

 

(왼) padding='valid'로 패딩X - 입력보다 출력의 크기가 작다         (오) padding='same'으로 패딩O - 입력과 출력의 크기가 같아진다

 

Conv layer의 출력 크기

$$ OutputHeight = OH = \frac{H+2P−FH}{S}+1 $$

$$ OutputWeight = OW = \frac{W+2P−FW}{S}+1 $$

  • H는 입력 데이터의 높이, W는 입력 데이터의 폭, FH는 filter의 높이, FW는 filter의 폭, S는 stride 크기, P는 패딩 사이즈

위 식의 결과값은 자연수가 되어야 한다(당연하다 행렬이다). 그리고 특성 맵의 행과 열 크기는 뒤에 이을 pooling 층의 크기의 배수여야 한다.

여담으로 CNN 층 쌓을 때 흔히 보는 ValueError: Shapes are incompatible 오류는 이 조건을 맞춰주지 않아서(크기 호환이 안돼서) 발생한다...ㅋㅋㅋ

 

 

2. Pooling layer

  풀링 층의 역할은 합성곱 층을 거쳐서 나온 특성 맵이 있을 때, 이를 이루는 합성곱 층을 resizing하여 새로운 layer을 얻는 것이다. 이를 통해 특성 맵의 크기를 줄이거나, 특정 데이터를 강조하도록 만들 수 있다. 풀링 방법도 여러 가지가 있다.

 

  • MaxPooling(최대풀링) - 최댓값 뽑기
  • Average Pooling(평균풀링) - 평균값 뽑기
  • MinPooling(최소풀링) - 최솟값 뽑기

MaxPooling과 AveragePooling의 예시

 

결국 풀링 층을 거치면 크기가 줄어든다. 왜 이런 식으로 특성 맵을 다운샘플링할까?

http://ufldl.stanford.edu/tutorial/supervised/Pooling/ 풀링에 대한 이 문서를 번역해보았다. 

96x96의 input data가 있다고 가정해보자. feature의 개수는 400개, 8x8 크기의 filter를 사용한다고 하면, 합성곱 층을 지나온 후의 출력 크기는 다음과 같을 것이다(합성곱 층의 출력 크기 공식을 참고)
\( OH = OW = (96-8+1) \)이므로, 크기는 \( (96-8+1) \times (96-8+1) \)
feature 400개가 있으니까, 총 feature 개수는 \( 892 \times 400 = 3,168,400 \)이다.

이를 다 펼치고 합성곱 신경망 마지막 층인 Dense layer와 연결한다면 어마어마한 수의 가중치 파라미터가 생긴다. 이는 곧 과대적합을 발생시킨다.

  따라서 다운샘플링을 사용하는 이유는 처리할 특성 맵의 가중치 개수를 줄이기 위해서이다. 풀링 층을 추가해주면 정해진 픽셀 안에서 조건에 맞는 값을 뽑고, 크기를 조절할 수 있기 때문에 과대적합을 방지할 수 있는 것이다.

 

Pooling layer의 출력 크기

$$ OutputRowSize = \frac{InputRowSize}{PoolingSize} $$

$$ OutputColumnSize = \frac{InputColumnSize}{PoolingSize} $$