CNN classify Cats and Dogs

  • get data
In [1]:
# !wget http://www.superdatascience.com/wp-content/uploads/2017/04/Convolutional_Neural_Networks.zip
# !unzip Convolutional_Neural_Networks.zip
In [2]:
import warnings
warnings.filterwarnings("ignore")

import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"   # see issue #152
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D, Flatten, Dense, Dropout

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
Using TensorFlow backend.
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 2070622769429467382
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 4980145766
locality {
  bus_id: 1
}
incarnation: 17975378673379469628
physical_device_desc: "device: 0, name: GeForce GTX 1060 6GB, pci bus id: 0000:01:00.0, compute capability: 6.1"
]
In [3]:
# initializing
classifier = Sequential()
# Step 1  - Convolution
classifier.add(Convolution2D(192, (3, 3), input_shape=(64, 64, 3), activation='relu'))
# step 2 - Pooling
classifier.add(MaxPooling2D(pool_size=(2,2)))
classifier.add(Dropout(rate= 0.03))

# add another convolution layer
classifier.add(Convolution2D(128, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2,2)))
classifier.add(Dropout(rate= 0.02))

# add another convolution layer
classifier.add(Convolution2D(64, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2,2)))
classifier.add(Dropout(rate= 0.01))

# step 3 - Flattening
classifier.add(Flatten())
# step 4 - full Connection
classifier.add(Dense(128, activation='relu'))
# step 5 - Output layer
classifier.add(Dense(1, activation='sigmoid'))
# compile
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

classifier.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 62, 62, 192)       5376      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 31, 31, 192)       0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 31, 31, 192)       0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 29, 29, 128)       221312    
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 14, 14, 128)       0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 14, 14, 128)       0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 12, 12, 64)        73792     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 6, 6, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 2304)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               295040    
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 129       
=================================================================
Total params: 595,649
Trainable params: 595,649
Non-trainable params: 0
_________________________________________________________________

image proprocessing & trainning, testing

In [4]:
# !dir dataset
from keras.preprocessing.image import ImageDataGenerator
1, 1.,7., 9
Out[4]:
(1, 1.0, 7.0, 9)
In [5]:
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)

training_set = train_datagen.flow_from_directory(
        './Convolutional_Neural_Networks/dataset/training_set',
        target_size=(64, 64),
        batch_size=16,
        class_mode='binary')

test_set = test_datagen.flow_from_directory(
        './Convolutional_Neural_Networks/dataset/test_set',
        target_size=(64, 64),
        batch_size=16,
        class_mode='binary')
Found 8000 images belonging to 2 classes.
Found 2000 images belonging to 2 classes.
In [6]:
from time import time, ctime
start = time()
classifier.fit_generator(
        training_set,
        steps_per_epoch= 8000/16,
        epochs=40,
        validation_data= test_set,
        validation_steps= 2000/16)
eclipse=time()-start
print ('used: {:.2f} s'.format(eclipse))
Epoch 1/40
500/500 [==============================] - 27s 55ms/step - loss: 0.6807 - acc: 0.5684 - val_loss: 0.6677 - val_acc: 0.5765
Epoch 2/40
500/500 [==============================] - 24s 49ms/step - loss: 0.6513 - acc: 0.6184 - val_loss: 0.6343 - val_acc: 0.6410
Epoch 3/40
500/500 [==============================] - 24s 49ms/step - loss: 0.6220 - acc: 0.6590 - val_loss: 0.6115 - val_acc: 0.6775
Epoch 4/40
500/500 [==============================] - 26s 51ms/step - loss: 0.5865 - acc: 0.6959 - val_loss: 0.5721 - val_acc: 0.7015
Epoch 5/40
500/500 [==============================] - 26s 52ms/step - loss: 0.5586 - acc: 0.7144 - val_loss: 0.5314 - val_acc: 0.7415
Epoch 6/40
500/500 [==============================] - 26s 51ms/step - loss: 0.5361 - acc: 0.7294 - val_loss: 0.5575 - val_acc: 0.7115
Epoch 7/40
500/500 [==============================] - 26s 51ms/step - loss: 0.5193 - acc: 0.7441 - val_loss: 0.5228 - val_acc: 0.7415
Epoch 8/40
500/500 [==============================] - 27s 54ms/step - loss: 0.4962 - acc: 0.7572 - val_loss: 0.5047 - val_acc: 0.7600
Epoch 9/40
500/500 [==============================] - 27s 55ms/step - loss: 0.4808 - acc: 0.7670 - val_loss: 0.4713 - val_acc: 0.7760
Epoch 10/40
500/500 [==============================] - 29s 58ms/step - loss: 0.4634 - acc: 0.7760 - val_loss: 0.4947 - val_acc: 0.7735
Epoch 11/40
500/500 [==============================] - 26s 53ms/step - loss: 0.4594 - acc: 0.7758 - val_loss: 0.4702 - val_acc: 0.7705
Epoch 12/40
500/500 [==============================] - 26s 52ms/step - loss: 0.4396 - acc: 0.7915 - val_loss: 0.4574 - val_acc: 0.7905
Epoch 13/40
500/500 [==============================] - 26s 52ms/step - loss: 0.4274 - acc: 0.7987 - val_loss: 0.4761 - val_acc: 0.7750
Epoch 14/40
500/500 [==============================] - 26s 51ms/step - loss: 0.4119 - acc: 0.8081 - val_loss: 0.5116 - val_acc: 0.7655
Epoch 15/40
500/500 [==============================] - 26s 52ms/step - loss: 0.4037 - acc: 0.8105 - val_loss: 0.4255 - val_acc: 0.8075
Epoch 16/40
500/500 [==============================] - 28s 56ms/step - loss: 0.3987 - acc: 0.8154 - val_loss: 0.4369 - val_acc: 0.7980
Epoch 17/40
500/500 [==============================] - 27s 54ms/step - loss: 0.3874 - acc: 0.8220 - val_loss: 0.4492 - val_acc: 0.7975
Epoch 18/40
500/500 [==============================] - 26s 52ms/step - loss: 0.3807 - acc: 0.8258 - val_loss: 0.4394 - val_acc: 0.8005
Epoch 19/40
500/500 [==============================] - 26s 53ms/step - loss: 0.3645 - acc: 0.8365 - val_loss: 0.4086 - val_acc: 0.8220
Epoch 20/40
500/500 [==============================] - 27s 54ms/step - loss: 0.3521 - acc: 0.8399 - val_loss: 0.3972 - val_acc: 0.8250
Epoch 21/40
500/500 [==============================] - 26s 52ms/step - loss: 0.3504 - acc: 0.8369 - val_loss: 0.4060 - val_acc: 0.8155
Epoch 22/40
500/500 [==============================] - 27s 55ms/step - loss: 0.3310 - acc: 0.8540 - val_loss: 0.3975 - val_acc: 0.8245
Epoch 23/40
500/500 [==============================] - 26s 51ms/step - loss: 0.3365 - acc: 0.8495 - val_loss: 0.4065 - val_acc: 0.8235
Epoch 24/40
500/500 [==============================] - 26s 51ms/step - loss: 0.3268 - acc: 0.8541 - val_loss: 0.3978 - val_acc: 0.8300
Epoch 25/40
500/500 [==============================] - 26s 52ms/step - loss: 0.3117 - acc: 0.8643 - val_loss: 0.4556 - val_acc: 0.8045
Epoch 26/40
500/500 [==============================] - 26s 52ms/step - loss: 0.3077 - acc: 0.8629 - val_loss: 0.4262 - val_acc: 0.8265
Epoch 27/40
500/500 [==============================] - 26s 51ms/step - loss: 0.2976 - acc: 0.8661 - val_loss: 0.4183 - val_acc: 0.8190
Epoch 28/40
500/500 [==============================] - 26s 51ms/step - loss: 0.2880 - acc: 0.8745 - val_loss: 0.4455 - val_acc: 0.8235
Epoch 29/40
500/500 [==============================] - 25s 51ms/step - loss: 0.2779 - acc: 0.8788 - val_loss: 0.4679 - val_acc: 0.8150
Epoch 30/40
500/500 [==============================] - 25s 51ms/step - loss: 0.2805 - acc: 0.8798 - val_loss: 0.4049 - val_acc: 0.8350
Epoch 31/40
500/500 [==============================] - 27s 54ms/step - loss: 0.2760 - acc: 0.8840 - val_loss: 0.4043 - val_acc: 0.8340
Epoch 32/40
500/500 [==============================] - 26s 52ms/step - loss: 0.2727 - acc: 0.8792 - val_loss: 0.4338 - val_acc: 0.8375
Epoch 33/40
500/500 [==============================] - 26s 52ms/step - loss: 0.2695 - acc: 0.8877 - val_loss: 0.4701 - val_acc: 0.8165
Epoch 34/40
500/500 [==============================] - 26s 51ms/step - loss: 0.2551 - acc: 0.8929 - val_loss: 0.4269 - val_acc: 0.8395
Epoch 35/40
500/500 [==============================] - 26s 52ms/step - loss: 0.2412 - acc: 0.8966 - val_loss: 0.4778 - val_acc: 0.8195
Epoch 36/40
500/500 [==============================] - 26s 52ms/step - loss: 0.2423 - acc: 0.8966 - val_loss: 0.4510 - val_acc: 0.8375
Epoch 37/40
500/500 [==============================] - 26s 51ms/step - loss: 0.2364 - acc: 0.9005 - val_loss: 0.4317 - val_acc: 0.8370
Epoch 38/40
500/500 [==============================] - 26s 52ms/step - loss: 0.2278 - acc: 0.9056 - val_loss: 0.5216 - val_acc: 0.8115
Epoch 39/40
500/500 [==============================] - 29s 58ms/step - loss: 0.2278 - acc: 0.9015 - val_loss: 0.5014 - val_acc: 0.8155
Epoch 40/40
500/500 [==============================] - 28s 55ms/step - loss: 0.2087 - acc: 0.9114 - val_loss: 0.4820 - val_acc: 0.8390
used: 1051.52 s
In [8]:
print (eclipse)
# ctime()
1051.5185248851776
In [9]:
eclipse/60
Out[9]:
17.525308748086292

