기본적인 딥러닝 모델을 케라스로 쉽게 구현할수 있습니다. 몇개의 파라미터를 고쳐가면서 해보면, 99%이상의 정확도를 얻을 수 있습니다.
LeNet을 이용한 기본적인 CNN (Deep Convolution Neural Network) 구축하기¶
- 케라스를 이용하면 단 몇가지 코드로 신경망을 구축할 수 있다.
In [1]:
from keras import backend
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation, Flatten, Dense
from keras.utils import np_utils
from keras.optimizers import SGD, RMSprop, Adam
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
- dataset은 mnist를 이용한 데이터셋이다.
In [2]:
from keras.datasets import mnist
- ordering 은 tf의 경우 채널이 나중에 넣는다. 예를들어 이미지가 2828이라면, 2828*1로 넣으면 되고, th는 반대다.
In [3]:
backend.set_image_dim_ordering("tf")
데이터셋 로드¶
In [4]:
(train_x_ori, train_y_ori), (test_x_ori, test_y_ori) = mnist.load_data()
In [5]:
plt.imshow(train_x_ori[1], cmap='Greys')
Out[5]:
In [6]:
plt.imshow(train_x_ori[5], cmap='Greys')
Out[6]:
In [7]:
train_x_ori = train_x_ori.astype('float32')
test_x_ori = test_x_ori.astype('float32')
스케일을 조정하고, 채널정보를 추가¶
- 그림이 3차원이 아닌 이유는, 채널정보가 있기 때문이다. 채널정보는 그레이스케일의 경우 1, RGB일 경우 3으로 조정하면 된다.
In [8]:
train_x = train_x_ori / 255
test_x = test_x_ori / 255
train_x = train_x[:, :, :,np.newaxis,]
test_x = test_x[:, :, :, np.newaxis]
- 1차원이 늘어난것을 알수있다.
In [9]:
train_x.shape
Out[9]:
y 라벨의 경우도 교체¶
- 각각 y라벨의 경우도 원핫 인코딩 형식으로 변환해 주어야 한다. 0~9정수는 못읽음
In [11]:
train_y = np_utils.to_categorical(train_y_ori, 10)
test_y = np_utils.to_categorical(test_y_ori, 10)
In [12]:
train_y.shape
Out[12]:
LeNet 모델 만들기¶
- 딥러닝은 피처를 추출하는것이 관건이며, feature를 추출하기위해 Conv2D를 이용해 컨볼루션 필터를 적용한다.
- 그리고 특정한 신경이 활성화된다면 (relu), 이에 대해서 중요한 정보만 추출하게 되는 MaxPooling2D를 이용한다.
- 최종적으로는 골라내야하는 손글씨 종류가 10개기 때문에 softmax로 확률값을 총 10개를 추출한다.
In [13]:
class LeNet :
@staticmethod
def build(input_shape, classes):
model = Sequential()
model.add(Conv2D(20, kernel_size = 5, padding="same", input_shape=input_shape))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2), strides = (2,2)))
model.add(Conv2D(50, kernel_size = 5, padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size = (2,2), strides = (2,2)))
model.add(Flatten())
model.add(Dense(500))
model.add(Activation("relu"))
model.add(Dense(10))
model.add(Activation("softmax"))
return model
In [14]:
model = LeNet.build(input_shape = (28, 28, 1), classes = 10)
In [15]:
model.compile(loss = "categorical_crossentropy", optimizer=Adam(), metrics=["accuracy"])
In [16]:
history = model.fit(train_x, train_y, batch_size=256, epochs=10, verbose=1, validation_split=0.2)
In [17]:
score = model.evaluate(test_x, test_y, verbose=1)
최종 정확도¶
In [18]:
print("최종 정확도 : " + str( score[1] * 100 ) + " %" )
- 최종정확도는 epoch가 거듭될수록 좋아지는것을 확인가능하다.
In [19]:
plt.plot(history.history['acc'])
Out[19]:
- 중요한건 validation셋에 대한 정확도가 더 중요하다.
In [20]:
plt.plot(history.history['val_acc'])
Out[20]:
다른방법으로, 프로세스 이해하기¶
- 우리가 지금까지 진행했던건 너무 당연하게 여겨지는 노말라이제이션과 relu를 이용했는데, 다른 방법을 이용해서 나온 결과는 어떨지 확인해보자
- 스케일을 조정하지 않으면 어떨까? 1로 나누면, 아무 스케일링이 없다.
In [21]:
train_x = train_x_ori / 1
test_x = test_x_ori / 1
train_x = train_x[:, :, :,np.newaxis,]
test_x = test_x[:, :, :, np.newaxis]
In [22]:
history = model.fit(train_x, train_y, batch_size=256, epochs=10, verbose=1, validation_split=0.2)
In [23]:
score = model.evaluate(test_x, test_y, verbose=1)
- 스케일이 제대로 조정되지 않으면 최종정확도는 당연히 모델이 제대로 훈련되지 않아 똥인것을 알수있습니다.
In [25]:
print("최종 정확도 : " + str( score[1] * 100 ) + " %" )
In [49]:
train_x = train_x_ori / 255
test_x = test_x_ori / 255
train_x = train_x[:, :, :,np.newaxis,]
test_x = test_x[:, :, :, np.newaxis]
여러가지 파라미터 교체¶
- optimizer를 RMSprop
- activation function tanh로 모델교체
- convolution layer를 한층으로,
- dense layer 50개
- pool과 stride를 교체
In [65]:
class LeNet :
@staticmethod
def build(input_shape, classes):
model = Sequential()
model.add(Conv2D(10, kernel_size = 5, padding="same", input_shape=input_shape))
model.add(Activation("tanh"))
model.add(MaxPooling2D(pool_size = (3,3), strides = (3,3)))
model.add(Flatten())
model.add(Dense(50))
model.add(Activation("tanh"))
model.add(Dense(10))
model.add(Activation("softmax"))
return model
In [66]:
model = LeNet.build(input_shape = (28, 28, 1), classes = 10)
In [67]:
model.compile(loss = "categorical_crossentropy", optimizer=RMSprop(), metrics=["accuracy"])
In [68]:
history = model.fit(train_x, train_y, batch_size=256, epochs=10, verbose=1, validation_split=0.2)
In [69]:
score = model.evaluate(test_x, test_y, verbose=1)
print("최종 정확도 : " + str( score[1] * 100 ) + " %" )