Classify Fashion-MNIST with a simple CNN


Original by Margaret Maynard-Reid, 4/24/2018
Oringal Notebook: https://github.com/margaretmz/deep-learning/blob/master/fashion_mnist_keras.ipynb
Oringal Tutorial: https://medium.com/tensorflow/hello-deep-learning-fashion-mnist-with-keras-50fcff8cd74a


In [0]:
!pip install -q tf-nightly-gpu-2.0-preview

In [2]:
import tensorflow as tf
print(tf.__version__)


2.0.0-dev20190502

In [3]:
import tensorflow as tf

import numpy as np
import matplotlib.pyplot as plt

# Load the fashion-mnist pre-shuffled train data and test data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()

print("x_train shape:", x_train.shape, "y_train shape:", y_train.shape)


x_train shape: (60000, 28, 28) y_train shape: (60000,)

Visualize the data


In [4]:
# Print training set shape - note there are 60,000 training data of image size of 28x28, 60,000 train labels)
print("x_train shape:", x_train.shape, "y_train shape:", y_train.shape)

# Print the number of training and test datasets
print(x_train.shape[0], 'train set')
print(x_test.shape[0], 'test set')

# Define the text labels
fashion_mnist_labels = ["T-shirt/top",  # index 0
                        "Trouser",      # index 1
                        "Pullover",     # index 2 
                        "Dress",        # index 3 
                        "Coat",         # index 4
                        "Sandal",       # index 5
                        "Shirt",        # index 6 
                        "Sneaker",      # index 7 
                        "Bag",          # index 8 
                        "Ankle boot"]   # index 9

# Image index, you can pick any number between 0 and 59,999
img_index = 5
# y_train contains the lables, ranging from 0 to 9
label_index = y_train[img_index]
# Print the label, for example 2 Pullover
print ("y = " + str(label_index) + " " +(fashion_mnist_labels[label_index]))
# # Show one of the images from the training dataset
plt.imshow(x_train[img_index])


x_train shape: (60000, 28, 28) y_train shape: (60000,)
60000 train set
10000 test set
y = 2 Pullover
Out[4]:
<matplotlib.image.AxesImage at 0x7f6bd1d088d0>

In [5]:
w, h = 28, 28
x_train = x_train.reshape(x_train.shape[0], w, h, 1)
x_test = x_test.reshape(x_test.shape[0], w, h, 1)

x_train.shape


Out[5]:
(60000, 28, 28, 1)

In [6]:
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten

model = tf.keras.Sequential()

model.add(Conv2D(filters=64, kernel_size=2, padding='same', activation='relu', input_shape=(28,28,1))) 
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.3))

model.add(Conv2D(filters=32, kernel_size=2, padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.3))

model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

model.summary()


Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 28, 28, 64)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 64)        0         
_________________________________________________________________
dropout (Dropout)            (None, 14, 14, 64)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 14, 14, 32)        8224      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 32)          0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 7, 7, 32)          0         
_________________________________________________________________
flatten (Flatten)            (None, 1568)              0         
_________________________________________________________________
dense (Dense)                (None, 256)               401664    
_________________________________________________________________
dropout_2 (Dropout)          (None, 256)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                2570      
=================================================================
Total params: 412,778
Trainable params: 412,778
Non-trainable params: 0
_________________________________________________________________

In [7]:
%%time

BATCH_SIZE=1000
EPOCHS = 15

model.compile(loss='sparse_categorical_crossentropy',
             optimizer='adam',
             metrics=['accuracy'])
history = model.fit(x_train, y_train, epochs=EPOCHS, batch_size=BATCH_SIZE, validation_split=0.2, verbose=1)


