{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Cats and Dogs"},{"metadata":{},"cell_type":"markdown","source":"In this kernel we will be training a CNN model in Keras to identify if the image have a cat or a dog. We have a dataset of 25000 images dogs and cats and we will use that to train our model for predicting results"},{"metadata":{},"cell_type":"markdown","source":"We will create this whole Kernel in three basic steps:\n\n* Importing, Preprocessing and Visualising the dataset\n* Creating the CNN model\n* Finally, Evaluating results and Making predictions\n\nIf you found this kernel useful please **UPVOTE**. \n\nSo, let's get started"},{"metadata":{},"cell_type":"markdown","source":"# Step 1 :\n## Importing, Preprocessing and Visualising"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Importing the required libraries\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport os\nimport cv2\nfrom tqdm import tqdm\n\nfrom sklearn.model_selection import train_test_split\n\nimport keras\nfrom keras import layers\nfrom keras.layers import Conv2D, Conv2DTranspose, MaxPooling2D, Dense, Dropout, Flatten\nfrom keras.models import Sequential","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's import our dataset. We will read images one by one from the **train_dir** and will store them in the **train_images** array. Each image is read in Grayscale and will be resized to (50, 50).\n\n**train_labels** will store the labels for each of the images."},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# Importing and Processing the dataset\n\ntrain_dir = '../input/train/'\n\ntrain_images = []\ntrain_labels = []\n\nfor img in tqdm(os.listdir(train_dir)):\n    try:\n        img_r = cv2.imread(os.path.join(train_dir, img), cv2.IMREAD_GRAYSCALE)\n        train_images.append(np.array(cv2.resize(img_r, (50, 50), interpolation=cv2.INTER_CUBIC)))\n        if 'dog' in img:\n            train_labels.append(1)\n        else:\n            train_labels.append(0)\n    except Exception as e:\n        print('broken image')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Now, let's visualise the images in our dataset. As you can see in the bottom we have an image of a cute little kitty. Though, it's not very clear to us but model will not have much problems while learning from this image."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualising the image\n\nplt.title(train_labels[0])\n_ = plt.imshow(train_images[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Here, we have used **train_test_split** from **scikit-learn** to split our training images and labels into train and test data. Since, we have our test_size set to 0.2 our initial dataset will be split into 20000 training and 5000 test data elements."},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train, x_test, y_train, y_test = train_test_split(train_images, train_labels, test_size=0.2, random_state=42)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train = np.array(x_train)\nx_test = np.array(x_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Train Shape:\" + str(x_train.shape))\nprint(\"Test Shape:\" + str(x_test.shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.title(y_train[0])\n_ = plt.imshow(x_train[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Step 2:\n## Creating the CNN Model"},{"metadata":{},"cell_type":"markdown","source":"Now, we will start to build our Convolutional Neural Network model. We will feed training images to our model and then it will be used to make predictions. This is a very basic model and a much better CNN architecture can be used to increase the accuracy."},{"metadata":{},"cell_type":"markdown","source":"To read more about CNNs you can refer to this [link](http://cs231n.github.io/convolutional-networks/)"},{"metadata":{"trusted":true},"cell_type":"code","source":"def baseline_model():\n    model = Sequential()\n    \n    model.add(Conv2D(32, (3, 3), input_shape=(50, 50, 1), activation='relu'))\n    model.add(Conv2D(32, (3, 3), activation='relu'))\n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Conv2D(128, (3, 3), activation='relu'))\n    model.add(Conv2D(128, (3, 3), activation='relu'))\n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Dropout(0.2))\n\n    model.add(Flatten())\n    model.add(Dense(128, activation='relu'))\n    \n    model.add(Dropout(0.2))\n    \n    model.add(Dense(1, activation='sigmoid'))\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = baseline_model()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"After creating the model we will compile it. Compiling a model means to \"Configure the learning process\". Here, we have defined our optimizer, loss and evaluation metrics."},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train = x_train.reshape(-1, 50, 50, 1)\nx_test = x_test.reshape(-1, 50, 50, 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(np.array(x_train), y_train, validation_data=(np.array(x_test), y_test), epochs=20, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We have trained our model on the training images and labels. The history object stores all the details in the process of training the model. So, let's move on to analysing our the process of training and the results we have got."},{"metadata":{},"cell_type":"markdown","source":"# Step 3:\n## Evaluating results and Making Predictions"},{"metadata":{"trusted":true},"cell_type":"code","source":"hist = history.history","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The plot below shows how the loss in both training(**x_train**) and validation(**x_test**) over the span of ten epochs. We can see how the decrease in the validation loss has slowed down while we approach the final epcohs.This may have happened because of a little bit of variance. You can observe similar trends in training and validation accuracy."},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(hist['loss'], 'green', label='Training Loss')\nplt.plot(hist['val_loss'], 'blue', label='Validation Loss')\n_ = plt.legend()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The plot below shows the change in accuracy in all the epochs. From the plot we can clearly see that there is a slight slowdown in the increase in validation accuracy. This is because of the reasons I mentioned previously. In our model, this problem is very much under the control but sometimes it can be very visible. In such cases there are many ways to solve it, just do a quick google search to learn more about it."},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(hist['acc'], 'green', label='Training Accuracy')\nplt.plot(hist['val_acc'], 'blue', label='Validation Accuracy')\n_ = plt.legend()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Finally we will import the test data to make predictions. Note that this is not the same test data set which we created by splitting our training set. That dataset is usually referred as **validation** set. We use validation set to make sure that our model is not overfitting the training data."},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dir = '../input/test/'\ntest_images = []\n\nfor img in tqdm(os.listdir(test_dir)):\n    try:\n        img_r = cv2.imread(os.path.join(test_dir, img), cv2.IMREAD_GRAYSCALE)\n        test_images.append(np.array(cv2.resize(img_r, (50, 50), interpolation=cv2.INTER_CUBIC)))\n    except Exception as e:\n        print('broken image')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_ = plt.imshow(test_images[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"After analysing the model we will make the final predictions and will create the submission file"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_images = np.array(test_images)\ntest_images = test_images.reshape(-1, 50, 50, 1)\npredictions = model.predict(test_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predictions.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"counter = range(1, len(test_images) + 1)\nsolution = pd.DataFrame({\"id\": counter, \"label\":list(predictions)})\ncols = ['label']\n\nfor col in cols:\n    solution[col] = solution[col].map(lambda x: str(x).lstrip('[').rstrip(']')).astype(float)\n\nsolution.to_csv(\"dogsVScats.csv\", index = False)\n","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}