Keras 튜토리얼 (2)

CNN으로 cifar10 데이터 구분하기.

  • CNN에 대해서는 알고있다는 전제하에 keras 문법 활용 레시피 위주로 한다.

1. CNN(Convolution Neural Network)

1.0 필요 라이브러리 import

import pandas as pd
import numpy as np

from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten
from keras import losses
from keras import optimizers

from keras import datasets  # cifar10
from keras.utils import np_utils # one hot coding

import matplotlib.pyplot as plt
import seaborn as sns

import os

sns.set()

os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"   
os.environ["CUDA_VISIBLE_DEVICES"]="2"

1.2 데이터 확인

1.2.0 데이터 로딩
# data load & 확인
(X_train, y_train), (X_test, y_test) = datasets.cifar10.load_data()
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

name = [
    "airplane", "automobile",
    "bird", "cat",
    "deer", "dog",
    "frog", "horse",
    "ship", "truck"
]

# 결과
(50000, 32, 32, 3)
(50000, 1)
(10000, 32, 32, 3)
(10000, 1)
  • mnist랑 다르게 cifar10은 32\(\times\)32 크기의 rgb 3개(w\(\times\)h\(\times\)c)의 채널로 이루어진 50000개의 데이터이다.
  • label은 airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck의 10가지이다.

1.2.1 데이터 확인

plt.figure(figsize=(6, 12))

for i in range(6):
    n = np.random.randint(0, len(X_train))
    plt.subplot(320+1+i)
    plt.imshow(X_train[n])
    plt.title(y_train[n])

cnn확인

1.2.2 데이터 전처리

# 데이터 전처리

Y_train = np_utils.to_categorical(y_train)
Y_test = np_utils.to_categorical(y_test)

X_train = X_train.astype(np.float32) / 255.0
X_test = X_test.astype(np.float32) / 255.0

n = np.random.randint(0, 100)
print(Y_train.shape)
print(y_train[n])
print(Y_train[n])
print()
print(Y_test.shape)
print(y_test[n])
print(Y_test[n])

# 결과
(50000, 10)
[4]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]

(10000, 10)
[2]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]

1.3 CNN 모델 생성

class Conv(Sequential):
    def __init__(self, input_shape=(32, 32, 3), num_class=10, kernel_size=(3, 3), ):
        super().__init__()
        self.add(Conv2D(64, kernel_size=kernel_size,
                        activation="relu",
                        input_shape=input_shape, padding='same', name="input_Layer")
                 )
        self.add(BatchNormalization(name="Batch_norm00"))
        self.add(Dropout(0.25, name="Drop00"))

        self.add(Conv2D(64, kernel_size=kernel_size,
                        activation="relu", padding="same", name="Conv2D01"))
        self.add(BatchNormalization(name="Batch_norm01"))
        self.add(MaxPooling2D(pool_size=(2, 2)))
        self.add(Dropout(0.25, name="Drop01"))

        self.add(Conv2D(64, kernel_size=kernel_size,
                        activation="relu", padding="same", name="Conv2D02"))
        self.add(BatchNormalization(name="Batch_norm02"))
        self.add(MaxPooling2D(pool_size=(2, 2)))
        self.add(Dropout(0.25, name="Drop02"))

        self.add(Flatten(name="Flatten00"))
        self.add(Dense(512, activation="relu", use_bias=False, name="Dense00"))
        self.add(BatchNormalization(name="Batch_norm03"))
        self.add(Activation("relu"))
        self.add(Dropout(0.5, name="DropOut03"))
        self.add(Dense(10, activation="softmax", name="Dense01"))

        self.compile(loss=losses.categorical_crossentropy,
                     optimizer="rmsprop", metrics=['acc'])

1.4 모델 생성 &. 실행

1.4.1 모델 생성
conv2d = Conv()
conv2d.summary()

# 결과
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_Layer (Conv2D)         (None, 32, 32, 64)        1792      
_________________________________________________________________
Batch_norm00 (BatchNormaliza (None, 32, 32, 64)        256       
_________________________________________________________________
Drop00 (Dropout)             (None, 32, 32, 64)        0         
_________________________________________________________________
Conv2D01 (Conv2D)            (None, 32, 32, 64)        36928     
_________________________________________________________________
Batch_norm01 (BatchNormaliza (None, 32, 32, 64)        256       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64)        0         
_________________________________________________________________
Drop01 (Dropout)             (None, 16, 16, 64)        0         
_________________________________________________________________
Conv2D02 (Conv2D)            (None, 16, 16, 64)        36928     
_________________________________________________________________
Batch_norm02 (BatchNormaliza (None, 16, 16, 64)        256       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64)          0         
_________________________________________________________________
Drop02 (Dropout)             (None, 8, 8, 64)          0         
_________________________________________________________________
Flatten00 (Flatten)          (None, 4096)              0         
_________________________________________________________________
Dense00 (Dense)              (None, 512)               2097152   
_________________________________________________________________
Batch_norm03 (BatchNormaliza (None, 512)               2048      
_________________________________________________________________
activation_1 (Activation)    (None, 512)               0         
_________________________________________________________________
DropOut03 (Dropout)          (None, 512)               0         
_________________________________________________________________
Dense01 (Dense)              (None, 10)                5130      
=================================================================
Total params: 2,180,746
Trainable params: 2,179,338
Non-trainable params: 1,408
_________________________________________________________________
  • 정확도를 올려보고 싶어서 조금 복잡하게 했으나 영 결과는 좋지 못하다.
  • input_shape=(32, 32, 3)
    • 우리가 넣을 image의 사이즈
  • num_class=10
    • label의 갯수
  • kernel_size=(3, 3)
    • CNN에서 사용되는 kernel의 크기
1.4.2 모델 실행
history = conv2d.fit(
    X_train, Y_train, batch_size=32,
    epochs=50, validation_split=0.2)

# 결과
Epoch 1/2
40000/40000 [==============================] - 11s 265us/step - loss: 2.2678 - acc: 0.1394 - val_loss: 2.1680 - val_acc: 0.1905
                ....
1.4.3 모델 검정
loss, accuracy = conv2d.evaluate(X_test, Y_test, batch_size=100)

print("Test Loss\t:\t{:2.4f}".format(loss))
print("Test Accuracy\t:\t{:2.4f}".format(accuracy))

# 결과
10000/10000 [==============================] - 1s 81us/step
Test Loss	:	0.8359
Test Accuracy	:	0.7747
1.4.4 결과 그래프
h = pd.DataFrame(history.history).reset_index()

ax = h.plot(x="index", y=["loss", "val_loss"])
ax.set_ylabel("loss")
ax2 = ax.twinx()
ax2.set_ylabel("acc")
h.plot(x="index", y=["acc", "val_acc"], ax=ax2, colormap='viridis',)
plt.grid(False)
plt.show()

결과00

1.4.5 결과 확인
plt.figure(figsize=(6, 12))

for i in range(6):
    n = np.random.randint(0, len(X_test))
    plt.subplot(320+1+i)
    plt.imshow(X_test[n].reshape(32, 32, 3))
    plt.title("R:{}, P:{}".format(name[y_test[n][0]], name[np.argmax(yhat_test[n])]))

결과01