최초 작성일: 2020.10.03
최종 수정일: 2020.10.05
1. 시작
자고로 배운게 있으면 써먹어봐야 직성이 풀리는 법이다.
딥러닝을 배우긴 했지만 두루뭉실하기도 하고 막상 해보라고 하면 막막하기만 하다.
그래서 마침 연휴이기도 하고 간단한 프로젝트를 하나 진행해 보기로 했다.
얼굴 사진을 입력받아 cnn을 이용해 남자와 여자를 구분하는 NN을 구축하는 것이다.
개발환경은 ubuntu 18.04에서 진행했다.
2. 데이터 수집 및 전처리
데이터는 크롤링을 할 수도 있으나 크롤링 된 데이터를 다시 가공해야 하는 과정이 필요 하기에 kaggle에서 데이터셋을 받아서 활용하기로 했다.
www.kaggle.com/elangojoseph/face-detection
글을 작성중인 2020년 10월 13일 기준으로 데이터는 2600장 이상의 사진들로 구성되어 있으며 확장되지 않은 데이터를 제외하면 남성은 764장, 여성은 818장의 사진 데이터로 구성되어있다. 모든 이미지는 480*480px의 크기이다.
이 중 남성 100장, 여성 100장은 test셋으로 따로 두고 나머지 남성 664장, 여성 718장을 train셋으로 두었다.
듣기로는 학습에 있어 분류 문제는 1000~ 10000개의 데이터가 필요하다 하는데 일단 1000장 이상은 모았으니 괜찮을 것 같다.
이 후 반복문을 이용해 파일을 3차원 numpy array형태로 받아오려 했으나 사진의 크기가 커 불러오는데에 시간이 상당히 소요되었고 학습시간 역시 매우 오래 걸리는 문제가 발생했다.
문제 해결을 위해 모든 이미지를 60*60px로 수정했다.
그리고 이 과정에서 잘못된 데이터가 발견되어 제거했다.
작업을 거친 후 총 1382개의 train 데이터와 200개의 test데이터셋을 numpy array형태로 받아올 수 있었다.
비슷한 예제를 보면 이미지를 gray scale로 바꿔서 처리를 하던데 이건 이후 차이를 보기 위해 일단은 RGB로 뒀으며 255로 나누어 0~1사이의 값을 갖도록 했다.
이 후 남성은 0, 여성은 1로 구분해서 정답 데이터 y_test와, y_train을 작성하면 학습을 위한 데이터 준비는 끝났다.
3. 신경망 구축
신경망은 convolution과 max pooling을 반복했으며 이후 Affine 네트워크로 구성했다.
출력층은 0, 1로만 구분하면 되기에 마지막 층을 softmax로 뒀다.
summary로 본 모델 파라미터는 아래와 같다.
epoch는 30으로 설정하였고 20~30분정도 시간이 지나 학습이 완료됐다.
loss와 accuracy를 그래프로 그려보았다.
마지막 epoch에서 loss는 0.1535, accuracy는 0.9436이 나왔다.
depth나 epoch, layer 수를 조절하면 loss를 더 줄일 수 있을 것 같다.
이는 하이퍼파라미터 최적화의 문제이므로 이 후 개선시에 값을 수정해봐야 할 것 같다.
이 후 학습된 NN에 test데이터를 넣어 봤다.
$\hat{y}$: [0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, ... , 0, 0, 1, 1]
$y$: [0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, ... , 0, 0, 1, 1]
약95.0%의 정확도를 갖는것을 확인할 수 있었다.
4. 이후 간단한 테스트
인터넷에서 구한 사진 4장으로 테스트를 해 보았다.
1)
예측: 여성 97.3%
정답: 여성
-> 정답
2)
예측: 여성 99.1%
정답: 여성
-> 정답
3)
예측: 남성 96.1%
정답: 남성
-> 정답
4)
예측: 여성 79.9%
정답: 남성
-> 오답
일부러 중성적인 이미지, 헷갈리는 이미지로 고른 1, 3번은 정확하게 구분했는데 4번은 틀렸다.
왜 하필 여기서 틀렸는지는 조금 살펴봐야 할 것 같다.
4번 인물의 다른 사진
예측: 여성 99.4%
정답: 남성
-> 오답
예측: 남성 93.9%
정답: 남성
-> 정답
예측: 여성 92.5%
정답: 남성
-> 오답
예측: 여성 83.3%
정답: 남성
-> 오답
한번 빼도 다 틀렸다;;
정답을 틀린 원인을 알아내기 위해 몇가지 가설을 세워 보았다.
(1) 얼굴이 하얗게 나와 남성, 여성 구분을 잘못했다. -> X 반례: 3)번의 경우 정답을 맞췄다.
(2) 안경때문에 데이터가 성별을 제대로 구분하지 못했다. -> X 반례: train 데이터에 안경, 썬글라스를 쓴 사진도 있다.
(3) train 데이터가 서양인이라 동양인 얼굴을 구분하지 못했다. -> X 반례: 1), 2)번도 동양인이며 높은 확률로 정답을 맞췄다.
(4) 신경망이 그냥 4)번 인물을 싫어한다. -> X 그럴리가;;
(5) 학습 데이터와 입력 데이터가 다르다. -> 어...?
문득 train 데이터셋을 봤다.
train 데이터와 문제가 발생한 데이터와의 차이를 찾아보자.
train 데이터는 헤어스타일이 안보일 정도로 얼굴만 스크랩 된 이미지이다!
오답을 출력한 데이터를 수정해서 테스트 해보았다. 그 결과
예측: 남성 66.2%
정답: 남성
-> 정답
예측: 남성 59.6%
정답: 남성
-> 정답
예측: 남성 90.8%
정답: 남성
-> 정답
예측: 남성 66.1%
정답: 남성
-> 정답
확실히 전부 정답을 출력하긴 했으나 50~60%의 확률은 조금 아쉽다.
조금 더 train 데이터와 비슷하게 해보자.
예측: 남성 95.5%
정답: 남성
-> 정답
예측: 남성 95.0%
정답: 남성
-> 정답
예측: 남성 94.7%
정답: 남성
-> 정답
예측: 남성 96.0%
정답: 남성
-> 정답
처음에 전부 오답을 출력했으나 이번엔 매우 높은 확률로 정답을 출력했다.
이를 통해 학습시킨 신경망의 특징을 알 수 있었다.
"입력 이미지는 얼굴로 꽉 찬 이미지여야 한다."
이를 지키지 않았기에 주변의 배경, 머리카락 등 얼굴과 관련 없는 데이터(픽셀)이 신경망에 영향을 끼쳐 잘못된 결론을 도출하게 된 것이다.
따라서 데이터를 입력하기 전 이러한 조건을 신경써야 한다.
5. 아쉬운 점, 더 해봐야 할 것들
1) 딥러닝의 단점 중 하나로 꼽히는 많은 하이퍼 파라미터가 고민이다. 어떤 값을 수정해야 정확도를 높일 수 있는지는 시행착오를 거쳐야 할 것 같다.
2) GPU를 이용한 학습을 하기 위해 하루종일 인터넷을 뒤져보며 여러가지 방법을 시도해보았으나 오류만 계속 출력됐다. GPU를 이용하면 더 깊은 NN, 더 많은 epoch, 더 큰 이미지를 이용해 학습할 수 있을것 같다. GPU를 정상적으로 사용하는 방법을 더 찾아봐야 할 것 같다.
3) 본 프로젝트는 단순히 얼굴을 이용한 남성, 여성만을 분류했으나 이를 확장하여 얼굴의 장신구(안경, 귀걸이 등...)을 찾아내거나 표정분석, 동영상 등에서 실시간 얼굴 인식 등 다양하게 확장할 수 있을 것 같다.
4) 동일한 조건에서 학습을 처음부터 다시 수행하면 loss, accuracy, test set의 정확도가 바뀐다. "그렇다면 이 중 가장 좋은 결과를 출력하는 신경망을 저장하고 사용하는것이 옳은것인가?"를 고민해봐야 할 것 같다.
6. 소스코드
github.com/mooooondh/FaceRecognition
<참고자료>
[1] 오렐리앙 제롱. Hands-On Machine Learning with Scikit-Learn, Keras&Tensorflow 2판. 한빛미디어
<이미지 출처>
[그림 1] 자체
[그림 2] 자체
[그림 3] 자체
[그림 4] 자체
[그림 5] m.blog.naver.com/PostView.nhn?blogId=leenilee&logNo=90167679262&proxyReferer=https:%2F%2Fwww.google.com%2F
[그림 6] www.donga.com/news/Entertainment/article/all/20200604/101369659/5
[그림 7] m.blog.naver.com/PostView.nhn?blogId=leenilee&logNo=90167679262&proxyReferer=https:%2F%2Fwww.google.com%2F
[그림 8] www.hankookilbo.com/News/Read/201911061399719665
[그림 9] www.etoday.co.kr/news/view/1921431
[그림 10] ko.wikipedia.org/wiki/%EC%9C%A0%EC%9E%AC%EC%84%9D
[그림 11] www.ytn.co.kr/_ln/0106_201912191534546373
[그림 12] www.edaily.co.kr/news/read?newsId=01394006622558456&mediaCodeNo=258
[그림 13] 자체
[그림 14] www.hankookilbo.com/News/Read/201911061399719665
[그림 15] www.etoday.co.kr/news/view/1921431
[그림 16] www.ytn.co.kr/_ln/0106_201912191534546373
[그림 17] www.edaily.co.kr/news/read?newsId=01394006622558456&mediaCodeNo=258
[그림 18] www.hankookilbo.com/News/Read/201911061399719665
[그림 19] www.etoday.co.kr/news/view/1921431
[그림 20] www.ytn.co.kr/_ln/0106_201912191534546373
[그림 21] www.edaily.co.kr/news/read?newsId=01394006622558456&mediaCodeNo=258
'프로젝트' 카테고리의 다른 글
[아쿠쿠아] v1.4.0 출시! (2) | 2024.02.25 |
---|---|
ASL 알파벳 번역기 만들기 2편 (0) | 2021.06.27 |
ASL 알파벳 번역기 만들기 1편 (0) | 2021.06.02 |
평점기반 도서 추천 (1) | 2020.10.27 |
X-ray 사진을 이용한 폐렴 진단(CNN) (0) | 2020.10.06 |