{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.7"
    },
    "colab": {
      "provenance": [],
      "include_colab_link": true
    },
    "accelerator": "TPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/Sahel-Eskandar/Project-Notebooks/blob/main/5_Transfer_leaning_example.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yUqf4MFrMrdE",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 80
        },
        "outputId": "490952cb-6df8-46f1-e692-44c4424b7559"
      },
      "source": [
        "import os\n",
        "import keras\n",
        "import numpy as np\n",
        "from PIL import Image\n",
        "import tensorflow as tf\n",
        "from random import randint\n",
        "import matplotlib.pyplot as plt\n",
        "from keras import backend as k\n",
        "from keras.utils import np_utils\n",
        "from keras.optimizers import adam\n",
        "from keras.models import Sequential\n",
        "from sklearn.metrics import confusion_matrix\n",
        "from sklearn.preprocessing import MinMaxScaler\n",
        "from keras.preprocessing.image import img_to_array\n",
        "from keras.metrics import categorical_crossentropy\n",
        "#from sklearn.cross_validation import train_test_split\n",
        "from keras.layers import Dense,Dropout,Activation,Flatten,Conv2D\n",
        "from keras.layers.convolutional import Convolution2D,MaxPooling2D\n",
        "\n",
        "#from keras import backend as K\n",
        "#K.set_image_dim_ordering('th')\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Using TensorFlow backend.\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<p style=\"color: red;\">\n",
              "The default version of TensorFlow in Colab will soon switch to TensorFlow 2.x.<br>\n",
              "We recommend you <a href=\"https://www.tensorflow.org/guide/migrate\" target=\"_blank\">upgrade</a> now \n",
              "or ensure your notebook will continue to use TensorFlow 1.x via the <code>%tensorflow_version 1.x</code> magic:\n",
              "<a href=\"https://colab.research.google.com/notebooks/tensorflow_version.ipynb\" target=\"_blank\">more info</a>.</p>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "umKObpr3TDa1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 129
        },
        "outputId": "ab9668ed-fc8f-4b48-d2e9-f9da587f4387"
      },
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "error",
          "ename": "SyntaxError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-2-fda26d7833e7>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m    Mount the drive\u001b[0m\n\u001b[0m            ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ec130YomXKxD"
      },
      "source": [
        "import os\n",
        "import pprint\n",
        "if 'COLAB_TPU_ADDR' not in os.environ:\n",
        "  print('ERROR: Not connected to a TPU runtime; ')\n",
        "else:\n",
        "  tpu_address = 'grpc://' + os.environ['COLAB_TPU_ADDR']\n",
        "  print ('TPU address is', tpu_address)\n",
        "\n",
        "  with tf.Session(tpu_address) as session:\n",
        "    devices = session.list_devices()\n",
        "    \n",
        "  print('TPU devices:')\n",
        "  pprint.pprint(devices)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "deYvCJAGWlkk"
      },
      "source": [
        "#process for reproducing same result\n",
        "import os\n",
        "import random as rm\n",
        "\n",
        "# The below is necessary in Python 3.2.3 onwards to\n",
        "# have reproducible behavior for certain hash-based operations.\n",
        "# See these references for further details:\n",
        "# https://docs.python.org/3.4/using/cmdline.html#envvar-PYTHONHASHSEED\n",
        "# https://github.com/fchollet/keras/issues/2280#issuecomment-306959926\n",
        "os.environ['PYTHONHASHSEED']='0'\n",
        "\n",
        "# The below is necessary for starting Numpy generated random numbers\n",
        "# in a well-defined initial state.\n",
        "np.random.seed(1)\n",
        "\n",
        "# The below is necessary for starting core Python generated random numbers\n",
        "# in a well-defined state.\n",
        "rm.seed(1)\n",
        "\n",
        "# The below tf.set_random_seed() will make random number generation\n",
        "# in the TensorFlow backend have a well-defined initial state.\n",
        "# For further details, see: https://www.tensorflow.org/api_docs/python/tf/set_random_seed\n",
        "tf.set_random_seed(1)\n",
        "\n",
        "# Force TensorFlow to use single thread.\n",
        "# Multiple threads are a potential source of\n",
        "# non-reproducible results.\n",
        "# For further details, see: https://stackoverflow.com/questions/42022950/which-seeds-have-to-be-set-where-to-realize-100-reproducibility-of-training-res\n",
        "from keras import backend as k\n",
        "session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)\n",
        "\n",
        "sess=tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph())\n",
        "k.set_session(sess)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "iU9InxFyTlPM"
      },
      "source": [
        "pp='/content/drive/My Drive/app1/'\n",
        "train_path=pp+'cat-and-dog/training_set/'\n",
        "valid_path=pp+'cat-and-dog/valid_set/'\n",
        "test_path=pp+'cat-and-dog/test_set/'"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "sRe0Ff95MrdL"
      },
      "source": [
        "from keras.preprocessing.image import ImageDataGenerator\n",
        "img_size=224\n",
        "datagen = ImageDataGenerator(rescale=1./255)\n",
        "train_batches=datagen.flow_from_directory(\n",
        "               train_path,\n",
        "               target_size=(img_size,img_size),\n",
        "               classes=['dogs','cats'],\n",
        "               batch_size=10,\n",
        "               color_mode=\"grayscale\")\n",
        "valid_batches=datagen.flow_from_directory(\n",
        "               valid_path,\n",
        "               target_size=(img_size,img_size),\n",
        "               classes=['dogs','cats'],\n",
        "               batch_size=10,\n",
        "               color_mode=\"grayscale\")\n",
        "test_batches=datagen.flow_from_directory(\n",
        "               test_path,\n",
        "               target_size=(img_size,img_size),\n",
        "               classes=['dogs','cats'],\n",
        "               batch_size=4,\n",
        "               color_mode=\"grayscale\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ONBHxOJ_MrdQ"
      },
      "source": [
        "# Build VGG16 model-Sequential"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uHsQrw3fMrdR"
      },
      "source": [
        "VGG16 works with activation=\"softmax\" which does not works here."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vtkrv8-gMrdS"
      },
      "source": [
        "#vgg16_model=keras.applications.vgg16.VGG16()\n",
        "vgg16_model = keras.applications.VGG16(weights='imagenet', input_shape = (3,224,224))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "D05jw6A7MrdV"
      },
      "source": [
        "vgg16_model.summary()\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VwznCV3qMrdZ"
      },
      "source": [
        "vgg16 is a model not a sequential model. It needs to be transformed to a sequential model.\n",
        "Sequential model create models layer-by-layer for most problems. It is limited in that it does not allow you to create models that share layers or have multiple inputs or outputs."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "r-tkcF6uMrda"
      },
      "source": [
        "type(vgg16_model)\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CjZPQsIsMrde"
      },
      "source": [
        "model=Sequential()\n",
        "for layer in vgg16_model.layers[:-1]:\n",
        "    model.add(layer)\n",
        "    model.trainable=False  "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "56-Ukt1xMrdl"
      },
      "source": [
        "Remove the last layer of 1000 categories and add the current selection"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "a8pIXo0dMrdm"
      },
      "source": [
        "model.add(Dense(units=2))\n",
        "model.add(Activation(tf.nn.softmax))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "eowz95fAMrdp"
      },
      "source": [
        "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
        "model.fit_generator(\n",
        "                generator=train_batches,\n",
        "                validation_data=valid_batches,\n",
        "                steps_per_epoch=4,#train_batches.samples(8005)/train_batches.batch_size(50),\n",
        "                validation_steps=4,#valid_batches.samples/valid_batches.batch_size,\n",
        "                verbose=2,\n",
        "                #shuffle=False,\n",
        "                epochs=3)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VK-YwJbYMrdt"
      },
      "source": [
        "# Prediction"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0MWGAh9EMrdw"
      },
      "source": [
        "from keras.preprocessing.image import load_img\n",
        "# load an image from file\n",
        "image_path='dog.6.jpg'\n",
        "image = load_img(image_path, target_size=(224, 224))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7tihchtsMrdz"
      },
      "source": [
        "np.shape(image)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "w1FQcPXYMrd2"
      },
      "source": [
        "from keras.preprocessing.image import img_to_array\n",
        "# convert the image pixels to a numpy array\n",
        "image = img_to_array(image)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UaO4grWQMrd6"
      },
      "source": [
        "image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))\n",
        "from keras.applications.vgg16 import preprocess_input\n",
        "# prepare the image for the VGG model\n",
        "image = preprocess_input(image)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "A78BpEPNMrd9"
      },
      "source": [
        "#from keras.applications.vgg16 import decode_predictions\n",
        "# predict the probability across all output classes\n",
        "yhat = model.predict(image)\n",
        "yhat"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8rAiFY5-MreB"
      },
      "source": [
        "#from keras.applications.vgg16 import decode_predictions\n",
        "# convert the probabilities to class labels\n",
        "#label = decode_predictions(yhat)\n",
        "# retrieve the most likely result, e.g. highest probability\n",
        "#label = label[0][0]\n",
        "# print the classification\n",
        "#print('%s (%.2f%%)' % (label[1], label[2]*100))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "j2VHJud1MreH"
      },
      "source": [
        "# Build VGG16 model-Freez layers"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "iIGSiNRCMreI"
      },
      "source": [
        "#keras.applications.vgg16.VGG16()\n",
        "#include_top=False ---> exclude the last layer of the VGG model.\n",
        "vgg_model = keras.applications.VGG16(weights='imagenet', include_top=False, input_shape = (3,224,224))\n",
        "\n",
        "# Creating dictionary that maps layer names to the layers\n",
        "layer_dict = dict([(layer.name, layer) for layer in vgg_model.layers])"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "g_BMU1tEMreM"
      },
      "source": [
        "# Getting output tensor of the last VGG layer that we want to include\n",
        "x = layer_dict['block5_pool'].output\n",
        "\n",
        "# Stacking a new simple convolutional network on top of it    \n",
        "#x = Conv2D(filters=64, kernel_size=(3, 3), activation='relu')(x)\n",
        "#x = MaxPooling2D(pool_size=(2, 2))(x)\n",
        "x = Flatten()(x)\n",
        "x = Dense(256, activation='relu')(x)\n",
        "x = Dropout(0.5)(x)\n",
        "x = Dense(2, activation=tf.nn.softmax)(x)\n",
        "\n",
        "# Creating new model. Please note that this is NOT a Sequential() model.\n",
        "from keras.models import Model\n",
        "custom_model = Model(input=vgg_model.input, output=x)\n",
        "\n",
        "# Make sure that the pre-trained bottom layers are not trainable\n",
        "for layer in custom_model.layers[:-3]:\n",
        "    layer.trainable = False\n",
        "\n",
        "# Do not forget to compile it\n",
        "custom_model.compile(loss='categorical_crossentropy',\n",
        "                     optimizer='rmsprop',\n",
        "                     metrics=['accuracy'])\n",
        "\n",
        "custom_model.fit_generator(\n",
        "                generator=train_batches,\n",
        "                validation_data=valid_batches,\n",
        "                steps_per_epoch=4,#train_batches.samples(8005)/train_batches.batch_size(50),\n",
        "                validation_steps=4,#valid_batches.samples/valid_batches.batch_size,\n",
        "                verbose=2,\n",
        "                #shuffle=False,\n",
        "                epochs=3)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xkQnpvjkMreP"
      },
      "source": [
        "yhat = custom_model.predict(image)\n",
        "yhat"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "x-cypGKWMreT"
      },
      "source": [
        "# Build VGG16 model-Initial weight"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "n5IfwiPxMreU"
      },
      "source": [
        "#keras.applications.vgg16.VGG16()\n",
        "vgg_model = keras.applications.VGG16(weights='imagenet', include_top=False, input_shape = (3,224,224))\n",
        "\n",
        "for layer in vgg_model.layers[:5]:\n",
        "    layer.trainable = True\n",
        "\n",
        "for layer in vgg_model.layers:\n",
        "    print(layer, layer.trainable)\n",
        "    "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SAVC9tExMreX"
      },
      "source": [
        "#Adding custom Layers \n",
        "x = vgg_model.output\n",
        "x = Flatten()(x)\n",
        "x = Dense(256, activation=\"relu\")(x)\n",
        "x = Dropout(0.5)(x)\n",
        "x = Dense(256, activation=\"relu\")(x)\n",
        "predictions = Dense(2, activation=\"softmax\")(x)\n",
        "\n",
        "model_final = Model(input = vgg_model.input, output = predictions)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "t6_Y_8afMrea"
      },
      "source": [
        "# creating the final model \n",
        "\n",
        "# Do not forget to compile it\n",
        "model_final.compile(loss='categorical_crossentropy',\n",
        "                     optimizer='adam',\n",
        "                     metrics=['accuracy'])\n",
        "\n",
        "\n",
        "model_final.fit_generator(\n",
        "                generator=train_batches,\n",
        "                validation_data=valid_batches,\n",
        "                steps_per_epoch=4,#train_batches.samples/train_batches.batch_size,,\n",
        "                validation_steps=4,#valid_batches.samples/valid_batches.batch_size,,\n",
        "                verbose=2,\n",
        "                #shuffle=False, \n",
        "                epochs=3)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GJBW9Q_RMred"
      },
      "source": [
        "# Data Augmentation"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CNHxdS40Mref"
      },
      "source": [
        "Data Augmentation occures when creating new data with modification.\n",
        "Filpp, Rotate, Zoom,Color change,Cropping"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "J3VIGZtAMreg"
      },
      "source": [
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "from scipy import misc,ndimage\n",
        "import keras\n",
        "from keras import backend as k\n",
        "from keras.preprocessing.image import ImageDataGenerator"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0y54xWlcMrej"
      },
      "source": [
        "gen=ImageDataGenerator(rotation_range=10,width_shift_range=0.1,\n",
        "                       height_shift_range=0.1,shear_range=0.15,\n",
        "                       zoom_range=0.1,channel_shift_range=10,\n",
        "                       horizontal_flip=True)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pMBt1TCQMrel"
      },
      "source": [
        "import cv2\n",
        "image_path='/Users/atousa/Desktop/McMaster/BDA-102/Neural_network/data/cat-and-dog/dog.6.jpg'"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JbjkligtMreo"
      },
      "source": [
        "image=cv2.imread(image_path)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "t0x5-nTkMrer"
      },
      "source": [
        "np.shape(image)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "A1r_KDGeMreu"
      },
      "source": [
        "import matplotlib.pyplot as plt\n",
        "plt.imshow(image[:,:,0], cmap='gray')\n",
        "plt.show()"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "x9h0rFCrMrew"
      },
      "source": [
        "generate batches of image"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "trgsbcDvMrex"
      },
      "source": [
        "np.shape(image)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "89NWaKEnMre0"
      },
      "source": [
        "image = np.moveaxis(image, -1, 0)\n",
        "image.shape"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hjRJyDXhMre4"
      },
      "source": [
        "image_batch = image.reshape((1,) + image.shape)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DzymrDl0Mre7"
      },
      "source": [
        "np.shape(image_batch)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "M2GqKqG5Mre-"
      },
      "source": [
        "Get 10 sample of the batches"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "eRanS4S6Mre-"
      },
      "source": [
        "aug_iter=gen.flow(image_batch, batch_size=2)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mrxvC-lmMrfE"
      },
      "source": [
        "aug_images=[next(aug_iter)[0].astype(np.uint8) for i in range(10)]\n",
        "np.shape(aug_images)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DYDnYCmGMrfJ"
      },
      "source": [
        "for i in range(0,10):\n",
        "    img = aug_images[i]\n",
        "    plt.imshow(img[1,:,:].astype('uint8'), cmap='gray')\n",
        "    plt.show()    "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uRx-bpU-MrfL"
      },
      "source": [],
      "execution_count": null,
      "outputs": []
    }
  ]
}