[1] data download and data load
import requests
url = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
file_name = 'cats_and_dogs_filtered.zip'
response = requests.get(url)
with open(file_name, 'wb') as f:
f.write(response.content)
print('다운로드 완료')
import zipfile
# Unzip the archive
local_zip = './cats_and_dogs_filtered.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall()
zip_ref.close()
이 노트북에서 나중에 데이터 증강을 사용할 때 새 모델을 쉽게 초기화할 수 있도록 모델 생성을 함수 내부에 배치한다.
import os
base_dir = 'cats_and_dogs_filtered'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
# Directory with training cat pictures
train_cats_dir = os.path.join(train_dir, 'cats')
# Directory with training dog pictures
train_dogs_dir = os.path.join(train_dir, 'dogs')
# Directory with validation cat pictures
validation_cats_dir = os.path.join(validation_dir, 'cats')
# Directory with validation dog pictures
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
print(train_cats_dir)
print(train_dogs_dir)
print(validation_cats_dir)
print(validation_dogs_dir)
# output
cats_and_dogs_filtered/train/cats
cats_and_dogs_filtered/train/dogs
cats_and_dogs_filtered/validation/cats
cats_and_dogs_filtered/validation/dogs
[2] ImageDataGenerator
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale= 1./255)
test_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = train_datagen.flow_from_directory(
train_dir,
batch_size=20,
class_mode = 'binary',
target_size=(150,150),
)
validation_generator = test_datagen.flow_from_directory(
validation_dir,
batch_size=20,
class_mode = 'binary',
target_size=(150,150),
)
# output
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
[3] model build & model compile & training
import tensorflow as tf
def create_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3,3), input_shape=(150,150,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(
loss = 'binary_crossentropy',
optimizer= tf.keras.optimizers.RMSprop(learning_rate=0.001),
metrics=['accuracy'],
)
return model
EPOCH = 20
model = create_model()
history = model.fit(train_generator,
steps_per_epoch = 100, # 2,000 images = batch_size * steps
epochs =20,
validation_data = validation_generator,
validation_steps=50, # 1,000 images = batch_size * steps
verbose= 2)
[3] acc, loss visualization
[4] Data augmentation
과적합을 방지하는 간단한 방법 중 하나는 이미지를 약간 늘리는 것입니다. 생각해 보면 대부분의 고양이 사진은 매우 비슷합니다. 귀가 맨 위에 있고 그 다음은 눈, 그 다음은 입 등입니다. 눈과 귀 사이의 거리와 같은 것들도 항상 상당히 유사합니다.
이미지를 약간 조정하면 어떻게 될까요? 이미지 회전, 스쿼시 등이 바로 이미지 확대의 전부입니다. 그리고 이를 쉽게 만들어주는 API가 있습니다!
이미지 크기를 조정하는 데 사용한 ImageDataGenerator를 살펴보세요. 이미지를 확대하는 데 사용할 수 있는 다른 속성이 있습니다.
train_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
rotation_range
는 그림을 무작위로 회전하는 각도(0~180) 값width_shift
및 height_shift
는 그림을 수직 또는 수평으로 무작위로 이동하는 범위(전체 너비 또는 높이의 일부)shear_range
는 전단 변환을 무작위로 적용하기 위한 것zoom_range
는 사진 내부를 무작위로 확대/축소하는 데 사용horizontal_flip
은 이미지의 절반을 수평으로 무작위로 뒤집는 것.fill_mode
는 회전 또는 너비/높이 이동 후에 나타날 수 있는 새로 생성된 픽셀을 채우는 데 사용되는 전략[5] 모델 재학습
model_for_aug = create_model()
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest'
)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_dir,
batch_size=20,
target_size=(150,150),
class_mode='binary'
)
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary'
)
history_with_aug = model_for_aug.fit(
train_generator,
steps_per_epoch=100,
validation_data = validation_generator,
validation_steps= 50,
verbose=2
)
[6] 모델 재평가
EPOCHS = 20
# Create new model
model_for_aug = create_model()
# This code has changed. Now instead of the ImageGenerator just rescaling
# the image, we also rotate and do other operations
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255)
# Flow training images in batches of 20 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
train_dir, # This is the source directory for training images
target_size=(150, 150), # All images will be resized to 150x150
batch_size=20,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')
# Flow validation images in batches of 20 using test_datagen generator
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
# Train the new model
history_with_aug = model_for_aug.fit(
train_generator,
steps_per_epoch=100, # 2000 images = batch_size * steps
epochs=EPOCHS,
validation_data=validation_generator,
validation_steps=50, # 1000 images = batch_size * steps
verbose=2)
여기서는 과적합을 방지하는 간단한 방법인 데이터 증강을 사용했다.
이미 가지고 있는 동일한 이미지를 간단히 조정하여 기본 결과를 향상시킬 수 있다. ImageDataGenerator 클래스에는 이를 수행하기 위한 기본 제공 매개변수가 있는데, train_datagen에서 값을 좀 더 수정해 보고 어떤 결과가 나오는지 확인해보자.
이러한 경우는 모든 경우에 적용되는 것은 아니다. 다음 장에서는 데이터 증강이 검증 정확도를 향상시키는 데 도움이 되지 않는 시나리오가 나오게 된다.