๐ ํ์ต๋ชฉํ
*transposed convolutional layer
๋ถํ (segmentation)
๋ถํ ์ด๋ ์ด๋ฏธ์ง๋ฅผ ํฝ์ ์์ค์์ ๋ถ๋ฅํ๋ ๋ฌธ์ ์ด๋ค.
์ ๊ฒฝ๋ง์ ์ด์ฉํด ๋ถํ ํ๋ ๊ฐ์ฅ ๋จ์ํ ๋ฐฉ๋ฒ์ ๋ชจ๋ ํฝ์ ๊ฐ๊ฐ์ ์ถ๋ก ํ๋ ๊ฒ์ด๋ค. ( ) ๊ทธ๋ฌ๋ ์ด๋ฌํ ์์ผ๋ก๋ ํฝ์ ์๋งํผ forward ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ์ฌ ๊ธด ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค. (์ ํํ๋ ํฉ์ฑ๊ณฑ ์ฐ์ฐ์์ ๋ง์ ์์ญ์ ์ธ๋ฐ์์ด ๋ค์ ๊ณ์ฐํ๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ๋๋ค.)์ด๋ฌํ ๋ญ๋น๋ฅผ ์ค์ฌ์ฃผ๋ ๊ธฐ๋ฒ์ด ๋ฐ๋ก ์ด๋ค. ์ด๋ ๋จ ํ๋ฒ์ forward ์ฒ๋ฆฌ๋ก ๋ชจ๋ ํฝ์ ์ ํด๋์ค๋ฅผ ๋ถ๋ฅํด์ฃผ๋ ๋๋ผ์ด ๊ธฐ๋ฒ์ด๋ค.(์ ๋ ฅ ์ด๋ฏธ์ง์ ๋ชจ๋ ํฝ์ ๊ฐ์ ๋ํด classification scores๋ฅผ ๋งค๊ธด ๊ฐ์ด ์ถ๋ ฅ๋์ด ๋ชจ๋ ํฝ์ ์ ๊ฐ๊ฐ ๋ฅผ ์ ์ฉํ์ฌ loss๋ฅผ ๊ณ์ฐํ์ฌ ํ๊ท ๋ด๊ณ ํจ์ผ๋ก์จ ํ๋ จ์ ์งํํ๋ค.) ์ ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ ์ฌ๋ฌผ ์ธ์์์ ์ฌ์ฉํ ์ ๊ฒฝ๋ง์ ์์ ์ฐ๊ฒฐ ๊ณ์ธต์์๋ ์ค๊ฐ ๋ฐ์ดํฐ์ ๊ณต๊ฐ ๋ณผ๋ฅจ(๋ค์ฐจ์ ํํ)์ 1์ฐจ์์ผ๋ก ๋ณํํ์ฌ() ํ ์ค๋ก ๋์ด์ ๋ ธ๋๋ค์ด ์ฒ๋ฆฌํ์ผ๋, ์์๋ ๊ณต๊ฐ ๋ณผ๋ฅจ์ ์ ์งํ ์ฑ ๋ง์ง๋ง ์ถ๋ ฅ๊น์ง ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ ๋ง์ง๋ง์ ๊ณต๊ฐ ํฌ๊ธฐ๋ฅผ ํ๋ํ๋ ์ฒ๋ฆฌ๋ฅผ ๋์ ํ๋ค๋ ๊ฒ๋ ํน์ง์ด๋ค. ์ด ํ๋ ์ฒ๋ฆฌ๋ก ์ธํด ์ค์ด๋ ์ค๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅ ์ด๋ฏธ์ง์ ๊ฐ์ ํฌ๊ธฐ๊น์ง ๋จ๋ฒ์ ํ๋ํ ์ ์๋ค.
1) Contracting Path : ์ด๋ฏธ์ง์ context(๋งฅ๋ฝ) ํ์
2) Expanding Path : feature map์ upsampling ํ๊ณ 1)์์ ํฌ์ฐฉํ feature map์ context์ concatenation(๊ฒฐํฉ) โ ์ด๋ ๋์ฑ ์ ํํ localization์ ํ๋ ์ญํ ์ ํ๋ค.
Keras ์ ์ฒ๋ฆฌ ๋ ์ด์ด
, tf.image
tf.keras.layers.Resizing
tf.keras.layers.Rescaling
### Resizing & Rescaling
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)
### ํฝ์
๊ฐ์ด [0,1]๋ก ํ์คํ๋์๋์ง ํ์ธ
print("Min and max pixel values:", (result.numpy().min(), result.numpy().max()))
"""
>>> Min and max pixel values: (0.0, 1.0)
"""
### ๋ช ๊ฐ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ๋์ผํ ์ด๋ฏธ์ง์ ๋ฐ๋ณต์ ์ ์ฉ
data_augmentation = tf.keras.Sequential([
layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
layers.experimental.preprocessing.RandomRotation(0.2),
])
# Add the image to a batch
image = tf.expand_dims(image, 0)
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")
์ด๋ฌํ ๋ค์ํ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์๋ค.
์ต์ 1: ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ๋ชจ๋ธ์ ์ผ๋ถ๋ก ๋ง๋ค๊ธฐ
[์ ์์ฌํญ]
- ๋ฐ์ดํฐ ์ฆ๊ฐ์ ๋๋จธ์ง ๋ ์ด์ด์ ๋๊ธฐ์ ์ผ๋ก ๊ธฐ๊ธฐ์์ ์คํ๋๋ฉฐ GPU ๊ฐ์์ ์ด์ฉํ๋ค.
model.save
๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ๋ด๋ณด๋ผ ๋ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๊ฐ ๋ชจ๋ธ์ ๋๋จธ์ง ๋ถ๋ถ๊ณผ ํจ๊ป ์ ์ฅ๋๋ค. ๋์ค์ ์ด ๋ชจ๋ธ์ ๋ฐฐํฌํ๋ฉด ๋ ์ด์ด ๊ตฌ์ฑ์ ๋ฐ๋ผ ์ด๋ฏธ์ง๊ฐ ์๋์ผ๋ก ํ์คํ๋๋ค.
์ด๋ฅผ ํตํด ์๋ฒ์ธก ๋ ผ๋ฆฌ๋ฅผ ๋ค์ ๊ตฌํํด์ผ ํ๋ ๋ ธ๋ ฅ์ ๋ ์ ์๋ค.- ์ฐธ๊ณ ) ๋ฐ์ดํฐ ์ฆ๊ฐ์ ํ ์คํธํ ๋ ๋นํ์ฑํ๋๋ฏ๋ก ์ ๋ ฅ ์ด๋ฏธ์ง๋
model.fit
(model.evaluate
๋๋model.predict
๊ฐ ์๋) ํธ์ถ ์ค์๋ง ์ฆ๊ฐ๋๋ค.
model = tf.keras.Sequential([
resize_and_rescale,
data_augmentation,
layers.Conv2D(16, 3, padding='same', activation='relu'),
# ํน๋ณํ ๊ธฐ์ค์ ์์ต๋๋ค. 16๊ฐ๋ฅผ ํด๋ ๋๊ณ , 32๊ฐ๋ฅผ ํด๋ ๋ฉ๋๋ค. ์ฌ๋ฌ ๊ฐ์ง๋ก ํด๋ณด๊ณ ์ฑ๋ฅ์ด ๋ ์ข์ ์ชฝ์ ์ ํํฉ๋๋ค.
# (,3) -> (3, 3)
layers.MaxPooling2D(),
# Rest of your model
])
์ต์ 2: ๋ฐ์ดํฐ์ธํธ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด ์ ์ฉํ๊ธฐ
[์ ์์ฌํญ]
- ๋ฐ์ดํฐ ์ฆ๊ฐ์ CPU์์ ๋น๋๊ธฐ์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฉฐ ์ฐจ๋จ๋์ง ์๋๋ค. ์๋์ ๊ฐ์ด
Dataset.prefetch
๋ฅผ ์ฌ์ฉํ์ฌ GPU์์ ๋ชจ๋ธ ํ๋ จ์ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ์ ์ค์ฒฉํ ์ ์๋ค.(tf.data API๋ก ์ฑ๋ฅ ํฅ์ํ๊ธฐ๊ฐ์ด๋์์ ๋ฐ์ดํฐ์ธํธ ์ฑ๋ฅ์ ๋ํด ์์ธํ ์์๋ณผ ์ ์๋ค.)- ์ด ๊ฒฝ์ฐ, ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋
model.save
๋ฅผ ํธ์ถํ ๋ ๋ชจ๋ธ๊ณผ ํจ๊ป ๋ด๋ณด๋ด์ง์ง ์๋๋ค. ์ ์ฅํ๊ธฐ ์ ์ ์ด ๋ ์ด์ด๋ฅผ ๋ชจ๋ธ์ ์ฐ๊ฒฐํ๊ฑฐ๋ ์๋ฒ์ธก์์ ๋ค์ ๊ตฌํํด์ผ ํ๋ค. ํ๋ จ ํ, ๋ด๋ณด๋ด๊ธฐ ์ ์ ์ ์ฒ๋ฆฌ ๋ ์ด์ด๋ฅผ ์ฐ๊ฒฐํ ์ ์๋ค.- ์ฐธ๊ณ ) ๋ฐ์ดํฐ ์ฆ๊ฐ์ ํ๋ จ ์ธํธ์๋ง ์ ์ฉํด์ผ ํ๋ค.
### Dataset.map
aug_ds = train_ds.map(
lambda x, y: (resize_and_rescale(x, training=True), y))
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)
# Batch all datasets
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), # 5๊ฐ์ ๋ ์ด๋ธ(๋ค์ค ๋ถ๋ฅ)
metrics=['accuracy'])
epochs=5
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)
๋ค์์ผ๋ก ์๊ฐ๋๋ ๋ ๋ ์ด์ด๋ ํ๋ฅ ์ ๋ฐ๋ผ ์ด๋ฏธ์ง์ ์์์ ๋ฌด์์๋ก ๋ฐ์ ํ๋ค.
def random_invert_img(x, p=0.5):
if tf.random.uniform([]) < 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):
augmented_image = random_invert(image)
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_image[0].numpy().astype("uint8"))
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)
_ = plt.imshow(RandomInvert()(image)[0])
์์ layers.preprocessing
์ ํธ๋ฆฌํฐ๋ ํธ๋ฆฌํ๋ค. ๋ณด๋ค ์ธ๋ฐํ ์ ์ด๋ฅผ ์ํด์๋ tf.data
๋ฐ tf.image
๋ฅผ ์ฌ์ฉํ์ฌ ๊ณ ์ ํ ๋ฐ์ดํฐ ์ฆ๊ฐ ํ์ดํ๋ผ์ธ ๋๋ ๋ ์ด์ด๋ฅผ ์์ฑํ ์ ์๋ค. (TensorFlow ์ ๋์จ ์ด๋ฏธ์ง: ์์
๋ฐ TensorFlow I/O: ์ ๊ณต๊ฐ ๋ณํ๋ ํ์ธํด๋ณผ ๊ฒ)
### ๊ฝ ๋ฐ์ดํฐ์ธํธ ๋ถ๋ฌ์ค๊ธฐ
(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,
)
### ์์
ํ ์ด๋ฏธ์ง ๊ฒ์
image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))
### ์๋ณธ ์ด๋ฏธ์ง์ ์ฆ๊ฐ ์ด๋ฏธ์ง๋ฅผ ๋๋ํ ์๊ฐํ & ๋น๊ต
def visualize(original, augmented):
fig = plt.figure()
plt.subplot(1,2,1)
plt.title('Original image')
plt.imshow(original)
plt.subplot(1,2,2)
plt.title('Augmented image')
plt.imshow(augmented)
### ์ด๋ฏธ์ง ๋ค์ง๊ธฐ : ์ด๋ฏธ์ง๋ฅผ ์์ง ๋๋ ์ํ์ผ๋ก ๋ค์ง๊ธฐ
flipped = tf.image.flip_left_right(image)
visualize(image, flipped)
### ์ด๋ฏธ์ง๋ฅผ ํ์์กฐ๋ก ๋ง๋ค๊ธฐ
grayscaled = tf.image.rgb_to_grayscale(image)
visualize(image, tf.squeeze(grayscaled))
_ = plt.colorbar()
### ์ด๋ฏธ์ง ํฌํ์ํค๊ธฐ : ์ฑ๋ ๊ณ์๋ฅผ ์ ๊ณตํ์ฌ ์ด๋ฏธ์ง๋ฅผ ํฌํ์ํจ๋ค.(smoothing ํจ๊ณผ)
saturated = tf.image.adjust_saturation(image, 3)
visualize(image, saturated)
### ์ด๋ฏธ์ง ๋ฐ๊ธฐ ๋ณ๊ฒฝํ๊ธฐ : ๋ฐ๊ธฐ ๊ณ์๋ฅผ ์ ๊ณตํ์ฌ ์ด๋ฏธ์ง์ ๋ฐ๊ธฐ๋ฅผ ๋ณ๊ฒฝ
bright = tf.image.adjust_brightness(image, 0.4)
visualize(image, bright)
### ์ด๋ฏธ์ง ์ค์ ์๋ฅด๊ธฐ : ์ด๋ฏธ์ง๋ฅผ ์ค์์์ ์ํ๋ ์ด๋ฏธ์ง ๋ถ๋ถ๊น์ง ์๋ฅด๊ธฐ
cropped = tf.image.central_crop(image, central_fraction=0.5)
visualize(image,cropped)
### ์ด๋ฏธ์ง ํ์ ํ๊ธฐ : 90๋ ํ์
rotated = tf.image.rot90(image)
visualize(image, rotated)
Dataset.map
์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์ฆ๊ฐ์ ๋ฐ์ดํฐ์ธํธ์ ์ ์ฉ
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)
# Add 6 pixels of padding
image = tf.image.resize_with_crop_or_pad(image, IMG_SIZE + 6, IMG_SIZE + 6)
# Random crop back to the original size
image = tf.image.random_crop(image, size=[IMG_SIZE, IMG_SIZE, 3])
image = tf.image.random_brightness(image, max_delta=0.5) # Random brightness
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 = (
val_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)
test_ds = (
test_ds
.map(resize_and_rescale, num_parallel_calls=AUTOTUNE)
.batch(batch_size)
.prefetch(AUTOTUNE)
)