{"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 Classification\n\nThis notebook's goal is to perform `MultiClass Image Classification` on the `dog-breeds-identifier` dataset from Kaggle \n\n## 1. Problem\n   * Identifying the breed of a dog given an image of a dog.\n## 2. Data\n   * The data used is from Kaggle's dog breed identification competition.\n   * [Dataset](https://www.kaggle.com/competitions/dog-breed-identification/data)\n## 3. Evaluation\n   * The evaluation is a file with prediction probabilities for each dog breed of each test image.\n   * Evaluation will be done on Multi Class Log Loss between the predicted probability and the observed target.\n   * [Evaluation Criteria](https://www.kaggle.com/competitions/dog-breed-identification/overview/evaluation)\n## 4. Features\n   * Images are unstructured data so it is probably best to use deep learning/transfer learning.\n   * There are 120 dog breeds i.e. 120 different classes\n   * There are around 10000+ images in the training set (Labelled)\n   * There are around 10000+ images in the test set (Unlabelled)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"## Getting the workspace ready\n   * Import TensorFlow 2.x ✅\n   * Import TensorFlow Hub ✅\n   * Make sure we're using a GPU ✅","metadata":{}},{"cell_type":"code","source":"# Import TensorFlow 2.x and TensorFlow Hub into Kaggle\nimport tensorflow as tf\nimport tensorflow_hub as hub\nprint(\"TF Version: \", tf.__version__)\nprint(\"TF Hub Version: \", hub.__version__)\n\n# Check if GPU is available\nprint(\"GPU\", \"available...\" if tf.config.list_physical_devices(\"GPU\") else \"not available...\");","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:43.024369Z","iopub.execute_input":"2022-12-27T17:32:43.024746Z","iopub.status.idle":"2022-12-27T17:32:43.031264Z","shell.execute_reply.started":"2022-12-27T17:32:43.024714Z","shell.execute_reply":"2022-12-27T17:32:43.029950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Importing Tools\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nimport datetime\n\nfrom matplotlib.pyplot import imread\nfrom IPython.display import display, Image\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:43.039292Z","iopub.execute_input":"2022-12-27T17:32:43.039602Z","iopub.status.idle":"2022-12-27T17:32:43.045403Z","shell.execute_reply.started":"2022-12-27T17:32:43.039576Z","shell.execute_reply":"2022-12-27T17:32:43.044344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Getting Data Ready\n\nOur data has to be in numerical format to use in a machine learning model. So we convert the images into Tensors.\n\nAccess the data and check the labels","metadata":{}},{"cell_type":"code","source":"# Checking the labels of the data\nlabels_csv = pd.read_csv(\"/kaggle/input/dog-breed-identification/labels.csv\")\nprint(labels_csv.describe())","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:43.049653Z","iopub.execute_input":"2022-12-27T17:32:43.049982Z","iopub.status.idle":"2022-12-27T17:32:43.093794Z","shell.execute_reply.started":"2022-12-27T17:32:43.049955Z","shell.execute_reply":"2022-12-27T17:32:43.092806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:43.095581Z","iopub.execute_input":"2022-12-27T17:32:43.096560Z","iopub.status.idle":"2022-12-27T17:32:43.108355Z","shell.execute_reply.started":"2022-12-27T17:32:43.096523Z","shell.execute_reply":"2022-12-27T17:32:43.107389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get how many images are there for each breed(label)\nlabels_csv[\"breed\"].value_counts().plot(kind=\"bar\", figsize=(20, 10));","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:43.111594Z","iopub.execute_input":"2022-12-27T17:32:43.111850Z","iopub.status.idle":"2022-12-27T17:32:44.998470Z","shell.execute_reply.started":"2022-12-27T17:32:43.111826Z","shell.execute_reply":"2022-12-27T17:32:44.997488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.mean(labels_csv[\"breed\"].value_counts()), np.median(labels_csv[\"breed\"].value_counts())","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.002455Z","iopub.execute_input":"2022-12-27T17:32:45.002749Z","iopub.status.idle":"2022-12-27T17:32:45.015569Z","shell.execute_reply.started":"2022-12-27T17:32:45.002721Z","shell.execute_reply":"2022-12-27T17:32:45.014509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View an image\nImage(\"/kaggle/input/dog-breed-identification/train/0021f9ceb3235effd7fcde7f7538ed62.jpg\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.017077Z","iopub.execute_input":"2022-12-27T17:32:45.017612Z","iopub.status.idle":"2022-12-27T17:32:45.029075Z","shell.execute_reply.started":"2022-12-27T17:32:45.017577Z","shell.execute_reply":"2022-12-27T17:32:45.027978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Getting Images and their Labels\n\nWe have the image ID's and their labels in a DataFrame(`labels_csv`), we can create:\n* A list of filepaths to training image\n* An array of all labels\n* An array of all unique labels","metadata":{}},{"cell_type":"code","source":"# Create pathnames from image ID's\nfilenames = [\"/kaggle/input/dog-breed-identification/train/\" + fname + \".jpg\" for fname in labels_csv[\"id\"]]\n\n# Check the first 5 filenames\nfilenames[:5]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.031208Z","iopub.execute_input":"2022-12-27T17:32:45.032181Z","iopub.status.idle":"2022-12-27T17:32:45.042988Z","shell.execute_reply.started":"2022-12-27T17:32:45.032146Z","shell.execute_reply":"2022-12-27T17:32:45.041998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check if the number of filenames match the number of actual images\n\nif len(os.listdir(\"/kaggle/input/dog-breed-identification/train/\")) == len(filenames):\n    print(\"Filenames match actual amount of files.\")\nelse: \n    print(\"Filenames do not match actual amount of files.\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.044635Z","iopub.execute_input":"2022-12-27T17:32:45.044982Z","iopub.status.idle":"2022-12-27T17:32:45.056717Z","shell.execute_reply.started":"2022-12-27T17:32:45.044948Z","shell.execute_reply":"2022-12-27T17:32:45.055754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image(filenames[300])","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.058506Z","iopub.execute_input":"2022-12-27T17:32:45.058998Z","iopub.status.idle":"2022-12-27T17:32:45.067866Z","shell.execute_reply.started":"2022-12-27T17:32:45.058964Z","shell.execute_reply":"2022-12-27T17:32:45.066872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = labels_csv[\"breed\"]\nlabels = np.array(labels)\nlabels","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.069611Z","iopub.execute_input":"2022-12-27T17:32:45.070387Z","iopub.status.idle":"2022-12-27T17:32:45.077769Z","shell.execute_reply.started":"2022-12-27T17:32:45.070315Z","shell.execute_reply":"2022-12-27T17:32:45.076655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(labels)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.082479Z","iopub.execute_input":"2022-12-27T17:32:45.082726Z","iopub.status.idle":"2022-12-27T17:32:45.089425Z","shell.execute_reply.started":"2022-12-27T17:32:45.082703Z","shell.execute_reply":"2022-12-27T17:32:45.088353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check if the number of labels match the number of filenames\n\nif len(labels) == len(filenames):\n    print(\"Number of Labels match the number of Filenames.\")\nelse:\n    print(\"Number of Labels do not match the number of Filenames.\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.090854Z","iopub.execute_input":"2022-12-27T17:32:45.091397Z","iopub.status.idle":"2022-12-27T17:32:45.098014Z","shell.execute_reply.started":"2022-12-27T17:32:45.091363Z","shell.execute_reply":"2022-12-27T17:32:45.096746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find all unique label values\nunique_breeds = np.unique(labels)\nlen(unique_breeds)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.099256Z","iopub.execute_input":"2022-12-27T17:32:45.100155Z","iopub.status.idle":"2022-12-27T17:32:45.114770Z","shell.execute_reply.started":"2022-12-27T17:32:45.100121Z","shell.execute_reply":"2022-12-27T17:32:45.113699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn every label into a boolean array\nboolean_labels = [label == np.array(unique_breeds) for label in labels]\nboolean_labels[:1]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.116006Z","iopub.execute_input":"2022-12-27T17:32:45.116975Z","iopub.status.idle":"2022-12-27T17:32:45.179043Z","shell.execute_reply.started":"2022-12-27T17:32:45.116925Z","shell.execute_reply":"2022-12-27T17:32:45.178068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating a validation set\n\nThis Kaggle Dataset does not come with a validation dataset. Using `train_test_split` we can make a validation set.","metadata":{}},{"cell_type":"code","source":"# Setting up X and y variables\nX = filenames\ny = boolean_labels","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.180199Z","iopub.execute_input":"2022-12-27T17:32:45.180547Z","iopub.status.idle":"2022-12-27T17:32:45.187374Z","shell.execute_reply.started":"2022-12-27T17:32:45.180513Z","shell.execute_reply":"2022-12-27T17:32:45.186381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Working with 10000+ images while experimenting is quite time consuming so, I'll work on a portion of the full dataset before using the full dataset.","metadata":{}},{"cell_type":"code","source":"# Number of images used for experimenting\nNUM_IMAGES = 1000 \nNUM_IMAGES","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.188965Z","iopub.execute_input":"2022-12-27T17:32:45.189634Z","iopub.status.idle":"2022-12-27T17:32:45.199459Z","shell.execute_reply.started":"2022-12-27T17:32:45.189598Z","shell.execute_reply":"2022-12-27T17:32:45.198522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Split X & y into training and validation using NUM_IMAGES\nX_train, X_val, y_train, y_val = train_test_split(X[:NUM_IMAGES],\n                                                  y[:NUM_IMAGES],\n                                                  test_size=0.2,\n                                                  random_state=42)\nlen(X_train), len(X_val), len(y_train), len(y_val)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.202582Z","iopub.execute_input":"2022-12-27T17:32:45.202853Z","iopub.status.idle":"2022-12-27T17:32:45.213528Z","shell.execute_reply.started":"2022-12-27T17:32:45.202830Z","shell.execute_reply":"2022-12-27T17:32:45.212390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train[:1], y_train[:1]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.214823Z","iopub.execute_input":"2022-12-27T17:32:45.215850Z","iopub.status.idle":"2022-12-27T17:32:45.224038Z","shell.execute_reply.started":"2022-12-27T17:32:45.215816Z","shell.execute_reply":"2022-12-27T17:32:45.223022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Preprocessing the images (Turning the images into Tensors)\n\nCreating a function that processes the images into Tensors by:\n1. Take image filename as input.\n2. Uses TensorFlow to read a file and save it to a variable, `image`.\n3. Turn the `image` into Tensors.\n4. Resize the `image` to the shape (224, 224).\n5. Return the modified `image`.","metadata":{}},{"cell_type":"code","source":"# We need to resize the image because of the varying sizes of the images\nimage1 = imread(filenames[200])\nimage2 = imread(filenames[300])\nimage1.shape, image2.shape","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.225458Z","iopub.execute_input":"2022-12-27T17:32:45.226027Z","iopub.status.idle":"2022-12-27T17:32:45.241492Z","shell.execute_reply.started":"2022-12-27T17:32:45.225992Z","shell.execute_reply":"2022-12-27T17:32:45.240485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##### Function to convert image to tensor","metadata":{}},{"cell_type":"code","source":"# Defining the IMAGE_SIZE\nIMG_SIZE = 224\n\ndef process_image(image_path):\n    \"\"\"\n    Takes an image file path and turns it into a Tensor.\n    \"\"\"\n    # Read in image file\n    image = tf.io.read_file(image_path)\n    # Turn the jpg image into numerical Tensor with 3 colour channels (Red, Green, Blue)\n    image = tf.image.decode_jpeg(image, channels=3)\n    # Convert the colour channel values from 0-255 values to 0-1\n    image = tf.image.convert_image_dtype(image, tf.float32)\n    # Resize the image to our desired size (224, 224)\n    image = tf.image.resize(image, size=[IMG_SIZE, IMG_SIZE])\n    \n    return image","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.242998Z","iopub.execute_input":"2022-12-27T17:32:45.243437Z","iopub.status.idle":"2022-12-27T17:32:45.249843Z","shell.execute_reply.started":"2022-12-27T17:32:45.243400Z","shell.execute_reply":"2022-12-27T17:32:45.248294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating Data Batches","metadata":{}},{"cell_type":"code","source":"# Function to return a tuple (image, label)\ndef get_image_label(image_path, label):\n    \"\"\"\n    Takes an image file path and the associated label,\n    preprocess the image and returns in form of a tuple (image, label).\n    \"\"\"\n    image = process_image(image_path)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.252162Z","iopub.execute_input":"2022-12-27T17:32:45.252485Z","iopub.status.idle":"2022-12-27T17:32:45.258959Z","shell.execute_reply.started":"2022-12-27T17:32:45.252444Z","shell.execute_reply":"2022-12-27T17:32:45.257848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**WARNING: DO NOT EXCEED 32 BATCH SIZE**","metadata":{}},{"cell_type":"code","source":"# Define the default batch size\nBATCH_SIZE = 32\n\n# Turn the data into batches\ndef create_batches(x, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False):\n    \"\"\"\n    Creates batches of data out of image (X) and label (y) pairs.\n    Shuffles the data if it is given training data but does not shuffle if it is validation data.\n    Also accepts test data as input (no labels).\n    \"\"\"\n    if test_data:\n        # This is test data i.e. it does not contain labels.\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    elif valid_data:\n        # This is validation data so no need to shuffle it.\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    else:\n        # This is training data so it is shuffled.\n        print(\"Creating training data batches...\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                                   tf.constant(y))) # labels\n        \n        # Shuffling filepaths and lavels before mapping image processor function (Faster)\n        data = data.shuffle(buffer_size=len(x))\n        \n        # Create (image, label) tuples\n        data = data.map(get_image_label)\n        \n        # Turn the data into batches\n        data_batch = data.batch(BATCH_SIZE)\n        \n    return data_batch","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.260891Z","iopub.execute_input":"2022-12-27T17:32:45.261398Z","iopub.status.idle":"2022-12-27T17:32:45.272199Z","shell.execute_reply.started":"2022-12-27T17:32:45.261364Z","shell.execute_reply":"2022-12-27T17:32:45.271203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_batches(X_train, y_train)\nval_data = create_batches(X_val, y_val, valid_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.275509Z","iopub.execute_input":"2022-12-27T17:32:45.275763Z","iopub.status.idle":"2022-12-27T17:32:45.317634Z","shell.execute_reply.started":"2022-12-27T17:32:45.275739Z","shell.execute_reply":"2022-12-27T17:32:45.316689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the different attributes of our data batches\ntrain_data.element_spec, val_data.element_spec","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.319019Z","iopub.execute_input":"2022-12-27T17:32:45.319341Z","iopub.status.idle":"2022-12-27T17:32:45.326019Z","shell.execute_reply.started":"2022-12-27T17:32:45.319291Z","shell.execute_reply":"2022-12-27T17:32:45.325019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualizing Data Batches","metadata":{}},{"cell_type":"code","source":"# Function to show 16 images from a data batch \ndef show_16_images(images, labels):\n    \"\"\"\n    Displays 16 images from a data batch.\n    \"\"\"\n    fig, ax = plt.subplots(figsize=(10, 10))\n    # Loop through 16 images\n    for i in range(16):\n        ax = plt.subplot(4, 4, i+1)\n        # Display an image\n        plt.imshow(images[i])\n        # Add image label as the title\n        plt.title(unique_breeds[labels[i].argmax()])\n        # Turn grid lines off\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.327729Z","iopub.execute_input":"2022-12-27T17:32:45.328296Z","iopub.status.idle":"2022-12-27T17:32:45.335612Z","shell.execute_reply.started":"2022-12-27T17:32:45.328263Z","shell.execute_reply":"2022-12-27T17:32:45.334574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training images from the training data batch\ntrain_images, train_labels = next(train_data.as_numpy_iterator())\nshow_16_images(train_images, train_labels)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:45.337035Z","iopub.execute_input":"2022-12-27T17:32:45.337389Z","iopub.status.idle":"2022-12-27T17:32:46.341444Z","shell.execute_reply.started":"2022-12-27T17:32:45.337355Z","shell.execute_reply":"2022-12-27T17:32:46.340308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validation images from the validation data batch\nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_16_images(val_images, val_labels)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:46.343254Z","iopub.execute_input":"2022-12-27T17:32:46.343883Z","iopub.status.idle":"2022-12-27T17:32:47.920229Z","shell.execute_reply.started":"2022-12-27T17:32:46.343846Z","shell.execute_reply":"2022-12-27T17:32:47.919275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating and Training a Model\n\nUsing **Transfer Learning** by using an existing model from `TensorFlow Hub`\n\n* I am using the [mobilenet_v2_130_224](https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/5) model.\n* It is trained on the ImageNet Data Set.\n* It uses the input size 224x224 pixels.\n\n### Building a model","metadata":{}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3]\n\n# Setup output shape of the model\nOUTPUT_SHAPE = len(unique_breeds)\n\n# Setup model URL from TensorFlow Hub\nMODEL_URL = \"https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/5\"","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:47.922045Z","iopub.execute_input":"2022-12-27T17:32:47.922671Z","iopub.status.idle":"2022-12-27T17:32:47.928772Z","shell.execute_reply.started":"2022-12-27T17:32:47.922633Z","shell.execute_reply":"2022-12-27T17:32:47.927531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Using the Keras API to build the model.\n\nFunction to build the model,\n* Takes input shape, output shape and model URL as parameter.\n* Defines the layers in Keras model in a sequential fashion.\n* Compiles the model.\n* Builds the model.\n* Returns the model.","metadata":{}},{"cell_type":"code","source":"# Create function build Keras Model\ndef create_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, model_url=MODEL_URL):\n    print(\"Building model with: \", model_url)\n    \n    # Setup the model layers\n    model = tf.keras.Sequential([\n        hub.KerasLayer(MODEL_URL), # Layer 1 (Input Layer)\n        tf.keras.layers.Dense(units=OUTPUT_SHAPE,\n                              activation=\"softmax\") # Layer 2 (Output Layer)\n    ])\n    \n    # Compile the model\n    model.compile(\n        loss=tf.keras.losses.CategoricalCrossentropy(),\n        optimizer=tf.keras.optimizers.Adam(),\n        metrics=[\"accuracy\"]\n    )\n    \n    # Build the model\n    model.build(INPUT_SHAPE)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:47.939460Z","iopub.execute_input":"2022-12-27T17:32:47.939910Z","iopub.status.idle":"2022-12-27T17:32:47.947992Z","shell.execute_reply.started":"2022-12-27T17:32:47.939869Z","shell.execute_reply":"2022-12-27T17:32:47.946883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating a model\nmodel = create_model()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:47.949828Z","iopub.execute_input":"2022-12-27T17:32:47.950660Z","iopub.status.idle":"2022-12-27T17:32:49.529300Z","shell.execute_reply.started":"2022-12-27T17:32:47.950614Z","shell.execute_reply":"2022-12-27T17:32:49.528252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating Callbacks","metadata":{}},{"cell_type":"markdown","source":"#### TensorBoard Callback","metadata":{}},{"cell_type":"code","source":"# Loading the tensorboard notebook extension\n%load_ext tensorboard","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.530871Z","iopub.execute_input":"2022-12-27T17:32:49.531315Z","iopub.status.idle":"2022-12-27T17:32:49.537259Z","shell.execute_reply.started":"2022-12-27T17:32:49.531277Z","shell.execute_reply":"2022-12-27T17:32:49.536215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to build TensorBoard Callback\ndef create_tensorboard_callback():\n    logdir = os.path.join(\"/kaggle/working/logs/\",\n                          datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n    return tf.keras.callbacks.TensorBoard(logdir)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.538729Z","iopub.execute_input":"2022-12-27T17:32:49.539377Z","iopub.status.idle":"2022-12-27T17:32:49.547610Z","shell.execute_reply.started":"2022-12-27T17:32:49.539339Z","shell.execute_reply":"2022-12-27T17:32:49.546536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Early Stopping Callback","metadata":{}},{"cell_type":"code","source":"# Create early stopping callback (stops training when model stops improving)\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3) # Stops after 3 non improving models","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.549060Z","iopub.execute_input":"2022-12-27T17:32:49.549646Z","iopub.status.idle":"2022-12-27T17:32:49.560239Z","shell.execute_reply.started":"2022-12-27T17:32:49.549609Z","shell.execute_reply":"2022-12-27T17:32:49.559294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training model\n\nTraining the model on a subset of 1000 images i.e. approx. 10% of the dataset.","metadata":{}},{"cell_type":"code","source":"# Set number of epochs (Edit as required)\nNUM_EPOCHS = 100","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.561710Z","iopub.execute_input":"2022-12-27T17:32:49.562142Z","iopub.status.idle":"2022-12-27T17:32:49.569305Z","shell.execute_reply.started":"2022-12-27T17:32:49.562104Z","shell.execute_reply":"2022-12-27T17:32:49.568381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train and return the model\n\ndef train_model():\n    \"\"\"\n    Trains a given model and returns the trained model.\n    \"\"\"\n    \n    # Create a model\n    model = create_model()\n    \n    # Create new TensorBoard session\n    tensorboard = create_tensorboard_callback()\n    \n    # Fit the model to the data\n    model.fit(x=train_data, \n              epochs=NUM_EPOCHS,\n              validation_data=val_data,\n              validation_freq=1,\n              callbacks=[tensorboard, early_stopping])\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.570881Z","iopub.execute_input":"2022-12-27T17:32:49.571528Z","iopub.status.idle":"2022-12-27T17:32:49.580728Z","shell.execute_reply.started":"2022-12-27T17:32:49.571490Z","shell.execute_reply":"2022-12-27T17:32:49.579706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit model to the data\nmodel = train_model()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:32:49.582656Z","iopub.execute_input":"2022-12-27T17:32:49.582940Z","iopub.status.idle":"2022-12-27T17:33:47.508146Z","shell.execute_reply.started":"2022-12-27T17:32:49.582908Z","shell.execute_reply":"2022-12-27T17:33:47.507167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%tensorboard --logdir /kaggle/working/logs","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:47.509730Z","iopub.execute_input":"2022-12-27T17:33:47.510122Z","iopub.status.idle":"2022-12-27T17:33:47.523895Z","shell.execute_reply.started":"2022-12-27T17:33:47.510084Z","shell.execute_reply":"2022-12-27T17:33:47.522686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making Predictions and Evaluating the trained Model","metadata":{}},{"cell_type":"code","source":"# Make Predictions on the validation data\npredictions = model.predict(val_data, verbose=1)\npredictions","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:47.525252Z","iopub.execute_input":"2022-12-27T17:33:47.525800Z","iopub.status.idle":"2022-12-27T17:33:48.420347Z","shell.execute_reply.started":"2022-12-27T17:33:47.525763Z","shell.execute_reply":"2022-12-27T17:33:48.419379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions.shape","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.422022Z","iopub.execute_input":"2022-12-27T17:33:48.422465Z","iopub.status.idle":"2022-12-27T17:33:48.432625Z","shell.execute_reply.started":"2022-12-27T17:33:48.422434Z","shell.execute_reply":"2022-12-27T17:33:48.431398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Convert the Prediction Probabilities into Predicted Labels","metadata":{}},{"cell_type":"code","source":"def get_pred_label(prediction_probabilities):\n    \"\"\"\n    Turns array of prediction probabilities into a label.\n    \"\"\"\n    \n    return unique_breeds[np.argmax(prediction_probabilities)]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.435977Z","iopub.execute_input":"2022-12-27T17:33:48.436299Z","iopub.status.idle":"2022-12-27T17:33:48.443419Z","shell.execute_reply.started":"2022-12-27T17:33:48.436269Z","shell.execute_reply":"2022-12-27T17:33:48.442394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Unbatch our dataset","metadata":{}},{"cell_type":"code","source":"def unbatch_data(data):\n    \"\"\"\n    Takes a batched dataset of (image, label) Tensors and returns separate arrays\n    of images and labels.\n    \"\"\"\n    images=[]\n    labels=[]\n    \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","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.445286Z","iopub.execute_input":"2022-12-27T17:33:48.445858Z","iopub.status.idle":"2022-12-27T17:33:48.453675Z","shell.execute_reply.started":"2022-12-27T17:33:48.445818Z","shell.execute_reply":"2022-12-27T17:33:48.451716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Unbatch validation data\nval_images, val_labels = unbatch_data(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.455118Z","iopub.execute_input":"2022-12-27T17:33:48.456643Z","iopub.status.idle":"2022-12-27T17:33:48.914537Z","shell.execute_reply.started":"2022-12-27T17:33:48.456602Z","shell.execute_reply":"2022-12-27T17:33:48.913506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Change n to change the sample image which is predicted\ndef plot_pred(prediction_probabilities, labels, images, n=2):\n    \"\"\"\n    View the prediction, ground truth label and image for sample n.\n    \"\"\"\n    pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]\n    \n    # Get the pred label\n    pred_label = get_pred_label(pred_prob)\n    \n    # Plot image & remove ticks\n    plt.imshow(image)\n    plt.yticks([])\n    \n    # Change the color of the title depending on if the prediction is right or wrong\n    if pred_label == true_label:\n        color = \"green\"\n    else:\n        color = \"red\"\n    plt.title(\"{} {:2.0f}% ({})\".format(pred_label,\n                                        np.max(pred_prob)*100,\n                                        true_label),\n                                        color=color)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.916195Z","iopub.execute_input":"2022-12-27T17:33:48.916587Z","iopub.status.idle":"2022-12-27T17:33:48.926909Z","shell.execute_reply.started":"2022-12-27T17:33:48.916553Z","shell.execute_reply":"2022-12-27T17:33:48.925809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:48.928235Z","iopub.execute_input":"2022-12-27T17:33:48.928839Z","iopub.status.idle":"2022-12-27T17:33:49.118219Z","shell.execute_reply.started":"2022-12-27T17:33:48.928797Z","shell.execute_reply":"2022-12-27T17:33:49.117295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_pred_conf(prediction_probabilities, labels, n=1):\n    \"\"\"\n    Plots the top 10 highest prediction confidences along with\n    the truth label for sample n.\n    \"\"\"\n    pred_prob, true_label = prediction_probabilities[n], labels[n]\n    # Get the predicted label\n    pred_label = get_pred_label(pred_prob)\n    # Find the top 10 prediction confidence indexes\n    top_10_pred_indexes = pred_prob.argsort()[-10:][::-1]\n    # Find the top 10 prediction confidence values\n    top_10_pred_values = pred_prob[top_10_pred_indexes]\n    # Find the top 10 prediction labels\n    top_10_pred_labels = unique_breeds[top_10_pred_indexes]\n    # Setup plot\n    top_plot = plt.bar(np.arange(len(top_10_pred_labels)), \n                       top_10_pred_values, \n                       color=\"grey\")\n    plt.xticks(np.arange(len(top_10_pred_labels)),\n               labels=top_10_pred_labels,\n               rotation=\"vertical\")\n    # Change color of true label\n    if np.isin(true_label, top_10_pred_labels):\n        top_plot[np.argmax(top_10_pred_labels == true_label)].set_color(\"green\")\n    else:\n        pass","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:49.119731Z","iopub.execute_input":"2022-12-27T17:33:49.120776Z","iopub.status.idle":"2022-12-27T17:33:49.128934Z","shell.execute_reply.started":"2022-12-27T17:33:49.120740Z","shell.execute_reply":"2022-12-27T17:33:49.127905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,\n               labels=val_labels,\n               n=2)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:49.130276Z","iopub.execute_input":"2022-12-27T17:33:49.130793Z","iopub.status.idle":"2022-12-27T17:33:50.262262Z","shell.execute_reply.started":"2022-12-27T17:33:49.130754Z","shell.execute_reply":"2022-12-27T17:33:50.261300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Let's check a few predictions","metadata":{}},{"cell_type":"code","source":"i_multiplier = 0\nnum_rows = 3\nnum_cols = 2\nnum_images = num_rows*num_cols\nplt.figure(figsize=(5*2*num_cols, 5*num_rows))\nfor i in range(num_images):\n  plt.subplot(num_rows, 2*num_cols, 2*i+1)\n  plot_pred(prediction_probabilities=predictions,\n            labels=val_labels,\n            images=val_images,\n            n=i+i_multiplier)\n  plt.subplot(num_rows, 2*num_cols, 2*i+2)\n  plot_pred_conf(prediction_probabilities=predictions,\n                labels=val_labels,\n                n=i+i_multiplier)\nplt.tight_layout(h_pad=1.0)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:50.263508Z","iopub.execute_input":"2022-12-27T17:33:50.264085Z","iopub.status.idle":"2022-12-27T17:33:51.872212Z","shell.execute_reply.started":"2022-12-27T17:33:50.264053Z","shell.execute_reply":"2022-12-27T17:33:51.871379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving the model","metadata":{}},{"cell_type":"code","source":"def save_model(model, suffix=None):\n    \"\"\"\n    Saves a given model in a models directory and appends suffix (str)\n    for clarity and reuse\n    \"\"\"\n    model_name = suffix + \".h5\"\n    print(f\"Saving model {model_name}\")\n    model.save(model_name)\n    return model_name","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:51.874013Z","iopub.execute_input":"2022-12-27T17:33:51.875141Z","iopub.status.idle":"2022-12-27T17:33:51.880454Z","shell.execute_reply.started":"2022-12-27T17:33:51.875091Z","shell.execute_reply":"2022-12-27T17:33:51.879456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to load model\ndef load_model(model_name):\n    \"\"\"\n    Loads saved model.\n    \"\"\"\n    print(f\"Loading model {model_name}\")\n    model = tf.keras.models.load_model(model_name,\n                                       custom_objects={\"KerasLayer\": hub.KerasLayer})\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:51.881627Z","iopub.execute_input":"2022-12-27T17:33:51.882389Z","iopub.status.idle":"2022-12-27T17:33:51.895766Z","shell.execute_reply.started":"2022-12-27T17:33:51.882356Z","shell.execute_reply":"2022-12-27T17:33:51.894642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"save_model(model, suffix=\"1000-images-Adam\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:51.897699Z","iopub.execute_input":"2022-12-27T17:33:51.898248Z","iopub.status.idle":"2022-12-27T17:33:52.127840Z","shell.execute_reply.started":"2022-12-27T17:33:51.898210Z","shell.execute_reply":"2022-12-27T17:33:52.126903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_1000_images = load_model(\"/kaggle/working/1000-images-Adam.h5\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:52.130059Z","iopub.execute_input":"2022-12-27T17:33:52.130780Z","iopub.status.idle":"2022-12-27T17:33:53.918666Z","shell.execute_reply.started":"2022-12-27T17:33:52.130739Z","shell.execute_reply":"2022-12-27T17:33:53.917613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:53.920020Z","iopub.execute_input":"2022-12-27T17:33:53.920406Z","iopub.status.idle":"2022-12-27T17:33:54.451285Z","shell.execute_reply.started":"2022-12-27T17:33:53.920367Z","shell.execute_reply":"2022-12-27T17:33:54.450357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_1000_images.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:54.452950Z","iopub.execute_input":"2022-12-27T17:33:54.453357Z","iopub.status.idle":"2022-12-27T17:33:55.581287Z","shell.execute_reply.started":"2022-12-27T17:33:54.453303Z","shell.execute_reply":"2022-12-27T17:33:55.580365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training model on the full data","metadata":{"execution":{"iopub.status.busy":"2022-12-27T16:18:40.118449Z","iopub.execute_input":"2022-12-27T16:18:40.118821Z","iopub.status.idle":"2022-12-27T16:18:40.125534Z","shell.execute_reply.started":"2022-12-27T16:18:40.118791Z","shell.execute_reply":"2022-12-27T16:18:40.124488Z"}}},{"cell_type":"code","source":"len(X), len(y)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:55.582677Z","iopub.execute_input":"2022-12-27T17:33:55.583381Z","iopub.status.idle":"2022-12-27T17:33:55.590252Z","shell.execute_reply.started":"2022-12-27T17:33:55.583343Z","shell.execute_reply":"2022-12-27T17:33:55.589218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_data = create_batches(X, y)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:55.591861Z","iopub.execute_input":"2022-12-27T17:33:55.592643Z","iopub.status.idle":"2022-12-27T17:33:55.667164Z","shell.execute_reply.started":"2022-12-27T17:33:55.592605Z","shell.execute_reply":"2022-12-27T17:33:55.666289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_model = create_model()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:55.668548Z","iopub.execute_input":"2022-12-27T17:33:55.669180Z","iopub.status.idle":"2022-12-27T17:33:57.402669Z","shell.execute_reply.started":"2022-12-27T17:33:55.669144Z","shell.execute_reply":"2022-12-27T17:33:57.401621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_model_tensorboard = create_tensorboard_callback()\n\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"accuracy\",\n                                                             patience=3)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:57.404018Z","iopub.execute_input":"2022-12-27T17:33:57.404390Z","iopub.status.idle":"2022-12-27T17:33:57.737384Z","shell.execute_reply.started":"2022-12-27T17:33:57.404356Z","shell.execute_reply":"2022-12-27T17:33:57.736292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%tensorboard --logdir /kaggle/working/logs","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:57.738763Z","iopub.execute_input":"2022-12-27T17:33:57.740739Z","iopub.status.idle":"2022-12-27T17:33:57.756124Z","shell.execute_reply.started":"2022-12-27T17:33:57.740696Z","shell.execute_reply":"2022-12-27T17:33:57.755188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_model.fit(x=full_data,\n               epochs=NUM_EPOCHS,\n               callbacks=[full_model_tensorboard, \n                          full_model_early_stopping])","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:33:57.757707Z","iopub.execute_input":"2022-12-27T17:33:57.758120Z","iopub.status.idle":"2022-12-27T17:43:34.831533Z","shell.execute_reply.started":"2022-12-27T17:33:57.758081Z","shell.execute_reply":"2022-12-27T17:43:34.830251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"save_model(full_model, suffix=\"all-images-Adam\")","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:43:34.833090Z","iopub.execute_input":"2022-12-27T17:43:34.833414Z","iopub.status.idle":"2022-12-27T17:43:35.059266Z","shell.execute_reply.started":"2022-12-27T17:43:34.833385Z","shell.execute_reply":"2022-12-27T17:43:35.058189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Making Predicitons on the Test Dataset","metadata":{}},{"cell_type":"code","source":"test_path = \"/kaggle/input/dog-breed-identification/test/\"\ntest_filenames = [test_path + fname for fname in os.listdir(test_path)]\ntest_filenames[:5]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:43:35.061262Z","iopub.execute_input":"2022-12-27T17:43:35.061868Z","iopub.status.idle":"2022-12-27T17:43:35.090689Z","shell.execute_reply.started":"2022-12-27T17:43:35.061795Z","shell.execute_reply":"2022-12-27T17:43:35.089163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(test_filenames)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:43:35.092662Z","iopub.execute_input":"2022-12-27T17:43:35.093027Z","iopub.status.idle":"2022-12-27T17:43:35.103193Z","shell.execute_reply.started":"2022-12-27T17:43:35.092992Z","shell.execute_reply":"2022-12-27T17:43:35.102052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = create_batches(test_filenames, test_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:43:35.109284Z","iopub.execute_input":"2022-12-27T17:43:35.109665Z","iopub.status.idle":"2022-12-27T17:43:35.158397Z","shell.execute_reply.started":"2022-12-27T17:43:35.109629Z","shell.execute_reply":"2022-12-27T17:43:35.157212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predictions = load_model(\"/kaggle/working/all-images-Adam.h5\").predict(test_data,\n                                                                            verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:43:35.165556Z","iopub.execute_input":"2022-12-27T17:43:35.166110Z","iopub.status.idle":"2022-12-27T17:44:02.426365Z","shell.execute_reply.started":"2022-12-27T17:43:35.166075Z","shell.execute_reply":"2022-12-27T17:44:02.425213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predictions[0]","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:44:02.427887Z","iopub.execute_input":"2022-12-27T17:44:02.428272Z","iopub.status.idle":"2022-12-27T17:44:02.439209Z","shell.execute_reply.started":"2022-12-27T17:44:02.428235Z","shell.execute_reply":"2022-12-27T17:44:02.437941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Preparing test dataset predictions for Kaggle Submission","metadata":{}},{"cell_type":"code","source":"preds_df = pd.DataFrame(columns=[\"id\"] + list(unique_breeds))\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:44:02.440695Z","iopub.execute_input":"2022-12-27T17:44:02.441811Z","iopub.status.idle":"2022-12-27T17:44:02.463158Z","shell.execute_reply.started":"2022-12-27T17:44:02.441634Z","shell.execute_reply":"2022-12-27T17:44:02.462247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Append test image ID's to prediction DataFrame\ntest_path = \"/kaggle/input/dog-breed-identification/test/\"\npreds_df[\"id\"] = [os.path.splitext(path)[0] for path in os.listdir(test_path)]\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:44:02.465056Z","iopub.execute_input":"2022-12-27T17:44:02.466029Z","iopub.status.idle":"2022-12-27T17:44:02.516386Z","shell.execute_reply.started":"2022-12-27T17:44:02.465992Z","shell.execute_reply":"2022-12-27T17:44:02.515295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Add the prediction probabilities to each dog breed column\npreds_df[list(unique_breeds)] = test_predictions\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:44:02.517888Z","iopub.execute_input":"2022-12-27T17:44:02.518527Z","iopub.status.idle":"2022-12-27T17:44:03.015071Z","shell.execute_reply.started":"2022-12-27T17:44:02.518491Z","shell.execute_reply":"2022-12-27T17:44:03.013955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df.to_csv(\"/kaggle/working/full_submission.csv\",\n                 index=False)","metadata":{"execution":{"iopub.status.busy":"2022-12-27T17:44:03.016720Z","iopub.execute_input":"2022-12-27T17:44:03.017257Z","iopub.status.idle":"2022-12-27T17:44:04.171604Z","shell.execute_reply.started":"2022-12-27T17:44:03.017202Z","shell.execute_reply":"2022-12-27T17:44:04.170182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}