TensorFlow와 Keras를 사용해서 딥러닝을 해보자 #1 시행착오

Explanation

오늘은 대 AI의 시대 속에서 한번 직접 TensorFlow와 Keras를 사용해서 간단하게 학습을 시키고 직접 확인해 보려 합니다!

여담으로, 올해 공부하려고 했던 두 가지 중 하나가 웹 브라우저 개발이고 나머지 하나가 AI 였는데요. 그런데 생각보다 웹 브라우저 개발이 오래걸려서.. 조금 많이 밀렸습니다.
지금 이 글은 그 시작으로 아주 간단한 첫 걸음이지만, 목표는 GAN(Generative Adversarial Networks) 이미지에 대한 학습을 시키고 개발하고 있는 웹 브라우저에 적용해서 웹 페이지에 GAN 이미지가 있을때, 해당 이미지에 알림를 띄우는 기능을 넣는 것이랍니다!
틈틈이 공부한 내용이나 개발에 진척이 있다면 블로그를 통해서 공유하도록 하겠습니다!

이번에 해볼 것은 여러 장의 고양이 이미지와 그 밖의 동물들의 이미지를 가지고 학습을 시킨 후에 특정 이미지가 주어졌을 때, 이 이미지가 고양이인지 아닌지 알아내는 api 서버를 만드는 것까지 입니다.
(언어는 파이썬을 사용하고 api 서버는 플라스크를 사용합니다.)

저는 딥러닝도 머신러닝도 AI도 잘 모른답니다. (파이썬도 한 5년 만에 써보는 거 같아요.)
이 글은 아주 짧게 공부하면서 작성하는 글이기 때문에, 부족한 부분이 많습니다. 그냥 어떤 순서로 어떻게 동작하는지 가볍게 보는 정도로만 봐주시면 좋을 것 같습니다 :)

1. 데이터 셋 만들기

일단 기본적으로 학습을 시키려면, 공부거리가 있어야겠죠?! 그래서 고양이 이미지와 고양이가 아닌 이미지를 인터넷에서 수집하였습니다. 이 대목에서 당연히 숙련된 개발자라면 스크래핑 서버를 만들어서 인터넷에서 싹싹 긁어 오겠지만, 저는 미숙한 개발자이기 때문에 저작권까지 생각해서 https://unsplash.com 에서 한땀 한땀 수집하였습니다.
총 고양이 이미지 60개, 그밖의 동물 이미지 60개를 만들었는데, 이 정도로 될지 모르겠네요.
일단 해보고 잘 안되면 추가하는 쪽으로 하겠습니다.

늘 그렇듯, 이 글에 작성된 코드는 깃허브 저장소를 통해서 모두 확인할 수 있으며 위 데이터 셋 이미지도 확인할 수 있습니다.
https://github.com/falsy/blog-post-example/tree/master/tensorflow-keras

2. 학습 코드 만들기

앞서 이야기한대로 TensorFlow와 Keras를 사용해서 학습 코드를 만들어 줄 건데요.
우선 필요한 패키지를 먼저 정의하고 설치해 줍니다.

개발 환경은 macOS이고 Python은 v3.9.7 를 사용하고 있습니다.

가상 환경을 만들고 활성화해주고, 패키지를 설치해 줍니다.

가상환경은 ‘deactivate’ 명령어로 종료할 수 있습니다.

flask 는 후에 만들 api 서버의 프레임워크이고 tensorflow는 딥러닝 라이브러리이고 pillow는 파이썬 이미지 라이브러리의 유지 보수 버전이고 scipy는 학습시키려고 하니까 설치하라고 하더라고요?! 뭔지는 잘 모르겠네요.

이제 본격적으로 코드를 볼까요

짜잔! 뭔가 생각보다 간단하고 그럴싸해 보이죠?!
사실 ChatGPT가 만들어 준 코드라 뭔지 저도 잘 모릅니다..

그래도 코드를 좀 알아야 뭘 할 수 있겠죠?

주석 그대로 데이터 셋 이미지가 있는 디렉토리 경로 입니다.

ImageDataGenerator는 이미지의 크기가 일정하지 않을때, 이미지의 크기를 동일하게 만들어주고 여러가지 옵션의 이미지의 양을 늘려서 모델의 성능을 올려주는 역할을 합니다. 위 코드를 짧게 살펴보면 ‘shear_range’ 무작위로 기울기를 변형한 이미지를 추가하고(찌그러트림), ‘zoom_range’ 무작위 이미지를 확대하거나 축소한 이미지를, 그리고 ‘horizontal_flip’는 무작위 이미지를 좌우반전한 이미지가 전달됩니다. 그리고 ‘target_size’로 이미지의 사이즈는 150×150으로 동일하게 합니다.

‘ResNet50’라는 모델을 기본 학습 모델로 사용하고 있는데요. ‘ResNet50’는 ResNet 계열의 딥러닝 모델로 이미지 인식 및 분류 작업에 많이 사용되는 모델입니다.

그리고 ‘ResNet50’의 메커니즘이나 특징을 이해하는 건..
저의 프로젝트 의지를 현격하게 저하시킬 가능성이 농후하기 때문에 여기까지..

‘x = GlobalAveragePooling2D()(x)’
– 전역 평균 풀링 레이어를 추가하여 공간적 크기를 줄입니다.
‘x = Dense(1024, activation=’relu’)(x)’
– 1024개의 뉴런과 ReLU 활성화 함수를 가진 완전 연결 레이어를 추가합니다.
‘predictions = Dense(1, activation=’sigmoid’)(x)’
– 1개의 뉴런과 sigmoid 활성화 함수를 가진 출력 레이어를 추가합니다. 이 레이어는 이진 분류를 위해 사용됩니다.

무슨 말인지 하나도 모르겠습니다.
괜찮습니다. 차차 알아가기면 되니까요.

train_generator: 학습 데이터 생성기입니다.
validation_data=val_generator: 검증 데이터 생성기입니다.
epochs=10: 에포크 수를 10으로 설정합니다.

여기서 에포크는 학습 데이터 셋을 몇번 반복해서 학습시킬지를 나타냅니다. 예를 들어서 학습 데이터 셋이 100개고 epochs 수가 10이라면 총 1000개의 이미지를 학습합니다. 근데 이게 또 너무 많으면 훈련 데이터가 과적합해서 안좋을 수도 있어서 적당한 수치를 맞추는게 중요하다고 합니다.

이제 한번 코드를 실행해 볼까요?

학습을 하면 아래와 같이 로그가 찍히는데요.

각각 ‘accuracy’ 학습 데이터의 정확도, ‘loss’ 학습 데이터의 손실, ‘val_accuracy’ 검증 데이터의 모델 정확도, ‘val_loss’ 검증 데이터셋의 모델 손실값으로, 대략 위 데이터는 모델이 데이터셋을 잘 예측했지만, 예측은 50%에다가 검증 데이터 손실도 0.7365로 굉장히 높은데요.

이렇게 되면 검증 데이터 손실이 너무 커서 잘 맞추지 못합니다..

3. 망..

처음이라 뭐가 문제인지조차 모르지만, 아마도 데이터 셋 이미지가 너무 적어서 그런 게 아닐까 싶어요..

조금 더 테스트 해봐야 하는데, 오늘 제가 사용하고 있는 서버를 업데이트를 해줘야해서..
포스팅은 여기까지하고 내일 이어서 진행하도록 하겠습니다!

내일 이어서..