{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom sklearn.model_selection import train_test_split\nimport os\nimport seaborn as sns\nimport random\nimport zipfile\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n    \nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n    \n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-07-16T17:19:12.297858Z","iopub.execute_input":"2023-07-16T17:19:12.298644Z","iopub.status.idle":"2023-07-16T17:19:22.076250Z","shell.execute_reply.started":"2023-07-16T17:19:12.298593Z","shell.execute_reply":"2023-07-16T17:19:22.075297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Extract the files</h3>","metadata":{}},{"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(\".\")\n    \nos.listdir(\".\")","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:22.078343Z","iopub.execute_input":"2023-07-16T17:19:22.079003Z","iopub.status.idle":"2023-07-16T17:19:36.007427Z","shell.execute_reply.started":"2023-07-16T17:19:22.078969Z","shell.execute_reply":"2023-07-16T17:19:36.006507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Load images and their respective labels</h3>","metadata":{}},{"cell_type":"code","source":"test_images = os.listdir(\"./train/\")\ncategories = []\nfor filename in test_images:\n    category = filename.split('.')[0]\n    if category == 'dog':\n        categories.append(1)\n    else:\n        categories.append(0)\n\ndf = pd.DataFrame({\n    'filename': test_images,\n    'category': categories\n})","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:36.008879Z","iopub.execute_input":"2023-07-16T17:19:36.009459Z","iopub.status.idle":"2023-07-16T17:19:36.057980Z","shell.execute_reply.started":"2023-07-16T17:19:36.009426Z","shell.execute_reply":"2023-07-16T17:19:36.057131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:36.060744Z","iopub.execute_input":"2023-07-16T17:19:36.061290Z","iopub.status.idle":"2023-07-16T17:19:36.076190Z","shell.execute_reply.started":"2023-07-16T17:19:36.061259Z","shell.execute_reply":"2023-07-16T17:19:36.075119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Class Distribution in Dataset</h3>","metadata":{}},{"cell_type":"code","source":"category_counts = df['category'].value_counts()\ncategory_percentages = category_counts / category_counts.sum() * 100\n\nplt.figure(figsize=(6, 6))\nsns.set(style='darkgrid')\nlabels = ['Dog', 'Cat']\ncolors = ['#ff9999', '#66b3ff']\n\nexplode = (0.1, 0)\n\nplt.pie(category_counts, labels=labels, colors=colors, explode=explode, autopct='%1.1f%%', startangle=90)\nplt.title('Distribution of Dogs & Cats in the dataset')\nplt.axis('equal')\nplt.show()\n\nfor label, count, percentage in zip(labels, category_counts, category_percentages):\n    print(f\"{label}: {count} samples, {percentage:.1f}%\")","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:36.077945Z","iopub.execute_input":"2023-07-16T17:19:36.078280Z","iopub.status.idle":"2023-07-16T17:19:36.255457Z","shell.execute_reply.started":"2023-07-16T17:19:36.078250Z","shell.execute_reply":"2023-07-16T17:19:36.254652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Sample Image</h3>","metadata":{}},{"cell_type":"code","source":"IMAGE_WIDTH=256\nIMAGE_HEIGHT=256\nIMAGE_SIZE=(IMAGE_WIDTH, IMAGE_HEIGHT)\nIMAGE_CHANNELS=3\n\nsample = random.choice(test_images)\nimage = load_img(\"./train/\"+sample, target_size=IMAGE_SIZE)\nplt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:36.256821Z","iopub.execute_input":"2023-07-16T17:19:36.257357Z","iopub.status.idle":"2023-07-16T17:19:36.704154Z","shell.execute_reply.started":"2023-07-16T17:19:36.257326Z","shell.execute_reply":"2023-07-16T17:19:36.703307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Model Creation</h3>","metadata":{}},{"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(2, activation='softmax')) # 2 because we have cat and dog classes\n\nmodel.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:36.705106Z","iopub.execute_input":"2023-07-16T17:19:36.705395Z","iopub.status.idle":"2023-07-16T17:19:40.058016Z","shell.execute_reply.started":"2023-07-16T17:19:36.705369Z","shell.execute_reply":"2023-07-16T17:19:40.055361Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Data Preprocessing</h3>","metadata":{}},{"cell_type":"code","source":"df[\"category\"] = df[\"category\"].replace({0: 'cat', 1: 'dog'}) \ntrain_df, validate_df = train_test_split(df, test_size=0.20, random_state=42)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)\ntotal_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]\nbatch_size=15","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:40.059183Z","iopub.execute_input":"2023-07-16T17:19:40.059605Z","iopub.status.idle":"2023-07-16T17:19:40.097686Z","shell.execute_reply.started":"2023-07-16T17:19:40.059554Z","shell.execute_reply":"2023-07-16T17:19:40.096670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:40.100671Z","iopub.execute_input":"2023-07-16T17:19:40.101482Z","iopub.status.idle":"2023-07-16T17:19:40.121839Z","shell.execute_reply.started":"2023-07-16T17:19:40.101445Z","shell.execute_reply":"2023-07-16T17:19:40.120973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Training Dataset Generator</h3>","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    \"./train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:40.131790Z","iopub.execute_input":"2023-07-16T17:19:40.133662Z","iopub.status.idle":"2023-07-16T17:19:40.632457Z","shell.execute_reply.started":"2023-07-16T17:19:40.133608Z","shell.execute_reply":"2023-07-16T17:19:40.631541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Validation Dataset Generator</h3>","metadata":{"execution":{"iopub.status.busy":"2023-06-17T15:02:51.707178Z","iopub.execute_input":"2023-06-17T15:02:51.707662Z","iopub.status.idle":"2023-06-17T15:02:51.943634Z","shell.execute_reply.started":"2023-06-17T15:02:51.707604Z","shell.execute_reply":"2023-06-17T15:02:51.941933Z"}}},{"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    \"./train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:40.633981Z","iopub.execute_input":"2023-07-16T17:19:40.634678Z","iopub.status.idle":"2023-07-16T17:19:40.700256Z","shell.execute_reply.started":"2023-07-16T17:19:40.634645Z","shell.execute_reply":"2023-07-16T17:19:40.699423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Model Training</h3>","metadata":{}},{"cell_type":"code","source":"epochs=50\nhistory = model.fit(\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,\n)","metadata":{"execution":{"iopub.status.busy":"2023-07-16T17:19:40.701813Z","iopub.execute_input":"2023-07-16T17:19:40.702161Z","iopub.status.idle":"2023-07-16T18:27:02.908701Z","shell.execute_reply.started":"2023-07-16T17:19:40.702131Z","shell.execute_reply":"2023-07-16T18:27:02.907641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Feature Map Generation</h3>","metadata":{}},{"cell_type":"code","source":"sample = random.choice(test_images)\nimage = load_img(\"./train/\"+sample, target_size=IMAGE_SIZE)\nplt.imshow(image)\nimage = img_to_array(image)\nimage = image.reshape((1,) + image.shape)\nimage /= 255.0\nlayer_outputs = [layer.output for layer in model.layers[1:7]]  # Choose the layers whose feature maps you want to visualize\nactivation_model = Model(inputs=model.input, outputs=layer_outputs)\nactivations = activation_model.predict(image)\nlayer_names = ['conv1', 'batchnorm1', 'pool1', 'conv2', 'batchnorm2', 'pool2']\nimages_per_row = 8\n\nfor layer_name, layer_activation in zip(layer_names, activations):\n    num_features = layer_activation.shape[-1] #retrieves the number of feature maps in the layer_activation tensor by accessing the last dimension.\n    size = layer_activation.shape[1] #retrieves the spatial size (height or width) of each feature map from the layer_activation tensor.\n    num_cols = num_features // images_per_row\n    display_grid = np.zeros((size * num_cols, images_per_row * size)) #A NumPy array of zeros is created to store the visualizations of the feature maps.\n\n    for col in range(num_cols):\n        for row in range(images_per_row):\n            channel_image = layer_activation[0, :, :, col * images_per_row + row]\n            channel_image -= channel_image.mean() #centers the distribution of pixel values around zero.\n            channel_image /= channel_image.std() #normalizes the distribution of pixel values.\n            channel_image *= 64 #increase the contrast of the visualization.\n            channel_image += 128 #adjust the brightness.\n            channel_image = np.clip(channel_image, 0, 255).astype('uint8') #pixel values are clipped to the range of 0 to 255 to ensure they fall within the valid range\n            display_grid[col * size : (col + 1) * size, row * size : (row + 1) * size] = channel_image\n\n    scale = 1. / size\n    plt.figure(figsize=(scale * display_grid.shape[1], scale * display_grid.shape[0]))\n    plt.title(layer_name)\n    plt.grid(False)\n    plt.imshow(display_grid, aspect='auto', cmap='viridis')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:27:02.910049Z","iopub.execute_input":"2023-07-16T18:27:02.910343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Save Model</h3>","metadata":{}},{"cell_type":"code","source":"model.save_weights(\"model.h5\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Performance of the model over Epochs</h3>","metadata":{}},{"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12))\nax1.plot(history.history['loss'], color='b', label=\"Training loss\")\nax1.plot(history.history['val_loss'], color='r', label=\"validation loss\")\nax1.set_xticks(np.arange(1, epochs, 1))\nax1.set_title(\"Training Loss (Red) Vs Validation Loss (Blue)\")\n\nax2.plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\nax2.plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\nax2.set_xticks(np.arange(1, epochs, 1))\nax2.set_title(\"Training Accuracy (Blue) Vs Validation Accuracy (Red)\")\n\nlegend = plt.legend(loc='best', shadow=True)\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:39:29.397413Z","iopub.execute_input":"2023-07-16T18:39:29.397810Z","iopub.status.idle":"2023-07-16T18:39:31.827913Z","shell.execute_reply.started":"2023-07-16T18:39:29.397778Z","shell.execute_reply":"2023-07-16T18:39:31.826883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Prepare Testing Data</h3>","metadata":{}},{"cell_type":"code","source":"test_filenames = os.listdir(\"./test1/\")\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nnb_samples = test_df.shape[0]\n\ntest_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"./test1/\", \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=IMAGE_SIZE,\n    batch_size=batch_size,\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:39:48.430045Z","iopub.execute_input":"2023-07-16T18:39:48.430425Z","iopub.status.idle":"2023-07-16T18:39:48.569751Z","shell.execute_reply.started":"2023-07-16T18:39:48.430395Z","shell.execute_reply":"2023-07-16T18:39:48.568825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Test</h3>","metadata":{}},{"cell_type":"code","source":"predict = model.predict(test_generator, steps=np.ceil(nb_samples/batch_size))","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:39:52.900240Z","iopub.execute_input":"2023-07-16T18:39:52.900809Z","iopub.status.idle":"2023-07-16T18:40:19.547778Z","shell.execute_reply.started":"2023-07-16T18:39:52.900766Z","shell.execute_reply":"2023-07-16T18:40:19.546863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:40:24.755532Z","iopub.execute_input":"2023-07-16T18:40:24.756504Z","iopub.status.idle":"2023-07-16T18:40:24.763776Z","shell.execute_reply.started":"2023-07-16T18:40:24.756458Z","shell.execute_reply":"2023-07-16T18:40:24.762872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['category'] = np.argmax(predict, axis=-1)\nlabel_map = dict((category,filename) for filename,category in train_generator.class_indices.items())\ntest_df['category'] = test_df['category'].replace(label_map)\ntest_df['category'] = test_df['category'].replace({ 'dog': 1, 'cat': 0 })","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:40:28.122976Z","iopub.execute_input":"2023-07-16T18:40:28.123344Z","iopub.status.idle":"2023-07-16T18:40:28.142646Z","shell.execute_reply.started":"2023-07-16T18:40:28.123315Z","shell.execute_reply":"2023-07-16T18:40:28.141530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"category_counts = test_df['category'].value_counts()\ncategory_percentages = category_counts / category_counts.sum() * 100\n\nplt.figure(figsize=(6, 6))\nsns.set(style='darkgrid')\nlabels = ['Dog', 'Cat']\ncolors = ['#ff9999', '#66b3ff']\n\nexplode = (0.1, 0)\n\nplt.pie(category_counts, labels=labels, colors=colors, explode=explode, autopct='%1.1f%%', startangle=90)\nplt.title('Distribution of Dogs & Cats in the predicted dataset')\nplt.axis('equal')\nplt.show()\n\nfor label, count, percentage in zip(labels, category_counts, category_percentages):\n    print(f\"{label}: {count} samples, {percentage:.1f}%\")","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:40:33.627222Z","iopub.execute_input":"2023-07-16T18:40:33.627573Z","iopub.status.idle":"2023-07-16T18:40:33.792935Z","shell.execute_reply.started":"2023-07-16T18:40:33.627544Z","shell.execute_reply":"2023-07-16T18:40:33.791928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h3>Predicted Result</h3>","metadata":{}},{"cell_type":"code","source":"sample_test = test_df.sample(18)\nsample_test.head()\nplt.figure(figsize=(12, 24))\ncount = 0\nfor index, row in sample_test.iterrows():\n    filename = row['filename']\n    category = row['category']\n    img = load_img(\"./test1/\"+filename, target_size=IMAGE_SIZE)\n    plt.subplot(6, 3, count + 1)\n    plt.imshow(img)\n    category = \"dog\" if category else \"cat\"\n    plt.xlabel(filename + '(Predicted: ' + \"{}\".format(category) + ')' )\n    count += 1\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-16T18:40:39.085452Z","iopub.execute_input":"2023-07-16T18:40:39.085839Z","iopub.status.idle":"2023-07-16T18:40:44.764639Z","shell.execute_reply.started":"2023-07-16T18:40:39.085807Z","shell.execute_reply":"2023-07-16T18:40:44.763207Z"},"trusted":true},"execution_count":null,"outputs":[]}]}