BIG_PY
home
Introduce
home
🥧

Chapter 3: 합성곱 신경망

Note(Material)

BIG_PY-LEVEL_3-기린그린그런그림-팀-chapter-3.pdf
16519.1KB

3.1 다층 퍼셉트론을 이용한 이미지 분류

다층 퍼셉트론(Multi-Layer Perceptron, MLP) 구조는 하나의 입력층과 하나 또는 그 이상의 은닉층, 하나의 출력층으로 구성된다.
이 절에서는 2장에서 배운 MLP를 이용하여, MNIST 데이터셋을 대상으로 이미지 분류 문제를 풀어본다.
이 절에서 만들 분류기의 목표는 손글씨 이미지를 0부터 9까지의 숫자(10개 클래스)로 분류하는 것이다.

3.1.1 입력층

신경망으로 2차원 이미지를 다루려면 이미지를 제공하기 전에 신경망이 이해할 수 있는 형태로 변환해야 한다.
컴퓨터는 [그림 3-2]의 왼쪽 손글씨 이미지를 오른쪽 28x28 행렬로 인식한다.
이 때 이 행렬의 요솟값은 0부터 255의 범위를 가지며, 0은 검은색, 255는 흰색, 그 사이의 값은 회색조이다.
MLP는 모양이 (1,n)인 1차원 벡터만 입력받는다.
따라서 모양이 (x,y)인 2차원 이미지 행렬을 입력층에 입력하려면, 행렬을 모양이 (1,n)인 벡터로 변환해야 한다.
이 과정을 이미지 벡터 변환(image flattening)이라고 한다.
예를 들어 다음과 같은 (4,4) 크기의 행렬을 입력층에 입력하려면
다음과 같이 모양이 (1,16)인 벡터로 변환해야 한다.
픽셀값 0이 검정색, 255가 흰색이라고 하면 이 입력 벡터는 다음과 같다.
케라스 라이브러리를 사용하면 다음과 같은 코드로 이미지 행렬을 벡터로 변환할 수 있다.
from keras.models import Sequential # 케라스 라이브러리 임포트 from keras.layers import Flatten # 이미지 행렬을 벡터로 변환하는 Flatten 층 임포트 model = Sequential() # 모델 정의 model.add( Flatten(input_shape = (28,28)) ) # Flatten 층을 입력층으로 모델에 추가
Python
복사
케라스에서 제공하는 Flatten 클래스는 2차원 이미지 행렬을 입력받아 1차원 벡터로 변환한다.
이 때 주의할 점은 Flatten 층을 만들 때 입력 이미지의 크기를 반드시 파라미터로 지정해야 한다는 것이다.

3.1.2 은닉층

앞 장에서 설명한 신경망은 하나 이상의 은닉층을 가질 수 있으며, 이 때 각 층은 하나 이상의 뉴런으로 구성된다.
우리가 할 일은 이런 층을 설계하는 것이다.
예제에서는 노드 512개를 가진 은닉층을 두 층 만들고, 각 층마다 ReLU 활성화 함수를 추가한다.
활성화 함수
- 은닉층에 한해서는 대부분의 경우 ReLU 함수가 가장 성능이 좋다.
- 분류 문제(클래스가 중복되지 않는 경우)에는 출력층에 소프트맥스(softmax)를 사용하는 것이 가장 좋다. 소프트맥스 함숫값은 입력된 이미지가 해당 클래스에 속할 확률로 해석할 수 있다.
2장에서와 마찬가지로 2개의 전결합층(밀집층: dense layer)을 모델에 추가한다.
from keras.layers import Dense # Dense 층 임포트 # 2개의 Dense 층을 모델에 추가 model.add(Dense(512, activation = 'relu')) model.add(Dense(512, activation = 'relu'))
Python
복사

3.1.3 출력층

분류 문제의 출력층 노드 수는 분류대상 클래스 수와 같다.
이 문제에서는 0부터 9까지의 숫자 10개가 분류 대상이므로 노드 10개를 갖는 Dense 층을 추가하면 된다.
model.add(Dense(10, activation = 'softmax'))
Python
복사

