{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"collapsed":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"975ec57d056fe10261cd1b3638f34491300bae7f","collapsed":true},"cell_type":"code","source":"ls ../input/smalldata/smalldata/smalldata","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","collapsed":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"markdown","source":"## Dataset\n\nProvided dataset contains 25000 images of dogs and cats in  'train.zip'  folder and image files are named based on whether the image is of dog or cat. Dataset also contains 'test .zip'  folder which contains 12,500 images and image files are named with a number.Our goal is to create a CNN model which generates a probability that the image is a dog (1 = dog, 0 = cat) for each image in the test set."},{"metadata":{"_uuid":"881055b5d1b6edc20d4f578b01ae57b126dc87f9"},"cell_type":"markdown","source":"## Load general packages"},{"metadata":{"_uuid":"5f16a6a0848f46d8d551ee76c22dd761c8190f46","trusted":true,"collapsed":true},"cell_type":"code","source":"%matplotlib inline\nfrom matplotlib import pyplot as plt\nfrom PIL import Image\nfrom PIL import ImageFile \nimport numpy as np\nimport os \nimport cv2\nfrom tqdm import tqdm_notebook\nfrom random import shuffle\nimport pandas as pd\nimport random\nfrom tqdm import tqdm\nimport seaborn as sns\nimport math","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b732a5082bcd1b3986fcad10e0fffb842017e86a"},"cell_type":"markdown","source":"## Load Keras packages"},{"metadata":{"trusted":true,"_uuid":"64ebeb06a96cb0643ae24bd0f277360a9cd2eacd"},"cell_type":"code","source":"import keras\nfrom keras import applications\nfrom keras import optimizers\nfrom keras import backend as K\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D,GlobalMaxPooling2D\nfrom keras.layers import Activation, Dropout, Flatten, Dense\nfrom keras.constraints import maxnorm\nfrom keras.optimizers import SGD\nfrom keras.utils import np_utils\nfrom keras.callbacks import Callback,ModelCheckpoint\nfrom keras.applications import VGG16\nfrom keras.applications import ResNet50\nfrom keras.models import load_model\nfrom keras.preprocessing.image import load_img\nfrom sklearn.metrics import classification_report","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cba4b4b3e9743e6a8ec11eb02b2ea25ec8f1c118"},"cell_type":"markdown","source":"## Intialize variables\nThe image size is 224.The images are stored in two folders, train and test and there are two image classes: Dog and Cat.\nMy plan is to use all training data (25,000 images) of which 20,000 imgaes for  traning and 5000 for valdation of the models.\nWe will use a subset of the training data set (20,000 images). From the training set,80% will be used for training, 20% for validation."},{"metadata":{"trusted":true,"_uuid":"977057f5a6c4a36864ad0cca7c094dafaea07c9e","collapsed":true},"cell_type":"code","source":"batch_size = 32\nepochs = 10\nnum_classes = 2\nnum_t_samples = 20000\nnum_v_samples = 5000\npath='../input/dogs-vs-cats-redux-kernels-edition/'\ndir= '../input/dogscats/data/data/'\ntrain_data_path = path+'train/'\ntest_data_path =  path+'test/'\ntrain_data_dir = dir+'train/'\nvalidation_data_dir=dir+'validation/'\ntest_dir='../input/dogscatstest/test1/test1/'\nsample_test_dir='../input/sample-testdata/sample test data/sample test data'\nimg_size=224\n#img_size=150","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"498136ea6e8538496eb475efa5e01d74014e4710"},"cell_type":"markdown","source":"## Explore  the data"},{"metadata":{"trusted":true,"_uuid":"194585669334ad46676bff90a7fd432f1fbc6ea4","collapsed":true},"cell_type":"code","source":"# Define the path for training and test image data.\ntrain_images_path = [train_data_path+i for i in os.listdir(train_data_path)] \ntrain_images= os.listdir(train_data_path)\nvalidation_images=os.listdir(train_data_path)\ntest_images = os.listdir(test_data_path)\ntest_images_path = [test_data_path+i for i in os.listdir(test_data_path)] ","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f03ec07a1c83342196ede4160a0cf6b2de8dc7bb"},"cell_type":"markdown","source":"## Class distribution\nLet's explore the train data to check the cats and dogs image  distribution. "},{"metadata":{"trusted":true,"_uuid":"3bab9ab45f16f7279ce63acf4f58b1f9be70b605","collapsed":true},"cell_type":"code","source":"# Visualize class distribution of traning data.\ndef image_plot(image_data):\n    labels = []\n    for img in image_data:\n        labels.append(img.split('.')[-3])\n    sns.countplot(labels)\n    plt.title('Cats and Dogs')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"68cd20dfcf7bea08adc9b890286722c5f126229d","collapsed":true},"cell_type":"code","source":"# Plotting training data to visualize class distribution by calling image_plot().\nimage_plot(train_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e348b737feaf3ecaf531a16b2310ca203e500176","collapsed":true},"cell_type":"code","source":"# Visualize image height and width of the test data.\ntestheight = []\ntestwidth=[]\nfor img in tqdm(test_images_path):\n    im = Image.open(img)\n    testheight.append(im.size[0])\n    testwidth.append(im.size[1])\n\ndef plot_testheight():\n    plt.hist(testheight)\n    plt.title(\"Height\")\n    plt.xlabel(\"Value\")\n    plt.ylabel(\"Frequency\")\ndef plot_testwidth():\n    plt.hist(testwidth)\n    plt.title(\"Width\")\n    plt.xlabel(\"Value\")\n    plt.ylabel(\"Frequency\")\n\ndef plot_testimage_size(height=True):\n    if (height):\n        plot_testheight()\n    else:\n        plot_testwidth()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"2a6fff2d88adf2cb01598f3fb4e73f4a41c77028","collapsed":true},"cell_type":"code","source":"plot_testimage_size(True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cbfce4592086404d4f53b32b7ccdd575a3ae00e9","collapsed":true},"cell_type":"code","source":"plot_testimage_size(False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"38eec4db7d9bd19ae2b1528f03390b64b31c392b"},"cell_type":"code","source":"# Statistical analysis of the training image sizes\nprint (\"Training images mean height: {}\".format(np.mean(testheight)))\nprint (\"Training images mean width: {}\".format(np.mean(testwidth)))\nprint (\"Training images max height is {} and min height is {}.\".format(max(testheight),min(testheight)))\nprint (\"Training images max width is {} and min width is {}.\".format(max(testwidth),min(testwidth)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"86b97481605d006935b53540eae89cf14b09463e","collapsed":true},"cell_type":"code","source":"# Visualize image height and width of the traning data.\ntrainheight = []\ntrainwidth=[]\nfor img in tqdm(train_images_path):\n    im = Image.open(img)\n    trainheight.append(im.size[0])\n    trainwidth.append(im.size[1])\n\ndef plot_trainheight():\n    plt.hist(trainheight)\n    plt.title(\"Height\")\n    plt.xlabel(\"Value\")\n    plt.ylabel(\"Frequency\")\ndef plot_trainwidth():\n    plt.hist(trainwidth)\n    plt.title(\"Width\")\n    plt.xlabel(\"Value\")\n    plt.ylabel(\"Frequency\")\n\ndef plot_trainimage_size(height=True):\n    if (height):\n        plot_trainheight()\n    else:\n        plot_trainwidth()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b6c47dad44730a17a966646f0c7b853e02f42c6c","collapsed":true},"cell_type":"code","source":"plot_trainimage_size(True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3066bc94b3e9735208f203a48c463ac358a10d16","collapsed":true},"cell_type":"code","source":"plot_trainimage_size(False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fe1d60583b300757906e5e68f9a99d2519b049e9","collapsed":true},"cell_type":"code","source":"# Statistical analysis of the training image sizes\nprint (\"Training images mean height: {}\".format(np.mean(height)))\nprint (\"Training images mean width: {}\".format(np.mean(width)))\nprint (\"Training images max height is {} and min height is {}.\".format(max(height),min(height)))\nprint (\"Training images max width is {} and min width is {}.\".format(max(width),min(width)))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4e9c9dc746fab9af9d331770ec6fd2b3be7a3201"},"cell_type":"markdown","source":"\n## Display of Image Samples\nDisplay set of  25 images of train and test images."},{"metadata":{"trusted":true,"_uuid":"7ee54bda88313094541b853239a52d6cb94cd3b3","collapsed":true},"cell_type":"code","source":"def create_image_label(img):\n    image = img.split('.')[-3]\n    if image == 'cat': return 'cat'\n    elif image == 'dog': return 'dog'\n# Function to process training image data into numpy array.\ndef process_data(image_files,image_folder,Train=True):\n    image_data = []\n    for image in tqdm(image_files):\n        path = os.path.join(image_folder,image)\n        if(Train):\n            label =create_image_label(image)\n        else:\n            label = img.split('.')[0]\n        image_data.append([path,label])\n    shuffle(image_data)\n    return image_data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ad059c3065ca9b80a3b7e0acaf9b3068e9464941","collapsed":true},"cell_type":"code","source":"train=process_data(train_images,train_data_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"401f1b20b174276bf82a7aec2a2c95b3eee7d181","collapsed":true},"cell_type":"code","source":"test=process_data(test_images,test_data_path,False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"60167d560b561bc177779539bb20cfd18633a78b","collapsed":true},"cell_type":"code","source":"# Function to to display 25 sample images from train and test data\ndef display_images(input_data,Test=False):\n    f, ax = plt.subplots(5,5, figsize=(15,15))\n    for i,data in enumerate(input_data[:25]):\n        img_label = data[1]\n        img_path = data[0]\n        original = load_img('{}'.format(img_path))\n        #label = np.argmax(img_num)\n        if img_label  =='dog': \n            str_label='Dog'\n        elif img_label == 'cat': \n            str_label='Cat'\n        if(Test):\n            str_label=\"None\"\n        ax[i//5, i%5].imshow(original)\n        ax[i//5, i%5].axis('off')\n        ax[i//5, i%5].set_title(\"Label: {}\".format(str_label))\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5b4b18a7baa1375d67853578514c33587153f53a","collapsed":true},"cell_type":"code","source":"display_images(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1fee108816479708ea6b4bc19ced4a7d79c4bb05","collapsed":true},"cell_type":"code","source":"display_images(test,True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"191a7524dc802947ca71515e8eb65800137d0d70","collapsed":true},"cell_type":"code","source":"if K.image_data_format() == 'channels_first':\n    input_shape = (3, img_size, img_size)\nelse:\n    input_shape = (img_size, img_size, 3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"be4e8cb0fa96074bd1e08275251b5a7f2a51c4a1"},"cell_type":"code","source":"#Process training data to make it ready for fitting.\ntrain_datagen = ImageDataGenerator(rescale=1. / 255,shear_range=0.2,zoom_range=0.2,horizontal_flip=True)\nval_datagen = ImageDataGenerator(rescale=1. / 255)\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntrain_generator = train_datagen.flow_from_directory(train_data_dir,target_size=(img_size, img_size),\n                                                    batch_size=batch_size,class_mode='categorical',shuffle=True)\nvalidation_generator = val_datagen.flow_from_directory(validation_data_dir,target_size=(img_size, img_size),\n                                                        batch_size=batch_size,class_mode='categorical',shuffle=True) \ntest_generator = test_datagen.flow_from_directory(test_dir,target_size=(img_size, img_size),batch_size=batch_size,\n                                                  class_mode='categorical',shuffle=False)\nsample_test_generator=test_datagen.flow_from_directory(sample_test_dir,\n                                                  target_size=(img_size, img_size),\n                                                  batch_size=batch_size,\n                                                  class_mode='categorical',shuffle=False,seed=42)\nfilename=test_generator.filenames","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"bab422491079a93e59a66559da75e20631e124e5"},"cell_type":"markdown","source":"## Implementation of a CNN model from scratch"},{"metadata":{"trusted":true,"_uuid":"5096050aa9c9247ffe9a590f39af066a58db336c","collapsed":true},"cell_type":"code","source":"print ('Creating model...')\nnew_model = Sequential()\nnew_model.add(Conv2D(32, (3, 3), input_shape=input_shape))\nnew_model.add(Activation('relu'))\nnew_model.add(MaxPooling2D(pool_size=(2, 2)))\nnew_model.add(Conv2D(32, (3, 3)))\nnew_model.add(Activation('relu'))\nnew_model.add(MaxPooling2D(pool_size=(2, 2)))\nnew_model.add(Conv2D(64, (3, 3)))\nnew_model.add(Activation('relu'))\nnew_model.add(MaxPooling2D(pool_size=(2, 2)))\nnew_model.add(Flatten())\nnew_model.add(Dense(64))\nnew_model.add(Activation('relu'))\nnew_model.add(Dropout(0.5))\nnew_model.add(Dense(num_classes))\nnew_model.add(Activation('softmax'))\nprint ('Summary of the model...')\nnew_model.summary()\nprint ('Compiling model...')\n#new_model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])\n#new_model.compile(optimizer=SGD(lr=1e-3), loss='categorical_crossentropy', metrics=['accuracy'])\nnew_model.compile(optimizer=SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True), loss='categorical_crossentropy', metrics=['accuracy'])\nprint ('Model is ready to be fit with training data.')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"60ca5941564e8a6ad332e5c7bc70c4e8804d1dc2"},"cell_type":"code","source":"# Create logs, filepath and checkpoints for the model.\nclass LossHistory(Callback):\n    def on_train_begin(self, logs={}):\n        self.losses = []\n        self.val_losses = []\n    def on_epoch_end(self, batch, logs={}):\n        self.losses.append(logs.get('loss'))\n        self.val_losses.append(logs.get('val_loss'))\nhistory = LossHistory()\nearly_stopping = keras.callbacks.EarlyStopping(monitor='val_loss',min_delta=0,patience=20,verbose=0, mode='auto')\ncheckpoint = ModelCheckpoint('new_model.h5',monitor='val_loss', verbose=1, save_best_only=True,mode='auto')\ncallbacks_list = [checkpoint,history,early_stopping]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c034e06cff3702ef1ef5f049bf752fe03097b6e","collapsed":true},"cell_type":"code","source":"# Fit the model on batches of 20000 samples of training  data and validate on 5000 samples.\nfitted_new_model=new_model.fit_generator(train_generator,\n    steps_per_epoch=math.ceil(num_t_samples/batch_size),\n    epochs=epochs,validation_data=validation_generator,\n    validation_steps=math.ceil(num_v_samples/batch_size),callbacks=callbacks_list,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ed452b65456100003a9a79d9f2b21eae833bd94a","collapsed":true},"cell_type":"code","source":"# Plot Val_loss,train_loss and val_acc and train_acc.\nacc = fitted_new_model.history['acc']\nval_acc = fitted_new_model.history['val_acc']\nloss = fitted_new_model.history['loss']\nval_loss =fitted_new_model.history['val_loss']\nepochs = range(len(acc)) \nplt.plot(epochs, acc, 'b', label='Training acc')\nplt.plot(epochs, val_acc, 'r', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, 'b', label='Training loss')\nplt.plot(epochs, val_loss, 'r', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e56770aedb9dc5de325bcca9a90b36988515eeee"},"cell_type":"code","source":"ls '../input/dogs-and-cats-final-kernel-explore-cnn-scratch/new_model.h5'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0236daecc850334714899458d6d33287f0b484a0"},"cell_type":"code","source":"new_model=load_model('../input/dogs-and-cats-final-kernel-explore-cnn-scratch/new_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fb702390b938306886e4a1b1179e95db3ac0007a"},"cell_type":"code","source":"#Get the sample test data filenames from the generator\nfnames = sample_test_generator.filenames\n# Get the ground truth from generator\nground_truth = sample_test_generator.classes\n# Get the label to class mapping from the generator\nlabel2index = sample_test_generator.class_indices\n# Getting the mapping from class index to class label\nidx2label = dict((v,k) for k,v in label2index.items())\n# Get the predictions from the model using the generator\npredictions = new_model.predict_generator(sample_test_generator,\nsteps=math.ceil(sample_test_generator.samples/sample_test_generator.batch_size),verbose=1)\npredicted_classes = np.argmax(predictions,axis=1)\nerrors = np.where(predicted_classes != ground_truth)[0]\nprint(\"No of errors = {}/{}\".format(len(errors),sample_test_generator.samples))\n# Display missclassified images\nfor i in range(len(errors)):\n    pred_class = np.argmax(predictions[errors[i]])\n    pred_label = idx2label[pred_class]\n    title = 'Original label:{}, Prediction :{}, confidence : {:.3f}'.format(fnames[errors[i]].split('/')[0],pred_label,\n        predictions[errors[i]][pred_class])\n    original = load_img('{}/{}'.format(sample_test_dir,fnames[errors[i]]))\n    plt.figure(figsize=[7,7])\n    plt.axis('off')\n    plt.title(title)\n    plt.imshow(original)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1196f6d39238fcd09e75c2f98712eeaf23880f78"},"cell_type":"code","source":"#get the predictions for the test data\n#predicted_classes = model.predict_classes(Xt)\n#get the indices to be plotted\n#y_true = np.argmax(yt,axis=1)\ncorrect = np.nonzero(predicted_classes==ground_truth)[0]\nincorrect = np.nonzero(predicted_classes!=ground_truth)[0]\ntarget_names = [\"Class {}:\".format(i) for i in range(num_classes)]\nprint(classification_report(ground_truth, predicted_classes, target_names=target_names))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"948600dd1b7aee2c01ca72802a97375e0949041f","collapsed":true},"cell_type":"code","source":"# Proces test data to generate predictions on provided test data.\ntest_generator.reset()\npred=new_model.predict_generator(test_generator,steps=math.ceil(test_generator.samples/test_generator.batch_size),verbose=1)\npredicted_class_indices=np.argmax(pred,axis=1)\nlabels = (train_generator.class_indices)\nlabels = dict((v,k) for k,v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]\nnew_preds=[]\nfor i in range(len(predictions)):\n    if predictions[i]=='dogs':\n        new_preds.append('dog')\n    else:\n        new_preds.append('cat')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"7154858054767e1071075ad72605b2e95c1c27bd"},"cell_type":"code","source":"# Display predictions with 25 pictures with their labels.\ndef display_testdata(testdata,filenames):\n    f, ax = plt.subplots(5,5, figsize=(15,15))\n    i=0\n    for a,b in zip(testdata,filenames):\n        pred_label=a\n        fname=b\n        title = 'Prediction :{}'.format(pred_label)   \n        original = load_img('{}/{}'.format(test_dir,fname))\n        ax[i//5,i%5].axis('off')\n        ax[i//5,i%5].set_title(title)\n        ax[i//5,i%5].imshow(original)\n        i=i+1\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a1c7b492f2f57f871b48bf0e97e242bcd4e8b1ba","collapsed":true},"cell_type":"code","source":"display_testdata(new_preds[7700:7725],filename[7700:7725])","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}