{"cells":[{"metadata":{"id":"yob603y6XI5O"},"cell_type":"markdown","source":"### **Initialization**\n* I use these 3 lines of code on top of my each notebook because it won't cause any trouble while reloading or reworking on the Project or Problem. And the third line of code helps to make visualization within the Notebook.","execution_count":null},{"metadata":{"id":"0m3GGOsKVatj","trusted":true},"cell_type":"code","source":"# Initialization\n# I use these three lines of code on top of my each Notebook\n%reload_ext autoreload\n%autoreload 2\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"id":"yAS3EwUFXZs9"},"cell_type":"markdown","source":"**Downloading the Dependencies**\n* I prefer to download all necessary Libraries and Dependencies on one particular cell which mainly focus on Libraries and Dependencies.","execution_count":null},{"metadata":{"id":"bxTc6Aa3XUY2","trusted":true},"cell_type":"code","source":"# Downloading all necessary Libraries and Dependencies\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport os\nimport random\nimport zipfile\nimport tensorflow as tf\n\n#from google.colab import files\nfrom shutil import  copyfile\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.optimizers import RMSprop\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator","execution_count":null,"outputs":[]},{"metadata":{"id":"geHpIqqqYBmm"},"cell_type":"markdown","source":"**Getting the Data**\n* I am using Google Colab for this Project, so the act of reading the Data might be different from different platforms. I have used the link below to download the full data of [Dog vs. Cat](https://www.kaggle.com/c/dogs-vs-cats/overview) from [Kaggle](https://www.kaggle.com/). You can manually download the Data from [Kaggle](https://www.kaggle.com/c/dogs-vs-cats/data) as well.","execution_count":null},{"metadata":{"id":"FmjBQAJSX-ET","outputId":"b1406f80-91d6-481d-ff5f-e5e7366ad743","trusted":true},"cell_type":"code","source":"# Loading the Data or Downloading the Data.\n# Using Google Colab for reading or loading the Data.\n# Uncomment the line below\n!wget --no-check-certificate \\\n    \"https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip\" \\\n    -O \"/tmp/cats-and-dogs.zip\"\n","execution_count":null,"outputs":[]},{"metadata":{"id":"aMTVT8EQZog3"},"cell_type":"markdown","source":"**Processing the Data**\n* The following Python code will use OS library to access the file system and zip file library, allowing you to unzip the file.","execution_count":null},{"metadata":{"id":"AU2l4IyPZfZp","trusted":true},"cell_type":"code","source":"# Processing the zip file of the Data\nlocal_zip = \"/tmp/cats-and-dogs.zip\"\nzip_ref = zipfile.ZipFile(local_zip, \"r\")\nzip_ref.extractall(\"/tmp\")\nzip_ref.close()","execution_count":null,"outputs":[]},{"metadata":{"id":"I8IKI6Qdbet5"},"cell_type":"markdown","source":"* Now, Let's find the total number of Cats and Dogs Images in the Data directories.","execution_count":null},{"metadata":{"id":"iqHrNDlralIE","outputId":"9d1dbe14-4636-43b7-cd3c-af5016e5e24e","trusted":true},"cell_type":"code","source":"# Finding the total number of Cats and Dogs images in the directory.\n# Total number of Cats.\nprint(f\"Total number of Cats is {len(os.listdir('/tmp/PetImages/Cat/'))}\")\n# Total number of Dogs.\nprint(f\"Total number of Dogs is {len(os.listdir('/tmp/PetImages/Dog/'))}\")","execution_count":null,"outputs":[]},{"metadata":{"id":"bdetkrUKcvt9"},"cell_type":"markdown","source":"**Creating new Directories**\n* Creating a new directory for cats-vs-dogs and subdirectories for training and validation. These subdirectories will need more subdirectories for cats and dogs.","execution_count":null},{"metadata":{"id":"7vhMa1mEcqBW","trusted":true},"cell_type":"code","source":"# Using os.mkdir to create new directories\n# Creating new directories for training and validation\ntry:\n  os.mkdir(\"/tmp/cats-vs-dogs\")\n  os.mkdir(\"/tmp/cats-vs-dogs/training\")\n  os.mkdir(\"/tmp/cats-vs-dogs/validation\")\n  os.mkdir(\"/tmp/cats-vs-dogs/training/Cats\")\n  os.mkdir(\"/tmp/cats-vs-dogs/training/Dogs\")\n  os.mkdir(\"/tmp/cats-vs-dogs/validation/Cats\")\n  os.mkdir(\"/tmp/cats-vs-dogs/validation/Dogs\")\nexcept OSError:\n  pass","execution_count":null,"outputs":[]},{"metadata":{"id":"I7adetE5fx7Q"},"cell_type":"markdown","source":"**Splitting the Data into Training and Validation**\n* I will write a function which will takes a SOURCE directory containing the files, a TRAINING directory that a portion of files will be copied to, a VALIDATION directory that a portion of files will be copied to, and SPLIT_SIZE to determine the portion. 90% of the Images will be copied into TRAINING directory and remaining 10% of the Images will be copied into VALIDATION directory. Every Images will be checked, if any of the Images has zero file length then they won't be copied over.","execution_count":null},{"metadata":{"id":"uRY5X2BPe6L3","outputId":"5a5da76c-f1ca-47cb-97b2-4ab69c35b667","trusted":true},"cell_type":"code","source":"# Writing the function which splits the data into Training and Validation or Testing.\ndef split_data(SOURCE, TRAINING, VALIDATION, SPLIT_SIZE):\n  files = []\n  for filename in os.listdir(SOURCE):\n    file = SOURCE + filename\n    if os.path.getsize(file) > 0:\n      files.append(filename)\n    else:\n      print(filename, \"is zero length, so ignoring!\")\n  \n  training_length = int(len(files) * SPLIT_SIZE)\n  validation_length = int(len(files) - training_length)\n  shuffled_set = random.sample(files, len(files))\n  training_set = shuffled_set[0:training_length]\n  validation_set = shuffled_set[0:validation_length]\n\n  for filename in training_set:\n    this_file = SOURCE + filename\n    destination = TRAINING + filename\n    copyfile(this_file, destination)\n\n  for filename in validation_set:\n    this_file = SOURCE + filename\n    destination = VALIDATION + filename\n    copyfile(this_file, destination)\n\n\nCAT_SOURCE_DIR = \"/tmp/PetImages/Cat/\"\nTRAINING_CAT_DIR = \"/tmp/cats-vs-dogs/training/Cats/\"\nVALIDATION_CAT_DIR = \"/tmp/cats-vs-dogs/validation/Cats/\"\n\nDOG_SOURCE_DIR = \"/tmp/PetImages/Dog/\"\nTRAINING_DOG_DIR = \"/tmp/cats-vs-dogs/training/Dogs/\"\nVALIDATION_DOG_DIR = \"/tmp/cats-vs-dogs/validation/Dogs/\"\n\nSPLIT_SIZE = 0.9\n\nsplit_data(CAT_SOURCE_DIR, TRAINING_CAT_DIR, VALIDATION_CAT_DIR, SPLIT_SIZE)\nsplit_data(DOG_SOURCE_DIR, TRAINING_DOG_DIR, VALIDATION_DOG_DIR, SPLIT_SIZE)","execution_count":null,"outputs":[]},{"metadata":{"id":"AVIzh83emC2u"},"cell_type":"markdown","source":"* Finding the total number of Images in Training and Validation Dataset. The Training Dataset has 90% of the total Images present in the directory and Validation Dataset has 10% of the total Images present in the directory.","execution_count":null},{"metadata":{"id":"vl_rBfcZlYnv","outputId":"a7f79659-7a10-4d40-bf44-1738d1aefe15","trusted":true},"cell_type":"code","source":"# Total number of images in Training\nprint(f\"Total number of training Cats is {len(os.listdir('/tmp/cats-vs-dogs/training/Cats/'))}\")\nprint(f\"Total number of training Dogs is {len(os.listdir('/tmp/cats-vs-dogs/training/Dogs/'))}\")\n\n# Total number of images in Validation\nprint(f\"Total number of validation Cats is {len(os.listdir('/tmp/cats-vs-dogs/validation/Cats/'))}\")\nprint(f\"Total number of validation Dogs is {len(os.listdir('/tmp/cats-vs-dogs/validation/Dogs/'))}\")","execution_count":null,"outputs":[]},{"metadata":{"id":"BgdFoqQbqH1M"},"cell_type":"markdown","source":"* Let's define each of these directories as follows:","execution_count":null},{"metadata":{"id":"-BOVG3Qzn3Z4","trusted":true},"cell_type":"code","source":"# Directory with training cats images\ntrain_cats_dir = os.path.join(\"/tmp/cats-vs-dogs/training/Cats\")\n\n# Directory with training dogs images.\ntrain_dogs_dir = os.path.join(\"/tmp/cats-vs-dogs/training/Dogs\")\n\n# Directory with validation cats images\nvalidation_cats_dir = os.path.join(\"/tmp/cats-vs-dogs/validation/Cats\")\n\n# Directory with validation dogs images\nvalidation_dogs_dir = os.path.join(\"/tmp/cats-vs-dogs/validation/Dogs\")","execution_count":null,"outputs":[]},{"metadata":{"id":"DNDI1K4lr5Ai"},"cell_type":"markdown","source":"* Now, Let's look at the filenames in cats and dogs training and validation directories.","execution_count":null},{"metadata":{"id":"6ujXFBThryvz","outputId":"4b30f2d3-5d9e-4783-9c95-7e28e4f64d12","trusted":true},"cell_type":"code","source":"# Training Cat directory\ntrain_cat_names = os.listdir(train_cats_dir)\nprint(train_cat_names[:10])\n\n# Training Dog directory\ntrain_dog_names = os.listdir(train_dogs_dir)\nprint(train_dog_names[:10])\n\n# Validation Cat directory\nvalidation_cat_names = os.listdir(validation_cats_dir)\nprint(validation_cat_names[:10])\n\n# Validation Dog directory\nvalidation_dog_names = os.listdir(validation_dogs_dir)\nprint(validation_dog_names[:10])","execution_count":null,"outputs":[]},{"metadata":{"id":"CP8zSjewtTA3"},"cell_type":"markdown","source":"**Data Visualization**\n* Now, Let's look at the few pictures of the Images to get the sense of how does the Data actually looks like.","execution_count":null},{"metadata":{"id":"pC2RG6INtCjo","outputId":"3a188943-6917-4fee-d3a1-c6904e1673d1","trusted":true},"cell_type":"code","source":"# Parameters for our graph \nnrows = 4\nncols = 4\n\n# Index for iterating over images\npic_index = 0\n\n# Setup matplotlib figure\nfig = plt.gcf()\nfig.set_size_inches(ncols*4, nrows*4)\n\npic_index += 8\nnext_cat_px = [os.path.join(train_cats_dir, fname) for fname in train_cat_names[pic_index-8:pic_index]]\nnext_dog_px = [os.path.join(train_dogs_dir, fname) for fname in train_dog_names[pic_index-8:pic_index]]\n\nfor i, img_path in enumerate(next_cat_px + next_dog_px):\n  # Set subplots\n  sp = plt.subplot(nrows, ncols, i+1)\n  sp.axis(\"Off\")\n\n  img = mpimg.imread(img_path)\n  plt.imshow(img)\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"id":"CG4OWQfJxMTL"},"cell_type":"markdown","source":"### **Convolutional Neural Network : InceptionV3**\n* Building Convolutional Neural Network from scratch using Tensorflow and Keras API.\n* Using InceptionV3 for the purpose of transfer learning.\n* Since it is a two class Classification problem i.e a Binary Classfication problem, I will use sigmoid activation so that the output of my network will be a single scalar between 0 and 1, encodig the probability of the images.","execution_count":null},{"metadata":{"id":"3heD6k2WwnHP","outputId":"d88c335e-9b00-441c-d052-33969c1b84a7","trusted":true},"cell_type":"code","source":"# Creating convolutional neural network with transfer learning.\n# Creating the pretrained model\npre_trained_model = InceptionV3(input_shape=(300, 300, 3),\n                                weights=\"imagenet\",\n                                include_top=False)\n\n# Making all the layers in pretrained model nontrainable\n# Freezing all the layers of pretrained model\nfor layer in pre_trained_model.layers:\n  layer.trainable = False\n  \n# Summary of the Model\npre_trained_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"id":"HSb-YJXryFli"},"cell_type":"markdown","source":"**Processing the Model**\n* Working on pretrained model.","execution_count":null},{"metadata":{"id":"sRmPusv1yNZE","outputId":"fecd2480-733e-4233-f044-cdc73221bf43","trusted":true},"cell_type":"code","source":"# Working on pretrained model.\nlast_layer = pre_trained_model.get_layer(\"mixed9\")\nprint(f\"The shape of last output layer is {last_layer.output_shape}\")\nlast_output = last_layer.output","execution_count":null,"outputs":[]},{"metadata":{"id":"iSANk4EIy1Du"},"cell_type":"markdown","source":"**Callbacks**\n* It stops the further execution of the program when the certain accuracy is achieved. I will build the callbacks which will stop the execution of the program after 99% accuracy is achieved by the model.","execution_count":null},{"metadata":{"id":"-BDzvEbQzB_K","trusted":true},"cell_type":"code","source":"# Building the Callbacks \nclass myCallback(tf.keras.callbacks.Callback):\n  def on_epoch_end(self, epoch, logs={}):\n    if(logs.get(\"accuracy\") > 0.99):\n      print(\"\\nReached 99% accurcy so stopping the execution of the program!\")\n      self.model.stop_training = True\n\n# Instantiation\ncallbacks = myCallback()","execution_count":null,"outputs":[]},{"metadata":{"id":"SvbXMacBzF-M"},"cell_type":"markdown","source":"**Processing the Model**\n* Preparing the Final Model from pretrained model.","execution_count":null},{"metadata":{"id":"Ol3urmjvzMe8","trusted":true},"cell_type":"code","source":"# Processing the Model\n\n# Flatten the output layer of pretrained model into 1 dimension\nx = tf.keras.layers.Flatten()(last_output)\n# Adding fully connected layer with relu activation\nx = tf.keras.layers.Dense(units=1024, activation=\"relu\")(x)\n# Adding dropout with rate 0.2\nx = tf.keras.layers.Dropout(0.2)(x)\n# Adding final sigmoid layer for activation\nx = tf.keras.layers.Dense(1, activation=\"sigmoid\")(x)\n\n# Preparing the final Model\nmodel = Model(pre_trained_model.input, x)","execution_count":null,"outputs":[]},{"metadata":{"id":"S16cpFu70loq"},"cell_type":"markdown","source":"* Next, I will configure the specifications for model training. I will train the model with binary_crossentropy loss, because it is a binary classification problem and the activation is sigmoid.\n* Here, I will be using RMSprop which is preferable for Stochastic Gradient Descent because RMSprop automates learning rate tuning for us.","execution_count":null},{"metadata":{"id":"h81w3tWs0ODn","trusted":true},"cell_type":"code","source":"# Compile the Model\nmodel.compile(loss=\"binary_crossentropy\",\n              optimizer=RMSprop(lr=0.0001),\n              metrics=[\"accuracy\"])","execution_count":null,"outputs":[]},{"metadata":{"id":"pXZ7BhKH0A40"},"cell_type":"markdown","source":"* Let's look at the summary of the Neural Network.","execution_count":null},{"metadata":{"id":"UO6S7qpTzsNu","outputId":"b5bd0b0e-28c8-4f76-f0ad-f8828ae8c81f","trusted":true},"cell_type":"code","source":"# Summary of Neural Network\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"id":"E4HJ-Oe41CQy"},"cell_type":"markdown","source":"**Data Processing**\n* I will process our images by normalizing pixel values in range of [0, 1] which is originally in range of [0, 255]","execution_count":null},{"metadata":{"id":"NejSCJ0O06XF","outputId":"c5c2ff57-fa4f-4ec1-d7b3-adfcb786b355","trusted":true},"cell_type":"code","source":"# Normalizing all the images\n# All images are rescaled by 1./255\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\")\n\nvalidation_datagen = ImageDataGenerator(rescale=1./255)\n\n# Flow training images in batches of 128 using train_datagen generator\ntrain_generator = train_datagen.flow_from_directory(\n    \"/tmp/cats-vs-dogs/training\",\n    target_size=(300, 300),\n    batch_size=128,\n    class_mode=\"binary\"\n)\n\n# Flow validation images in batches of 32 using validation_datagen generator\nvalidation_generator = validation_datagen.flow_from_directory(\n    \"/tmp/cats-vs-dogs/validation\",\n    target_size=(300, 300),\n    batch_size=32, \n    class_mode=\"binary\"\n)","execution_count":null,"outputs":[]},{"metadata":{"id":"xThNS0044JJP"},"cell_type":"markdown","source":"### **Training the Model**\n* I will train the Model for 100 epochs and 8 epoch per steps.\n* The Loss and Accuracy are the great indication of the progress of training. It's making a guess to the classification of the training data and then measuring it against the known label calculating the result. Accuracy is the portion of the correct guesses.","execution_count":null},{"metadata":{"id":"JspREvgW4AT9","outputId":"a5a60367-ccfd-4d23-d678-1609964b99d6","trusted":true},"cell_type":"code","source":"# Training the Model\nhistory = model.fit(\n    train_generator,\n    steps_per_epoch=8, \n    epochs=50,\n    verbose=2,\n    validation_data=validation_generator,\n    validation_steps=8,\n    callbacks=[callbacks]\n)","execution_count":null,"outputs":[]},{"metadata":{"id":"spfc3e-YEb48"},"cell_type":"markdown","source":"**Model Visualization**\n* Plotting Loss vs Accuracy","execution_count":null},{"metadata":{"id":"2I6vBxBT5p62","outputId":"c6b74784-b877-4259-f55c-085f35890797","trusted":true},"cell_type":"code","source":"# Plotting loss vs accuracy\n\nacc = history.history[\"accuracy\"]\nval_acc = history.history[\"val_accuracy\"]\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\n\nepochs = range(len(acc))\n\nplt.plot(epochs, acc, \"r\", label=\"Training accuracy\")\nplt.plot(epochs, val_acc, \"b\", label=\"Validation accuracy\")\nplt.title(\"Training and Validation accuracy\")\n\nplt.figure()\n\nplt.plot(epochs, loss, \"r\", label=\"Training loss\")\nplt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\nplt.title(\"Training and Validation loss\")\n\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Important points to take:**\n\n* Implementation of ImageDataGenerator API\n* Implementation of Convolutional Neural Networks with Transfer Learning\n* Implementation of Inception V3","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"**Please upvote my work. It inspires and motivates me alot.**\n* You can access it in my [GitHub](https://github.com/ThinamXx) as well. You can also see my other projects my [GitHub](https://github.com/ThinamXx). My GitHub account is [ThinamXx](https://github.com/ThinamXx).","execution_count":null}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}