이미지 회전과 같은 무작위 변환을 적용하여 훈련 세트의 다양성을 증가시키는 기술인 데이터 증강의 예에 대해 정리하겠다.
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist
데이터셋 다운로드
(train_ds,val_ds,test_ds),metadata=tfds.load('tf_flowers',
split=['train[:80%]','train[80%:90%]','train[90%:]'],
with_info=True,
as_supervised=True)
num_classes=metadata.features['label'].num_classes
print(num_classes)
get_label_name=metadata.features['label'].int2str
image,label=next(iter(train_ds))
_=plt.imshow(image)
_=plt.title(get_label_name(label))
Keras 전처리 레이어 사용하기
- 크기 빛 배율 조정하기
IMG_SIZE=180
resize_and_rescale=tf.keras.Sequential([
layers.experimental.preprocessing.Resizing(IMG_SIZE,IMG_SIZE),
layers.experimental.preprocessing.Rescaling(1./255)
# 배율 조정 레이어는 픽셀 값을 [0,1]로 표준화한다.
# [-1,1]을 원할경우, Rescaling(1./127.5, offset=-1)을 사용하면 된다.
])
result=resize_and_rescale(image)
plt.imshow(result)
print("Min and max pixel values:", result.numpy().min(), result.numpy().max())
데이터 증강
데이터 증강에도 전처리 레이어를 사용할 수 있다. 몇개의 전처리 레이어를 만들어 동일한 이미지에 반복적으로 적용해 보겠다.
data_augmentation=tf.keras.Sequential([
layers.experimental.preprocessing.Rescaling(1./255),
layers.experimental.preprocessing.RandomFlip('horizontal_and_vertical'),
layers.experimental.preprocessing.RandomRotation(0.2)
])
image=tf.expand_dims(image,0)
# 배치 차원 추가
plt.figure(figsize=(10, 10))
for i in range(9):
augmented_image = data_augmentation(image[0])
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image)
plt.axis("off")
layers.RandomContrast,\
layers.RandomCrop,\
layers.RandomZoom 등 데이터 증강에 사용할 수 있는 다양한 전처리 레이어가 있다.
전처리 레이어를 사용하는 두 가지 옵션
옵션1: 전처리 레이어를 모델의 일부로 만들기
model=tf.keras.Sequential([
resize_and_rescale,
data_augmentation,
layers.Conv2D(16,3,padding='same',activation='relu'),
layers.MaxPool2D()
])
이 경우 유의해야 할 두 가지 중요한 사항이 있다.
1. 데이터 증강은 나머지 레이어와 동기적으로 기기에서 실행되며 GPU 가속을 이용한다.
2. model.save를 사용하여 모델을 내보낼 때 전처리 레이어가 모델의 나머지 부분과 함께 저장된다. 나중에 이 모델을 배포하면 레이어 구성에 따라 이미지가 자동으로 표준화된다.
참고: 데이터 증강은 테스트할 때 비활성화되므로 입력 이미지는 model.fit(model.evaluate 또는 model.predict가 아님) 호출 중에만 증강된다.
옵션 2: 데이터세트에 전처리 적용하기
이 접근 방식에서는 Dataset.map을 사용하여 증강 이미지 배치를 생성하는 데이터세트를 만든다.
데이터 증강은 CPU에서 비동기적으로 이루어지며 차단되지 않는다. 아래와 같이 Dataset.prefetch를 사용하여 GPU에서 모델 훈련을 데이터 전처리와 중첩할 수 있다.
이 경우, 전처리 레이어는 model.save를 호출할 때 모델과 함께 내보내지지 않는다. 저장하기 전에 이 레이어를 모델에 연결하거나 서버측에서 다시 구현해야 한다. 훈련 후, 내보내기 전에 전처리 레이어를 연결할 수 있다.
데이터세트에 전처리 레이어 적용하기
데이터 증강은 훈련 세트에만 적용해야 한다.
batch_size=32
AUTOTUNE=tf.data.experimental.AUTOTUNE
def prepare(ds,shuffle=False,augment=False):
# resize and rescale all datasets
ds=ds.map(lambda x,y: (resize_and_rescale(x),y),
num_parallel_calls=AUTOTUNE)
if shuffle:
ds=ds.shuffle(1000)
ds=ds.batch(batch_size)
# use data augmentation only on the training set
if augment:
ds=ds.map(lambda x,y:(data_augmentation(x,training=True),y),
num_parallel_calls=AUTOTUNE)
# use buffered prefecting on all datasets
return ds.prefetch(buffer_size=AUTOTUNE)
train_ds=prepare(train_ds,shuffle=True,augment=True)
val_ds=prepare(val_ds)
test_ds=prepare(test_ds)
모델 훈련하기
model = tf.keras.Sequential([
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
epochs=5
history=model.fit(train_ds,validation_data=val_ds,epochs=epochs)
참고:https://www.tensorflow.org/tutorials/images/data_augmentation?hl=ko