predict

In [10]:
import numpy as np
from keras.preprocessing import image
In [12]:
t1 = image.load_img('./Convolutional_Neural_Networks/dataset/single_prediction/cat_or_dog_1.jpg',
                  target_size=(64,64))
In [13]:
type(t1)
Out[13]:
PIL.Image.Image
In [14]:
t1
Out[14]:
In [15]:
t1.size
Out[15]:
(64, 64)
In [16]:
arr1 = image.img_to_array(t1)
arr1.shape
Out[16]:
(64, 64, 3)
In [17]:
arr1[:1][0][0:6]
Out[17]:
array([[54., 58.,  7.],
       [58., 63.,  9.],
       [64., 67., 10.],
       [71., 75., 16.],
       [72., 76., 17.],
       [72., 78., 16.]], dtype=float32)
In [19]:
t2 = image.load_img('./Convolutional_Neural_Networks/dataset/single_prediction/cat_or_dog_2.jpg',
                  target_size=(64,64))
In [20]:
t2
Out[20]:
In [21]:
arr2 = image.img_to_array(t2)
arr2.shape
Out[21]:
(64, 64, 3)
In [22]:
np.expand_dims(arr1, axis=0).shape
Out[22]:
(1, 64, 64, 3)
In [23]:
np.concatenate([arr1, arr2]).shape
Out[23]:
(128, 64, 3)
In [24]:
np.concatenate([arr1, arr2], axis=2).shape
Out[24]:
(64, 64, 6)
In [25]:
np.concatenate([np.expand_dims(arr1, axis=0), np.expand_dims(arr2, axis=0)]).shape
Out[25]:
(2, 64, 64, 3)

predict only takes batch of input

In [26]:
classifier.predict(np.expand_dims(arr2, axis=0)/255.0)
Out[26]:
array([[0.03821517]], dtype=float32)
In [27]:
classifier.predict(np.concatenate([np.expand_dims(arr1, axis=0), np.expand_dims(arr2, axis=0)])/255.0)
Out[27]:
array([[0.9999999 ],
       [0.03821515]], dtype=float32)
In [28]:
training_set.class_indices
Out[28]:
{'cats': 0, 'dogs': 1}

predict on folder with pics

In [36]:
test_datagen = ImageDataGenerator(rescale=1./255)
test_datagen
Out[36]:
<keras.preprocessing.image.ImageDataGenerator at 0x1a10d5bc940>
In [40]:
pred = test_datagen.flow_from_directory(
        'Convolutional_Neural_Networks/dataset/single_prediction/',
        target_size=(64, 64))
Found 2 images belonging to 1 classes.
In [42]:
result = classifier.predict_generator(pred, steps=1)
type(result)
Out[42]:
numpy.ndarray
In [43]:
result
Out[43]:
array([[0.9999999 ],
       [0.03821517]], dtype=float32)
In [44]:
pred.filenames
Out[44]:
['pred\\cat_or_dog_1.jpg', 'pred\\cat_or_dog_2.jpg']