CNN — Convolution neural networks — Dress recognition

Narendra L
Sep 6, 2018 · 6 min read

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.9196

The 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

Narendra L

Written by

Techdummies@YouTube + Python:Web-Design:Bigdata:DataScience

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade