[Deep Learning] MNIST using keras

5 minute read

Keras with MNIST dataset

import numpy as np
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical

Data load

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print(train_images.shape, test_images.shape)
print(train_labels.shape, test_labels.shape)
(60000, 28, 28) (10000, 28, 28)
(60000,) (10000,)
type(train_images), type(train_images[0]), train_images[0].shape
(numpy.ndarray, numpy.ndarray, (28, 28))
type(train_labels), type(train_labels[0]), train_labels[0]
(numpy.ndarray, numpy.uint8, 5)
train_images.shape, train_labels.dtype
((60000, 28, 28), dtype('uint8'))


MNIST image and Preprocessing

import matplotlib.pyplot as plt
%matplotlib inline
plt.subplot(1,2,1)
plt.imshow(train_images[0], cmap=plt.cm.binary)
plt.subplot(1,2,2)
plt.imshow(train_images[0]/255, cmap=plt.cm.binary)
plt.show

output_10_1

# just for checking
print(type(train_labels), train_labels[:10])
train_images.shape, train_labels.shape
<class 'numpy.ndarray'> [5 0 4 1 9 2 1 3 1 4]
((60000, 28, 28), (60000,))


train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype('float32')/255         # scaling

test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype('float32')/255

train_labels = to_categorical(train_labels)   # one-hot encoding
test_labels = to_categorical(test_labels)
train_images.shape, train_labels.shape
((60000, 28, 28, 1), (60000, 10))
print(train_labels[:10], type(train_labels), )
[[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]] <class 'numpy.ndarray'>


MLP

입력 이미지를 하나로 쭉 펴서 모델 학습. 좋은 성능이 나오지 않음.

여기서는 숫자가 가운데에 정렬되어 있기 때문에 비교적 좋은 성능을 보임.

Single flattened layer

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28*28*1))
train_images = train_images.astype('float32')/255         # scaling

test_images = test_images.reshape((10000, 28*28*1))
test_images = test_images.astype('float32')/255

train_labels = to_categorical(train_labels)   # one-hot encoding
test_labels = to_categorical(test_labels)
# a single MLP layer

model = models.Sequential()
# vectorize
model.add(layers.Dense(10, activation='softmax', input_shape = (28*28*1, )))
model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 10)                7850      
=================================================================
Total params: 7,850
Trainable params: 7,850
Non-trainable params: 0
_________________________________________________________________


model.compile(optimizer= 'rmsprop',             # set up hyperparamers
             loss = 'categorical_crossentropy',
             metrics = ['accuracy'])

history = model.fit(train_images, train_labels, epochs=30, batch_size=128, verbose=2)

test_loss, test_acc = model.evaluate(test_images, test_labels) # default batch size=32
print('test_acc = ',test_acc)
Epoch 1/30
469/469 - 2s - loss: 0.6063 - accuracy: 0.8486
Epoch 2/30
469/469 - 1s - loss: 0.3314 - accuracy: 0.9079
...
Epoch 30/30
469/469 - 1s - loss: 0.2482 - accuracy: 0.9336
313/313 [==============================] - 1s 2ms/step - loss: 0.2729 - accuracy: 0.9275
test_acc =  0.9275000095367432
plt.subplot(1,2,1)
plt.plot(history.history['loss'])
plt.subplot(1,2,2)
plt.plot(history.history['accuracy'])

output_20_1

history.history.keys()
dict_keys(['loss', 'accuracy'])


MLP with hidden layers

model = models.Sequential()
model.add(layers.Dense(100, activation='relu', input_shape = (28*28*1, ))) # fully-connected
model.add(layers.Dense(100, activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(10, activation='softmax'))
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 100)               78500     
_________________________________________________________________
dense_2 (Dense)              (None, 100)               10100     
_________________________________________________________________
flatten (Flatten)            (None, 100)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                1010      
=================================================================
Total params: 89,610
Trainable params: 89,610
Non-trainable params: 0
_________________________________________________________________
print(model.input)
print(model.output)
KerasTensor(type_spec=TensorSpec(shape=(None, 784), dtype=tf.float32, name='dense_1_input'), name='dense_1_input', description="created by layer 'dense_1_input'")
KerasTensor(type_spec=TensorSpec(shape=(None, 10), dtype=tf.float32, name=None), name='dense_3/Softmax:0', description="created by layer 'dense_3'")
print(model.input_shape)
print(model.output_shape)
model.input
(None, 784)
(None, 10)
<KerasTensor: shape=(None, 784) dtype=float32 (created by layer 'dense_1_input')>
model.layers[0].input, model.layers[0].output, model.layers[0].trainable
(<KerasTensor: shape=(None, 784) dtype=float32 (created by layer 'dense_1_input')>,
 <KerasTensor: shape=(None, 100) dtype=float32 (created by layer 'dense_1')>,
 True)


