{"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":"markdown","source":"# Dog Breed Identification Using Deep Learning\n\n---\n\n## Problem Statement ~\n\nWe often do you get stuck thinking about the name of a dog’s breed. There are many dog breeds and most of them are similar to each other. Can we use a dog breeds dataset and build a Deep\nLearning model that will classify different dog breeds from an image. Use Convolutional Neural Networks to build the model.\n\n## Dataset\n\nThe dataset for this project is available on Kaggle. <br>\n\n**Link** : https://www.kaggle.com/c/dog-breed-identification/data\n\n## Evaluation\n\nWe shall use <code>Accuracy</code>, <code>Precision</code>, <code>Recall</code> and <code>F1 score</code> to evaluate the performance of our models, along with the heatmap of the confusion matrix.<br>\n\n---\n\n## Table of Contents\n\n### 1. Environment Setup\n### 2. Dataset Gathering\n### 3. Exploratory Data Analysis\n### 4. Dataset Preprocessing\n### 5. Model Evaluation\n### 6. Performance Measurement","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"# 1. Environment Setup:\n---\n\n> In this step, we have installed and imported all neccessary libraries required to proceed with the solution to the given problem statement.","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport tqdm\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport tensorflow as tf\nimport tensorflow_hub as hub\nimport matplotlib.pyplot as plt\nwarnings.filterwarnings(\"ignore\")                   # Suppressing Jupyter Notebook Warnings\nfrom IPython.display import display, Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import precision_recall_fscore_support\nfrom sklearn.metrics import confusion_matrix, accuracy_score\nfrom sklearn.metrics import confusion_matrix, classification_report, accuracy_score, precision_score, recall_score, f1_score","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:46.879649Z","iopub.execute_input":"2022-04-29T11:54:46.880023Z","iopub.status.idle":"2022-04-29T11:54:53.278904Z","shell.execute_reply.started":"2022-04-29T11:54:46.879924Z","shell.execute_reply":"2022-04-29T11:54:53.278181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Dataset Gathering\n---\n> In this step, we have gathered the dataset from kaggle and have verified its integrity.","metadata":{}},{"cell_type":"code","source":"# Importing the labels dataset\nlabels_csv = pd.read_csv('../input/dog-breed-identification/labels.csv')\n\n# Viewing the head of the dataset\nlabels_csv.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:53.281993Z","iopub.execute_input":"2022-04-29T11:54:53.282654Z","iopub.status.idle":"2022-04-29T11:54:53.328497Z","shell.execute_reply.started":"2022-04-29T11:54:53.282612Z","shell.execute_reply":"2022-04-29T11:54:53.327837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Saving the training dataset path to a variable\ntrain_path = \"../input/dog-breed-identification/train/\"\n\n# Creating image paths from the name\nfilenames = [train_path + fname + \".jpg\" for fname in labels_csv['id']]\n\n# Viewing the first 10 filenames\nfilenames[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:53.329828Z","iopub.execute_input":"2022-04-29T11:54:53.330304Z","iopub.status.idle":"2022-04-29T11:54:53.342588Z","shell.execute_reply.started":"2022-04-29T11:54:53.330268Z","shell.execute_reply":"2022-04-29T11:54:53.341926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checking whether the number of filenames in the directory matches to that of ours\nprint(len(os.listdir(train_path)) == len(filenames))","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:53.345239Z","iopub.execute_input":"2022-04-29T11:54:53.345792Z","iopub.status.idle":"2022-04-29T11:54:53.692156Z","shell.execute_reply.started":"2022-04-29T11:54:53.345754Z","shell.execute_reply":"2022-04-29T11:54:53.691391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Exploratory Data Analysis\n---\n> In this step, we took a deeper look at the data, and checked if the data is properly gathered in the previous steps.","metadata":{}},{"cell_type":"code","source":"# Viewing an image using filename\nImage(\"../input/dog-breed-identification/train/0042188c895a2f14ef64a918ed9c7b64.jpg\")","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:53.693416Z","iopub.execute_input":"2022-04-29T11:54:53.694162Z","iopub.status.idle":"2022-04-29T11:54:53.707207Z","shell.execute_reply.started":"2022-04-29T11:54:53.694121Z","shell.execute_reply":"2022-04-29T11:54:53.706477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualizing the distribution of images accoding to class\nlabels_csv[\"breed\"].value_counts().plot.bar(figsize=(20, 10));","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:53.708625Z","iopub.execute_input":"2022-04-29T11:54:53.709133Z","iopub.status.idle":"2022-04-29T11:54:55.566359Z","shell.execute_reply.started":"2022-04-29T11:54:53.709096Z","shell.execute_reply":"2022-04-29T11:54:55.565559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Data Preprocessing:\n---\n> In this step, we have cleaned the data thus obtained for the previous steps before splitting them into training and testing datasets. We have also cleaned the images obtained by reshaping their shapes and changing their color changes.","metadata":{}},{"cell_type":"code","source":"# Converting the label columns to Numpy array\nlabels = labels_csv['breed'].to_numpy()\n\n# Viewing the first 10 labels\nlabels[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:55.567500Z","iopub.execute_input":"2022-04-29T11:54:55.567748Z","iopub.status.idle":"2022-04-29T11:54:55.574811Z","shell.execute_reply.started":"2022-04-29T11:54:55.567712Z","shell.execute_reply":"2022-04-29T11:54:55.574075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Saving the count of total number of unique breeds to a variabkle\nunique_breeds = np.unique(labels)\n\nprint(\"Total number of unique breeds : \", len(unique_breeds))","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:55.576460Z","iopub.execute_input":"2022-04-29T11:54:55.577164Z","iopub.status.idle":"2022-04-29T11:54:55.592852Z","shell.execute_reply.started":"2022-04-29T11:54:55.577126Z","shell.execute_reply":"2022-04-29T11:54:55.592201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Converting the labels to a boolean array\nboolean_labels = [label == np.array(unique_breeds) for label in labels]\n\n# Viewing how it looks like\nboolean_labels[0]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:55.593974Z","iopub.execute_input":"2022-04-29T11:54:55.594284Z","iopub.status.idle":"2022-04-29T11:54:55.684355Z","shell.execute_reply.started":"2022-04-29T11:54:55.594248Z","shell.execute_reply":"2022-04-29T11:54:55.683673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating training and validation sets\n\n# Separating the features and labels\nX = filenames\ny = boolean_labels\n\nprint(f\"Number of training images: {len(X)}\")\nprint(f\"Number of labels: {len(y)}\")\n\nX_train, X_val, y_train, y_val = train_test_split(X,\n                                                  y, \n                                                  test_size=0.2,\n                                                  random_state=42)\n\nprint(f\"Number of training images : {len(X_train)}\")\nprint(f\"Number of validation images : {len(X_val)}\")","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:55.687650Z","iopub.execute_input":"2022-04-29T11:54:55.687845Z","iopub.status.idle":"2022-04-29T11:54:55.702452Z","shell.execute_reply.started":"2022-04-29T11:54:55.687821Z","shell.execute_reply":"2022-04-29T11:54:55.701795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Image Preprocessing:\n\n> In this step, we have resized and reshaped the images and we have also changed their color changes.","metadata":{}},{"cell_type":"code","source":"# Reading an image in and checking shape\nimage = plt.imread(filenames[42])\nprint(f\"Image Shape : {image.shape}\")\n\n# Converting the image to a Tensorflow Tensor\ntf.constant(image)","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:55.703687Z","iopub.execute_input":"2022-04-29T11:54:55.704142Z","iopub.status.idle":"2022-04-29T11:54:57.940089Z","shell.execute_reply.started":"2022-04-29T11:54:55.704108Z","shell.execute_reply":"2022-04-29T11:54:57.939287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setting the Image Size\nIMAGE_SIZE = 224\n\n# Creating a function to preprocess the images\ndef process_image(image_path):\n    \n    # Read in the image\n    image = tf.io.read_file(image_path)\n    \n    # Turn the image into numerical tensors\n    image = tf.image.decode_jpeg(image, channels=3)\n    \n    # Convert the color channel values from 0-225 to 0-1\n    image = tf.image.convert_image_dtype(image, tf.float32)\n    \n    # Resize the image\n    image = tf.image.resize(image, size=[IMAGE_SIZE, IMAGE_SIZE])\n    \n    return image","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:57.941562Z","iopub.execute_input":"2022-04-29T11:54:57.941821Z","iopub.status.idle":"2022-04-29T11:54:57.948726Z","shell.execute_reply.started":"2022-04-29T11:54:57.941787Z","shell.execute_reply":"2022-04-29T11:54:57.948041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Batching the Data:\n> Here, we have created batches after processing the images with their labels for faster and effective training.","metadata":{}},{"cell_type":"code","source":"# Creating a function to return a tuple (image, label)\ndef get_image_label(image_path, label):\n    \"\"\"\n    Takes an image file path name and the associated label,\n    processes the image and returns a tuple of (image, label).\n    \"\"\"\n    image = process_image(image_path)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:57.949629Z","iopub.execute_input":"2022-04-29T11:54:57.949816Z","iopub.status.idle":"2022-04-29T11:54:57.958139Z","shell.execute_reply.started":"2022-04-29T11:54:57.949788Z","shell.execute_reply":"2022-04-29T11:54:57.957351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setting the batch size at 32 \nBATCH_SIZE = 32\n\n# Create a function to turn data into batches\ndef create_data_batches(x, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False):\n    \"\"\"\n    Function to batch the data\n    \"\"\"\n    # If the data is a test dataset, we probably don't have labels\n    if test_data:\n        print(\"Creating test data batches...\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x))) # only filepaths\n        data_batch = data.map(process_image).batch(BATCH_SIZE)\n        return data_batch\n  \n    # If the data if a valid dataset, we don't need to shuffle it\n    elif valid_data:\n        print(\"Creating validation data batches...\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                                   tf.constant(y))) # labels\n        data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n        return data_batch\n\n    else:\n        # If the data is a training dataset, we shuffle it\n        print(\"Creating training data batches...\")\n        # Turn filepaths and labels into Tensors\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                                   tf.constant(y))) # labels\n    \n        # Shuffling pathnames and labels before mapping image processor function is faster than shuffling images\n        data = data.shuffle(buffer_size=len(x))\n\n        # Create (image, label) tuples (this also turns the image path into a preprocessed image)\n        data = data.map(get_image_label)\n\n        # Turn the data into batches\n        data_batch = data.batch(BATCH_SIZE)\n    return data_batch","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:57.959192Z","iopub.execute_input":"2022-04-29T11:54:57.959803Z","iopub.status.idle":"2022-04-29T11:54:57.969797Z","shell.execute_reply.started":"2022-04-29T11:54:57.959767Z","shell.execute_reply":"2022-04-29T11:54:57.969135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating training and validation data batches\ntrain_data = create_data_batches(X_train, y_train)\nval_data = create_data_batches(X_val, y_val, valid_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:57.970739Z","iopub.execute_input":"2022-04-29T11:54:57.971328Z","iopub.status.idle":"2022-04-29T11:54:58.230828Z","shell.execute_reply.started":"2022-04-29T11:54:57.971293Z","shell.execute_reply":"2022-04-29T11:54:58.229528Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checking the different attributes of our data batches\ntrain_data.element_spec, val_data.element_spec","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:58.232048Z","iopub.execute_input":"2022-04-29T11:54:58.232290Z","iopub.status.idle":"2022-04-29T11:54:58.238256Z","shell.execute_reply.started":"2022-04-29T11:54:58.232256Z","shell.execute_reply":"2022-04-29T11:54:58.237405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Model Evaluation:\n---\n> In this step, we have chosen the ResNet50V2 as it poses the most performance in problems such as these. To squeeze out even more performance in this case, we have used Adam optimizer and Categorical Cross Entropy.","metadata":{}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None, IMAGE_SIZE, IMAGE_SIZE, 3] # batch, height, width, colour channels\n\n# Model URL for ResNet50V2\nMODEL_URL = \"https://tfhub.dev/tensorflow/resnet_50/classification/1\"\n\n# Creating the model for ResNet50V2\nmodel = tf.keras.Sequential([\n    # Layer 1 : Input Layer\n    hub.KerasLayer(MODEL_URL),\n    \n    # Layer 2 : Output Layer\n    tf.keras.layers.Dense(120, activation='softmax')\n])\n\n# Compiling the model\nmodel.compile(loss=tf.keras.losses.CategoricalCrossentropy(),\n               optimizer=tf.keras.optimizers.Adam(),\n               metrics=['accuracy'])\n\n# Building the model\nmodel.build(INPUT_SHAPE)\n\n# Summary of the model\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:54:58.239573Z","iopub.execute_input":"2022-04-29T11:54:58.239885Z","iopub.status.idle":"2022-04-29T11:55:09.015495Z","shell.execute_reply.started":"2022-04-29T11:54:58.239851Z","shell.execute_reply":"2022-04-29T11:55:09.014742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating Tensorflow EarlyStopping\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=5)\n# Fitting the model\nhist = model.fit(train_data, epochs=50, validation_data=val_data, callbacks=[early_stopping])","metadata":{"execution":{"iopub.status.busy":"2022-04-29T11:55:09.016848Z","iopub.execute_input":"2022-04-29T11:55:09.017264Z","iopub.status.idle":"2022-04-29T12:17:44.123749Z","shell.execute_reply.started":"2022-04-29T11:55:09.017225Z","shell.execute_reply":"2022-04-29T12:17:44.122915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Model Evaluation:\n\n> In this step, we have plotted the performance of the model in terms of accuracy vs epochs and loss vs epochs.","metadata":{}},{"cell_type":"code","source":"# Creating graphs to visualize the accuracy and loss for the models\nfig, axes = plt.subplots(nrows=1,ncols=2, figsize=(16, 8), squeeze=False)\n\nfig.tight_layout(pad=5)\n\nplt.style.use('fivethirtyeight')\n\n# Graph for ResNet50V2 Training Accuracy vs Validation Accuracy\naxes[0][0].plot(hist.history['accuracy'])\naxes[0][0].plot(hist.history['val_accuracy'])\naxes[0][0].set_ylabel(\"Accuracy\")\naxes[0][0].set_xlabel(\"Epochs\")\naxes[0][0].set_title('ResNet50V2 Train Acc vs Val Acc')\naxes[0][0].legend(['Train', 'Test'], loc='upper left')\n\n# Graph for ResNet50V2 Training Loss vs Validation Loss\naxes[0][1].plot(hist.history['loss'])\naxes[0][1].plot(hist.history['val_loss'])\naxes[0][1].set_ylabel(\"Loss\")\naxes[0][1].set_xlabel(\"Epochs\")\naxes[0][1].set_title('ResNet50V2 Train Loss vs Val Loss')\naxes[0][1].legend(['Train', 'Test'], loc='upper left')","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:17:44.125412Z","iopub.execute_input":"2022-04-29T12:17:44.126119Z","iopub.status.idle":"2022-04-29T12:18:00.451358Z","shell.execute_reply.started":"2022-04-29T12:17:44.126079Z","shell.execute_reply":"2022-04-29T12:18:00.450679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Making predictions\npredictions = model.predict(val_data, verbose=2)\n\n# Viewing the predictions\npredictions[0]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:00.452478Z","iopub.execute_input":"2022-04-29T12:18:00.453117Z","iopub.status.idle":"2022-04-29T12:18:06.033743Z","shell.execute_reply.started":"2022-04-29T12:18:00.453075Z","shell.execute_reply":"2022-04-29T12:18:06.032904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 6. Performance Measurement\n---\n> In this step, we have evaluated the performance measure of the model and along with that we have also plotted a heatmap for the confusion matrix.","metadata":{}},{"cell_type":"code","source":"# Checking the shape of the prediction\nprint(\"Viewing the Shape : \", predictions.shape)\n\n# Checking the maximum probability\nprint(f\"Maximum value (probability of prediction) : {np.max(predictions[0])}\")\n\n# Maximum index\nprint(f\"Maximum index : {np.argmax(predictions[0])}\")\n\n# Predicted label\nprint(f\"Predicted Label : {unique_breeds[np.argmax(predictions[0])]}\")","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:06.035583Z","iopub.execute_input":"2022-04-29T12:18:06.036294Z","iopub.status.idle":"2022-04-29T12:18:06.045540Z","shell.execute_reply.started":"2022-04-29T12:18:06.036251Z","shell.execute_reply":"2022-04-29T12:18:06.043055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating a function to unbatch the data\ndef unbatching(data):\n    '''\n    This fuction is used to unbatch the data\n    '''\n    # Creating variables to save the images and labels\n    images = []\n    labels = []\n    \n    # Looping through the unbatched data\n    for image, label in data.unbatch().as_numpy_iterator():\n        images.append(image)\n        labels.append(unique_breeds[np.argmax(label)])\n    return images, labels\n\n# Unbatching the validation data\nval_images, val_labels = unbatching(val_data)\nval_images[0], val_labels[0]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:06.047154Z","iopub.execute_input":"2022-04-29T12:18:06.047992Z","iopub.status.idle":"2022-04-29T12:18:11.218639Z","shell.execute_reply.started":"2022-04-29T12:18:06.047945Z","shell.execute_reply":"2022-04-29T12:18:11.217905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Getting the predicted labels\npredicted_labels = [unique_breeds[np.argmax(predictions[i])] for i in range(len(predictions))]","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:11.220111Z","iopub.execute_input":"2022-04-29T12:18:11.220991Z","iopub.status.idle":"2022-04-29T12:18:11.237592Z","shell.execute_reply.started":"2022-04-29T12:18:11.220950Z","shell.execute_reply":"2022-04-29T12:18:11.236943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"confusion_matrix(val_labels, predicted_labels).shape","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:11.238937Z","iopub.execute_input":"2022-04-29T12:18:11.239846Z","iopub.status.idle":"2022-04-29T12:18:11.262755Z","shell.execute_reply.started":"2022-04-29T12:18:11.239808Z","shell.execute_reply":"2022-04-29T12:18:11.262138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plotting the confusion matrix\n\nimport seaborn as sns\nfrom sklearn.metrics import precision_recall_fscore_support\nplt.figure(figsize=(50, 50))\nmat = confusion_matrix(val_labels, predicted_labels)\nsns.heatmap(mat.T, square = True, annot = True, cmap = \"rocket\", xticklabels = np.unique(val_labels), yticklabels = np.unique(predicted_labels))\nplt.xlabel(\"True Labels\")\nplt.ylabel(\"Predicted Labels\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:11.264038Z","iopub.execute_input":"2022-04-29T12:18:11.264902Z","iopub.status.idle":"2022-04-29T12:18:50.116755Z","shell.execute_reply.started":"2022-04-29T12:18:11.264865Z","shell.execute_reply":"2022-04-29T12:18:50.115902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(classification_report(val_labels, predicted_labels))","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:50.118065Z","iopub.execute_input":"2022-04-29T12:18:50.118457Z","iopub.status.idle":"2022-04-29T12:18:50.196488Z","shell.execute_reply.started":"2022-04-29T12:18:50.118419Z","shell.execute_reply":"2022-04-29T12:18:50.195831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Getting the perfromance metrics of our champion model\nprint(\"#******** ResNet50V2 Performance Metrics ********#\")\nprint(\" \")\nprint(f\"Accuracy Score  = {accuracy_score(val_labels, predicted_labels) * 100}\")\nprint(f\"Precision Score = {precision_score(val_labels, predicted_labels, average='macro') * 100}\")\nprint(f\"Recall Score    = {recall_score(val_labels, predicted_labels, average='macro') * 100}\")\nprint(f\"F1 Score        = {f1_score(val_labels, predicted_labels, average='macro') * 100}\")","metadata":{"execution":{"iopub.status.busy":"2022-04-29T12:18:50.197926Z","iopub.execute_input":"2022-04-29T12:18:50.198778Z","iopub.status.idle":"2022-04-29T12:18:50.285855Z","shell.execute_reply.started":"2022-04-29T12:18:50.198741Z","shell.execute_reply":"2022-04-29T12:18:50.285043Z"},"trusted":true},"execution_count":null,"outputs":[]}]}