간만의 포스팅이다.
CNN으로 Classification을 만들었다.
필자가 하고자 했던 것은 얼굴 사진으로 얼굴이 건조한지 아닌지를 분류하고 싶었다.
(정확히 말하자면, 얼굴의 각질의 유무를 구분하고 싶었다.)
이미지를 통한 분류 작업이었기 때문에 CNN으로 눈을 돌렸다.
우선, CNN의 여러가지 기법을 찾아보았다.
간단한 기법인 줄 알았지만 역사도 길고, CNN기법에서도 여러가지가 있다는 것을 링크에서 확인했다.
그 중 가장 많이 보고 들었던 VGG-16을 처음으로 시도해보았다.
이미지 데이터가 있어야 했기에 데이터는 구글과 네이버에서 크롤링을 진행했다.
쓸만한 데이터가 각질을 포함한 얼굴 부분, 각질이 없는 얼굴 부분 각각 150개정도밖에 나오지 않았다.
training set의 class별 최소 1000개 이상이 있어야 한다고 한다.
under-fitting이 될 것 같아 이를 증폭하는 작업이 필요했다.
keras의 augmentation을 제공하는 줄 모르고 OpenCV를 이용하여 직접 (flip 및 rotation) Augmentation을 진행했다.
('11101'이라는 이미지와 flip시킨 '10111'은 컴퓨터가 다르게 받아들일 것으로 생각했다.)
물론, 데이터의 양과 다양함이 부족했다.
기껏해봤자 8배정도 늘어났다.
그래서 찾아본 것은 keras에서 제공하는 코드를 이용했다.
ImageDataGenerator를 사용했다.
위의 코드를 사용하여 좌우반전/회전/좌우반전,회전을 통해 비어있는 공간을 어떻게 할 것인지 등을 선택할 수 있으며,
마지막에 언급한 parameter는 fill_mode인데 내가 하고자 했던 분류에서는 이 fill_mode를 어떤것으로 할 지에 따라 성능이 다르게 나왔다.
여러가지 방법으로 fill_mode를 했다.
처음 이용한 방법은 default값인 'nearest'를 사용했다.
뒤에서 언급하겠지만 결론적으로는 필자는 'reflect'방법을 사용했다.
무튼, 이렇게 augmentation을 하고 VGG-16, 19의 코드로 모델을 만들고 분류를 시켜보았지만, accuracy가 51~54에서 머물렀다. 분명 문제가 있는것이었고, 이를 파악하기 위해 여러가지 생각을 했다.
1)pooling의 방법을 잘 못 한것은 아닌가?
2)이미지의 색상에 따라 다르게 받아들이는 것일까?
3)Augmentation을 시행할 때 특성을 잃어버리는 것은 아닐까?
1)의 문제를 파고들어 보았다.
pooling의 방법에는 Max와 Average가 있다.
Max는 kernel 내의 값들 중 가장 높은 값을 다음 layer에 반영하는 것이고,
Average는 kernel 내의 값들의 평균을 다음 layer에 반영하는 것이다.
처음에는 모든 pooling을 Max로 진행했고, 마지막에는 모든 pooling을 Average로 진행했다.
모든 경우의 수를 시행했다.
Q. 보통은 Max로 진행하던데 왜 Average를 섞어가면서 했나요?
A. 한국 사람의 얼굴을 기준으로 한다면, 피부와 각질은 확연한 차이가 있다.
각질은 흰색이며 이는 피부와 구분이 된다.
만약 Max로만 진행한다면 흰색인 각질과 피부에 반사된 조명을 다음 layer에 전달할거라고 생각했다.
그렇기에 Average를 섞어 사용한다면, 피부의 특성도 다음 layer에 전달될 것이라고 생각했고, 그에 따른 각질도 다음 layer에 전달될 것이라고 생각했다.
위에서 언급했듯 accuracy는 51~54에 그쳤다.
이건 눈을 감고 찍어도 나올 수 있는 수치고 생각한다.
(우선 성능을 뽑아냈어야 했기에 앞의 링크 중 눈에 띈 EfficientNet을 이용하여 진행했다.)
무엇인가가 단단히 잘못됐다고 생각했지만, VGG 내에서 어떻게 진행되는지 확인할 방법이 없어 다음으로 넘어갔다.
다음 포스팅에서 마저 작성하겠다.
'Python > EfficientNet' 카테고리의 다른 글
EfficienNet(2) (0) | 2021.04.19 |
---|