3.1.4 모델 완성하기

추가한 층을 모두 합쳐 [그림 3-5]와 같은 신경망을 완성한다.
케라스로 구현한 모델의 전체 코드는 다음과 같다.
from keras.models import Sequential from keras.layers import Flatten, Dense model = Sequential() # 신경망 구조 정의 model.add( Flatten(input_shape = (28,28)) ) # Flatten 층을 입력층으로 모델에 추가. model.add(Dense(512, activation = 'relu')) # 각 노드가 512개인 2개의 은닉층을 모델에 추가. model.add(Dense(512, activation = 'relu')) # 은닉층의 활성화 함수는 ReLU를 사용하는 것이 좋음. model.add(Dense(10, activation = 'softmax')) # 노드 10개를 가진 Dense 층을 출력층으로 모델에 추가. model.summary() # 모델 구조를 간략하게 출력.
Python
복사
이 코드를 실행하면 [그림 3-6]과 같이 모델 구조를 간략하게 정리해서 출력한다.
Flatten 층의 출력을 보면 요소 수가 784인 벡터(None, 784)임을 알 수 있다.
이는 크기가 28x28 픽셀인 이미지가 (1, 784) 벡터로 변환되었음을 의미한다.
우리가 계획한 대로 2개 은닉층(dense_1, dense_2)의 노드 수도 512개임을 확인하였다.
마지막으로 출력층(dense_3)은 노드 10개를 갖는다.
출력된 내용 중 Param # 필드는 해당 층의 파라미터(가중치) 수를 의미한다.
학습은 이들 가중치가 조정되는 과정이며, 가중치 수는 다음과 같이 계산된다.
1.
Flatten 층과 그다음 층을 잇는 파라미터 수는 0이다. (Flatten 층은 이미지를 나타내는 행렬을 벡터로 변환하는 역할만 하기 때문)
2.
dense_1 층과 dense_2 층을 잇는 파라미터 수는 (입력층 노드 수 * dense_1 층 노드 수) + 편향 수 = (784 * 512) + 512 = 401,920 개다.
3.
dense_2 층과 dense_3 층을 잇는 파라미터 수는 (dense_2 층 노드 수 * dense_3 층 노드 수) + 편향 수 = (512 * 512) + 512 = 262,656 개다.
4.
dense_3 층과 출력층을 잇는 파라미터 수는 (dense_3 층 노드 수 * 출력층 노드 수) + 편향 수 = (512 * 10) + 10 = 5,130 개다.
5.
신경망 전체 파라미터 수는 401,920 + 262.656 + 5.130 = 669,706 개다.
이처럼 그리 크지 않은 신경망도 무려 669,706 개나 되는 파라미터 (가중치와 편향)를 손실 함숫값이 최소가 되도록 학습해야 한다.
여기서 층 수를 증가시키거나 층의 노드 수를 증가시킨다면 파라미터 수가 훨씬 더 늘어날 것이다.
이 점이 바로 MLP의 두 가지 주요 단점 중 하나다. (파라미터 수가 많으면 계산이 복잡해지고 결과적으로 계산 시간이 오래 걸림)

3.1.5 MLP로 이미지를 다룰 때의 단점

공간적 특징의 손실
2차원 이미지를 1차원 벡터로 변형하면 이미지 내 공간적 특징이 손실된다.
즉, 2차원 정보를 모두 폐기한 것과 같다.
서로 가까이 위치한 픽셀 간의 관계를 알 수 없기 때문에 정보의 손실이 생긴다.
CNN은 입력을 위해 이미지를 1차원 벡터로 변환할 필요가 없다.
전결합층
전결합(fully-connected)이란, 이전 층의 모든 노드가 다음 층의 모든 노드와 연결된다는 뜻이다.
크기(shape)가 큰 이미지를 층수가 수백 개인 신경망에 이용하면 파라미터 수가 굉장히 많아져 계산이 복잡해지고 처리 속도가 느려지게 된다.
CNN은 지역적으로 연결된(locally connected) 구조의 층을 갖는다.
즉, CNN의 노드는 이전 층의 노드 중 일부하고만 연결된다.
지역적 연결을 가진 층은 전결합층에 비해 파라미터 수가 훨씬 적다.
CNN은 이 두 가지 단점을 개선하기 위해 고안된 구조이다.

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

