딥러닝 - 컨볼루셔널 네트워크를 이용한 이미지 인식의 개념
이번 글에서는 딥러닝 중에서 이미지 인식에 많이 사용되는 컨볼루셔널 뉴럴 네트워크 (Convolutional neural network) 이하 CNN에 대해서 알아보도록 하자.
이 글을 읽기에 앞서서 머신러닝에 대한 기본 개념이 없는 경우는 다음 글들을 참고하기 바란다.
머신러닝의 개요 http://bcho.tistory.com/1140
머신러닝의 기본 원리는 http://bcho.tistory.com/1139
이산 분류의 원리에 대해서는 http://bcho.tistory.com/1142
인공 신경망에 대한 개념은 http://bcho.tistory.com/1147
CNN은 전통적인 뉴럴 네트워크 앞에 여러 계층의 컨볼루셔널 계층을 붙인 모양이 되는데, 그 이유는 다음과 같다. CNN은 앞의 컨볼루셔널 계층을 통해서 입력 받은 이미지에 대한 특징(Feature)를 추출하게 되고, 이렇게 추출된 특징을 기반으로 기존의 뉴럴 네트워크를 이용하여 분류를 해내게 된다.
컨볼루셔널 레이어 (Convolutional Layer)
컨볼루셔널 레이어는 앞에서 설명 했듯이 입력 데이타로 부터 특징을 추출하는 역할을 한다.
컨볼루셔널 레이어는 특징을 추출하는 기능을 하는 필터(Filter)와, 이 필터의 값을 비선형 값으로 바꾸어 주는 액티베이션 함수(Activiation 함수)로 이루어진다.
그럼 각 부분의 개념과 원리에 대해서 살펴보도록 하자.
<그림 Filter와 Activation 함수로 이루어진 Convolutional 계층>
필터 (Filter)
필터 개념 이해
필터는 그 특징이 데이타에 있는지 없는지를 검출해주는 함수이다. 예를 들어 아래와 같이 곡선을 검출해주는 필터가 있다고 하자.
필터는 구현에서는 위의 그림 좌측 처럼 행렬로 정의가 된다.
입력 받은 이미지 역시 행렬로 변환이 되는데, 아래 그림을 보자.
쥐 그림에서 좌측 상단의 이미지 부분을 잘라내서 필터를 적용하는 결과이다.
잘라낸 이미지와, 필터를 곱하면
과 같이 결과 값이 매우 큰 값이 나온다.
만약에 아래 그림처럼 쥐 그림에서 곡선이 없는 부분에 같은 필터를 적용해보면
결과 값이 0에 수렴하게 나온다.
즉 필터는 입력받은 데이타에서 그 특성을 가지고 있으면 결과 값이 큰값이 나오고, 특성을 가지고 있지 않으면 결과 값이 0에 가까운 값이 나오게 되서 데이타가 그 특성을 가지고 있는지 없는지 여부를 알 수 있게 해준다.
다중 필터의 적용
입력값에는 여러가지 특징이 있기 때문에 하나의 필터가 아닌 여러개의 다중 필터를 같이 적용하게 된다.
다음과 같이 |,+,- 모양을 가지고 있는 데이타가 있다고 하자
각 데이타가 |와 - 의 패턴(특징을) 가지고 있는지를 파악하기 위해서 먼저 | (세로) 필터를 적용해보면 다음과 같은 결과가 나온다.
(맨앞의 상자는 필터이다.) 두번째 상자부터 원본 이미지에 세로선(|) 이 없는 경우 결과 이미지에 출력이 없고, 세로선이 있는 경우에는 결과 이미지에 세로 선이 있는 것을 확인할 수 있다.
마찬가지로 가로선(-) 특징이 있는지 가로 선을 추출하는 필터를 적용해보면 다음과 같은 결과를 얻을 수 있다.
이렇게 각기 다른 특징을 추출하는 필터를 조합하여 네트워크에 적용하면, 원본 데이타가 어떤 형태의 특징을 가지고 있는지 없는지를 판단해 낼 수 있다. 다음은 하나의 입력 데이타에 앞서 적용한 세로와 가로선에 대한 필터를 동시에 적용한 네트워크의 모양이다.
Stride
그러면 이 필터를 어떻게 원본 이미지에 적용할까? 큰 사진 전체에 하나의 큰 필터 하나만을 적용할까?
아래 그림을 보자, 5x5 원본 이미지가 있을때, 3x3인 필터를 좌측 상단에서 부터 왼쪽으로 한칸씩 그 다음 한줄을 내려서 또 왼쪽으로 한칸씩 적용해서 특징을 추출해낸다.
오른쪽 Convolved Feature 행렬이 바로 원본 이미지에 3x3 필터를 적용하여 얻어낸 결과 이다.
이렇게 필터를 적용 하는 간격 (여기서는 우측으로 한칸씩 그리고 아래로 한칸씩 적용하였다.) 값을 Stride라고 하고, 필터를 적용해서 얻어낸 결과를 Feature map 또는 activation map 이라고 한다.
Padding
앞에서 원본 데이타에 필터를 적용한 내용을 보면 필터를 적용한 후의 결과값은 필터 적용전 보다 작아졌다. 5x5 원본 이미지가 3x3의 1 stride 값을 가지고 적용되었을때, 결과 값은 3x3으로 크기가 작아졌다.
그런데, CNN 네트워크는 하나의 필터 레이어가 아니라 여러 단계에 걸쳐서 계속 필터를 연속적으로 적용하여 특징을 추출하는 것을 최적화 해나가는데, 필터 적용 후 결과 값이 작아지게 되면 처음에 비해서 특징이 많이 유실 될 수 가 있다. 필터를 거쳐감에 따라서 특징이 유실되는 것을 기대했다면 문제가 없겠지만, 아직까지 충분히 특징이 추출되기 전에, 결과 값이 작아지면 특징이 유실된다. 이를 방지 하기 위한 방법으로 padding 이라는 기법이 있는데, padding은 결과 값이 작아지는 것을 방지하기 위해서 입력값 주위로 0 값을 넣어서 입력 값의 크기를 인위적으로 키워서, 결과값이 작아지는 것을 방지 하는 기법이다.
다음 그림을 보자, 32x32x3 입력값이 있을때, 5x5x3 필터를 적용 시키면 결과값 (feature map)의 크기는 28x28x3 이 된다. 이렇게 사이즈가 작아지는 것을 원하지 않았다면 padding을 적용하는데, input 계층 주위로 0을 둘러 싸서, 결과 값이 작아지고 (피쳐가 소실 되는것)을 막는다
32x32x3 입력값 주위로 2 두깨로 0을 둘러싸주면 36x36x3 이 되고 5x5x3 필터 적용하더라도, 결과값 은 32x32x3으로 유지된다.
< 그림, 32x32x3 데이타에 폭이 2인 padding을 적용한 예 >
패딩은 결과 값을 작아지는 것을 막아서 특징이 유실되는 것을 막는 것 뿐 아니라, 오버피팅도 방지하게 되는데, 원본 데이타에 0 값을 넣어서 원래의 특징을 희석 시켜 버리고, 이것을 기반으로 머신러닝 모델이 트레이닝 값에만 정확하게 맞아 들어가는 오버피팅 현상을 방지한다.
오버 피팅에 대해서는 별도의 다른 글을 통해서 설명한다.
필터는 어떻게 만드는 것일까?
그렇다면 CNN에서 사용되는 이런 필터는 어떻게 만드는 것일까? CNN의 신박한 기능이 바로 여기에 있는데, 이 필터는 데이타를 넣고 학습을 시키면, 자동으로 학습 데이타에서 학습을 통해서 특징을 인식하고 필터를 만들어 낸다.
Activation function
필터들을 통해서 Feature map이 추출되었으면, 이 Feature map에 Activation function을 적용하게 된다.
Activation function의 개념을 설명하면, 위의 쥐 그림에서 곡선값의 특징이 들어가 있는지 안들어가 있는지의 필터를 통해서 추출한 값이 들어가 있는 예에서는 6000, 안 들어가 있는 예에서는 0 으로 나왔다.
이 값이 정량적인 값으로 나오기 때문에, 그 특징이 “있다 없다”의 비선형 값으로 바꿔 주는 과정이 필요한데, 이 것이 바로 Activation 함수이다.
예전에 로지스틱 회귀 ( http://bcho.tistory.com/1142 )에서 설명하였던 시그모이드(sigmoid) 함수가 이 Activation 함수에 해당한다.
간단하게 짚고 넘어가면, 결과 값을 참/거짓 으로 나타내는 것이 아니라, 참에 가까워면 0.5~1사이에서 1에 가까운 값을 거짓에 가까우면 0~0.5 사이의 값으로 리턴하는 것이다.
<그림. Sigmoid 함수>
뉴럴 네트워크나 CNN (CNN도 뉴럴 네트워크이다.) 이 Activation 함수로 이 sigmoid 함수는 잘 사용하지 않고, 아래 그림과 같은 ReLu 함수를 주요 사용한다.
<그림. ReLu 함수>
이 함수를 이용하는 이유는 뉴럴 네트워크에서 신경망이 깊어질 수 록 학습이 어렵기 때문에, 전체 레이어를 한번 계산한 후, 그 계산 값을 재 활용하여 다시 계산하는 Back propagation이라는 방법을 사용하는데, sigmoid 함수를 activation 함수로 사용할 경우, 레이어가 깊어지면 이 Back propagation이 제대로 작동을 하지 않기 때문에,(값을 뒤에서 앞으로 전달할때 희석이 되는 현상. 이를 Gradient Vanishing 이라고 한다.) ReLu라는 함수를 사용한다.
풀링 (Sub sampling or Pooling)
이렇게 컨볼루셔날 레이어를 거쳐서 추출된 특징들은 필요에 따라서 서브 샘플링 (sub sampling)이라는 과정을 거친다.
컨볼루셔널 계층을 통해서 어느정도 특징이 추출 되었으면, 이 모든 특징을 가지고 판단을 할 필요가 없다.
쉽게 예를 들면, 우리가 고해상도 사진을 보고 물체를 판별할 수 있지만, 작은 사진을 가지고도 그 사진의 내용이 어떤 사진인지 판단할 수 있는 원리이다.
그래서, 추출된 Activation map을 인위로 줄이는 작업을 하는데, 이 작업을 sub sampling 도는 pooling 이라고 한다. Sub sampling은 여러가지 방법이 있는데, max pooling, average pooling, L2-norm pooling 등이 있고, 그중에서 max pooling 이라는 기법이 많이 사용된다.
Max pooling (맥스 풀링)
맥스 풀링은 Activation map을 MxN의 크기로 잘라낸 후, 그 안에서 가장 큰 값을 뽑아내는 방법이다.
아래 그림을 보면 4x4 Activation map에서 2x2 맥스 풀링 필터를 stride를 2로 하여 2칸씩 이동하면서 맥스 풀링을 한 예인데, 좌측 상단에서는 6이 가장 큰 값이기 때문에 6을 뽑아내고, 우측 상단에는 2,4,7,8 중 8 이 가장 크기 때문에 8을 뽑아 내었다.
맥스 풀링은 특징의 값이 큰 값이 다른 특징들을 대표한다는 개념을 기반으로 하고 있다.
(주의 풀링은 액티베이션 함수 마다 매번 적용하는 것이 아니라, 데이타의 크기를 줄이고 싶을때 선택적으로 사용하는 것이다.)
이런 sampling 을 통해서 얻을 수 있는 장점은 다음과 같다.
전체 데이타의 사이즈가 줄어들기 때문에 연산에 들어가는 컴퓨팅 리소스가 적어지고
데이타의 크기를 줄이면서 소실이 발생하기 때문에, 오버피팅을 방지할 수 있다.
컨볼루셔널 레이어
이렇게 컨볼루셔널 필터와 액티베이션 함수 (ReLU) 그리고 풀링 레이어를 반복적으로 조합하여 특징을 추출한다.
아래 그림을 보면 여러개의 컨볼루셔널 필터(CONV)와 액티베이션 함수 (RELU)와 풀링 (POOL) 사용된것을 볼 수 있다.
Fully connected Layer
컨볼루셔널 계층에서 특징이 추출이 되었으면 이 추출된 특징 값을 기존의 뉴럴 네트워크 (인공 신경 지능망)에 넣어서 분류를 한다.
그래서 CNN의 최종 네트워크 모양은 다음과 같이 된다.
<그림. CNN 네트워크의 모양>
Softmax 함수
Fully connected network (일반적인 뉴럴 네트워크)에 대해서는 이미 알고 있겠지만, 위의 그림에서 Softmax 함수가 가장 마지막에 표현되었기 때문에, 다시 한번 짚고 넘어가자.
Softmax도 앞에서 언급한 sigmoid나 ReLu와 같은 액티베이션 함수의 일종이다.
Sigmoid 함수가 이산 분류 (결과값에 따라 참 또는 거짓을 나타내는) 함수라면, Softmax 는 여러개의 분류를 가질 수 있는 함수이다. 아래 그림이 Softmax 함수의 그림이다.
이것이 의미하는 바는 다음과 같다. P3(x)는 특징(feature) x에 대해서 P3일 확률, P1(x)는 특징 x 에 대해서 P1인 확률이다.
Pn 값은 항상 0~1.0의 범위를 가지며, P1+P2+...+Pn = 1이 된다.
예를 들어서 사람을 넣었을때, 설현일 확률 0.9, 지현인 확율 0.1 식으로 표시가 되는 것이다.
Dropout 계층
위 CNN 그래프에서 특이한 점중 하나는 Fully connected 네트워크와 Softmax 함수 중간에 Dropout layer (드롭아웃) 라는 계층이 있는 것을 볼 수 있다.
드롭 아웃은 오버피팅(over-fit)을 막기 위한 방법으로 뉴럴 네트워크가 학습중일때, 랜덤하게 뉴런을 꺼서 학습을 방해함으로써, 학습이 학습용 데이타에 치우치는 현상을 막아준다.
<그림. 드롭 아웃을 적용한 네트워크 >
그림 출처 : https://leonardoaraujosantos.gitbooks.io/artificial-inteligence/content/dropout_layer.html
일반적으로 CNN에서는 이 드롭아웃 레이어를 Fully connected network 뒤에 놓지만, 상황에 따라서는 max pooling 계층 뒤에 놓기도 한다.
다음은 드롭아웃을 적용하고 학습시킨 모델과 드롭 아웃을 적용하지 않은 모델 사이의 예측 정확도를 비교한 결과 이다.
<그림. 드룹아웃을 적용한 경우와 적용하지 않고 학습한 경우, 에러율의 차이 >
이렇게 복잡한데 어떻게 구현을 하나요?
대략적인 개념은 이해를 했다. 그렇다면 구현을 어떻게 해야 할까? 앞에서 설명을 할때, softmax 나 뉴런에 대한 세부 알고리즘 ReLu 등과 같은 알고리즘에 대한 수학적인 공식을 설명하지 않았다. 그렇다면 이걸 하나하나 공부해야 할까?
아니다. 작년에 구글에서 머신러닝용 프로그래밍 프레임워크로 텐서 플로우라는 것을 발표했다.
이 텐서 플로우는 (http://www.tensorflow.org)는 이런 머신 러닝에 특화된 프레임웍으로, 머신러닝에 필요한 대부분의 함수들을 이미 구현하여 제공한다.
실제로 CNN을 구현한 코드를 보자. 이 코드는 홍콩 과학기술 대학교의 김성훈 교수님의 강의를 김성훈님이란 분이 텐서 플로우 코드로 구현하여 공유해놓은 코드중 CNN 구현 예제이다. https://github.com/FuZer/Study_TensorFlow/blob/master/08%20-%20CNN/CNN.py
첫번째 줄을 보면, tf.nn.conv2d 라는 함수를 사용하였는데, 이 함수는 컨볼루셔널 필터를 적용한 함수 이다. 처음 X는 입력값이며, 두번째 w 값은 필터 값을 각각 행렬로 정의 한다. 그 다음 strides 값을 정의해주고, 마지막으로 padding 인자를 통해서 padding 사이즈를 정한다.
컨볼루셔널 필터를 적용한 후 액티베이션 함수로 tf.nn.relu를 이용하여 ReLu 함수를 적용한 것을 볼 수 있다.
다음으로는 tf.nn.max_pool 함수를 이용하여, max pooling을 적용하고 마지막으로 tf.nn.dropout 함수를 이용하여 dropout을 적용하였다.
전문적인 수학 지식이 없이도, 이미 잘 추상화된 텐서플로우 함수를 이용하면, 기본적인 개념만 가지고도 머신러닝 알고리즘 구현이 가능하다.
텐서 플로우를 공부하는 방법은 여러가지가 있겠지만, 유투브에서 이찬우님이 강의 하고 계신 텐서 플로우 강의를 듣는 것을 추천한다. 한글이고 설명이 매우 쉽다. 그리고 매주 일요일에 생방송을 하는데, 궁금한것도 물어볼 수 있다.
https://www.youtube.com/channel/UCRyIQSBvSybbaNY_JCyg_vA
그리고 텐서플로우 사이트의 튜토리얼도 상당히 잘되어 있는데, https://www.tensorflow.org/versions/r0.12/tutorials/index.html 를 보면 되고 한글화도 잘 진행되고 있다. 한글화된 문서는 https://tensorflowkorea.gitbooks.io/tensorflow-kr/content/ 에서 찾을 수 있다.
구현은 할 수 있겠는데, 그러면 이 모델은 어떻게 만드나요?
그럼 텐서플로우를 이용하여 모델을 구현할 수 있다는 것은 알았는데, 그렇다면 모델은 어떻게 만들까? 정확도를 높이려면 수십 계층의 뉴럴 네트워크를 설계해야 하고, max pooling 함수의 위치와 padding등 여러가지를 고려해야 하는데, 과연 이게 가능할까?
물론 전문적인 지식을 가진 데이타 과학자라면 이런 모델을 직접 설계하고 구현하고 테스트 하는게 맞겠지만, 이런 모델들은 이미 다양한 모델이 만들어져서 공개 되어 있다.
그중에서 CNN 모델은 매년 이미지넷 (http://www.image-net.org/) 이라는데서 추최하는 ILSVRC (Large Scale Visual Recognition Competition) 이라는 대회에서, 주최측이 제시하는 그림을 누가 잘 인식하는지를 겨루는 대회이다.
<그림. 이미지넷 대회에 사용되는 이미지들 일부>
이 대회에서는 천만장의 이미지를 학습하여, 15만장의 이미지를 인식하는 정답률을 겨루게 된다. 매년 알고리즘이 향상되는데, 딥러닝이 주목 받은 계기가된 AlexNet은 12년도 우승으로, 8개의 계층으로 16.4%의 에러율을 내었고, 14년에는 19개 계층을 가진 VGG 알고리즘이 7.3%의 오차율을 기록하였고, 14년에는 구글넷이 22개의 레이어로 6.7%의 오차율을 기록하였다. 그리고 최근에는 마이크로소프트의 152개의 레이어로 ResNet이 3.57%의 오차율을 기록하였다. (참고로 인간의 평균 오류율은 5% 내외이다.)
현재는 ResNet을 가장 많이 참고해서 사용하고 있고, 쉽게 사용하려면 VGG 모델을 사용하고 있다.
결론
머신러닝과 딥러닝에 대해서 공부를 하면서 이게 더이상 수학자나 과학자만의 영역이 아니라 개발자도 들어갈 수 있는 영역이라는 것을 알 수 있었고, 많은 딥러닝과 머신러닝 강의가 복잡한 수학 공식으로 설명이 되지만, 이건 아무래도 설명하는 사람이 수학쪽에 배경을 두고 있기 때문 일것이고, 요즘은 텐서플로우 프레임웍을 사용하면 복잡한 수학적인 지식이 없이 기본적인 머신러닝에 대한 이해만을 가지고도 머신러닝 알고리즘을 개발 및 서비스에 적용이 가능한 시대가 되었다고 본다.
그림 출처 및 참고 문서
김성훈 교수님의 모두를 위한 딥러닝 https://hunkim.github.io/ml/
A Beginner’s guide to understanding convolutional network https://adeshpande3.github.io/adeshpande3.github.io/A-Beginner's-Guide-To-Understanding-Convolutional-Neural-Networks/
'빅데이타 & 머신러닝 > 머신러닝' 카테고리의 다른 글
텐서플로우 #2 - 행렬과 텐서플로우 (7) | 2016.12.26 |
---|---|
텐서플로우-#1 자료형의 이해 (15) | 2016.12.09 |
머신러닝의 과학습 / 오버피팅의 개념 (1) | 2016.11.30 |
딥러닝의 개념과 유례 (3) | 2016.11.27 |
수학포기자를 위한 딥러닝-#4 로지스틱 회귀를 이용한 분류 모델 (4) | 2016.10.10 |