model.compile(optimizer= 'rmsprop',             # set up hyperparamers
             loss = 'categorical_crossentropy',
             metrics = ['accuracy'])
model.fit(train_images, train_labels, epochs=30, batch_size=200) 
Epoch 1/30
300/300 [==============================] - 1s 4ms/step - loss: 0.3686 - accuracy: 0.8949
Epoch 2/30
300/300 [==============================] - 1s 4ms/step - loss: 0.1604 - accuracy: 0.9528
...
Epoch 30/30
300/300 [==============================] - 1s 4ms/step - loss: 0.0023 - accuracy: 0.9993
test_loss, test_acc = model.evaluate(test_images, test_labels) # default batch size=32
print('test_acc = ',test_acc)
313/313 [==============================] - 1s 2ms/step - loss: 0.1246 - accuracy: 0.9789
test_acc =  0.9789000153541565



CNN

# keras.layers.Conv2D(filters, kernel_size,...)
# - filters: the dimensionality of the output space (the number of output filters).
# - parameter 수: 입력채널수 X 필터폭 X 필터높이 X 출력채널수 
# - bias 도 고려
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape(60000, 28, 28, 1)
train_images = train_images.astype('float32')/255         # scaling

test_images = test_images.reshape(10000, 28, 28, 1)
test_images = test_images.astype('float32')/255

train_labels = to_categorical(train_labels)   # one-hot encoding
test_labels = to_categorical(test_labels)
from keras import layers
from keras import models

model = models.Sequential()

model.add(layers.Conv2D(32, (3,3), activation='relu', input_shape = (28, 28, 1)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64, (3,3), activation='relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64, (3,3), activation='relu'))
# print(model.output_shape)

model.add(layers.Flatten())
model.add(layers.Dense(10, activation='softmax'))
print(model.output_shape)

model.summary()   
(None, 10)
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 576)               0         
_________________________________________________________________
dense (Dense)                (None, 10)                5770      
=================================================================
Total params: 61,514
Trainable params: 61,514
Non-trainable params: 0
_________________________________________________________________
# number of parameters
# conv2d_1 : 3*3*1*32 + 32 = 320
# conv2d_2 : 3*3*32*64 + 64 = 18496
# conv2d_3 : 3*3*64*64 + 64 = 36928
# dense_6 : 3*3*64*10 + 10 = 5770


model.compile(optimizer= 'rmsprop',
             loss = 'categorical_crossentropy',
             metrics = ['accuracy'])
model.fit(train_images, train_labels, epochs=30, batch_size=200)
Epoch 1/30
300/300 [==============================] - 19s 8ms/step - loss: 0.6169 - accuracy: 0.8129
Epoch 2/30
300/300 [==============================] - 2s 8ms/step - loss: 0.0823 - accuracy: 0.9749
...
Epoch 30/30
300/300 [==============================] - 2s 8ms/step - loss: 7.0306e-04 - accuracy: 0.9998
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('test_acc = ',test_acc)
313/313 [==============================] - 1s 2ms/step - loss: 0.0607 - accuracy: 0.9912
test_acc =  0.9911999702453613



Without Deep Learning

# just for reference
from sklearn.model_selection import train_test_split
from sklearn import datasets, svm, metrics
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import accuracy_score
import numpy as np
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28*28*1))
X = train_images.astype('float32')/255         # scaling
y = train_labels
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
((45000, 784), (15000, 784), (45000,), (15000,))
clf = SGDClassifier(max_iter=200)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(accuracy_score(y_test, y_pred))
0.9111333333333334

Leave a comment