반응형

/**

날짜 : 2017.1.22

작성자 : 3개월

제목 : MNIST 데이터로 CNN Training 해보기

*/



1. 패키지 로드 & 데이터 읽기


""" Simple Convolutional Neural Network for MNIST """
import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
K.set_image_dim_ordering('th')
import cPickle, gzip, numpy

# Load the dataset
f = gzip.open('mnist.pkl.gz', 'rb')
train_set, valid_set, test_set = cPickle.load(f)
f.close()


필요한 패키지들을 불러오고 데이터들을 불러옵니다.

mnist.pkl.gz는 

https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/data/mnist.pkl.gz 

에서 다운로드 후 코드와 같은 폴더에 붙여 넣으시면 됩니다.


# train_set 은 튜플로 두 개의 ndsarray를 원소로 가지고 있음
print train_set
print type(train_set)
print len(train_set)

# 튜플을 이렇게 둘로 나눌 수 있음
X_train, y_train = train_set
X_test, y_test = test_set

print type(X_train)
print len(X_train)
print len(y_train)
print X_train
print y_train


이제 MNIST 데이터를 읽어들였고, training set과 test set이 준비 완료되었습니다. 하지만 cnn에서는 x vector의 형태를 알맞게 고치는 preprocessing 작업이 필요합니다.  


2. 데이터 preprocessing


""" In Keras, the layers used for two-dimensional convolutions expect pixel values with the dimensions [pixels][width][height]. """
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32') X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32') # normalize inputs from 0-255 to 0-1 X_train = X_train / 255 X_test = X_test / 255 # one hot encode outputs y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) num_classes = y_test.shape[1] # fix random seed for reproducibility seed = 7 numpy.random.seed(seed)


위와 같이 numpy의 reshape함수를 이용하여 X vector를 [pixels][width][height] 형태로 바꿔줍니다. (이 때 X_train.shape = (50000L, 784L) 라서 X_train.shape[0] = 50000 입니다.)


  • keras에서 cnn을 구현할 때 [pixels][width][height] 형태로 input을 받습니다. (Theano Backend의 경우)

piexels는 흑백이므로 1을 입력하고 MNIST데이터는 28x28 손글씨 이미지이므로 width = 28, height = 28을 입력합니다. 만약 컬러라면 3을 넣어야합니다. 이제 모든 training 데이터와 test 데이터의 준비는 끝났습니다.


3. CNN 모델 


def cnn_model():
    # create model
    model = Sequential()
    model.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(1, 28, 28), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(127, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))
    # Compile model
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model


CNN 모델을 구축하여보겠습니다. 

위 모델은 Convolution Layer-ReLU-Pooling Layer-(Dropout)-Fully Connected Network로 이어지는 구조이며 기본적인 CNN의 구조입니다.


  • Convolution2D(32,5,5...)에서 32는 feature map의 갯수라 할 수 있고 5,5는 5x5 필터 사이즈를 의미합니다. 
  • border_mode는 zero-padding에 관한 세팅입니다. valid는 valid convolution을 의미하여 padding을 주지 않습니다. 만약 same인 경우 same convolution이며 zero-padding을 넣어 convolution 결과의 사이즈과 인풋과 같게 합니다.


4. Training & Test


# build the model
model = cnn_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), nb_epoch=10, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))



이제 CNN을 트레이닝해보겠습니다. validation set은 test set으로 대체하였고, epoch=10, batch_size=200으로 하였습니다. verbose는 로깅에 관한 세팅으로 개념을 이해할 때는 무시하셔도 좋습니다.





error는 validation error을 기준으로 하며 마지막 epoch의 validation error에서 (1-0.9370)*100을 하여 6.3%가 됩니다. 앞서 MLP로 training하였을때는 7% 대에 error를 보였지만 CNN을 통해서 error rate를 낮출 수 있었습니다.






반응형
반응형