본문 바로가기

Backup/Projects

CNN을 이용한 얼굴 분류기

딥러닝(CNN)을 이용해 얼굴 분류기을 만든 과정에 있어 여기저기 참고하여 실습한 내용을 정리하였다.

목차는 실험보고서처럼 구성하였으며 아래와 같다.



1. 서론

 -. 본 실험을 통해 CNN기수에 대한 이해와 인물 얼굴 분류기을 제작해 보려 한다.

 -. 본 실험은 배운 이론을 바탕으로 데이터 수집부터 keras을 이용해 구현까지 직접 수행해 보았다.


2. 실험 관련 이론

 -. 일반적인 FCNN과 CNN의 가장 큰 차이점이라 함은 이미지 인식에 있어 이미지의 모든 픽셀을 분석하지않고 지역적, 공간적 상관관계을 고려한 학습을 한다. 따라서 효과적으로 Data-representation을 수행하고 이를 통해 분류 작업에 있어 높은 성능을 보인다.

 -. 실험에서 단순 층계수, 노드수의 hyper-parameter말고도 optimizer로 Adam, activation function으로 relu/softmax, loss function으로 cross-entropy을 지정하여 수행하였다.


3. 실험방법 및 수행

 -. 데이터 전처리 : web crawerl을 통해 얻은 이미지을 openCV API을 통해 얼굴만 cropping하여 데이터을 확보하였다.

 -. 모델 설계 : 분석을 위해 최소한의 CNN구조을 2conv 계층, 1fcnn 계층으로 구성하였다.

 -. 학습 과정 : over fitting을 방지하기 위해 early stopping을 하였다.


4. 결과 및 토론

 -. 평가 및 테스트 : test-set 기준 정확도 90%의 성능을 가진다

 -. 네트워크 분석 : 학습된 weight와 feature map 시각화을 통해 CNN의 원리을 분석해보려 한다. 


5. 결론

 -. CNN을 마스터 하기위해 fine-tunning, R-CNN, YOLO등을 다음에 만들어보려한다.

 -. Unsupervised(generative model), Reinforce learning도 연구하려 한다.





2. 실험 관련 이론


2-1.Convolutional Neural Network


CNN은 이미지 인식에 좋은 성능을 보이고 가장 널리 사용되는 알고리즘이다.


사람의 시각 피질 메커니즘에 영감을 아 설계된 네트워크이다.
물론 FCNN도 사람 신경망을 착안하여 만들어진 모델이지만 이미지 인식에 있어 모든 픽셀마다 weight가 다려서 분석하지 
않고 위치에 관계없이 시각적 특징을 추출하기 위하여 제안되었으며지역적 연결(local connection)과 
파라미터 공유(shared weight)을 고려하여 학습한다.
따라서 FCNN으론 몇백개의 층으로 할수있는 일을 단 몇층만으로 효과적으로 feature extraction한 결과을 뒷단에 
FCNN층으로 전달하여 분류작업을 수행한다.
연산속도가 획기적으로 감소하며 local minimum에 빠지거나 vanishing gradient의 위험이 준다.
Image 외에도 많은 분야에서 CNN 기반 모델 활용 (ex. 알파고)




CNN 모델의 구성요소는 크게 4가지로 이루어져 있다.

흔히 Convolutional layer(Convolution, Activation, Pooling)와 FCNN Layer로 구분하기도 한다.



2-1-1. Convolution


convolution층에서는 각 filter가 입력 이미지의 픽셀 전체를 차례로 훓고 지나가며 linear combination을 진행하고 Feature Map을 구성한다.


여기서 convolution은 새로운것이 아니라 영상처리분야에서 있던 기술로 흔히 포토샵에서 blur처리나 edge을 추출할때 쓰이는 방법이다.



그런데 우리가 포토샵에서 쓰는 convolution기술은 사람이 명시적으로 지정한 filter을 통해 input이미지로부터 의도한 특징을 뽑아 새로운 featuremap을 만든다. 반면에 CNN에서의 Convolution은 학습을 통해 이미지 분류을 효과적으로 하기위한 특징들을 자동적으로 찾게끔 한다. 따라서 여기서 학습이란 처음에는 random 값의 filter을 사용하지만 weight parameter update하는것이 이 효과적인 filter을 찾는 작업이다.





일반적인 이미지의 픽셀은 RGB 컬러를 가지는 3차원 벡터이며 이미지는 Height X Width X Depth 모양을 가지고 있다.

그래서 필터는 앞단의 이미지의 depth와 같은 depth을 가지고 있어야 한다.

그리고 중요한건 FCNN 한 층에서 여러개의 노드가 있듯이 Convnet의 한 층에 여러개의 필터가 있고 하나의 필터가 하나의 feature map을 만든다.

 


처음에 설명했듯이 이런 conv층이 여러개 연속적으로 올수있고 대부분 처음에는 garbor filter을 가지다가 뒷단에 갈수록 학습된 weight들은 좀더 추상적인 특징을 추축하는 pattern을 가지게 된다.

