{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nimport os\nimport gc\nimport random","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import data\ntrain_dir = '../input/train/'\ntest_dir = '../input/test/'\n\ntrain_dogs = ['../input/train/{}'.format(i) for i in os.listdir(train_dir) if 'dog' in i] # get dog images\ntrain_cats = ['../input/train/{}'.format(i) for i in os.listdir(train_dir) if 'cat' in i]  # get cat images\n\ntest_imgs = ['../input/test/{}'.format(i) for i in os.listdir(test_dir)] # get test images\ntrain_imgs = train_dogs[:2000] + train_cats[:2000] # slice the dataset and use 2000 in each class\n\nrandom.shuffle(train_imgs) # suffle it randomly\n\n# clear list that are useless\ndel train_dogs\ndel train_cats\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import matplotlib.image as mpimg\nfor ima in train_imgs[0:3]:\n    img = mpimg.imread(ima)\n    plt.imshow(img)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# image dimensions and colour channels\nnrows = 150\nncols = 150\nchannel = 3\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# A function to read and process the images to an acceptable format for our model\ndef read_and_process_image(list_of_images):\n    \"\"\"\n    Returns two arrays:\n        X is an array of resized images\n        y is an array of labels\n    \"\"\"\n    X = []\n    y = []\n\n    for img in list_of_images:\n        try:\n            X.append(cv2.resize(cv2.cvtColor(cv2.imread(img, 1), cv2.COLOR_BGR2RGB), (nrows,ncols), interpolation = cv2.INTER_CUBIC)) # read the images\n            # get the labels  classify dog as 1 and cat as 0\n            if 'dog' in img:\n                y.append(1)\n            elif 'cat' in img:\n                y.append(0)\n        except Exception as e:\n            print('Exception raised as',e)\n            \n    return X,y ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X, y = read_and_process_image(train_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20,10))\ncolumns = 5\nfor i in range(columns):\n    plt.subplot(1,columns,i+1)\n    plt.imshow(X[i])\n    plt.title('dog' if y[i] else 'cat')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del train_imgs\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import seaborn as sns\n# convert list to numpy array\nX = np.array(X)\ny = np.array(y)\n\nsns.countplot(y)\nplt.title('count of dog and cat classes')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(X.shape, y.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# split the data into train and test set\nfrom sklearn.model_selection import train_test_split\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.20, random_state=2)\n\nprint('Shape of train images is', X_train.shape)\nprint('Shape of validation images is', X_val.shape)\nprint('Shape of train labels', y_train.shape)\nprint('Shape of validation labels', y_val.shape)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del X\ndel y\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# get the length of the train and validation set\nntrain = len(X_train)\nnval = len(X_val)\n\nbatch_size = 32 # factor of 2,8,16,32,64,128 so that values can be stored in cache memory.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ntrain_datagen = ImageDataGenerator(rescale = 1./255)\nval_datagen = ImageDataGenerator(rescale = 1./255)\n\ntrain_generator = train_datagen.flow(X_train, y_train, batch_size=30)\nval_generator = val_datagen.flow(X_val, y_val, batch_size=30)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for data_batch, labels_batch in val_generator:\n    print('data batch shape:', data_batch.shape)\n    print('labels batch shape:', labels_batch.shape)\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(data_batch[3])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels_batch[3]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import layers \nfrom keras import models\n\nmodel = models.Sequential() \nmodel.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))\nmodel.add(layers.MaxPooling2D((2, 2))) \nmodel.add(layers.Conv2D(64, (3, 3), activation='relu')) \nmodel.add(layers.MaxPooling2D((2, 2))) \nmodel.add(layers.Conv2D(128, (3, 3), activation='relu')) \nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Flatten()) \nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import optimizers\n\nmodel.compile(loss='binary_crossentropy',\n\noptimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_generator, steps_per_epoch=100, epochs=30, \n                              validation_data=val_generator, validation_steps=50)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nacc = history.history['acc'] \nval_acc = history.history['val_acc'] \nloss = history.history['loss'] \nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'bo', label='Training acc') \nplt.plot(epochs, val_acc, 'b', label='Validation acc') \nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss') \nplt.legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Clearly, Our model is overfitted:\nTry to solve problem of overfitting using Data Augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen = ImageDataGenerator(rotation_range=40, \n                             width_shift_range=0.2,\n                             height_shift_range=0.2, \n                             shear_range=0.2,\n                             zoom_range=0.2,\n                             horizontal_flip=True, \n                             fill_mode='nearest'\n                            )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train_generator = train_datagen.flow(X_train, y_train, batch_size=30)\nplt.imshow(X_train[0])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Generation of cat pictures via random data augmentation**"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing import image\nx = X_train[0]\nx = x.reshape((1,) + x.shape)\ni = 0\nfor batch in datagen.flow(x, batch_size=1):\n    plt.figure(i) \n    imgplot = plt.imshow(image.array_to_img(batch[0]))\n    i += 1\n    if i % 4 == 0:\n        break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = models.Sequential()\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu')) \nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu')) \nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Flatten()) \nmodel.add(layers.Dropout(0.5)) \nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))\nmodel.compile(loss='binary_crossentropy',\n\noptimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Use data augmentation\ntrain_datagen = ImageDataGenerator( rescale=1./255,\n                                   rotation_range=40,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   shear_range=0.2, \n                                   zoom_range=0.2, \n                                   horizontal_flip=True,\n                                  )\n\nval_datagen = ImageDataGenerator(rescale = 1./255)\n\ntrain_generator = train_datagen.flow(X_train, y_train, batch_size=30)\nval_generator = val_datagen.flow(X_val, y_val, batch_size=30)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_generator, steps_per_epoch=100,\n                              epochs=20, validation_data=val_generator,\n                              validation_steps=50)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save('./cat_dog_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nacc = history.history['acc'] \nval_acc = history.history['val_acc'] \nloss = history.history['loss'] \nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'bo', label='Training acc') \nplt.plot(epochs, val_acc, 'b', label='Validation acc') \nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss') \nplt.legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Accuracy around 84% is achieved with data augmentation which was 76% earlier**"},{"metadata":{},"cell_type":"markdown","source":"**Now, We'll use pretrained model to further improve the accuracy**"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications import VGG16\n\nconv_base = VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import models\nfrom keras import layers\n\nmodel = models.Sequential() \nmodel.add(conv_base) \nmodel.add(layers.Flatten()) \nmodel.add(layers.Dense(256, activation='relu')) \nmodel.add(layers.Dense(1, activation='sigmoid'))\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers\n\ntrain_datagen = ImageDataGenerator( rescale=1./255,\n                                   rotation_range=40,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   shear_range=0.2,\n                                   zoom_range=0.2,\n                                   horizontal_flip=True,\n                                   fill_mode='nearest')\nval_datagen = ImageDataGenerator(rescale = 1./255)\n\ntrain_generator = train_datagen.flow(X_train, y_train, batch_size=20)\nval_generator = val_datagen.flow(X_val, y_val, batch_size=20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=2e-5), metrics=['acc'])\n\nhistory = model.fit_generator(train_generator, steps_per_epoch=100, epochs=30, \n                              validation_data=val_generator, validation_steps=50)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del X_train\ndel X_val","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nacc = history.history['acc'] \nval_acc = history.history['val_acc'] \nloss = history.history['loss'] \nval_loss = history.history['val_loss']\n\nepochs = range(1, len(acc) + 1)\n\nplt.plot(epochs, acc, 'bo', label='Training acc') \nplt.plot(epochs, val_acc, 'b', label='Validation acc') \nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss') \nplt.legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Accuracy around 96% is achieved with pretrained model, which is much better than earlier approached model**\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# # import the modules we'll need\n# from IPython.display import HTML\n# import pandas as pd\n# import numpy as np\n# import base64\n\n# # function that takes in a dataframe and creates a text link to  \n# # download it (will only work for files < 2MB or so)\n# def create_download_link(df, title = \"solution\", filename = \"data.csv\"):  \n#     csv = df.to_csv()\n#     b64 = base64.b64encode(csv.encode())\n#     payload = b64.decode()\n#     html = '<a download=\"{filename}\" href=\"data:text/csv;base64,{payload}\" target=\"_blank\">{title}</a>'\n#     html = html.format(payload=payload,title=title,filename=filename)\n#     return HTML(html)\n\n# # create a random sample dataframe\n# # create a link to download the dataframe\n# create_download_link(solution)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Visualizing intermediate activations**"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import load_model\n\nmodel = load_model('./cat_dog_model.h5')\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import models\n\nlayer_outputs = [layer.output for layer in model.layers[:8]]\nactivation_model = models.Model(inputs=model.input, outputs=layer_outputs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing import image\nx = X_train[40]\nx = x.reshape((1,) + x.shape)\ni = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.imshow(x[0])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"activations = activation_model.predict(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"first_layer_activation = activations[0]\n\nprint(first_layer_activation.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.matshow(first_layer_activation[0, :, :, 4], cmap='viridis')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.matshow(first_layer_activation[0, :, :, 7], cmap='viridis')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"layer_names = [] \nfor layer in model.layers[:4]:\n    layer_names.append(layer.name)\nimages_per_row = 16\n\nfor layer_name, layer_activation in zip(layer_names, activations):\n    n_features = layer_activation.shape[-1]\n    size = layer_activation.shape[1]\n    n_cols = n_features // images_per_row\n    display_grid = np.zeros((size * n_cols, images_per_row * size))\n\n    for col in range(n_cols):\n        for row in range(images_per_row):\n            channel_image = layer_activation[0, :, :, col * images_per_row + row] \n            channel_image -= channel_image.mean() \n            channel_image /= channel_image.std()\n            channel_image *= 64 \n            channel_image += 128\n            channel_image = np.clip(channel_image, 0, 255).astype('uint8')\n            display_grid[col * size : (col + 1) * size, row * size : (row + 1) * size] = channel_image\n\n    scale = 1. / size \n    plt.figure(figsize=(scale * display_grid.shape[1], scale * display_grid.shape[0]))\n    plt.title(layer_name) \n    plt.grid(False)\n    plt.imshow(display_grid, aspect='auto', cmap='viridis')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}