2차원 행렬인 이미지를 1차원 벡터로 변환하면서 손실되는 정보전결합층의 계산 복잡도를 고려하며 이미지 입력을 다루려면 전혀 새로운 형태의 신경망이 필요하다.
이 새로운 신경망은 2차원 구조의 정보를 잃어버려서는 안 된다.
CNN은 바로 이러한 필요로부터 등장했다.
CNN은 2차원 이미지 행렬을 그대로 입력으로 받을 수 있으므로 픽셀값에 숨어 있는 패턴을 이해할 수 있다.

3.2 합성곱 신경망 구조

합성곱 신경망(CNN)은 첫 번째 층에서 기본적인 특징(모서리, 직선)을 학습하고, 그다음 층에서 이보다 좀 더 복잡한 패턴(원, 정사각형 등)을, 이어지는 층에서는 훨씬 복잡한 패턴(얼굴의 일부, 자동차 바퀴, 개의 수염 등)을 학습한다.
합성곱 신경망 역시 일반적인 신경망의 학습과 크게 다르지 않다.
뉴런으로 은닉층을 구성하고 이 층을 쌓아 신경망을 만든다.
가중치는 무작위(random) 값으로 초기화되며 활성화 함수를 사용한다.
오차(y - y_hat)를 계산해 이 오차를 역전파하며 가중치를 수정해가는 학습 과정은 동일하지만,
전결합층 대신 합성곱층을 사용하여 특징을 학습한다는 것이 차이점이다.

3.2.1 전체 학습 과정

딥러닝 이전에는 특징 추출을 사람이 직접 수행하고 추출된 특징 벡터를 분류기(SVM 등의 일반적ㅇ니 머신러닝 알고리즘)에 입력했다.
특징 학습과 분류를 동시에(3단계와 4단계) 할 수 있는 신경망(MLP와 CNN)의 덕분에 [그림 3-11]의 세 번째 단계를 사람이 직접 할 필요가 없어졌다.
앞서 손글씨 이미지 분류 프로젝트에서 MLP를 사용해서 특징을 학습하고 이미지를 분류하는 과정을 보았다(3단계와 4단계를 함께 수행).
전결합층의 문제는 분류보다는 특징 학습 단계에서 일어난다.
문제가 없는 부분은 그대로 두고 문제가 있는 부분만 고치면 된다.
전결합층이 특징 추출(3단계)에서 제역할을 다하지 못하고 있다면 이 역할을 지역적 연결을 가진 층(합성곱층)에 맡기면 된다.
반대로 전결합층은 일단 추출된 특징은 잘 분류한다(4단계).
이 역할은 그대로 전결합층에 맡긴다.
CNN의 추상적인 구조는 [그림 3-12]와 같다.
위 그림은 이미지를 2개의 클래스(3과 7)로 분류하는 CNN을 나타낸 것이다.
단계는 다음과 같다.
1.
이미지를 합성곱층에 입력한다.
2.
이미지가 합성곱층을 지나며 발견된 패턴이 특징 맵(feature map)으로 추출된다. 합성곱층의 출력은 1차원 특징 벡터로 변환된다. 이때 특징 추출이 끝날 때까지 이미지의 크기가 각 층을 지날 때마다 줄어들고, 특징 맵 수(층의 깊이)는 늘어나는 것을 볼 수 있다. 이 부분은 원래 이미지를 잘 나타내는 추상적인 특징을 학습하는 별도의 신경망이라고 볼 수 있다.
3.
1차원으로 변환된 특징 벡터는 이어지는 전결합층에 입력되어 이미지를 분류한다.
4.
예측 결과에 해당하는 출력층의 노드가 발화한다. 여기서는 두 가지 클래스 중 하나를 선택하므로(3과 7) 출력층의 노드가 2개뿐이다.

3.2.2 특징 추출 과정 들여다보기