아래 그림은 cs231n의 강의자료중 CIFAR10 data-set을 학습한 weight을 시각화 한것인데 아직까지 의문은 어떻게 weight들이 color을 가지는지 이해가 안된다. 첫단의 filter는 depth가 3이라 rgb로 시각화 할수있다 하지만 뒷단의 weight들은 분명 depth가 앞단의 filter개수만큼일텐데 어떻게 rgb로 표현이 가능한지 아직 의문이다.




마지막으로 convolution을 진행하면 dimention이 작아지는데 이때문에 dimention을 유지 혹은 콘트롤 하고자 padding, stride 와 같은 기술들이 있다. 



2-1-2. Activation

activation은 단순히 convolution으로 얻은 feature map을 relu등을 사용해 activate시킨 것이다.


2-1-3. Pooling

pooling층에서는 단순히 featuremap의 dimention을 subsampling 하여 차원을 축소시키는 방법이다.

중요한 저보는 유지하면서 입력의 크기을 줄임으로서 과적합을 예방하고 계산량을 감소시키는 효과을 가진다.

FCNN의 dropdown과 같은 효과을 가지며 subsampling 방법으로는 주로 2x2 max pooling을 사용한다.





여기까지가 흔히 convolution layer라고 불리우는 계층이며 일반적으로 convolution - activation - pooling 순으로 이루어져 있다.

pooling layer은 딥러닝의 hidden layer의 층이 늘어남에 따라 사용의 빈도가 감소하는 추세이다.


2-1-4. FCNN


마지막으로 convolutional layer을 통해 추출한 featuremap을 1d vector로 쭉 나열하여 일반적인 FCNN의 input으로 주어 분류작업을 수행한다.






2-2. Hyperparameter : optimizer, activation function, loss function


2-2-1. Adam optimizer


신경망에는 기본적인 Gradient decent를 시작으로 더 효과적인 optimization 알고리즘들이 지금도 연구되고 있다.

관성의 법칙을 이용해 스텝방향을 조정한 momentum, 또는 각 파라미터마다 다른 스텝사이즈을 가지게 하는 adagrad같은 것들이 있고 이 두 장점을 조합한 Adam이란것도 2015년도에 연구되어 최근의 딥러닝에서 가장 많이 default로 사용되는 optimizer이다. 물론 adam이 정답은 아니고 문제에 따라 잘 작동하는 optimizer가 있으니 이또한 hypterparameter이다.






2-2-2. relu/softmax activation function


relu는 2014년도 alexnet에서 처음 적용되면서 sigmoid의 vanishing gradient을 피해보고자 고안된것으로 오늘날에는 hidden layer의 default activatoin 으로 사용된다. 결국 신경망은 기울기을 통해 backprop과정에서 weight들을 업데이트 하는데 weighted sum이 -1 이하 또는 1이상일 경우 sigmoid는 기울기가 없다. 따라서 양수에서는 항상 기울기가 있으며 비선형성을 가지는 relu가 성능이 좋다고 한다.



그리고 분류작업에 있어 출력층으론 softmax을 사용하는게 일반적이다. Sigmoid 함수가 이산 분류(결과값에 따라 참 또는 거짓을 나타내는) 함수라면, Softmax 여러개의 분류를 가질 수 있는 함수이다.


좋은점이 결과가 class개수을 고려한 확률값으로 나오며 따라서 아래 그림을 보듯이 Pn 값은 항상 0~1.0의 범위를 가지며,  P1+P2+...+Pn = 1



2-2-3. cross-entropy


일반적으로 mean square error을 쓰지만 분류 작업에 있어서 만큼은 모델 결과와 정답의 정보량의 차이로부터 loss을 측정하는 cross-entropy가 효과적이다. 




label data도 어차피 oneshot encoding형태로 나오고 결과값도 확률 분포로 표현될수 있기 때문에 연산측면에서나 최적화 관점에서도 정보량 차이을 loss로 잡는게 더 효과적이라 한다.









3. 실험방법 및 수행


이젠 본격적으로 얼굴 분류기을 만드는 절차에 대해 설명하려 한다..



3-1. 데이터 전처리


딥러닝도 결국 data로 부터 학습을 해야 하니까 데이터가 많이 필요하다.

본 실험에서는 4개의 class을 지정(설현, 김연아, 박지성, 문재인)하여 web crawler을 이용해 데이터 수집 노가다을 피했다. 

이때 학습 쏠리는 현상을 방지하기 위해 데이터 분포도을 고려하여 각각 고르게 700장씩 확보해 두었다.


또 우리의 목표가 얼굴만 분별하면 되기 때문에 opencv api을 사용해 (haarcascade 알고리즘) 얼굴영역을 filtering하여 cropping하고 128x128 픽셀 크기로 resize하였다