Train on 48000 samples, validate on 12000 samples
Epoch 1/15
48000/48000 [==============================] - 7s 150us/sample - loss: 5.0050 - accuracy: 0.4942 - val_loss: 0.7625 - val_accuracy: 0.7138
Epoch 2/15
48000/48000 [==============================] - 3s 71us/sample - loss: 0.9092 - accuracy: 0.6697 - val_loss: 0.6098 - val_accuracy: 0.7735
Epoch 3/15
48000/48000 [==============================] - 4s 75us/sample - loss: 0.7638 - accuracy: 0.7132 - val_loss: 0.5440 - val_accuracy: 0.7904
Epoch 4/15
48000/48000 [==============================] - 4s 74us/sample - loss: 0.6828 - accuracy: 0.7402 - val_loss: 0.5009 - val_accuracy: 0.8207
Epoch 5/15
48000/48000 [==============================] - 4s 75us/sample - loss: 0.6381 - accuracy: 0.7584 - val_loss: 0.4655 - val_accuracy: 0.8298
Epoch 6/15
48000/48000 [==============================] - 4s 74us/sample - loss: 0.5982 - accuracy: 0.7722 - val_loss: 0.4391 - val_accuracy: 0.8292
Epoch 7/15
48000/48000 [==============================] - 3s 65us/sample - loss: 0.5698 - accuracy: 0.7829 - val_loss: 0.4182 - val_accuracy: 0.8456
Epoch 8/15
48000/48000 [==============================] - 4s 75us/sample - loss: 0.5447 - accuracy: 0.7936 - val_loss: 0.4035 - val_accuracy: 0.8528
Epoch 9/15
48000/48000 [==============================] - 4s 75us/sample - loss: 0.5186 - accuracy: 0.8041 - val_loss: 0.3790 - val_accuracy: 0.8623
Epoch 10/15
48000/48000 [==============================] - 4s 76us/sample - loss: 0.5037 - accuracy: 0.8115 - val_loss: 0.3686 - val_accuracy: 0.8662
Epoch 11/15
48000/48000 [==============================] - 4s 74us/sample - loss: 0.4880 - accuracy: 0.8175 - val_loss: 0.3581 - val_accuracy: 0.8679
Epoch 12/15
48000/48000 [==============================] - 3s 62us/sample - loss: 0.4693 - accuracy: 0.8248 - val_loss: 0.3456 - val_accuracy: 0.8755
Epoch 13/15
48000/48000 [==============================] - 3s 61us/sample - loss: 0.4559 - accuracy: 0.8303 - val_loss: 0.3433 - val_accuracy: 0.8759
Epoch 14/15
48000/48000 [==============================] - 3s 64us/sample - loss: 0.4422 - accuracy: 0.8347 - val_loss: 0.3290 - val_accuracy: 0.8804
Epoch 15/15
48000/48000 [==============================] - 4s 76us/sample - loss: 0.4367 - accuracy: 0.8375 - val_loss: 0.3245 - val_accuracy: 0.8795
CPU times: user 22.4 s, sys: 8.02 s, total: 30.4 s
Wall time: 56.3 s

In [8]:
train_loss, train_accuracy = model.evaluate(x_train, y_train, batch_size=BATCH_SIZE)
train_accuracy


60000/60000 [==============================] - 1s 14us/sample - loss: 0.3081 - accuracy: 0.8850
Out[8]:
0.8849667

In [9]:
test_loss, test_accuracy = model.evaluate(x_test, y_test, batch_size=BATCH_SIZE)
test_accuracy


10000/10000 [==============================] - 0s 14us/sample - loss: 0.3447 - accuracy: 0.8757
Out[9]:
0.8757

In [10]:
plt.xlabel('epochs')
plt.ylabel('loss')

plt.yscale('log')

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.legend(['Loss', 'Validation Loss'])


Out[10]:
<matplotlib.legend.Legend at 0x7f6ba75a0978>

In [11]:
plt.xlabel('epochs')
plt.ylabel('accuracy')

plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['Accuracy', 'Validation Accuracy'])


Out[11]:
<matplotlib.legend.Legend at 0x7f6ba740be10>

In [12]:
y_hat = model.predict(x_test)

# Plot a random sample of 10 test images, their predicted labels and ground truth
figure = plt.figure(figsize=(20, 8))
for i, index in enumerate(np.random.choice(x_test.shape[0], size=15, replace=False)):
    ax = figure.add_subplot(3, 5, i + 1, xticks=[], yticks=[])
    # Display each image
    ax.imshow(np.squeeze(x_test[index]))
    predict_index = np.argmax(y_hat[index])
    true_index = y_test[index]
    # Set the title for each image
    ax.set_title("{} ({})".format(fashion_mnist_labels[predict_index], 
                                  fashion_mnist_labels[true_index]),
                                  color=("green" if predict_index == true_index else "red"))



In [0]: