๐ Image Augmentation
์ด๋ฏธ์ง ์ฆ๊ฐ : ํ์ , ๋ฐ์ , ์๋ฅด๊ธฐ, ๋ฐ๊ธฐ ํน์ ์ฑ๋ ๋ณํ ๋ฑ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ๋๋ฆฌ๋ ๋ฐฉ๋ฒ
๋๋ถ๋ถ ์ ๋ฉด ๋ฐ์ดํฐ๋ฅผ ํ์ตํ๊ธฐ ๋๋ฌธ์, ํ๋จํด์ผํ๋ ๋ฌผ์ฒด๊ฐ ๊ธฐ์ธ์ด์ ธ ์๊ฑฐ๋ ๋ค์ง์ด์ง ์ด๋ฏธ์ง๋ฅผ ์ ์์ธกํ์ง ๋ชปํ๋ค๋ ์ทจ์ฝ์ ์ ๊ฐ์ง๊ณ ์๋ค. ๋ฐ๋ผ์, ์ผ๋ฐํ๊ฐ ์ ๋๋ ๋ชจ๋ธ์ ๋ง๋ค๊ธฐ ์ํด ํ์ต ๋ฐ์ดํฐ์ ์ ์๋ ์ด๋ฏธ์ง๋ฅผ ์ผ๋ถ๋ฌ ํ์ ํ๊ฑฐ๋ ๊ธฐ์ธ์ฌ์ ๋ํ๋ด๋ ๋ฐฉ๋ฒ์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ์ฆ๊ฐ์ด๋ผ๊ณ ํ๋ค. ์ด๋ฅผ ํตํด ๋์ฑ ๊ฐ๊ฑด(Robust)ํ ๋ชจ๋ธ์ ๋ง๋ค ์ ์๋ค.
๊ณผ๋์ ํฉ์ ์ผ๋ฐ์ ์ผ๋ก ํ๋ จ ๋ฐ์ดํฐ์ ์ด ์ ์ ๋ ๋ฐ์ํ๋ค. ๋ฐ์ดํฐ ์ฆ๊ฐ์ ํตํด ๋ชจ๋ธ์ด ๋ฐ์ดํฐ์ ๋ ๋ง์ ์ธก๋ฉด์ ํ์ ํ๊ฒ ๋๋ฏ๋ก ์ผ๋ฐํ๊ฐ ๋ ์ฝ๋ค!!!!!
tf_flowers ๋ฐ์ดํฐ์ ์ฌ์ฉํ๊ธฐ
import tensorflow_datasets as tfds
(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)
# train_ds์์ ๊ฐ์ ธ์จ ์ด๋ฏธ์ง, ๋ ์ด๋ธ ์๊ฐ
get_label_name = metadata.features['label'].int2str # label์ ์ซ์์์ ๋ฌธ์๋ก ๋ณํ
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
ํฌ๊ธฐ ๋ฐ ๋ฐฐ์จ ์กฐ์ ํ๊ธฐ
IMG_SIZE = 180
resized_and_rescale = tf.keras.Sequential([
layers.experimental.preprocessing.Resizing(IMG_SIZE, IMG_SIZE), # ํฌ๊ธฐ ์กฐ์
layers.experimental.preprocessing.Rescaling(1./255)]) # ํฝ์
๊ฐ ๋ฐฐ์จ ์กฐ์ : [0,1]๋ก ํ์คํ
cf) ํฝ์ ๊ฐ์ [-1,1]๋ก ํ์คํ๋ฅผ ์ํ ๊ฒฝ์ฐ, Rescaling(1./127.5, offset=-1)
์ด๋ฌํ layer์ ์ฉํ ์ด๋ฏธ์ง ์ ์ฉ ๊ฒฐ๊ณผ๋ณด๊ธฐ
result = resized_and_rescale(image)
print(result.numpy().min(), result.numpy().max())
>> 0.0 1.0 # ํฝ์
0~1 ํ์ธ
_ = plt.imshow(result)
๋ฐ์ดํฐ ์ฆ๊ฐ
data_augmentation = tf.keres.Sequential([
layers.experimental.preprocessing.RandomFlip('horizontal_and_vertical'),
layers.experimental.preprocessing.RandomRotation(0.2)])
# flip : ์ข์ฐ๋ฐ์ or ์ํ ๋ฐ์
# 0.2๊ฐ๋๋ก ๋ฌด์์๋ก ํ์
# ์ด๋ฏธ์ง์ ๋ฐฐ์น ์ฐจ์ ์ถ๊ฐ
image = tf.expand_dims(image, 0)
tensorflow๋ชจ๋ธ์ ๊ธฐ๋ณธ์ ์ผ๋ก batch๋จ์๋ก ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ค. ๋ฐ๋ผ์ ๋ชจ๋ธ์ ์ฌ๋ฌ ์ด๋ฏธ์ง๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ ค๋ฉด, ์ด๋ฏธ์ง๋ฅผ ๋ฐฐ์น ํํ๋ก ๋ณํํด์ผํ๋ค. tf.expand_dims๋ฅผ ์ฌ์ฉํด ์ด๋ฏธ์ง์ ๋ฐฐ์น ์ฐจ์์ ์ถ๊ฐํ๋ฉด, ํ ๋ฒ์ ์ฌ๋ฌ ์ด๋ฏธ์ง๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ํํ๊ฐ ๋๋ค. ์์ ์ฝ๋๋ 0์ผ๋ก ์ฒซ๋ฒ์งธ ์ฐจ์์ด ์ถ๊ฐ ๋๋ค๋ ๊ฒ์ด๋ค.(๋์ด, ๋๋น, ์ฑ๋) → (batch_size, ๋์ด, ๋๋น, ์ฑ๋)
๋ฐฐ์น ์ฐจ์ : ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฐจ์์ผ๋ก ์ฌ์ฉ๋๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก ๋ฐฐ์น ํฌ๊ธฐ๋ฅผ ๋ํ๋ธ๋ค.
๋ฐ์ดํฐ ์ฆ๊ฐ ์ ์ฒ๋ฆฌ ๋ ์ด์ด ์ฌ์ฉํ ์ด๋ฏธ์ง ์๊ฐํ
plt.figure(figsize=(10,10))
for i in range(9):
augmented_image = data_augmentation(image)
ax = plt.subplot(3,3, i+1)
plt.imshow(augmented_image[0]) # ๋ฐ์ดํฐ ์ฆ๊ฐ๊ณผ์ ์์ ๋๋ค์ฑ ์ ์ฉ๋ผ ๋งค ๋ฐ๋ณต๋ง๋ค ๋ค๋ฅธ ๊ฒฐ๊ณผ
plt.axis('off')
์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ์ฌ์ฉํ๋ ๋ ๊ฐ์ง ์ต์
์ฐธ๊ณ ) ๋ฐ์ดํฐ ์ฆ๊ฐ์ ํ๋ จ ์ธํธ์๋ง ์ ์ฉ!!!!!!!!!
- ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ๋ชจ๋ธ์ ์ผ๋ถ๋ก ๋ง๋ค๊ธฐ
model = tf.keras.Sequential([
resize_and_rescale,
data_augmentation,
layers.Conv2D(16,3, padding='same', activation='relu',
layers.MaxPooling2D()])
์ ์์ฌํญ
- ๋ฐ์ดํฐ ์ฆ๊ฐ์ ๋๋จธ์ง ๋ ์ด์ด์ ๋๊ธฐ์ ์ผ๋ก ๊ธฐ๊ธฐ์์ ์คํ๋๋ฉฐ GPU ๊ฐ์ ์ด์ฉ
- model.save๋ฅผ ์ฌ์ฉํด ๋ชจ๋ธ์ ๋ด๋ณด๋ผ ๋ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๊ฐ ๋ชจ๋ธ์ ๋๋จธ์ง ๋ถ๋ถ๊ณผ ํจ๊ป ์ ์ฅ๋จ. ๋์ค์ ์ด ๋ชจ๋ธ ๋ฐฐํฌ ์, ๋ ์ด์ด ๊ตฌ์ฑ์ ๋ฐ๋ผ ์ด๋ฏธ์ง๊ฐ ์๋์ผ๋ก ํ์คํ๋์ด ๋ค์ ๊ตฌํํด์ผ๋๋ ๋ ธ๋ ฅ์ ๋ ์ ์๋ค.
- ๋ฐ์ดํฐ ์ฆ๊ฐ์ ํ ์คํธํ ๋๋ ๋นํ์ฑํ (model.evalute, predict์ x) (model.fitํ ๋๋ง ๋ฐ์ดํฐ ์ฆ๊ฐ๋จ.)
- ๋ฐ์ดํฐ์ธํธ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด ์ ์ฉํ๊ธฐ
aug_ds = train_ds.map(lambda x,y : (resize_and_rescale(x, training=True), y))
์ ์์ฌํญ
- ๋ฐ์ดํฐ ์ฆ๊ฐ์ CPU์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฉฐ ์ฐจ๋จ๋์ง ์๋๋ค. ์๋์ ๊ฐ์ด Dataset.prefetch๋ฅผ ์ฌ์ฉํด GPU์์ ๋ชจ๋ธ ํ๋ จ์ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ์ ์ค์ฒฉ์ํฌ ์ ์๋ค.
- ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ model.save๋ฅผ ํธ์ถํ ๋ ๋ชจ๋ธ๊ณผ ํจ๊ป ๋ด๋ณด๋ด์ง์ง ์๋๋ค. ์ ์ฅํ๊ธฐ ์ ์ ์ด ๋ ์ด์ด๋ฅผ ์ฐ๊ฒฐํ๊ฑฐ๋, ์๋ฒ์ธก์์ ๋ค์ ๊ตฌํํด์ผ๋จ. ํ๋ จ ํ, ๋ด๋ณด๋ด๊ธฐ ์ ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด ์ฐ๊ฒฐ ๊ฐ๋ฅ
์ด ๋๋ฒ์งธ ๋ฐฉ๋ฒ์ธ, ๋ฐ์ดํฐ์ธํธ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ํด๋ณด์. ๋ํ ๋ณ๋ ฌ ์ฝ๊ธฐ ๋ฐ ๋ฒํผ๋ง๋ ํ๋ฆฌํ์น๋ฅผ ์ฌ์ฉํด I/O ์ฐจ๋จ ์์ด ๋์คํฌ์์ ๋ฐฐ์น๋ฅผ ์์ฑํด ์ฑ๋ฅ์ ๋์ด๋๋ก ๋ฐ์ดํธ์ ์ ๊ตฌ์ฑํด๋ณด์.
์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ์ ์ ์ฑ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ณ ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์์ ๋ฐ์ํ๋ I/O ์์ , CPU/GPU ์์ ์ ์ํด ์ ํ๋๋ค.
- AUTOTUNE : ๋ฐ์ดํฐ์ ์ฒ๋ฆฌํ๋ ๋์ CPU ๋ฐ GPU ์์์ ์ต๋ํ ๋์์ ํ์ฉํด ์ฒ๋ฆฌ ์๋ ํฅ์
- ๋ฒํผ ํฌ๊ธฐ : ๋ฐ์ดํฐ์ ์ ์ฒ๋ฆฌํ ๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ๋ ๋ฐ์ดํฐ์ ์์ด๋ค. ๋ฐ์ดํฐ์ ์ ์ผ๋ฐ์ ์ผ๋ก ํ ๋ฒ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ์ง ์๊ณ , ์ผ๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๊ณ ์ฒ๋ฆฌํ๋ค. ๋ฒํผ ํฌ๊ธฐ๊ฐ ํฌ๋ฉด ํ ๋ฒ์ ๋ ๋ง์ ๋ฐ์ดํฐ๊ฐ ๋ก๋๋ ๊ฒ์ด๋ฉฐ, ์์ผ๋ฉด ๋ก๋๋๋ ๋ฐ ๋ฐ์ดํฐ ์์ด ์ค์ด๋ค๊ฒ ์ง.
batch_size = 32
AUTOTUNE = tf.data.experimental.AUTOTUNE # ๋ฐ์ดํฐ์
์ฑ๋ฅํฅ์
def prepare(ds, shuffle=False, augment=False):
# ์ด๋ฏธ์ง ํฌ๊ธฐ ์กฐ์ , ํฝ์
๊ฐ ์ ๊ทํ
ds = ds.map(lambda x, y: (resize_and_recale(x), y), num_parallel_calls=AUTOTUNE)
if shuffle:
ds = ds.shuffle(1000)
# ๋ฐ์ดํฐ์
์ ๋ฐฐ์น๋ก ๋๋์ด ์ค๋น (batch_size:ํ๋ฒ์ ์ฒ๋ฆฌ๋๋ ๋ฐ์ดํฐ ๊ฐ์)
ds = ds.batch(batch_size)
# ํ๋ จ๋ฐ์ดํฐ์
์๋ง ๋ฐ์ดํฐ ์ฆ๊ฐ ์ ์ฉ
if augment:
ds = ds.map(lambda x,y : (data_augmentation(x, training=True),y), num_parallel_calls=AUTOTUNE)
# training=True : ๋ฐ์ดํฐ ์ฆ๊ฐ์ด ํ๋ จ ๋ชจ๋์์ ์ํ๋จ.
return ds.prefetch(buffer_size=AUTOTUNE)
# 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', activaiton='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128. acitvation='relu')
layers.Dense(num_classes)])
model.compile(optimizer='adam',
loss=tf.keras.SparseCategoricalCrossEntropy(from_logits=True),
metrics=['accuracy'])
# from_logits=True : softmaxํจ์ ์ ์ฉ ์ ์ ๋ก์ง ๊ฐ์ ์ฌ์ฉํด ์์ค ๊ณ์ฐํ๋ค.
# ์ด๋ ์์ค ํจ์ ๋ด๋ถ์์ softmax ์ ์ฉ๊ณผ์ ์ ์๋ตํ์ฌ ๊ณ์ฐ ํจ์จ์ฑ์ ๋์ธ๋ค.
history = model.fit(train_ds, validation_data=val_ds, epochs=5)
loss, acc = model.evaluate(test_ds)
์ฌ์ฉ์ ์ ์ ๋ฐ์ดํฐ ์ฆ๊ฐ
- layers.Lambda ๋ ์ด์ด ์ด์ฉ
์๋ ์ฐ๋ lambda ํจ์๋ฅผ ์ธต์ ์ ์ฉ์ํจ ๊ฒ์ด๋ค.
# ๋ฌด์์๋ก ๋ฐ์ ํจ๊ณผ ์ ์ฉํ๋ ํจ์๋ฅผ ์ ์ฉ์ํค์.
def random_invert_img(x, p=0.5):
if tf.random.uniform([])<p: # p: ๋ฐ์ ํ๋ฅ
x = (255-x)
else: x
return x
def random_invert(factor=0.5):
return layers.Lambda(lambda x: random_invert_img(x, factor))
random_invert = random_invert()
plt.figure(figsize=(10,10))
for i in range(9):
augemented_image = random_invert(image)
ax = plt.subplot(3,3, i+1)
plt.imshow(augmented_image[0].numpy().astype('uint8'))
# tensorํํ๋ก ์ ์ฅ๋์ด์์ด numpy array๋ก ๋ณํํ, ํฝ์
๊ฐ์ ๋ฐ์ดํฐํ์
์ 8๋นํธ ๋ถํธ์๋ ์ ์๋ก ๋ณํ
plt.axis('off')
- ์๋ธ ํด๋์ค ์์ฑ ์ด์ฉ
class RandomInvert(layers.Layer):
def __init__(self, factor=0.5, **kwargs):
super().__init__(**kwargs)
self.factor = factor
def call(self, x):
return random_invert_img(x)
tf.image ์ฌ์ฉํ๊ธฐ
์์ layers.preprocessing ์ ํธ๋ฆฌํฐ๋ ํธ๋ฆฌํ๋ค. ๋ณด๋ค ์ธ๋ฐํ ์ ์ด๋ฅผ ์ํด์๋ tf.data ๋ฐ tf.image๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ ์ฆ๊ฐ ํ์ดํ๋ผ์ธ ๋๋ ๋ ์ด์ด๋ฅผ ์์ฑํ ์ ์๋ค.
# ์ด๋ฏธ์ง ๋ค์ง๊ธฐ (์์ง ๋๋ ์ํ์ผ๋ก)
tf.image.flip_left_right(image)
# ์ด๋ฏธ์ง ํ์์กฐ๋ก ๋ง๋ค๊ธฐ
tf.image.rgb_to_grayscale(image)
# ์ฑ๋ ๊ณ์๋ฅผ ์ฃผ์ด ์ด๋ฏธ์ง ํฌํ์ํด.(์์ ๊ฐ์กฐํด ๋ ์ ๋ช
ํ๊ฒ ํํ)
tf.image.adjust_saturation(image, 3)
# ์ด๋ฏธ์ง ๋ฐ๊ธฐ ๋ณ๊ฒฝ
tf.image.adjust_brightness(image, 0.4)
# ์ด๋ฏธ์ง ์ค์ ์๋ฅด๊ธฐ
tf.image.central_crop(image, central_fraction=0.5)
# ์ด๋ฏธ์ง ํ์ ํ๊ธฐ
tf.image.rot90(image)
์ด๋ฌํ ๋ฐฉ๋ฒ๋ค์ด ์๋ค.
์ต์ข ์ ์ผ๋ก ์ ๋ฆฌ
def resize_and_rescale(image, label):
image = tf.cast(image, tf.float32) # ๋ฐ์ดํฐ ํ์
๋ณํ
image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])
image = (image/255.0)
return image, label
def augment(image, label):
image, label = resize_and_rescale(image, label)
image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE+6, IMG_SIZE+6)
image = tf.image.random_crop(image, size=[IMG_SIZE, IMG_SIZE,3])
image = tf.image.random_brightness(image, max_delta=0.5)
image = tf.clip_by_value(image,0,1)
return image, label
train_ds = (train_ds.shuffle(1000).map(augment, num_parallel_calls=AUTOTUNE).batch(batch_size).prefetch(AUTOTUNE))
# val_ds, test_ds๋ ๋๊ฐ์ด ํ์ฌ ๋ชจ๋ธ ํ
TensorFlow ์ ๋์จ ์ด๋ฏธ์ง: ์์ ๋ฐ TensorFlow I/O: ์ ๊ณต๊ฐ ๋ณํ
tf.data API๋ก ์ฑ๋ฅ ํฅ์ํ๊ธฐ (๋ฐ์ดํฐ์ธํธ ์ฑ๋ฅ ๊ด๋ จ)
'Machine Learning' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CV 4] Object Detection Model - YOLO (0) | 2023.05.07 |
---|---|
[CV 3] Beyond Classification - Segmentation, Object Dectection (0) | 2023.05.07 |
[CV] CNN, Tranfer Learning (0) | 2023.05.07 |
[Neural Networks 4] Hyperparameter Tuning (0) | 2023.04.24 |
[Neural Networks 3] ๋ ๋์ ์ ๊ฒฝ๋ง ํ์ต์ ์ํ ๋ฐฉ๋ฒ (0) | 2023.04.24 |