그런데도 아직 쓰레기 데이터가 많아(박지성 사진이여야하는데 루니가 있다던지... 문재인 사진이여야 하는데 안철수가 있다던지...) 이대로 학습을 진행하면 나중에 정확도가 65%밖에 올라가지 않는다. 그래서 몇 안되는 데이터셋이니 직접 눈으로 데이터 검증 과정을 한번 거쳤다.


그래서 최종 획득한 이미지는 각 class당 약 500장씩을 정재하였다.



3-2. 모델 설계 


모델 구성은 2개의 convolution layer, 1개의 fully connected layer로 구성하고 후미에 1 fcnn layer로 hidden layer들을 구성하였다.


첫 convnet의 8x8 filter 16개, 두번째 convnet은 5x5 filter 36개을 사용하였다. 그리고 fcnn에서는 128개의 relu node들을 사용하였고 마지막에는 4개의 class을 구분하기위해 softmax로 4개의 output을 가지게끔 하였다. 




3-3. 학습 과정


3-3-1. hyperparameters


feedforward 하기 전에 한가지 전처리를 하였는데 빠른 converge을 위해 input data들을 255로 나누어 0~1사이의 값으로 normalization하였다.

또 최종 분류로 softmax을 쓰기때문에 각 이미지마다 class label을 가지게 하였다.

학습과 성능 평가을 위해 전체 데이터들을 10%는 test-set, 10% validation-set,  80%는 train-set으로 나누어 사용하였다.



hyperparameter로는 cross-entropy loss function, adam optimization(learning rate = 0.001), batch size = 16, epoch = 10 로 설정하여 학습을 진행하였고

학습과정에서 epoch가 끝날때마다 validation set으로 성능 평가하여 loss을 monitoring 하니 아래와 같은 그래프가 나왔다. 

보다 싶이 epoch 1번부터 train loss가 연전되어서 저 지점이 overfitting이 시작되고 있는 지점이라 할수있다.

그래서 최종적으로 사용하는 모델은 train을 2epoch까지만 돌렸다.


4. 결과 및 토론



4-1. 평가 및 테스트


keras는 tensorflow에 비교적 학습한 모델을 저장하고 불러오는게 쉽다. 불러온 모델로 test-set의 데이터들을 이용해 분류작업을 수행하였다.

성능 평가을 위해 test-set으로 나온 결과을 아래와 같이 confusion matrix을 만들었다.








보시다 싶이 전체 데이터중 맞은 비율이 90%여서 모델의 정확도는 90%라 할수있다.

만약 테스트셋의 class가 balance하지 않았다면 F1-score도 봐야하는데 아래와 같이 똑같이 90%가 나왔다.





4-2. 네트워크 분석


그렇다면 내가 만든 CNN모델은 어떠한 일을 수행하여 90% 나 되는 성능을 내는걸까....

이를 이해하기 위해 학습된filter들과 activation된 feature map들을 시각화 해보겠다.




그런데 딥러닝이 다른 머신러닝 방법들과 비교되면서 어느정도 일반적인 비판은 신경망에서 학습된 특징들은 해석불가능 하다는 것이다. 


아래는 각 인풋 이미지에 따른conv1 layer와 conv2 layer의 feature map을 시각화 한것이다..


조금 억지가 될수있지만 conv2의 feature map을 보면 각 level의 feature map의 filter마다 얼굴 형이라든지 눈이라든지의 특징을 뽑아낸다.

이를 통해 input이미지을 여러 feature map으로 재해석하여 fcnn의 input으로 주어 좀더 분류에 도움이 되게끔 하는게 convolutional layer의 역할이라고 볼수 있겠다.







5, 결론


이렇게 한번 이론 실습을 정리해보니 확실히 이해가 되는거 같다.

다음에 하려는 실습으로는 CNN을 활용한 transfer learning, R-CNN, Yolo 등을 생각하고 있고

추후에 더 나아가서는 요즘 핫한 Generative models, Reinforment Learning도 공부하여 실습할 계획이다.




references : 


cs231n : http://cs231n.stanford.edu/

조대협님의 블로그 : http://bcho.tistory.com/1166

Hvass Laboratories tutorial: https://github.com/Hvass-Labs/TensorFlow-Tutorials

Ex-em(이도엽) 딥러닝 자료 : https://l.facebook.com/l.php?u=https%3A%2F%2Fdrive.google.com%2Fopen%3Fid%3D0B-qyuGELhRZ6dGhFeUNVaFNPbms&h=ATPYRYISDniYX5lENXzQy4wHaZEOhQgztfkCLGsGisRtmgMnbQTvV3-1yZfVlDDfT-qCjbX_E6f8wOjU1dZN18GzN6j_J8KeMuj8T0YCxCXgFUwTu4XzsnL88wgjndR-RDg8Tde7vutguaXWYvY_fCpE9syYRTNqzVwg2bdyHXTJe6DvMN-nlk5HZfnML-ROIp4mkaPOeqcrLuQV5DoCqJcEadsqtp6qKHcZDqXArXRhOTboO0VFfE97G1tdVz12tuguBFURIFRLIEIrsHuuH7jWPhlMPoZn