특징 추출 단게는 쉽게 설명하면 큰 이미지를 여러 개의 작은 특징 맵으로 나눈 뒤 이를 쌓아 벡터로 만드는 과정이다.
예를 들어 숫자 3이 쓰인 이미지가 입력되었다면 (깊이=1), 이 이미지는 숫자 3을 나타내는 다양한 특징의 위치가 담긴 여러 개의 이미지로 조각조각 나눠진다 (그림 3-13).
특징의 가짓수를 4가지라고 한다면 깊이는 4가 된다.
이미지가 합성곱층을 차례대로 통과하면 이미지의 크기는 작아지고 특징의 가짓수가 늘어나므로 깊이도 점점 깊어진다.
이미지가 합성곱층을 차례로 통과 ⇒ 이미지 크기 ⇒ 특징 수 ⇒ 깊이 깊어짐.
이 설명은 특징 추출 과정의 이해를 톱기 위한 일종의 비유다.
CNN에서는 실제로 이미지를 [그림 3-13]과 같이 여러 조각으로 분할하지 않는다.
실제로는 다른 사물이 찍힌 이미지와 구분되는 의미 있는 특징을 추출(extract meaningful feature)해서 다른 특징과 함께 쌓아둔다.

3.2.3 분류 과정 들여다보기

특징 추출이 끝난 뒤에는 전결합층 (일반적인 MLP)을 추가해서 특징 벡터를 입력받도록 한다.
이 전결합층은 ‘첫 번째 특징을 보면 모서리 같은 부분이 있어서 3, 7 또는 2 일 것이다. 두 번째 특징을 보면 곡선이 있는 것으로 보아하니 7은 확실이 아니다’와 같은 식으로 결국 숫자 3이라는 결론에 이르게 된다.

합성곱 신경망은 어떻게 패턴을 학습하는가

CNN에서는 한 층만에 바로 특징이 추출되는 것은 아니다.
이미지에서 특징을 제대로 추출하려면 수십 또는 수백 층을 거쳐야 한다.
특징이 학습되는 과정은 은닉층 하나하나를 거치며 점진적으로 진행된다.
첫 번째 은닉층은 대개 직선이나 모서리 같은 아주 간단한 특징을 학습한다.
두 번째 은닉층은 이들 특징을 조합해서 도형, 꼭짓점, 원 등의 특징을 인식한다.
이렇게 은닉층이 이어지면서 사람의 이목구비와 같은 복잡한 형태를 학습할 수 있다.
첫 번째 그림을 보면 초기 층에서 모서리 같은 구체적인 특징을 이미지에서 탐지하는 것을 볼 수 있다.
두 번째 그림에서 패턴의 패턴을 조합해서 얼굴의 일부에 해당하는 특징을 학습했다.
세 번째 그림에서는 패턴의 패턴의 패턴을 학습했다.
이 개념은 이후 장에서 고급 CNN 구조를 이해하는 데 매우 편리하다.

3.3 합성곱 신경망의 기본 요소

대부분의 합성곱 신경망에는 다음 세 가지 유형의 층이 있다 (그림 3-15).
1.
합성곱층 (convolutional layer, CONV)
2.
풀링층 (pooling layer, POOL)
3.
전결합층 (fully connected layer, FC)
지금부터는 각 층을 종류별로 더 자세히 살펴보며 동작 원리를 설명한다.
그리고 다시 전체 구조로 돌아와 이 절을 마무리한다.

3.3.1 합성곱층

