- 이번 글에서는 소규모의 강아지, 고양이 이미지 데이터셋으로 컨브넷을 훈련하는 실습을 진행해보겠습니다.
교재 홍보
- 다음의 교재의 내용을 참고하였습니다.
- 교재 구매 : https://www.yes24.com/Product/Goods/112012471
케라스 창시자에게 배우는 딥러닝 개정 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 |
