CNN — Convolution neural networks — Dress recognition

This notes shows how to implement Convolutional Neural Networks (CNNs) in Python with Keras, and how to overcome overfitting with dropout.
import numpy as np
from keras.utils import to_categorical
import matplotlib.pyplot as plt
% matplotlib inline
from keras.datasets import fashion_mnist
(train_X,train_Y), (test_X,test_Y) = fashion_mnist.load_data()
print "X shape = ", train_X.shape, " Y shape", train_Y.shape
# Y, output categories (sample)
print "sample Y = ", train_Y[:5]
print "Training samples count = ", len(train_X)
print "Testing samples count = ", len(test_X)
# 6:1 ratio for train vs test datasets
X shape = (60000, 28, 28) Y shape (60000,)
sample Y = [9 0 0 3 0]
Training samples count = 60000
Testing samples count = 10000
plt.imshow(train_X[0], cmap='gray')
print "Below Image belongs to =", train_Y[0]
Below Image belongs to = 9
plt.imshow(train_X[1], cmap='gray')
print "Below Image belongs to =", train_Y[1]
#Below Image belongs to = 0
Data Preprocessing
As you could see in the above plot, the images are grayscale images have pixel values that range from 0 to 255. Also, these images have a dimension of 28 x 28. As a result you’ll need to preprocess the data before you feed it into the model.
Step 1
convert each 28 x 28 image of the train and test set into a matrix # of size 28 x 28 x 1 which is fed into the network
temp_train_X = train_X
train_X = train_X.reshape(-1, 28, 28, 1)
test_X = test_X.reshape(-1, 28, 28, 1)
print train_X.shape, test_X.shape
(60000, 28, 28, 1) (10000, 28, 28, 1)
# Convert to float
train_X = train_X.astype('float32')
test_X = test_X.astype('float32')
# convert pixels to 0 or 1
train_X = train_X / 255.
test_X = test_X / 255.Convert class labels to ONE HOT ENCODER
# Y = [SHIRT, SHOE, TIE] ==One Hot Encode=== [[SHORT, SHOE, TIE], [1, 0, 0], [0, 1, 0], [0, 0, 1]]
# creates y axis those many number sof labels
# Keras use to_categorical method whic does automatically
train_Y_one_hot = to_categorical(train_Y)
test_Y_one_hot = to_categorical(test_Y)
print "few hot encoded y axis = ", test_Y[0:5]
print "===" * 15
print train_Y_one_hot[0], train_Y[0]
print train_X.shape, train_Y_one_hot.shape
few hot encoded y axis = [9 2 1 1 6]
=============================================
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.] 9
(60000, 28, 28, 1) (60000, 10)Then Split data in to test and training set
from sklearn.model_selection import train_test_split
train_X, valid_X, train_label, valid_label = train_test_split(train_X, train_Y_one_hot, test_size=0.2, random_state=13)Best convolution layer tutorials
http://brohrer.github.io/how_convolutional_neural_networks_work.html
# Convolution -> Relu -> Pooling (Repeat repeat repeat)
import keras
from keras.models import Sequential,Input,Model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import LeakyReLU
batch_size = 64
epochs = 20
num_classes = 10
fashion_model = Sequential()
fashion_model.add(Conv2D(32, kernel_size=(3, 3),activation='linear',input_shape=(28,28,1),padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D((2, 2),padding='same'))
fashion_model.add(Conv2D(64, (3, 3), activation='linear',padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D(pool_size=(2, 2),padding='same'))
fashion_model.add(Conv2D(128, (3, 3), activation='linear',padding='same'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(MaxPooling2D(pool_size=(2, 2),padding='same'))
fashion_model.add(Flatten())
fashion_model.add(Dense(128, activation='linear'))
fashion_model.add(LeakyReLU(alpha=0.1))
fashion_model.add(Dense(num_classes, activation='softmax'))
fashion_model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(),metrics=['accuracy'])
fashion_model.summary()And here the training summary
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_7 (Conv2D) (None, 28, 28, 32) 320
_________________________________________________________________
leaky_re_lu_9 (LeakyReLU) (None, 28, 28, 32) 0
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 14, 14, 32) 0
_________________________________________________________________
conv2d_8 (Conv2D) (None, 14, 14, 64) 18496
_________________________________________________________________
leaky_re_lu_10 (LeakyReLU) (None, 14, 14, 64) 0
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
conv2d_9 (Conv2D) (None, 7, 7, 128) 73856
_________________________________________________________________
leaky_re_lu_11 (LeakyReLU) (None, 7, 7, 128) 0
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 4, 4, 128) 0
_________________________________________________________________
flatten_3 (Flatten) (None, 2048) 0
_________________________________________________________________
dense_5 (Dense) (None, 128) 262272
_________________________________________________________________
leaky_re_lu_12 (LeakyReLU) (None, 128) 0
_________________________________________________________________
dense_6 (Dense) (None, 10) 1290
=================================================================
Total params: 356,234
Trainable params: 356,234
Non-trainable params: 0
_________________________________________________________________
fashion_train = fashion_model.fit(train_X, train_label, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(valid_X, valid_label))
Train on 48000 samples, validate on 12000 samples
Epoch 1/20
48000/48000 [==============================] - 87s 2ms/step - loss: 0.4677 - acc: 0.8294 - val_loss: 0.3295 - val_acc: 0.8792
Epoch 2/20
48000/48000 [==============================] - 160s 3ms/step - loss: 0.2926 - acc: 0.8934 - val_loss: 0.2773 - val_acc: 0.8979
Epoch 3/20
48000/48000 [==============================] - 87s 2ms/step - loss: 0.2476 - acc: 0.9074 - val_loss: 0.2521 - val_acc: 0.9066
Epoch 4/20
48000/48000 [==============================] - 80s 2ms/step - loss: 0.2147 - acc: 0.9196 - val_loss: 0.2359 - val_acc: 0.9151
Epoch 5/20
48000/48000 [==============================] - 85s 2ms/step - loss: 0.1880 - acc: 0.9300 - val_loss: 0.2382 - val_acc: 0.9148
Epoch 6/20
48000/48000 [==============================] - 138s 3ms/step - loss: 0.1665 - acc: 0.9378 - val_loss: 0.2218 - val_acc: 0.9211
Epoch 7/20
48000/48000 [==============================] - 135s 3ms/step - loss: 0.1438 - acc: 0.9467 - val_loss: 0.2579 - val_acc: 0.9142
Epoch 8/20
48000/48000 [==============================] - 82s 2ms/step - loss: 0.1248 - acc: 0.9539 - val_loss: 0.2234 - val_acc: 0.9253
Epoch 9/20
48000/48000 [==============================] - 127s 3ms/step - loss: 0.1085 - acc: 0.9597 - val_loss: 0.2467 - val_acc: 0.9217
Epoch 10/20
48000/48000 [==============================] - 182s 4ms/step - loss: 0.0893 - acc: 0.9667 - val_loss: 0.2728 - val_acc: 0.9187
Epoch 11/20
48000/48000 [==============================] - 168s 3ms/step - loss: 0.0801 - acc: 0.9704 - val_loss: 0.2645 - val_acc: 0.9193
Epoch 12/20
48000/48000 [==============================] - 106s 2ms/step - loss: 0.0687 - acc: 0.9745 - val_loss: 0.2874 - val_acc: 0.9221
Epoch 13/20
48000/48000 [==============================] - 86s 2ms/step - loss: 0.0586 - acc: 0.9779 - val_loss: 0.3126 - val_acc: 0.9171
Epoch 14/20
48000/48000 [==============================] - 75s 2ms/step - loss: 0.0539 - acc: 0.9793 - val_loss: 0.3157 - val_acc: 0.9221
Epoch 15/20
48000/48000 [==============================] - 78s 2ms/step - loss: 0.0427 - acc: 0.9841 - val_loss: 0.3392 - val_acc: 0.9217
Epoch 16/20
48000/48000 [==============================] - 77s 2ms/step - loss: 0.0425 - acc: 0.9840 - val_loss: 0.3654 - val_acc: 0.9254
Epoch 17/20
48000/48000 [==============================] - 76s 2ms/step - loss: 0.0374 - acc: 0.9859 - val_loss: 0.3787 - val_acc: 0.9212
Epoch 18/20
48000/48000 [==============================] - 76s 2ms/step - loss: 0.0365 - acc: 0.9863 - val_loss: 0.3733 - val_acc: 0.9196
Epoch 19/20
48000/48000 [==============================] - 76s 2ms/step - loss: 0.0335 - acc: 0.9874 - val_loss: 0.4251 - val_acc: 0.9193
Epoch 20/20
48000/48000 [==============================] - 76s 2ms/step - loss: 0.0269 - acc: 0.9902 - val_loss: 0.4138 - val_acc: 0.9196The training accuracy is 99%(acc), awesome.
From the val_loss: 0.4138
it shows us that the model is overfitting To avoid overfitting we have to have a droupout layer Before that let’s evaluate using test data
test_eval = fashion_model.evaluate(test_X, test_Y_one_hot, verbose=0)
print "Test Loss=",test_eval[0], " Test Accuracy=",test_eval[1]
Test Loss= 0.448352068252 Test Accuracy= 0.9124
predicted_classes = fashion_model.predict(test_X)
print "predicted= ", predicted_classes[0]It’s not like the expected label(looks like hot encoded version but varying values), let’s find the max in each predicted output
predicted= [ 3.36922089e-19 3.71982040e-14 7.71334506e-18 3.38777328e-15
2.33446251e-16 5.07623034e-15 3.01408459e-19 8.75168205e-09
5.17265352e-17 1.00000000e+00]
predicted_classes = np.argmax(np.round(predicted_classes),axis=1)
print predicted_classes[0]
9
print "predicted vs test shapes = ", predicted_classes.shape, test_Y.shape
print "predicted= ",predicted_classes[:10], " Test=", test_Y[:10]Looks like its working
Lets get correct and incorrect ones
predicted vs test shapes = (10000,) (10000,)
predicted= [9 2 1 1 6 1 4 6 5 7] Test= [9 2 1 1 6 1 4 6 5 7]
correct_ones = np.where(predicted_classes == test_Y)[0]
incorrect_ones = np.where(predicted_classes != test_Y)[0]
print "There are ", len(correct_ones), " Correct ones"
print "There are ", len(incorrect_ones), " Incorrect ones"
There are 9118 Correct ones
There are 882 Incorrect ones
Lets plot correct ones
for i, pred in enumerate(correct_ones[:9]):
plt.subplot(3, 3, i+1)
plt.imshow(test_X[i].reshape(28,28), cmap='gray')
plt.title("pred={} act={}".format(pred, test_Y[i]))
plt.tight_layout()
Lets plot INCORRECT/WRONG ones
for i, pred in enumerate(incorrect_ones[:9]):
plt.subplot(3, 3, i+1)
plt.imshow(test_X[i].reshape(28,28), cmap='gray')
plt.title("pred={} act={}".format(pred, test_Y[i]))
plt.tight_layout()
Ref: https://www.datacamp.com/community/tutorials/convolutional-neural-networks-python
