{"cells":[{"metadata":{"_uuid":"69988af3ecf4a59ebee5514efb9bbfa646dd353f"},"cell_type":"markdown","source":"# Dogs vs. Cats CNN with Keras"},{"metadata":{"_uuid":"a8343312adcb56ea7c941c92926d541b794267ef"},"cell_type":"markdown","source":"This notebook is referenced from https://www.kaggle.com/jeffd23/catdognet-keras-convnet-starter"},{"metadata":{"_uuid":"4709003f6d57329a5be60491cf95e74331c5ebd7"},"cell_type":"markdown","source":"# Importing packages"},{"metadata":{"trusted":true,"_uuid":"c1fd1a7a29caa93e3844dd6c673c2b76fcc600ae"},"cell_type":"code","source":"import tensorflow\nfrom tensorflow import keras\n%matplotlib inline\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"11cdd1874b5458fc5ca9dd1d26612a3ad9d0e9ef"},"cell_type":"code","source":"import os, cv2, random\nimport numpy as np\nimport pandas as pd","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b7d8c8f0015b6a96e99c628c50711fb4690b94a3"},"cell_type":"code","source":"from matplotlib import ticker\nimport seaborn as sns","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"aaa14e76c44300ae79b13309df19dffaef7d997d"},"cell_type":"markdown","source":"# Preparing train and test data"},{"metadata":{"trusted":true,"_uuid":"d54b4b32bffb2245aaddd47326cc73a903e93287"},"cell_type":"code","source":"TRAIN_DIR = '../input/train/'\nTEST_DIR = '../input/test/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1b2774e0e61ad84f030b79261ff0f7794f57660c"},"cell_type":"code","source":"ROWS = 64\nCOLS = 64\nCHANNELS = 3","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"24f679e91c8f8d6230ebc545d0aa100bbeb50836"},"cell_type":"markdown","source":"# List comprehension"},{"metadata":{"trusted":true,"_uuid":"f0769508f60007ec86bb6ebf2ddce6c094f38280"},"cell_type":"code","source":"train_images = [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR)] # use this for full dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"745663a864606d445a2ee9df7da665cb051f931f"},"cell_type":"code","source":"len(train_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b5088dd783dfab56f137050cdf4bcc503b1428e4"},"cell_type":"code","source":"train_images[1000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0164e2e8aeae35e10bb031d85a30e58300fc688a"},"cell_type":"code","source":"train_dogs =   [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'dog' in i]\ntrain_cats =   [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'cat' in i]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a583f6acdc8012421f733b60b153c3568852192c"},"cell_type":"code","source":"len(train_dogs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c7c3b75c90f37fc0cb74d95d9f12f8dbddadb6bc"},"cell_type":"code","source":"len(train_cats)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"68b69af66a4f07e90612852f67db9800e13233f9"},"cell_type":"code","source":"test_images =  [TEST_DIR+i for i in os.listdir(TEST_DIR)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b577058abdc005be86c3cdc1e5924c861d289069"},"cell_type":"code","source":"len(test_images)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3932c33d4b3f4f50e38358d93fd5e7e695f408ba"},"cell_type":"markdown","source":"# Slicing list data"},{"metadata":{"trusted":true,"_uuid":"c5ac265b56ece00074946a8dfba9a4a80d11467f"},"cell_type":"code","source":"# slice datasets for memory efficiency on Kaggle Kernels\ntrain_images = train_dogs[:1000] + train_cats[:1000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4e89ecd3538c26d68d7fd37f68332585b7b72d33"},"cell_type":"code","source":"len(train_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d5d1e814ca1e0a88a922716f7c4800ee9f0e0dd1"},"cell_type":"code","source":"random.shuffle(train_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2ebd34c2ca9d3062fd9bb9d16d67657823544890"},"cell_type":"code","source":"test_images =  test_images[:25]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"34f9c6eaf42cd7d8f6e6d073e98fa4765facf2ca"},"cell_type":"code","source":"len(test_images)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a5725b3fd5af4b70908a7f023f9ba367bda1b81b"},"cell_type":"markdown","source":"# Converting image to multi-dimensional array"},{"metadata":{"trusted":true,"_uuid":"fdd80d4d70cd87aa71c9518e1a9b234a59548794"},"cell_type":"code","source":"def read_image(file_path):\n    img = cv2.imread(file_path, cv2.IMREAD_COLOR)\n    return cv2.resize(img, (ROWS, COLS), interpolation=cv2.INTER_CUBIC)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"94cdd1a8d40b9bd3f111c5ec988bcf76c00f630f"},"cell_type":"code","source":"def prep_data(images):\n    count = len(images)\n    data = np.ndarray((count, CHANNELS, ROWS, COLS), dtype=np.uint8)\n\n    for i, image_file in enumerate(images):\n        image = read_image(image_file)\n        data[i] = image.T  # transpose mxn --> nxm\n        if i%250 == 0: print('Processed {} of {}'.format(i, count))\n    \n    return data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c6368fcd7dd5ba88a8a376bc016e669eb475963a"},"cell_type":"code","source":"train = prep_data(train_images)\ntest = prep_data(test_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"79dbcd47d9f2458710f8a8bcbab165ef973bea1b"},"cell_type":"code","source":"train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7e590a920b10fd44ec418a9b7fecad5ae468c76d"},"cell_type":"code","source":"test.shape","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"bd345025392552276c52fe07b6980520b43190d0"},"cell_type":"markdown","source":"# Storing labels to list"},{"metadata":{"trusted":true,"_uuid":"e58ffb39eb15ac1d881b273b277057d8a2ed199b"},"cell_type":"code","source":"labels = []\nfor i in train_images:\n    if 'dog.' in i:\n        labels.append(1)\n    else:\n        labels.append(0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cb8fd633f84ddbfd784e3098c31e2c24d3223e6d"},"cell_type":"code","source":"labels[0:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cb76b7c4ffab09606718d646779e2c873a93ae7b"},"cell_type":"code","source":"train_images[0:10]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2d6f7527990219527ec1e2bbcb3fd723e2345e74"},"cell_type":"code","source":"sns.countplot(labels)\nplt.title('Cats and Dogs')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"84eea98e5e203c13a3113d90b28309d6de156ff7"},"cell_type":"markdown","source":"# Checking out images"},{"metadata":{"trusted":true,"_uuid":"5c4ea5a2e7437cebb0442f09ac9535b61d865dd2"},"cell_type":"code","source":"def show_cats_and_dogs(idx):\n    cat = read_image(train_cats[idx])\n    dog = read_image(train_dogs[idx])\n    pair = np.concatenate((cat, dog), axis=1)\n    plt.figure(figsize=(10,5))\n    plt.imshow(pair)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c3ac8c423df9dfc8e476b01db75a942648fa9c2"},"cell_type":"code","source":"for idx in range(0,5):\n    show_cats_and_dogs(idx)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"56a7a0b04264f46ac61fa2fb926faf536de20ca7"},"cell_type":"markdown","source":"# Generating average images"},{"metadata":{"trusted":true,"_uuid":"462956f824a304bea1fd8fe871e22aeb38a27b2d"},"cell_type":"code","source":"dog_avg = np.array([dog[0].T for i, dog in enumerate(train) if labels[i]==1]).mean(axis=0)\nplt.imshow(dog_avg)\nplt.title('Your Average Dog')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cc3c68b8b19c3c494a29f544f84a3da17213e0e1"},"cell_type":"code","source":"cat_avg = np.array([cat[0].T for i, cat in enumerate(train) if labels[i]==0]).mean(axis=0)\nplt.imshow(cat_avg)\nplt.title('Your Average Cat')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e6ad4348a228efab6a8912020b4e655082c50438"},"cell_type":"markdown","source":"# CatdogNet-16"},{"metadata":{"trusted":true,"_uuid":"966063c53461c9a42849277e12bc2b0dffc1baf3"},"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Input, Dropout, Flatten, Conv2D, MaxPooling2D, Dense, Activation\nfrom keras.optimizers import RMSprop\nfrom keras.callbacks import ModelCheckpoint, Callback, EarlyStopping\nfrom keras.utils import np_utils","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c2467ed455b72211504fb1069520e5dc71d34511"},"cell_type":"code","source":"optimizer = RMSprop(lr=1e-4)\nobjective = 'binary_crossentropy'\n\ndef catdog():\n    model = Sequential()\n\n    model.add(Conv2D(32, (3, 3), padding='same', input_shape=(3, ROWS, COLS), activation='relu'))\n    model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(data_format=\"channels_first\", pool_size=(2, 2)))\n\n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(data_format=\"channels_first\", pool_size=(2, 2)))\n    \n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))\n    model.add(MaxPooling2D(data_format=\"channels_first\", pool_size=(2, 2)))\n    \n    model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))\n    model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))\n#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n    model.add(MaxPooling2D(data_format=\"channels_first\", pool_size=(2, 2)))\n\n#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n#     model.add(MaxPooling2D(pool_size=(2, 2)))\n\n    model.add(Flatten())\n    model.add(Dense(256, activation='relu'))\n    model.add(Dropout(0.5))\n    \n    model.add(Dense(256, activation='relu'))\n    model.add(Dropout(0.5))\n\n    model.add(Dense(1))\n    model.add(Activation('sigmoid'))\n\n    model.compile(loss=objective, optimizer=optimizer, metrics=['accuracy'])\n    return model\n\n\nmodel = catdog()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eb2e49937041c16502afad342b9e24512d5cf25b"},"cell_type":"code","source":"nb_epoch = 10\nbatch_size = 16\n\n## Callback for loss logging per epoch\nclass LossHistory(Callback):\n    def on_train_begin(self, logs={}):\n        self.losses = []\n        self.val_losses = []\n        \n    def on_epoch_end(self, batch, logs={}):\n        self.losses.append(logs.get('loss'))\n        self.val_losses.append(logs.get('val_loss'))\n\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, verbose=1, mode='auto')\n\ndef run_catdog():\n    \n    history = LossHistory()\n    model.fit(train, labels, batch_size=batch_size, epochs=nb_epoch,\n              validation_split=0.25, verbose=1, shuffle=True, callbacks=[history, early_stopping])\n    \n\n    predictions = model.predict(test, verbose=0)\n    return predictions, history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"797ff932f734ffb9f3ffef8023e5153ee75246c0"},"cell_type":"code","source":"%%time\npredictions, history = run_catdog()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"515bc1121912bcb35992db338614820573dca4a6"},"cell_type":"markdown","source":"# Plotting loss"},{"metadata":{"trusted":true,"_uuid":"0d64bbf8a6fb53ef67f5bf33d9c8c793265f3655"},"cell_type":"code","source":"loss = history.losses\nval_loss = history.val_losses\n\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.title('CatdogNet-16 Loss Trend')\nplt.plot(loss, 'blue', label='Training Loss')\nplt.plot(val_loss, 'green', label='Validation Loss')\nplt.xticks(range(0,nb_epoch)[0::2])\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8a444b85f6625e8fa80851ff1ecb99c262c7d0aa"},"cell_type":"markdown","source":"# Visualizing prediction result"},{"metadata":{"trusted":true,"_uuid":"8edef82140464b724f4f2d229a996bdfc11b91b0"},"cell_type":"code","source":"for i in range(0,25):\n    if predictions[i, 0] >= 0.5: \n        print('I am {:.2%} sure this is a Dog'.format(predictions[i][0]))\n    else: \n        print('I am {:.2%} sure this is a Cat'.format(1-predictions[i][0]))\n        \n    plt.imshow(test[i].T)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false,"_uuid":"d761c0066685a06373dd7baabe5fea3dbbdc380e"},"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.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}