Computer Vision with CNNs
For this exercise you will build a cats v dogs classifier
using the Cats v Dogs dataset from TFDS.
Be sure to use the final layer as shown
(Dense, 2 neurons, softmax activation)
The testing infrastructre will resize all images to 224x224
with 3 bytes of color depth. Make sure your input layer trains
images to that specification, or the tests will fail.
Make sure your output layer is exactly as specified here, or the
tests will fail.
์ด ์ฐ์ต์์๋ cats v dogs ๋ถ๋ฅ๊ธฐ๋ฅผ ๋ง๋ค ๊ฒ์ ๋๋ค. TFDS์ Cats v Dogs ๋ฐ์ดํฐ ์ธํธ ์ฌ์ฉ.
๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ์ต์ข ๋ ์ด์ด๋ฅผ ์ฌ์ฉํ์ญ์์ค
(Dense, ๋ด๋ฐ 2 ๊ฐ, activation='softmax')
ํ ์คํธ ์ธํ๋ผ๋ ๋ชจ๋ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๋ฅผ 224x224๋ก ์กฐ์ ํฉ๋๋ค(์ปฌ๋ฌ์ฌ์ง). ์ ๋ ฅ ๋ ์ด์ด๋ฅผ ํ์ธํ์ญ์์ค
ํ์ํ ๋ชจ๋์ import ํฉ๋๋ค.
import tensorflow_datasets as tfds
import tensorflow as tf
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, Dropout
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import ModelCheckpoint
tensorflow-datasets๋ฅผ ํ์ฉํฉ๋๋ค.
์ํ์์ ์ฃผ์ด์ง๋ ๋ฐ์ดํฐ์ ๋ก๋ ํํ
# ๋ฐ์ดํฐ์
๋ค์ด๋ก๋ ์ค๋ฅ (๋งํฌ ๊นจ์ง ํด๊ฒฐ)
setattr(tfds.image_classification.cats_vs_dogs, '_URL',"https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_5340.zip")
dataset_name = 'cats_vs_dogs'
# ์ฒ์ 80%์ ๋ฐ์ดํฐ๋ง ์ฌ์ฉ
train_dataset = tfds.load(name=dataset_name, split='train[:80%]')
# ์ต๊ทผ 20%์ ๋ฐ์ดํฐ๋ง ์ฌ์ฉ
valid_dataset = tfds.load(name=dataset_name, split='train[80%:]')
์ํ์์ ์๊ตฌํ๋ ์ ์ฒ๋ฆฌ ์๊ตฌ ์กฐ๊ฑด์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def preprocess(data):
# x, y ๋ฐ์ดํฐ๋ฅผ ์ ์ํฉ๋๋ค.
x = data['image']
y = data['label']
# image ์ ๊ทํ(Normalization)
x = x / 255
# ์ฌ์ด์ฆ๋ฅผ (224, 224)๋ก ๋ณํํฉ๋๋ค.
x = tf.image.resize(x, size=(224, 224))
# x, y ๋ฐ์ดํฐ๋ฅผ return ํฉ๋๋ค.
return x, y
๋ง๋ ์ ์ฒ๋ฆฌ ํจ์(preprocessing)๋ฅผ dataset์ mappingํ๊ณ , batch_size๋ ์ง์ ํฉ๋๋ค.
batch_size=32
train_data = train_dataset.map(preprocess).batch(batch_size)
valid_data = valid_dataset.map(preprocess).batch(batch_size)
์ด์ Modeling์ ํ ์ฐจ๋ก์ ๋๋ค.
Sequential
๋ชจ๋ธ ์์์ ์ธต์ ๊น๊ฒ ์์ ์ฌ๋ ค ์ฃผ๋ฉด ๋ฉ๋๋ค.
input_shape
๋ (height, width, color_channel)์
๋๋ค. cats vs dogs ๋ฌธ์ ์์๋ (224, 224, 3) ์ด ๋ฉ๋๋ค.activation='relu'
๋ฅผ ์ ์ฉํฉ๋๋ค.model = Sequential([
Conv2D(64, (3, 3), input_shape=(224, 224, 3), activation='relu'),
MaxPooling2D(2, 2),
Conv2D(64, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Conv2D(128, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Conv2D(128, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Conv2D(256, (3, 3), activation='relu'),
MaxPooling2D(2, 2),
Flatten(),
Dropout(0.5),
Dense(512, activation='relu'),
Dense(128, activation='relu'),
Dense(2, activation='softmax'),
])
])
model.summary()
optimizer
๋ ๊ฐ์ฅ ์ต์ ํ๊ฐ ์๋๋ ์๊ณ ๋ฆฌ์ฆ์ธ 'adam'์ ์ฌ์ฉํฉ๋๋ค.loss
์ค์ sigmoid
์ธ ๊ฒฝ์ฐ: binary_crossentropy
softmax
์ธ ๊ฒฝ์ฐ: categorical_crossentropy
sparse_categorical_crossentropy
)ImageDataGenerator
๋ ์๋์ผ๋ก Label์ ์ํซ์ธ์ฝ๋ฉ(one-hot encoding) ํด์ค๋๋ค.metrics
๋ฅผ 'acc' ํน์ 'accuracy'๋ก ์ง์ ํ๋ฉด, ํ์ต์ ์ ํ๋๋ฅผ ๋ชจ๋ํฐ๋ง ํ ์ ์์ต๋๋ค.model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['acc'])
val_loss
๊ธฐ์ค์ผ๋ก epoch ๋ง๋ค ์ต์ ์ ๋ชจ๋ธ์ ์ ์ฅํ๊ธฐ ์ํ์ฌ, ModelCheckpoint๋ฅผ ๋ง๋ญ๋๋ค.
checkpoint_path
๋ ๋ชจ๋ธ์ด ์ ์ฅ๋ ํ์ผ ๋ช
์ ์ค์ ํฉ๋๋ค.ModelCheckpoint
์ ์ ์ธํ๊ณ , ์ ์ ํ ์ต์
๊ฐ์ ์ง์ ํฉ๋๋ค.checkpoint_path = "my_checkpoint.ckpt"
checkpoint = ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
save_best_only=True,
monitor='val_loss',
verbose=1)
validation_data
๋ฅผ ๋ฐ๋์ ์ง์ ํฉ๋๋ค.epochs
์ ์ ์ ํ๊ฒ ์ง์ ํฉ๋๋ค.callbacks
์ ๋ฐ๋ก ์์์ ๋ง๋ checkpoint๋ฅผ ์ง์ ํฉ๋๋ค.model.fit(train_data,
validation_data=(valid_data),
epochs=20,
callbacks=[checkpoint],
)
ํ์ต์ด ์๋ฃ๋ ํ์๋ ๋ฐ๋์ load_weights
๋ฅผ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด, ์ด์ฌํ ModelCheckpoint๋ฅผ ๋ง๋ ์๋ฏธ๊ฐ ์์ต๋๋ค.
# checkpoint ๋ฅผ ์ ์ฅํ ํ์ผ๋ช
์ ์
๋ ฅํฉ๋๋ค.
model.load_weights(checkpoint_path)