playdata
Deep Learning(0913_day7) - CIFAR10(ImageAugmentation)
_JAEJAE_
2021. 9. 13. 17:25
CIFAR10 Dataset 신경망으로 훈련¶
imports¶
In [1]:
import numpy as np
import tensorflow as tf
from tensorflow.keras.datasets import cifar10
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Flatten, Dense
from tensorflow.keras.optimizers import SGD, Adam
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, BatchNormalization, Activation, GlobalAveragePooling2D
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import ImageDataGenerator
In [2]:
np.random.seed(42)
tf.random.set_seed(42)
데이터 적재¶
In [3]:
(train_images, train_labels), (test_images, test_labels) = cifar10.load_data()
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170500096/170498071 [==============================] - 3s 0us/step 170508288/170498071 [==============================] - 3s 0us/step
In [4]:
print(train_images.shape, train_labels.shape)
print(test_images.shape, test_labels.shape)
print(train_images[0].shape)
(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1) (32, 32, 3)
In [5]:
class_names = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
In [6]:
train_labels[:10]
Out[6]:
array([[6], [9], [9], [4], [1], [1], [2], [7], [8], [3]], dtype=uint8)
데이터 시각화¶
In [7]:
train_labels = np.int32(train_labels.flatten())
In [8]:
figure, axes = plt.subplots(figsize=(22, 10), nrows=3, ncols=8)
for i in range(3):
for j in range(8):
axes[i][j].imshow(train_images[(i*8)+j])
axes[i][j].set_title(class_names[train_labels[(i*8)+j]])
데이터 전처리¶
In [9]:
train_images = np.array(train_images/255.0, dtype=np.float32)
train_labels = np.array(train_labels, dtype=np.float32)
test_images = np.array(test_images/255.0, dtype=np.float32)
test_labels = np.array(test_labels, dtype=np.float32)
train_oh_labels = to_categorical(train_labels)
test_oh_labels = to_categorical(test_labels)
train_images, valid_images, train_oh_labels, valid_oh_labels = train_test_split(train_images, train_oh_labels, test_size=0.2, random_state=42)
In [10]:
train_images.shape, valid_images.shape, train_oh_labels.shape, valid_oh_labels.shape
Out[10]:
((40000, 32, 32, 3), (10000, 32, 32, 3), (40000, 10), (10000, 10))
데이터 증강(샘플 예시)¶
In [11]:
# data_generator = ImageDataGenerator(horizontal_flip=True) # 랜덤하게 진행하기 때문에 바뀌는 경우도 있고 아닌 경우도 있음
# data_generator = ImageDataGenerator(rotation_range=180)
data_generator = ImageDataGenerator(vertical_flip=True)
image = np.expand_dims(train_images[0], axis=0)
data_generator_iterator = data_generator.flow(image)
augmented_image = next(data_generator_iterator)
image = np.squeeze(image)
augmented_image = np.squeeze(augmented_image)
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(6*2, 6))
axes[0].imshow(image)
axes[1].imshow(augmented_image)
Out[11]:
<matplotlib.image.AxesImage at 0x7f76de314c90>
In [12]:
# data_generator = ImageDataGenerator(horizontal_flip=True)
# data_generator = ImageDataGenerator(rotation_range=180)
# data_generator = ImageDataGenerator(vertical_flip=True)
data_generator = ImageDataGenerator(horizontal_flip=True,
rotation_range=30,
vertical_flip=True,
zoom_range=(0.7, 0.9))
images = train_images[0:4]
data_generator_iterator = data_generator.flow(images)
augmented_image = next(data_generator_iterator)
fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(6*4, 6))
for i, image in enumerate(images):
axes[i].imshow(image)
fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(6*4, 6))
for i, aug_image in enumerate(augmented_image):
axes[i].imshow(aug_image)
In [13]:
BATCH_SIZE = 32
train_generator = ImageDataGenerator(horizontal_flip=True)
train_generator_iterator = train_generator.flow(train_images, train_oh_labels, batch_size=BATCH_SIZE)
valid_generator = ImageDataGenerator(horizontal_flip=True)
valid_generator_iterator = valid_generator.flow(valid_images, valid_oh_labels, batch_size=BATCH_SIZE)
Global Average Pooling 적용¶
In [14]:
def build_extended_model():
tf.keras.backend.clear_session()
input_tensor = Input(shape=(32, 32, 3))
x = Conv2D(filters=32, kernel_size=(3, 3), strides=1, padding="same")(input_tensor)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = Conv2D(filters=64, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(filters=128, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = Conv2D(filters=128, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(filters=256, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = Conv2D(filters=256, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
# x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(filters=512, kernel_size=(3, 3), strides=1, padding="same")(x)
x = BatchNormalization()(x)
x = Activation("relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
# x = Flatten()(x)
x = GlobalAveragePooling2D()(x)
x = Dropout(rate=0.5)(x)
x = Dense(300, activation="relu")(x)
x = Dropout(rate=0.3)(x)
x = Dense(100, activation="relu")(x)
x = Dropout(rate=0.3)(x)
output = Dense(10, activation="softmax")(x)
model = Model(inputs=input_tensor, outputs=output)
return model
모델 생성 및 컴파일¶
In [15]:
model = build_extended_model()
model.summary()
Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 32, 32, 3)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 32, 32, 32) 896 _________________________________________________________________ batch_normalization (BatchNo (None, 32, 32, 32) 128 _________________________________________________________________ activation (Activation) (None, 32, 32, 32) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 32, 32, 64) 18496 _________________________________________________________________ batch_normalization_1 (Batch (None, 32, 32, 64) 256 _________________________________________________________________ activation_1 (Activation) (None, 32, 32, 64) 0 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 16, 16, 64) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 16, 16, 128) 73856 _________________________________________________________________ batch_normalization_2 (Batch (None, 16, 16, 128) 512 _________________________________________________________________ activation_2 (Activation) (None, 16, 16, 128) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 16, 16, 128) 147584 _________________________________________________________________ batch_normalization_3 (Batch (None, 16, 16, 128) 512 _________________________________________________________________ activation_3 (Activation) (None, 16, 16, 128) 0 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 8, 8, 128) 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 8, 8, 256) 295168 _________________________________________________________________ batch_normalization_4 (Batch (None, 8, 8, 256) 1024 _________________________________________________________________ activation_4 (Activation) (None, 8, 8, 256) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 8, 8, 256) 590080 _________________________________________________________________ batch_normalization_5 (Batch (None, 8, 8, 256) 1024 _________________________________________________________________ activation_5 (Activation) (None, 8, 8, 256) 0 _________________________________________________________________ conv2d_6 (Conv2D) (None, 8, 8, 512) 1180160 _________________________________________________________________ batch_normalization_6 (Batch (None, 8, 8, 512) 2048 _________________________________________________________________ activation_6 (Activation) (None, 8, 8, 512) 0 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 4, 4, 512) 0 _________________________________________________________________ global_average_pooling2d (Gl (None, 512) 0 _________________________________________________________________ dropout (Dropout) (None, 512) 0 _________________________________________________________________ dense (Dense) (None, 300) 153900 _________________________________________________________________ dropout_1 (Dropout) (None, 300) 0 _________________________________________________________________ dense_1 (Dense) (None, 100) 30100 _________________________________________________________________ dropout_2 (Dropout) (None, 100) 0 _________________________________________________________________ dense_2 (Dense) (None, 10) 1010 ================================================================= Total params: 2,496,754 Trainable params: 2,494,002 Non-trainable params: 2,752 _________________________________________________________________
In [16]:
model.compile(optimizer=Adam(0.001), loss="categorical_crossentropy", metrics=["accuracy"])
Callback 정의¶
In [17]:
checkpoint_cb = ModelCheckpoint("my_keras_model.h5", save_best_only=True, verbose=1)
early_stopping_cb = EarlyStopping(patience=10, restore_best_weights=True)
reducelr_cb = ReduceLROnPlateau(monitor="val_loss", factor=0.2, patience=5, mode="min", verbose=1)
모델 학습¶
In [19]:
history = model.fit(train_generator_iterator, epochs=40, validation_data=valid_generator_iterator,
callbacks=[checkpoint_cb, early_stopping_cb, reducelr_cb])
Epoch 1/40 1250/1250 [==============================] - 68s 32ms/step - loss: 1.6851 - accuracy: 0.3584 - val_loss: 1.6107 - val_accuracy: 0.3910 Epoch 00001: val_loss improved from inf to 1.61065, saving model to my_keras_model.h5 Epoch 2/40 1250/1250 [==============================] - 40s 32ms/step - loss: 1.2623 - accuracy: 0.5510 - val_loss: 1.3285 - val_accuracy: 0.5221 Epoch 00002: val_loss improved from 1.61065 to 1.32849, saving model to my_keras_model.h5 Epoch 3/40 1250/1250 [==============================] - 40s 32ms/step - loss: 1.0395 - accuracy: 0.6420 - val_loss: 0.9931 - val_accuracy: 0.6446 Epoch 00003: val_loss improved from 1.32849 to 0.99310, saving model to my_keras_model.h5 Epoch 4/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.8905 - accuracy: 0.6992 - val_loss: 0.9183 - val_accuracy: 0.6835 Epoch 00004: val_loss improved from 0.99310 to 0.91830, saving model to my_keras_model.h5 Epoch 5/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.7911 - accuracy: 0.7350 - val_loss: 0.8444 - val_accuracy: 0.7119 Epoch 00005: val_loss improved from 0.91830 to 0.84442, saving model to my_keras_model.h5 Epoch 6/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.6963 - accuracy: 0.7705 - val_loss: 0.9830 - val_accuracy: 0.6945 Epoch 00006: val_loss did not improve from 0.84442 Epoch 7/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.6329 - accuracy: 0.7918 - val_loss: 0.6412 - val_accuracy: 0.7890 Epoch 00007: val_loss improved from 0.84442 to 0.64124, saving model to my_keras_model.h5 Epoch 8/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.5662 - accuracy: 0.8156 - val_loss: 0.8325 - val_accuracy: 0.7299 Epoch 00008: val_loss did not improve from 0.64124 Epoch 9/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.5148 - accuracy: 0.8334 - val_loss: 0.6691 - val_accuracy: 0.7745 Epoch 00009: val_loss did not improve from 0.64124 Epoch 10/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.4759 - accuracy: 0.8454 - val_loss: 0.5873 - val_accuracy: 0.7992 Epoch 00010: val_loss improved from 0.64124 to 0.58735, saving model to my_keras_model.h5 Epoch 11/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.4403 - accuracy: 0.8565 - val_loss: 0.5541 - val_accuracy: 0.8219 Epoch 00011: val_loss improved from 0.58735 to 0.55413, saving model to my_keras_model.h5 Epoch 12/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.4013 - accuracy: 0.8702 - val_loss: 0.5485 - val_accuracy: 0.8263 Epoch 00012: val_loss improved from 0.55413 to 0.54846, saving model to my_keras_model.h5 Epoch 13/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.3729 - accuracy: 0.8799 - val_loss: 0.4964 - val_accuracy: 0.8408 Epoch 00013: val_loss improved from 0.54846 to 0.49642, saving model to my_keras_model.h5 Epoch 14/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.3474 - accuracy: 0.8864 - val_loss: 0.6327 - val_accuracy: 0.8029 Epoch 00014: val_loss did not improve from 0.49642 Epoch 15/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.3149 - accuracy: 0.8985 - val_loss: 0.5795 - val_accuracy: 0.8246 Epoch 00015: val_loss did not improve from 0.49642 Epoch 16/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.2888 - accuracy: 0.9062 - val_loss: 0.5494 - val_accuracy: 0.8315 Epoch 00016: val_loss did not improve from 0.49642 Epoch 17/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.2675 - accuracy: 0.9140 - val_loss: 0.5777 - val_accuracy: 0.8372 Epoch 00017: val_loss did not improve from 0.49642 Epoch 18/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.2594 - accuracy: 0.9162 - val_loss: 0.5210 - val_accuracy: 0.8370 Epoch 00018: val_loss did not improve from 0.49642 Epoch 00018: ReduceLROnPlateau reducing learning rate to 0.00020000000949949026. Epoch 19/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.1609 - accuracy: 0.9493 - val_loss: 0.4152 - val_accuracy: 0.8847 Epoch 00019: val_loss improved from 0.49642 to 0.41522, saving model to my_keras_model.h5 Epoch 20/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.1286 - accuracy: 0.9579 - val_loss: 0.4481 - val_accuracy: 0.8865 Epoch 00020: val_loss did not improve from 0.41522 Epoch 21/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.1134 - accuracy: 0.9630 - val_loss: 0.4594 - val_accuracy: 0.8803 Epoch 00021: val_loss did not improve from 0.41522 Epoch 22/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0998 - accuracy: 0.9671 - val_loss: 0.4668 - val_accuracy: 0.8837 Epoch 00022: val_loss did not improve from 0.41522 Epoch 23/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0988 - accuracy: 0.9688 - val_loss: 0.4689 - val_accuracy: 0.8863 Epoch 00023: val_loss did not improve from 0.41522 Epoch 24/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0871 - accuracy: 0.9715 - val_loss: 0.5004 - val_accuracy: 0.8839 Epoch 00024: val_loss did not improve from 0.41522 Epoch 00024: ReduceLROnPlateau reducing learning rate to 4.0000001899898055e-05. Epoch 25/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0671 - accuracy: 0.9776 - val_loss: 0.4701 - val_accuracy: 0.8902 Epoch 00025: val_loss did not improve from 0.41522 Epoch 26/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0632 - accuracy: 0.9800 - val_loss: 0.4864 - val_accuracy: 0.8930 Epoch 00026: val_loss did not improve from 0.41522 Epoch 27/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0612 - accuracy: 0.9804 - val_loss: 0.4896 - val_accuracy: 0.8908 Epoch 00027: val_loss did not improve from 0.41522 Epoch 28/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0565 - accuracy: 0.9815 - val_loss: 0.5053 - val_accuracy: 0.8919 Epoch 00028: val_loss did not improve from 0.41522 Epoch 29/40 1250/1250 [==============================] - 40s 32ms/step - loss: 0.0563 - accuracy: 0.9826 - val_loss: 0.5125 - val_accuracy: 0.8903 Epoch 00029: val_loss did not improve from 0.41522 Epoch 00029: ReduceLROnPlateau reducing learning rate to 8.000000525498762e-06.
In [20]:
plt.plot(history.history["accuracy"], label="train")
plt.plot(history.history["val_accuracy"], label="valid")
plt.legend()
Out[20]:
<matplotlib.legend.Legend at 0x7f76d0032110>
테스트 데이터에 대해 평가¶
In [22]:
model.evaluate(test_images, test_oh_labels, batch_size=BATCH_SIZE, verbose=1)
313/313 [==============================] - 4s 12ms/step - loss: 0.4121 - accuracy: 0.8841
Out[22]:
[0.4120880365371704, 0.8841000199317932]
In [ ]: