이전 내용 확인
- 이번 글에서는 이전 블로그에 이어 훈련데이터가 적어 과대적합이 발생하는 문제를 해결하기 위해 데이터 증식에 대해 다뤄보고자 합니다.
- 첫번째 글 : https://ls-alt.tistory.com/28
교재 홍보
- 다음의 교재의 내용을 참고하였습니다.
- 교재 구매 : https://www.yes24.com/Product/Goods/112012471
케라스 창시자에게 배우는 딥러닝 개정 2판 - 예스24
단어 하나, 코드 한 줄 버릴 것이 없다!단 한 권의 딥러닝 책을 선택한다면 바로 이 책이다!케라스 창시자이자 구글 딥러닝 연구원인 저자는 ‘인공 지능의 민주화’를 강조한다. 이 책 역시 많
www.yes24.com
1. 데이터 증식 층 정의
- 훈련 데이터가 부족하기 때문에 이를 해결하기 위해 이미지에 여러 가지 랜덤한 변환을 적용하여 샘플을 늘려주는 데이터 증식 층을 정의합니다. 이 층은 후에 컨브넷 모델을 생성할 때 적용될 것입니다.
data_augmentation = keras.Sequential([
layers.RandomFlip('horizontal'), # 랜덤하게 이미지를 수평으로 뒤집는다.
layers.RandomRotation(0.1), # +-10% 범위에서 랜덤하게 이미지를 회전합니다.
layers.RandomZoom(0.2) # 20% 범위에서 랜덤하게 이미지를 확대 또는 축소합니다.
])
2. 증식 층에 이미지 넣기
- 정의한 증식 층에 이미지를 넣으면 아래처럼 하나의 이미지가 랜덤하게 변환된 것을 볼 수 있습니다.
plt.figure(figsize=(10, 10))
for images, _ in train_dataset.take(1): # 훈련 Dataset 객체에서 take(1)을 사용하여 1개의 배치를 샘플링합니다.
for i in range(9):
augmented_images = data_augmentation(images) # 증식층에 1개의 배치 이미지를 넣어 변환된 이미지를 얻습니다.
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_images[0].numpy().astype("uint8"))
plt.axis("off")

3. 모델 생성
- 앞에서 말한대로 데이터 증식 층을 적용한 모델을 생성하겠습니다.
- 이때, 데이터 증식은 기존 데이터의 재조합이기 때문에 과대적합을 제거하기 충분하지 않을 수도 있으므로 Dropuout층을 통해 신경망 내의 뉴런 연결을 임시로 끊음으로써 과대적합을 억제하는 데 기여하도록 하겠습니다.
inputs = keras.Input(shape=(180, 180, 3)) # 입력층
x = data_augmentation(inputs) # 데이터 증식 단계 통과
x = layers.Rescaling(1./255)(x) # 이미지 [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)
x = layers.Dropout(0.5)(x) # 드롭아웃을 적용하면 과대적합이 덜 일어난다.
# 출력층
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss="binary_crossentropy",
optimizer="rmsprop",
metrics=["accuracy"])
4. 모델 훈련
- 과대적합이 늦게 나타날 것이기 때문에 에포크 수를 늘려 모델을 훈련합니다.
- 모델 평가에서 데이터 증식과 Dropout은 없는 것처럼 취급됩니다.
callbacks = [
keras.callbacks.ModelCheckpoint(
filepath="convnet_from_scratch_with_augmentation.keras",
save_best_only=True,
monitor="val_loss")
]
history = model.fit(
train_dataset,
epochs=100,
validation_data=validation_dataset,
callbacks=callbacks)
5. 손실과 정확도 그래프
- vis함수를 이용해 그래프를 그려줍니다.
- 결과를 보면 이전과 달리 데이터 증식과 드롭아웃의 영향으로 이전(10epochs)보다 과대적합이 훨씬 늦은 60~70번째 에포크에서 발생함을 볼 수 있습니다.
vis(history)

6. 모델 평가
- callback을 통해 저장된 파일에서 모델을 로드하고 테스트 데이터셋으로 모델을 평가합니다.
- 아래와 같이 정확도 또한 79.4%로 이전(69.5) 보다 더 개선된 정확도를 보이고 있습니다.
- 하지만 데이터셋의 크기 자체가 작아 정확도 개선에 한계가 있으므로, 다음 글에서는 사전훈련된 모델로 정확도를 높이는 과정을 살펴보겠습니다.
test_model = keras.models.load_model("convnet_from_scratch_with_augmentation.keras") # callback을 통해 저장했던 모델을 불러옵니다.
test_loss, test_acc = test_model.evaluate(test_dataset)
print(f"테스트 정확도: {test_acc:.3f}")

'DeepLearning' 카테고리의 다른 글
| CNN_데이터 증식 (0) | 2023.09.01 |
|---|---|
| CNN_사전훈련된 모델 (0) | 2023.08.31 |
| CNN_강아지 vs 고양이 (0) | 2023.08.30 |
| CNN_MNIST (0) | 2023.08.29 |
| 다중 분류 모델_Reuter (0) | 2023.08.29 |