합성곱층은 합성곱 신경망의 핵심 구성 요소다.
이미지 위를 픽셀 단위로 오가며 특징을 찾는 확대경과 같은 역할을 하며, 이미지에 찍한 사물을 구분 짓는 특징을 추출해낸다.
합성곱이란
수학에서 말하는 합성곱은 두 함수를 인수로 새로운 함수를 만들어내는 연산이다.
합성곱 신경망에서 말하는 합성곱은 첫 번째 인수는 입력 이미지고, 두 번째 인수는 합성곱 필터에 해당한다.
첫 번째 합성곱층을 통해 합성곱층이 이미지를 처리하는 과정은 [그림 3-16]과 같다.
합성곱 필터(3x3)를 입력 이미지 위로 이동시키며 합성곱 필터가 위치한 부분에 해당하는 작은 이미지 조각을 처리한 결과를 모아서 새로운 이미지인 특징 맵을 만든다.
합성곱 필터
가운데에 위치한 3x3 크기의 행렬.
커널(kernel)이라고도 부름.
커널은 입력 이미지 위를 픽셀 단위로 움직이며 연산을 수행하며 픽셀값을 계산. 그리고 각 위치에서 연산된 픽셀값을 모아 ‘합성곱 연산을 거친’ 새로운 이미지를 만들어 다음 층으로 전달.
필터가 위치한 입력 이미지상의 범위를 수용 영역(receptive field)이라고 함.
커널 값
: 합성곱 신경망에서는 합성곱 행렬이 바로 가중치다.
다시 말해 합성곱 행렬은 무작위 값으로 초기화(randomly initialized)되며 신경망에 의해 학습되는 값이다. (따라서 합성곱 행렬의 값을 어떻게 정해야 할지 걱정할 필요 없음)
합성곱 연산
다음은 다층 퍼셉트론에서의 가중합 계산식이다.
CNN에서도 위와 같은 계산이 쓰인다.
다만 뉴런과 가중치가 행렬처럼 배열되어 있는 점이 다르다.
따라서 수용 영역에 들어온 각 픽셀값을 자신과 겹쳐진 합성곱 필터의 픽셀값과 곱하고 그 결과를 합해 새로운 이미지의 픽셀값 하나를 결정한다.
합성곱 필터(=커널)는 입력 이미지 위를 이동하며 입력 이미지 전체를 커버한다.
합성곱 필터가 한 번 움직일 때마다 위와 같은 픽셀 단위로 가중합이 계산되어 필터 중심에 해당하는 픽셀의 새로운 값이 결정된다.
이런 방법으로 만들어진 이미지를 특징 맵 또는 활성화 맵(activation map)이라고 한다.
합성곱층 전체 구조
합성곱층에는 하나 또는 그 이상의 합성곱 필터가 있다.
이전 합성곱층의 합성곱 필터 수만큼 특징 맵(합성곱 연산으로 생성된 이미지)이 출력되기 때문에 이 필터 수가 다음 층의 깊이를 결정한다.
from keras.layers import Conv2D model.add(Conv2D(filters=16, kernel_size=2, strides='1', padding='same', activation='relu'))
Python
복사
이 짧은 코드로 합성곱층 구현이 끝난다.
출력의 크기와 깊이를 결정하는 나머지 네 가지 하이퍼파라미터는 다음과 같다.
filters : 합성곱 필터 수. 출력의 깊이를 결정.
kernel_size : 합성곱 필터 행렬(커널)의 크기. (2x2, 3x3, 5x5)
strides : 스트라이드
padding : 패딩
합성곱 필터 수
합성곱층에는 하나 이상의 합성곱 필터가 있다.
이를 이해하기 위해 (2장에서 설명한) MLP의 다이어그램은 다음과 같다.
마찬가지로 합성곱층은 CNN의 은닉층이라 할 수 있다.
그리고 은닉층의 뉴런 수를 조절하듯이 합성곱층의 필터 수를 조절한다.
커널의 유닛 하나가 뉴런과 같다고 보면 된다.
[그림 3-22]는 커널 수를 함께 나타낸 CNN의 구조다.
커널 크기 (=합성곱 필터 크기)
커널은 가중치가 담긴 행렬로, 입력 이미지 위를 이동하며 특징을 추출하는 역할을 한다.
커널 크기는 합성곱 필터 크기 (너비X높이)를 의미한다.
커널 크기(kernel_size)는 합성곱층을 만들기 위해 필요한 하이퍼파라미터 중 하나다.
신경망의 모든 하이퍼파라미터가 그러하듯이 커널 크기 역시 모든 경우에 유효한 값은 없다.
합성곱 필터에는 신경망의 학습 대상이 되는 가중치가 들어 있다.
따라서 이론적으로는 커널 크기가 클수록 신경망이 복잡한 패턴을 학습할 수 있다.
그러나 그만큼 계산 복잡도가 상승하며 과적합을 일으키기도 쉬워진다.
커널은 거의 대부분 정사각형이며 최소 2x2, 최대 5x5 크기의 필터가 사용된다.
이보다 큰 필터를 사용할 수도 있지만 이미지의 세부 사항을 놓칠 수 있어서 바람직하지 않다.
스트라이드와 패딩
두 하이퍼파라미터는 합성곱층의 출력 모양을 결정한다.
스트라이드(stride) : 필터가 입력 이미지 위를 한 번에 이동하는 픽셀 수.
패딩(padding) : 흔히 말하는 제로패딩(zero-padding)은 이미지 둘레에 픽셀값이 0인 추가 픽셀을 덧붙이는 것을 말한다.
패딩의 주된 목적은 합성곱 연산을 거친 출력 이미지의 크기를 입력 이미지의 크기와 같게 유지하는 것이다.
층수가 많은 신경망을 구성할 때 패딩은 특히 중요하다.
NOTE
스트라이드와 패딩을 사용하는 목적은 다음 두 가지다.
1.
이미지에서 중요한 세부 사항을 놓치지 않고 다음 층으로 전달하는 것. (스트라이드는 1, 패딩으로 이미지 크기를 같게 유지한 경우)
2.
이미지의 공간적 정보를 계산하는 부하를 적절히 감소시키는 것.

