{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Transfer Learning For Binary-Class Image Classification Using Deep Convolutional Neural Network"},{"metadata":{},"cell_type":"markdown","source":"## Task 7:\n> Problem: Transfer learning\n> Show use the use of transfer learning to train a model on\n> less data (<1000 images) and still getting good results (>80% accuracy) to demonstrate use\n> of transfer learning. You are free to pick a model of your choice and dataset of your choice.\n> (just don’t pick dataset which is already used in initial training)"},{"metadata":{},"cell_type":"markdown","source":"**In this notebook I am going to solve above problem, I will implement the binary-class image classification using the VGG-16 Deep Convolutional Network used as a Transfer Learning framework where the VGGNet comes pre-trained on the ImageNet dataset. For the experiment, we will use the Kaggle dogs-vs-cats dataset and classify the image objects into 2 classes. The classification accuracies of the VGG-16 model will be visualized using the confusion matrices.**"},{"metadata":{},"cell_type":"markdown","source":"## What is Transfer Learning?\n\n**Transfer learning is a research problem in the field of machine learning. It stores the knowledge gained while solving one problem and applies it to a different but related problem. In deep learning, transfer learning is a technique whereby a neural network model is first trained on a problem similar to the problem that is being solved. Transfer learning has the advantage of decreasing the training time for a learning model and can result in lower generalization error.**"},{"metadata":{},"cell_type":"markdown","source":"## VGGNet – The Deep Convolutional Network\n\n**VGGNet is Deep Convolutional Neural Network that was proposed by Karen Simonyan and Andrew Zisserman of the University of Oxford in their research work ‘Very Deep Convolutional Neural Networks for Large-Scale Image Recognition’. The name of this model was inspired by the name of their research group ‘Visual Geometry Group (VGG)’. As this convolutional neural network has 16 layers in its architecture, it was named VGG-16. This model was proposed to reduce the number of parameters in a convolutional neural network with improved training time.**\n\n**The biggest advantage of this network is that we can load a pre-trained version of the network trained on more than a million images from the ImageNet database. A pre-trained network can classify images into thousands of object categories. Due to this advantage, I am going to apply this model on the Kaggle dogs-vs-cats dataset image dataset that has 2 object categories.**"},{"metadata":{},"cell_type":"markdown","source":"## The Dataset\n\nTo complete this task, I shall be using the Kaggle dogs-vs-cats dataset that is a publically available image data set provided by the Kaggle. It consists of 25000 colour images in 2 classes as a train dataset. I work on only train dataset so i am not going to discuss about test dataset and here i am talking about raw dataset which is actually train dataset as discussed above. I will slice first 1000 (raw_dataset[:1000]) images from the original raw dataset, out of which 503 are dog and 497 are cat. and then split it into validate as 100 and 900 as train. To test our model I have sliced 200 dataset from original raw dataset[10000:10200]."},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Importing libraries"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nfrom keras import layers\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation,GlobalMaxPooling2D\nfrom keras import applications\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import optimizers\nfrom keras.applications import VGG16\nfrom keras.models import Model\nimport seaborn as sns\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.metrics import confusion_matrix","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(os.listdir('../input/dogs-vs-cats-redux-kernels-edition'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import zipfile\n\n\nzip_files = ['test', 'train']\n# Will unzip the files\nfor zip_file in zip_files:\n    with zipfile.ZipFile(\"../input/dogs-vs-cats-redux-kernels-edition/{}.zip\".format(zip_file),\"r\") as z:\n        z.extractall(\".\")\n        print(\"{} unzipped\".format(zip_file))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"IMAGE_FOLDER_PATH=\"../working/train\"\nFILE_NAMES=os.listdir(IMAGE_FOLDER_PATH)\nWIDTH=150\nHEIGHT=150","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"targets=list()\nfull_paths=list()\nfor file_name in FILE_NAMES:\n    target=file_name.split(\".\")[0]\n    full_path=os.path.join(IMAGE_FOLDER_PATH, file_name)\n    full_paths.append(full_path)\n    targets.append(target)\n\nraw_dataset=pd.DataFrame()\nraw_dataset['image_path']=full_paths\nraw_dataset['target']=targets","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Dataset "},{"metadata":{"trusted":true},"cell_type":"code","source":"raw_dataset.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset = raw_dataset[:1000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset['target'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, validate_df = train_test_split(dataset, test_size=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df[\"target\"].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"validate_df[\"target\"].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Train generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rotation_range=15,\n    rescale=1./255,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest',\n    width_shift_range=0.1,\n    height_shift_range=0.1\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_size = 224\ninput_shape = (image_size, image_size, 3)\n\nepochs = 5\nbatch_size = 6","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    #\"../input/train/train/\", \n    x_col='image_path',\n    y_col='target',\n    class_mode='binary',\n    target_size=(image_size, image_size),\n    batch_size=batch_size\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"###  Validation generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    ##\"../input/train/train/\", \n    x_col='image_path',\n    y_col='target',\n    class_mode='binary',\n    target_size=(image_size, image_size),\n    batch_size=batch_size\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Defining VGG16 as a Deep Convolutional Neural Network and load it as a pre trained model. \n### Adding the Dense layers along with activation"},{"metadata":{"trusted":true},"cell_type":"code","source":"pre_trained_model = VGG16(input_shape=input_shape, include_top=False, weights=\"imagenet\")\n    \nfor layer in pre_trained_model.layers[:15]:\n    layer.trainable = False\n\nfor layer in pre_trained_model.layers[15:]:\n    layer.trainable = True\n    \nlast_layer = pre_trained_model.get_layer('block5_pool')\nlast_output = last_layer.output\n    \n# Flatten the output layer to 1 dimension\nx = GlobalMaxPooling2D()(last_output)\n# Add a fully connected layer with 512 hidden units and ReLU activation\nx = Dense(512, activation='relu')(x)\n# Add a dropout rate of 0.5\nx = Dropout(0.5)(x)\n# Add a final sigmoid layer for classification\nx = layers.Dense(1, activation='sigmoid')(x)\n\nmodel = Model(pre_trained_model.input, x)\n\nmodel.compile(loss='binary_crossentropy',\n              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),\n              metrics=['accuracy'])\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Now, we start training our VGG16, the deep convolutional neural network model."},{"metadata":{"trusted":true},"cell_type":"code","source":"Trained_model = model.fit_generator(\n    train_generator,\n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=total_validate//batch_size,\n    steps_per_epoch=total_train//batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_Trained_model(model_history, acc='accuracy', val_acc='val_accuracy'):\n    fig, axs = plt.subplots(1,2,figsize=(15,5))\n    axs[0].plot(range(1,len(model_history.history[acc])+1),model_history.history[acc])\n    axs[0].plot(range(1,len(model_history.history[val_acc])+1),model_history.history[val_acc])\n    axs[0].set_title('Model Accuracy Score')\n    axs[0].set_ylabel('Accuracy')\n    axs[0].set_xlabel('Epoch')\n    axs[0].set_xticks(np.arange(1,len(model_history.history[acc])+1),len(model_history.history[acc])/10)\n    axs[0].legend(['Train', 'Validation'], loc='best')\n    axs[1].plot(range(1,len(model_history.history['loss'])+1),model_history.history['loss'])\n    axs[1].plot(range(1,len(model_history.history['val_loss'])+1),model_history.history['val_loss'])\n    axs[1].set_title('Model Loss Score')\n    axs[1].set_ylabel('Loss')\n    axs[1].set_xlabel('Epoch')\n    axs[1].set_xticks(np.arange(1,len(model_history.history['loss'])+1),len(model_history.history['loss'])/10)\n    axs[1].legend(['Train', 'Validation'], loc='best')\n    plt.show()\n    \nplot_model_history(Trained_model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Prepare Testing Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"testdata_raw = raw_dataset[10000:10200]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"testdata_raw[\"target\"].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"testdata = testdata_raw.drop(columns=\"target\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Y_true = []\nfor i in testdata_raw[\"target\"]:\n    if i == \"dog\":\n        Y_true.append(1)\n    else:\n        Y_true.append(0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"testdata.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Create Testing Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    testdata,\n    #\"../input/test1/test1/\", \n    x_col='image_path',\n    y_col=None,\n    class_mode=None,\n    batch_size=batch_size,\n    target_size=(image_size, image_size),\n    shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Predict"},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames = test_generator.filenames\nnb_samples = len(filenames)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/batch_size))\nthreshold = 0.5\ntestdata['category'] = np.where(predict > threshold, 1,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_pred = testdata['category']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### See predicted result"},{"metadata":{"trusted":true},"cell_type":"code","source":"accuracy_score(Y_true,y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# Predict the values from the validation dataset\n\n# compute the confusion matrix\nconfusion_mtx = confusion_matrix(Y_true,y_pred) \n# plot the confusion matrix\nf,ax = plt.subplots(figsize=(5, 5))\nsns.heatmap(confusion_mtx, annot=True, linewidths=0.01,cmap=\"Greens\",linecolor=\"gray\", fmt= '.1f',ax=ax)\nplt.xlabel(\"Predicted Label\")\nplt.ylabel(\"True Label\")\nplt.title(\"Confusion Matrix\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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}