AI

[뛰어보자!] 이미지 분류 해보기 (개와 고양이)

brebb 2022. 8. 19. 02:08

이미지를 학습시키는 방법이 궁금해서 막 찾아보다가 개냐 고양이냐를 학습시켜서 판가름하는 모델을 보게 되었다.

결론부터 말하자면 난 무지랭이 이기 때문에 너무 신기하더라...

학습을 반복해서 시키거나 할 수록 정확도가 시각적으로 높아지는 부분이 나오는데 내가 짠 건 아니지만..ㅎㅎ
우~와! 소리가 절로 나왔다 ㅎㅎ

 


내가 참조한 내용은 아래  url 이고, tf.keras.Sequential 모델을 사용하여 이미지 분류기를 작성하고 tf.keras.preprocessing.image.ImageDataGenerator를 사용하여 데이터를 로드시켰다. 

 

https://east-rain.github.io/docs/Deep%20Learning/tensorflow%20tutorial/image_classification.html

아래 일반적인 ML 워크 플로우로 진행 되었다. 

 

1) 데이터 검사 및 이해

 

필요한 파일들을 가지고 온다. import~ 

뭘 가지고 오는지는 모르겠지만 os 패키지랑 NumPy, Tensorflow , Keras 클래스를 가지고 온다. 

 

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator

import os
import numpy as np
import matplotlib.pyplot as plt

 

다음으로 , Dogs vs Cats 데이터 세트를 다운로드 한다.  

스토리지 위치를 입력하고, 저장 경로까지 입력하니 코랩이 알아서 뭔가를 해주었다. ^^..

압축 해제를 한 후 검증 셋에 맞는 파일 경로로 변수를 지정해주었다. 

직접 스토리지 위치를 들어가보니 정말 많은 개와 고양이 이미지가 았었다. 

약 각 1000개씩 있었던 것 같다. 

 

 

2) 입력 파이프 라인 구축

위에 다운받은 이미지들을 부동 소수점 tensor로 변환을 해야 한다고 한다. 

이미지를 읽고, 내용을 RGB에 따라 적절하게 grid 형식으로 변환한다. 이후 부동 소수점 tensor로 변환시킨다. 

적힌 블로그에 의하면 신경망은 작은 입력값을 처리 하는 것을 선호해서 텐서를 0~255 사이의 값에서 0~1의 사이 값으로 재조정한다고 한다. 

 

이제 시각화 작업을 해주는데, 

검증 이미지를 불러오고 방향, 사이즈를 면적에 맞게 조정하는 작업을 해준다. 

이후 이미지가 있는지 확인을 했는데! 넘나 신기했다..

 

 

3) 모델 구축

 

모델을 생성하는 작업을 하는데, 512개의 유닛이 존재하는 fully connected layer가 가장 상단에 존재하고

활성화 함수로 relu 함수가 사용한다. 

여기서 relu  함수가 뭔지 몰라서 좀 찾아보았는데, 

 

  relu
  은닉 층으로 학습
  마지막 층이 아니면 거의 relu를 쓴다, 
  은닉층으로 역전파를 통해 좋은 성능이 나옴.
  sigmond
  이진 분류 문제
  대부분 마지막 층에서 사용되며 이진분류에서 주로 사용 된다. (ex, 일별 날씨를 보고 오늘 비와? 안와? )
  softmax
  클래스 분류 문제
  대부분 마지막 층에서 사용되며, 확률값을 활용하여 다양한 것들을 분류한다. 
  (ex. 화장품 구성 요소를 보고 크림인지, 토너인지를 구별)

 

4) 모델 훈련

모델을 요약해주고, 본격적으로 학습을 시켜준다. 

15번의 Epoch 작업을 해주었다. 오래 걸렸따....

 

history = model.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)

 

5) 모델 테스트

결과를 시각화해보았다.

 

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss=history.history['loss']
val_loss=history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

그래프가 나오니 너무 신기했다. 근데, vaildation Loss 가 처음 돌렸을 때 0.7이었고, 15번의 Epoch가 있었음에도 수치가 떨어지는 것을 볼 수 있다. 

이게 보니까 과적합이라고 한다. 학습 데이터와 검증 데이터의 정확도 차이는 과적합의 명확한 신호라고 한다. 

이렇게 과적합을 방지하는 방법들이 여러 개가 있다는데, 이 블로그에서는 데이터 보강방법, 드롭아웃 기법을 사용했다. 

 

 


6) 모델 개선 및 프로세스 반복 

 

과적합은 일반적으로 트레이닝 데이터가 부족할 때 생기는데, 데이터를 보강해서 충분한 이미지 개수로 트레이닝 데이터를 얻는다. 근데 데이터 보강은 학습 데이터에서 그럴듯하게? 보이는 이미지를 랜덤 하게 생성해내는 방법이다.

내가 참고했던 블로그의 목표는 동일한 데이터를 두 번 이상 학습하지 않는다는 것을 전제로 가지고 있다. tf.keras의 ImageDataGenerator 이 클래스를 사용하여 데이터 셋의 다양한 변화를 시도했다. 

랜덤의 수평 flip적용을 해보고, 랜덤 하게 회전도 해보고, 확대 증강도 적용하고, 앞에서 했던 방법을 모두 적용했다. 

 

 

두 번째로 사용하겠다고 했던 드롭아웃을 써보았다. 

첫 번째와 마지막 max pool 레이어에 드롭아웃을 적용한다. 드롭아웃은 각 훈련하는 Epoch동안 20%의 뉴런을 제외하고 학습을 시킨다. 이것은 트레이닝 데이터 셋에서 과적합을 방지하는데 도움을 준다고 한다. (잘 모르겠지만 해보았다. )

 

위에서 데이터 보강과 드롭아웃 작업을 해주고 난 뒤, 모델 컴파일을 해주고 다시 한번 학습을 시켜주었다. 

여기서도 꽤 시간이 걸리긴 했다. 15번의 epoch를 했기 때문이다. 

 

history = model_new.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)

 

대망의 마지막!!!!

모델 정확도를 위에서처럼 데이터로 시각화해보았다.

0.7을 웃돌았던 부분은 현저하게 아래로 훅 떨어진 것을 볼 수 있다. 그리고 Accuracy부분도 현저히 올라간 것을 볼 수 있다. 

 

 

 

지금은 걸음마도 안 뗀 애기중 애기인 것 같지만,

모방은 창조의 어머니라는 믿음을 가지고 하나하나 모방을 해보고 유레카를 외칠 것이다!