3.3.2 풀링층과 서브샘플링

합성곱층 수를 늘리면 출력층의 깊이가 깊어지는 만큼 최적화(학습)해야 할 파라미터 수가 늘어난다.
신경망의 규모가 커지면 학습에 필요한 계산 복잡도가 상승하고 그만큼 학습 시간도 오래 걸린다.
이런 단점을 해결해주는 것이 풀링층이다.
풀링(pooling) (또는 서브샘플링(subsampling))은 다음 층으로 전달되는 파라미터 수를 감소시키는 방법으로 신경망의 크기를 줄인다.
풀링 연산은 최대 또는 평균 같은 통계 함수로 입력 크기를 축소해 다음 층으로 전달되는 파라미터 수를 감소시킨다.
풀링층의 목적은 합성곱층에서 만든 특징 맵을 다운샘플링해서 파라미터 수를 줄여 계산 복잡도를 낮추는 것이다.
CNN 구조는 일반적으로 합성곱층 사이에 풀링층을 끼워 넣는 경우가 많다.
최대 풀링과 평균 풀링
풀링층의 풀링 연산은 최대 풀링과 평균 풀링이 주로 쓰인다.
단, 최대 풀링은 행렬에 별도의 가중치가 없다는 점이 다르다.
최대 풀링층은 자기 앞의 합성곱층에서 출력한 특징 맵을 입력받아 커널을 입력 이미지 위로 이동시키면서 윈도우 내 픽셀값의 최대값을 찾아 이를 출력 이미지의 픽셀값으로 삼는다.
합성곱층이 출력한 모든 특징 맵에 풀링을 적용하면 특징 맵의 크기는 작아지지만 개수는 유지된다.
전역 평균풀링(global average pooling)은 특징 맵 크기를 극단적으로 줄이는 방식이다.
윈도우 크기와 스트라이드를 설정하지 않고 전체 특징 맵 픽셀값의 평균을 구한다.
풀링층을 사용하는 이유
풀링층은 합성곱층의 규모를 줄여주는 효과가 있다.
합성곱층의 규모를 줄이는 것이 중요한 이유는 복잡한 프로젝트에 사용되는 CNN은 많은 수의 합성곱층을 포함하며 각각에 수십에서 수백 개에 이르는 합성곱 필터가 쓰이기 때문이다.
따라서 신경망 전체의 파라미터 수가 어마어마하게 늘어날 수도 있다.
이때 풀링층을 사용하면 중요한 특징을 잃지 않으면서 이미지 크기를 줄여 다음 층에 전달한다.
일종의 이미지 압축 프로그램이라고 생각하면 이해하기 쉽다.