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])
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()
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])]))