자료를 공개한 저자 오렐리앙 제롱과 강의자료를 지원한 한빛아카데미에게 진심어린 감사를 전합니다.
main_layers
: 오른쪽 모듈skip_layers
: 왼쪽 모듈. 보폭이 1보다 큰 경우에만 합성곱 모델 적용.DefaultConv2D = partial(keras.layers.Conv2D, kernel_size=3, strides=1,
padding="SAME", use_bias=False)
class ResidualUnit(keras.layers.Layer):
def __init__(self, filters, strides=1, activation="relu", **kwargs):
super().__init__(**kwargs)
self.activation = keras.activations.get(activation)
self.main_layers = [
DefaultConv2D(filters, strides=strides),
keras.layers.BatchNormalization(),
self.activation,
DefaultConv2D(filters),
keras.layers.BatchNormalization()]
self.skip_layers = []
if strides > 1:
self.skip_layers = [
DefaultConv2D(filters, kernel_size=1, strides=strides),
keras.layers.BatchNormalization()]
def call(self, inputs):
# main_layers
Z = inputs
for layer in self.main_layers:
Z = layer(Z)
# skip_layers
skip_Z = inputs
for layer in self.skip_layers:
skip_Z = layer(skip_Z)
return self.activation(Z + skip_Z)
model = keras.models.Sequential()
model.add(DefaultConv2D(64, kernel_size=7, strides=2,
input_shape=[224, 224, 3]))
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Activation("relu"))
model.add(keras.layers.MaxPool2D(pool_size=3, strides=2, padding="SAME"))
prev_filters = 64
for filters in [64] * 3 + [128] * 4 + [256] * 6 + [512] * 3:
strides = 1 if filters == prev_filters else 2
model.add(ResidualUnit(filters, strides=strides))
prev_filters = filters
model.add(keras.layers.GlobalAvgPool2D())
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(10, activation="softmax"))
keras.applications
에서 기본제공됨.model = keras.applications.resnet50.ResNet50(weights="imagenet")
224x224
모양의 이미지를 입력값으로 사용해야 함.tf.image.resize()
, tf.image.crop_and_resize()
등 다양한 함수 이용 가능.images_resized = tf.image.resize(images, [224, 224])
또는
images_resized = tf.image.crop_and_resize(images, [china_box, flower_box],
[0, 1], [224, 224])
preprocess_input()
제공. inputs = keras.applications.resnet50.preprocess_input(images_resized * 255)
Y_proba = model.predict(inputs)
decode_predictions()
메서드 활용top_K = keras.applications.resnet50.decode_predictions(Y_proba, top=3)
for image_index in range(len(images)):
print("Image #{}".format(image_index))
for class_id, name, y_proba in top_K[image_index]:
print(" {} - {:12s} {:.2f}%".format(class_id, name, y_proba * 100))
print()
Image #0
n03877845 - palace 43.39%
n02825657 - bell_cote 43.07%
n03781244 - monastery 11.70%
Image #1
n04522168 - vase 53.96%
n07930864 - cup 9.52%
n11939491 - daisy 4.97%
tensorflow_datasets
모듈의 load()
함수 활용하여 샘플 데이터셋 불러오기import tensorflow_datasets as tfds
dataset, info = tfds.load("tf_flowers", as_supervised=True, with_info=True)
tf_flowers
데이터셋['dandelion', 'daisy', 'tulips', 'sunflowers', 'roses']
test_set_raw, valid_set_raw, train_set_raw = tfds.load(
"tf_flowers",
split=["train[:10%]", "train[10%:25%]", "train[25%:]"],
as_supervised=True)
randomize=True
: 무작위적으로 사진자르기와 수평뒤집기 등을 활용한 데이터 증식224x224
모양으로 변환 후 preprocess_input()
메서드로 전치리 실행prefetch(1)
: 배치 미리 준비시키기def preprocess(image, label, randomize=False):
if randomize:
cropped_image = random_crop(image)
cropped_image = tf.image.random_flip_left_right(cropped_image)
else:
cropped_image = central_crop(image)
resized_image = tf.image.resize(cropped_image, [224, 224])
final_image = keras.applications.xception.preprocess_input(resized_image)
return final_image, label
batch_size = 32
train_set = train_set_raw.shuffle(1000).repeat()
train_set = train_set.map(partial(preprocess, randomize=True)).batch(batch_size).prefetch(1)
valid_set = valid_set_raw.map(preprocess).batch(batch_size).prefetch(1)
test_set = test_set_raw.map(preprocess).batch(batch_size).prefetch(1)
base_model = keras.applications.xception.Xception(weights="imagenet",
include_top=False)
avg = keras.layers.GlobalAveragePooling2D()(base_model.output)
output = keras.layers.Dense(n_classes, activation="softmax")(avg)
model = keras.models.Model(inputs=base_model.input, outputs=output)
lr=0.2
# 사전훈련된 층의 가중치 동결하기
for layer in base_model.layers:
layer.trainable = False
# 컴파일 후 훈련 시작
optimizer = keras.optimizers.SGD(lr=0.2, momentum=0.9, decay=0.01)
model.compile(loss="sparse_categorical_crossentropy", optimizer=optimizer,
metrics=["accuracy"])
history = model.fit(train_set,
steps_per_epoch=int(0.75 * dataset_size / batch_size),
validation_data=valid_set,
validation_steps=int(0.15 * dataset_size / batch_size),
epochs=5)
lr=0.0.01
# 사전훈련된 층의 가중치 동결 해제
for layer in base_model.layers:
layer.trainable = True
# 재 컴파일 후 훈련 시작
optimizer = keras.optimizers.SGD(learning_rate=0.01, momentum=0.9,
nesterov=True, decay=0.001)
model.compile(loss="sparse_categorical_crossentropy", optimizer=optimizer,
metrics=["accuracy"])
history = model.fit(train_set,
steps_per_epoch=int(0.75 * dataset_size / batch_size),
validation_data=valid_set,
validation_steps=int(0.15 * dataset_size / batch_size),
epochs=40)
base_model = keras.applications.xception.Xception(weights="imagenet",
include_top=False)
avg = keras.layers.GlobalAveragePooling2D()(base_model.output)
class_output = keras.layers.Dense(n_classes, activation="softmax")(avg)
loc_output = keras.layers.Dense(4)(avg)
model = keras.models.Model(inputs=base_model.input,
outputs=[class_output, loc_output])
model.compile(loss=["sparse_categorical_crossentropy", "mse"],
loss_weights=[0.8, 0.2], # 어느 출력에 보다 집중할지 결정
optimizer=optimizer, metrics=["accuracy"])
경계상자 레이블링이 완성된 후 입력되는 샘플이 두 개의 레이블을 사용하도록 입력값 형식을 다음과 같이 변경해야 함:
(images, (class_labels, bounding_boxes))
3x3
, 4x4
등등224 x 224
크기의 이미지7 x 7
크기의 특성맵으로 이루어짐.7 x 7
크기의 필터 10개 사용from IPython.display import YouTubeVideo
# a talk about IPython at Sage Days at U. Washington, Seattle.
# Video credit: William Stein.
YouTubeVideo('MPU2HistivI')