데이터 분석가
article thumbnail
Published 2023. 8. 30. 18:47
CNN_강아지 vs 고양이 DeepLearning
  • 이번 글에서는 소규모의 강아지, 고양이 이미지 데이터셋으로 컨브넷을 훈련하는 실습을 진행해보겠습니다.

교재 홍보

 

케라스 창시자에게 배우는 딥러닝 개정 2판 - 예스24

단어 하나, 코드 한 줄 버릴 것이 없다!단 한 권의 딥러닝 책을 선택한다면 바로 이 책이다!케라스 창시자이자 구글 딥러닝 연구원인 저자는 ‘인공 지능의 민주화’를 강조한다. 이 책 역시 많

www.yes24.com

데이터 생성

  • 먼저 캐글에서 데이터를 내려받기 위해 캐글웹사이트에 로그인하여 Account 페이지로 이동하고, 페이지에서 API섹션을 찾아 API 인증키를 로컬에 다운받아줍니다.
  • 그 후 아래의 코드를 실행해 다운받은 로컬파일을 업로드해줍니다.
from google.colab import files
files.upload()
  • 아래의 코드를 실행해 데이터를 내려받습니다.
  • 폴더를 만들어 API 인증키를 복사해서 보관하고 보안을 유지합니다.
# 폴더를 만들어 API 인증키를 복사해서 보관하고 보안을 유지
!mkdir ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json

# 데이터 다운로드
!kaggle competitions download -c dogs-vs-cats

!unzip -qq dogs-vs-cats.zip
!unzip -qq train.zip

데이터 분할

  • 이미지 데이터를 훈련, 검증, 테스트 데이터로 분할해줍니다.

모델 생성

  • MNIST예제에서 활용했던 모델 구조를 활용하여 모델을 만들겠습니다.
  • 차이점은 이전보다 이미지가 크고 복잡하기 때문에 Conv2D와 MaxPooling2D 단계를 하나씩 추가해주고, 리스케일링 층이 추가됐다는 점과 활성화 함수의 변화입니다.
from tensorflow import keras
from tensorflow.keras import layers

inputs = keras.Input(shape=(180, 180, 3)) # 180 * 180 크기의 RGB 이미지를 기대한다.
x = layers.Rescaling(1./255)(inputs) # [9, 255]범위의 이미지를 [0, 1]범위로 스케일을 조정한다.
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(1, activation="sigmoid")(x) # 이진분류 문제이므로 sigmoid 사용
model = keras.Model(inputs=inputs, outputs=outputs)
  • 모델을 컴파일 해줍니다.

데이터 전처리

  • 모델에 데이터를 입력하기 전에 부동 소수점 타입의 텐서로 전처리해줍니다. 현재 이미지가 JPEG파일로 되어 있으므로 다음의 과정을 거쳐야 합니다.
    • 사진 파일을 픽셀값으로 디코딩 -> 부동 소수점 타입의 텐서로 변환 -> 동일한 이미지 크기로 변환 -> 배치로 묶기(32개)
  • 이러한 복잡한 과정을 케라스의 image\_dataset\_from\_directory() 함수를 사용해 해결하겠습니다. 이 함수로 디스크의 이미지 파일을 자동으로 전처리된 텐서의 배치로 변환하는 데이터 파이프라인을 빠르게 구성 가능합니다.
from tensorflow.keras.utils import image_dataset_from_directory

new_base_dir = pathlib.Path('cats_vs_dogs_small')

# image_dataset_from_directory(directory)를 호출하면 지정된 경로의 서브디렉터리에 있는 각 이미지 파일을
# 인덱싱 -> 파일 읽기 -> 순서 섞기 -> 텐서로 디코딩 -> 동일 크기로 변환 -> 배치로 묶기의 과정을 거쳐 tf.Data.Dataset 객체를 만들어 반환
train_dataset = image_dataset_from_directory(
    new_base_dir / 'train', # 사전에 make_subset을 통해 디렉토리에 복사해둔 훈련데이터를 가져옴
    image_size=(180, 180),
    batch_size = 32
)

validation_dataset = image_dataset_from_directory(
    new_base_dir / 'validation',
    image_size=(180, 180),
    batch_size = 32
)

test_dataset = image_dataset_from_directory(
    new_base_dir / 'test',
    image_size=(180, 180),
    batch_size = 32
)
  • 아래의 코드로 Dataset 객체가 반환하는 데이터 및 레이블의 크기를 확인 가능합니다.
for data_batch, labels_batch in train_dataset:
  print('데이터 배치 크기:', data_batch.shape)
  print('레이블 배치 크기:', labels_batch.shape)
  break

모델 훈련

  • 이제 기존의 데이터를 전처리하여 만든 Dataset객체로 모델을 훈련하고 검증도 같이 진행해 보도록 하겠습니다.
  • callbacks를 통해 검증 데이터의 성능이 가장 좋은 에포크의 모델을 저장하므로, 과적합이 시작되는 에포크로 모델을 새로 훈련할 필요없이 저장된 모델을 바로 불러오면 된다.

손실과 정확도 그래프

  • history 객체를 불러와 훈련과 검증 데이터에 대한 손실과 정확도 그래프를 그려주는 vis함수를 이용해 그래프를 그려줍니다.
  • 그래프를 보면 대략 10번째 에포크 쯤에서 검증 정확도에 비해 훈련 정확도가 계속 높아져 과적합을 보임을 알 수 있고, 마찬가지로 검증 손실에 비해 훈련 손실은 계속해서 감소함을 확인할 수 있다.
def vis(history):
  history_dict = history.history
  loss_values = history_dict["loss"]
  val_loss_values = history_dict["val_loss"]
  acc = history_dict["accuracy"]
  val_acc = history_dict["val_accuracy"]
  epochs = range(1, len(loss_values) + 1)

  figure, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (15, 8))

  ax[0].plot(epochs, loss_values, "bo", label="Training loss")
  ax[0].plot(epochs, val_loss_values, "b", label="Validation loss")
  ax[0].set_title("Training and validation loss")
  ax[0].set_xlabel("Epochs")
  ax[0].set_ylabel("Loss")
  ax[0].legend()

  ax[1].plot(epochs, acc, "bo", label="Training acc")
  ax[1].plot(epochs, val_acc, "b", label="Validation acc")
  ax[1].set_title("Training and validation accuracy")
  ax[1].set_xlabel("Epochs")
  ax[1].set_ylabel("Accuracy")
  ax[1].legend()

  plt.show()

 vis(history)

모델 평가

  • 테스트 Dataset 객체로 모델을 평가해보자.
  • 과대적합 전의 상태를 평가하기 위해 callback을 통해 저장된 파일에서 모델을 로드합니다.
  • 아래와 같이 69.5%의 정확도를 보이는데 훈련 샘플의 개수가 2000개로 적기 때문에 과대적합을 해결해 정확도를 개선해야 하고, 이를 위한 방법으로 다음 시간에 데이터 증식과 사전 훈련된 모델을 활용해 보겠습니다.
test_model = keras.models.load_model("convnet_from_scratch.keras")
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"테스트 정확도: {test_acc:.3f}")

'DeepLearning' 카테고리의 다른 글

CNN_사전훈련된 모델  (0) 2023.08.31
CNN_데이터 증식  (0) 2023.08.30
CNN_MNIST  (0) 2023.08.29
다중 분류 모델_Reuter  (0) 2023.08.29
이진 분류 모델_IMDB데이터  (0) 2023.08.28
profile

데이터 분석가

@이꾹꾹

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!