{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Convolutional Neural Network (CNN)"},{"metadata":{},"cell_type":"markdown","source":"## Introduction"},{"metadata":{},"cell_type":"markdown","source":"Convolutional neural networks (CNNs or ConvNets) are popular group of neural networks in Deep Learning. \n\nIt was inspired by the the study conducted by Dr.Hubel and Dr.Wisel in 1960’s. They worked on the area of Sensory processing. In this study,they inserted a micro-electrode into the primary visual cortex of an partially anesthetized cat (cat was partially anesthetized so that it would not move during the study) and shown the images to the cat. They took the reading from the electrodes.\n\nThe CNN was introduced in 1980 but at that time due to limitation in the computational power of computer it was not popular. A kind of CNN called AlexNet won the [Image Net Chllange in 2012 A.D](http://www.image-net.org/challenges/LSVRC/2012/) then the CNN became very popular in image classification."},{"metadata":{},"cell_type":"markdown","source":"## Architecture of Convolutional Neural Network\n\nThe Image below shows the architecture of a typical Convolutional Neural Network."},{"metadata":{},"cell_type":"markdown","source":"![CNN Architecture](https://upload.wikimedia.org/wikipedia/commons/6/63/Typical_cnn.png)"},{"metadata":{},"cell_type":"markdown","source":"The image is converted into feature vector. If the image is of size 32X32 with RGB color channel then image. Then the input layer of a typical Neural Network would have 32323 = 3072 weights. This amount still seems manageable, but clearly this fully-connected structure does not scale to larger images. For example, an image of more respectable size, e.g. 200X200X3, would lead to neurons that have \n200X200X3 =120,000 weights. So in Convolution and pooling is done so that we can extratct the important features of a image and size is also reduced. \n\nA CNN consists of sequence of layers. Each layer has different function. The main layers to build a CNN are \n1. Input \n2. Convolutional Layer \n3. Pooling Layer\n4. Fully-Connected Layer"},{"metadata":{},"cell_type":"markdown","source":"### Input Layer\n\nIt holds the raw pixel values of the image. If we have an image of size 32X32 then widthof image=32, height of image=32, and  three color channels Red,Green,Blue.\n\n### Convolutional Layer\n\nIn this layer we use kernals to perform the convulution operation. Convolution is the first layer to extract high-level features from an input image. Convolution of an image with different filters can perform operations such as edge detection, blur and sharpen by applying filters.\n\n### Pooling Layer\nPooling is carried out in order to reduce the dimensionality (size). As we see in the diagram above the feature map is getting smaller and smaller. It is done via pooling operation. \n\n### Fully Connected Layer\nA fully connected layer is the plain old neural network. This layer computes the class scores. As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.\n\n**A typical CNN consist of one input layer, multiple sequence of convolutional and pooling layer and one fully connected layer.**"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport cv2\nimport zipfile\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport tensorflow as tf\nimport os\nimport pandas as pd\nimport tensorflow as tf\nfrom sklearn.model_selection import train_test_split\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":false},"cell_type":"markdown","source":"Extracting the Files From zipped floders"},{"metadata":{"trusted":true},"cell_type":"code","source":"with zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as z:\n    z.extractall(\".\")\n    \nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\",\"r\") as z:\n    z.extractall(\".\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Taking a Look at some of the Sample images of Dogs from the Dataset**"},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# define location of dataset\nfolder = '/kaggle/working/train/'\nfor i in range(9):\n    # define subplot\n    plt.subplot(330 + 1 + i)\n    # define filename\n    filename = folder + 'dog.' + str(i) + '.jpg'\n    # load image pixels\n    image = plt.imread(filename)\n    # plot raw pixel data\n    plt.imshow(image)\n    #show the figure\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Taking a Look at some of the Sample images of Cats from the Dataset**"},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(9):\n    # define subplot\n    plt.subplot(330 + 1 + i)\n    # define filename\n    filename = folder + 'cat.' + str(i) + '.jpg'\n    # load image pixels\n    image = plt.imread(filename)\n    # plot raw pixel data\n    plt.imshow(image)\n    #show the figure\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Setting the Constants that will be used throught the program**"},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_DIR = \"/kaggle/working/train/\"\nTEST_DIR=\"/kaggle/working/test1/\"\nTRAIN_SIZE = len([name for name in os.listdir(TRAIN_DIR)])\nprint(\"Number of training images:\", TRAIN_SIZE)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Setting the Size of the Image as 80X80 and three channels for RGB**"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_WIDTH=80\nIMAGE_HEIGHT=80\nIMAGE_SIZE=(IMAGE_WIDTH, IMAGE_HEIGHT)\nIMAGE_CHANNELS=3","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Using the File name to get the category. Using this information to build a dataframe of file name label**"},{"metadata":{"trusted":true},"cell_type":"code","source":"filenames = os.listdir(TRAIN_DIR)\ncategories = []\nfor filename in filenames:\n    category = filename.split('.')[0]\n    if category.lower()=='dog':\n        categories.append(\"dog\")\n    else:\n        categories.append(\"cat\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.DataFrame({\n    'filename': filenames,\n    'label': categories\n})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['label']=df['label'].astype(str)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Creating a Bar Graph to Visulize how many samples of each class do we have**"},{"metadata":{"trusted":true},"cell_type":"code","source":"df['label'].value_counts().plot(kind='bar')\nplt.title(\"Number of Cats and Dogs Sample in the Dataset\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['label'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Train your algorithm on these files and predict the labels for test1.zip (1 = dog, 0 = cat).**"},{"metadata":{"trusted":true},"cell_type":"code","source":"df['label'] = df['label'].map({\"dog\":\"1\",\"cat\":\"0\"})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['label']=df['label'].astype('str')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Splitting the Data in Training and Testing Set**"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df, valid_df = train_test_split(df, test_size=0.2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Using Image Generator to create the data for training the model. The image generator transforms the images in various ways for example by rotating the image. This allows us the train the model with images at different angles**"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(    \n    rotation_range=40,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    rescale=1./255.,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    fill_mode='nearest'\n    )\n\ntest_datagen = ImageDataGenerator(rescale=1./255)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    TRAIN_DIR, \n    x_col='filename',\n    y_col='label',\n    target_size=(IMAGE_WIDTH, IMAGE_HEIGHT),\n    class_mode='binary',\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"valid_generator = test_datagen.flow_from_dataframe(\n    valid_df, \n    TRAIN_DIR, \n    x_col='filename',\n    y_col='label',\n    target_size=(IMAGE_WIDTH, IMAGE_HEIGHT),\n    class_mode='binary'\n)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Defining the Model Structure. As explained earlier the CNN we build consist of Convolution, Pooling and Fully Connected Layer**"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Sequential()\n\n# First Set of Convolution and Pooling Layer\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\n\n# Second Set of Convolution and Pooling Layer\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\n\n# Third Set of Convolution and Pooling Layer\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\n\n# Fully Connected Layer\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1, activation='sigmoid')) # 2 because we have cat and dog classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Visulizing the Model as a Flowchart**"},{"metadata":{"trusted":true},"cell_type":"code","source":"tf.keras.utils.plot_model(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=0.001),\n    loss='binary_crossentropy',\n    metrics = ['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Training the Model. Adding some important metrices for in the history variable which we can use for visulization later on**"},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(train_generator,validation_data=valid_generator,steps_per_epoch=round(TRAIN_SIZE*(1.-0.2)/32),\n    validation_steps=round(TRAIN_SIZE*0.2/32),epochs=20,verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Visulizing the Training Metrices on Each Epoch**"},{"metadata":{"trusted":true},"cell_type":"code","source":"acc = history.history['accuracy']\nval_acc = history.history[ 'val_accuracy']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs   = range(len(acc)) # Get number of epochs\nplt.plot(epochs, acc)\nplt.plot(epochs, val_acc)\nplt.legend(['Training Accuracy','Validation Accuracy'])\nplt.title('Training and validation accuracy')\nplt.figure()\nplt.plot(epochs, loss)\nplt.plot(epochs, val_loss)\nplt.legend(['Training Loss','Validation Loss'])\nplt.title('Training and validation loss')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_filenames = os.listdir(TEST_DIR)\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntest_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    TEST_DIR, \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=IMAGE_SIZE,\n    batch_size=32,\n    shuffle=False\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\npredict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/32))\nthreshold = 0.5\ntest_df['category'] = np.where(predict > threshold, 1,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df['category'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df = test_df.copy()\nsubmission_df['id'] = submission_df['filename'].str.split('.').str[0]\nsubmission_df['label'] = submission_df['category']\nsubmission_df.drop(['filename', 'category'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)","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}