{"metadata":{"colab":{"provenance":[],"gpuType":"T4","toc_visible":true},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"accelerator":"GPU","kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30648,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Dog-breed-classification\n\nThis notebook builds dog-breed-classification model using Tensoeflow and TensorFlow Hub\n\n\n# Problem\n\nIdentfying breed of a dog given an image of a dog\n\nWhen I am sitting at a cafe, I want to know the breed of the dog.\n\n# Data\n\nThe data I am using is the Kaggle's dog breeds dataset used for a competition. You can find it here: https://www.kaggle.com/competitions/dog-breed-identification/data\n\n# Evaluation\n\nThe evaluation is a file with prediction probability\n\nhttps://www.kaggle.com/competitions/dog-breed-identification/overview\n\n# Features\n\n* We are dealing with unstructured data which is why we better use deep/transfer learning\n* There are 120 breeds of dogs.\n* There are 10000+ images in training dataset(with labels)\n* There are 10000+ images in test set","metadata":{"id":"QyWv6hWGo4Nj"}},{"cell_type":"code","source":"","metadata":{"id":"yA24S7KSo-3s"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Unzip uploaded data into Google drive\n# !unzip \"drive/MyDrive/Colab Notebooks/dog-breed-identification.zip\" -d \"drive/MyDrive/Dog vision\"","metadata":{"id":"XJK2w5dcjrn_"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Getting our data  ready","metadata":{"id":"IijWBTnSuQ0Y"}},{"cell_type":"code","source":"# Installing tensorflow\n# !pip install tensorflow","metadata":{"id":"J9kDF8C4kQav"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import necessary tools\nimport tensorflow_hub as hub\nimport tensorflow as tf\n\nprint(\"Tensorflow version:\", tf.__version__)\nprint(\"Hub version:\", hub.__version__)\n\nprint(\"GPU available\" if tf.config.list_physical_devices(\"GPU\") else \"not available\")","metadata":{"id":"uKsOBb8au1Zz","outputId":"0f787d1b-6405-4e63-9174-b10c2cb5b5e4"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Turning into tensors","metadata":{"id":"yLb7fdMAvscT"}},{"cell_type":"code","source":"# Load the data\n\nimport pandas as pd\nlabels_csv = pd.read_csv(\"/kaggle/input/dog-breed-identification/labels.csv\")\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"id":"zg-pVvy6I7DX","outputId":"0fdaef87-e4ff-4edc-90af-5d7acdc75a38","execution":{"iopub.status.busy":"2024-01-29T22:41:55.337094Z","iopub.execute_input":"2024-01-29T22:41:55.337978Z","iopub.status.idle":"2024-01-29T22:41:56.467196Z","shell.execute_reply.started":"2024-01-29T22:41:55.337939Z","shell.execute_reply":"2024-01-29T22:41:56.466122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv.head()","metadata":{"id":"fJSadXzpJy2a","outputId":"9331af4b-0013-4eae-a230-4ea4d15fb9bc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# How many breeds are there of each type?\n\nlabels_csv[\"breed\"].value_counts().plot.bar(figsize=(10, 20))","metadata":{"id":"tTrPBEnYJ8ya","outputId":"6a924f94-4b43-4c3e-d1cc-1848fcf19eca"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv[\"breed\"].value_counts().median()","metadata":{"id":"qhgq9CKHKjjM","outputId":"68f9769c-08cd-4995-bd37-0fa6f9b328be"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's see one of the images\nfrom IPython.display import Image\nImage(\"/kaggle/input/dog-breed-identification/train/001513dfcb2ffafc82cccf4d8bbaba97.jpg\")","metadata":{"id":"ATZIvJRxLJnK","outputId":"2598a2c0-35f7-4d0e-c4d2-606adf04c142","execution":{"iopub.status.busy":"2024-01-29T22:43:30.15157Z","iopub.execute_input":"2024-01-29T22:43:30.152015Z","iopub.status.idle":"2024-01-29T22:43:30.181905Z","shell.execute_reply.started":"2024-01-29T22:43:30.151963Z","shell.execute_reply":"2024-01-29T22:43:30.180979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create pathnames for each file","metadata":{"id":"hGXp-pUZMxAh"}},{"cell_type":"code","source":"pathnames = [\"Dog vision/train/\" + fname +  \".jpg\" for fname in labels_csv[\"id\"]]\npathnames[:10]","metadata":{"id":"UjU-ICNROQPr","outputId":"3f02bb4b-2cde-4664-ebd9-cb99f947652a"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check whether the number of files match\n\nimport os\nif len(os.listdir(\"Dog vision/train\")) == len(pathnames):\n  print(\"Match\")\nelse:\n  print(\"Unmatching\")","metadata":{"id":"Q8_VTG8DOgc1","outputId":"84cbceb1-f82d-4168-bcf5-f7aa0d9709c8"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Last check\nImage(pathnames[9000])","metadata":{"id":"-i8atKE3QiCD","outputId":"549da1bd-26c2-4029-e5ba-969f43506b05"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Turn labels into numbers","metadata":{"id":"u9cYMQCEQ3ob"}},{"cell_type":"code","source":"import numpy as np\nlabels = labels_csv[\"breed\"].to_numpy()\nlabels","metadata":{"id":"bNIz8tsxY193","outputId":"6e4ed618-bddf-4382-f3e4-e7478c9f3262"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(labels)","metadata":{"id":"zaNfj33JZYBt","outputId":"1f09114a-695b-4713-8f26-6ec0002f44f2"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make the list of unique breeds using numpy\n\nunique_breeds = np.unique(labels)","metadata":{"id":"e_wl2qPrbSHA"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn a single label into an array of booleans\nlabels[0] == unique_breeds","metadata":{"id":"JtU9pM8MZkNz","outputId":"09d618cd-53bc-48c8-862d-32e9606b65e0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's do the same to whole dataset\nboolean_labels = [label ==unique_breeds for label in labels]\nboolean_labels[:2]","metadata":{"id":"DEP1rglibinB","outputId":"7443776a-2fb0-47ec-fbaf-bb8952b66378"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turning boolean array into integers\n\nboolean_labels[0].astype(int)\n","metadata":{"id":"5t4fjBaIb9Yr","outputId":"2989d669-6bb5-422c-f411-ba096d3b782f"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Crating our own validation set\nSince data from Kaggle does not come with its validation set, I am going to create my own.","metadata":{"id":"UDlhX_JrdZC_"}},{"cell_type":"code","source":"# Set up x and y variables\nx = pathnames\ny = boolean_labels","metadata":{"id":"fQBnoMn-fjqc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set number of images to use for experimenting\n\nNUM_IMAGES = 1000 #@param {type: \"slider\", min:1000, max:10000, step:1000}","metadata":{"id":"fpUDRbaVf_5G"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Split our data\n\nfrom sklearn.model_selection import train_test_split\n\nx_train, x_val, y_train, y_val = train_test_split(x[:NUM_IMAGES], y[:NUM_IMAGES], test_size=0.2,\n                                                  random_state = 42)\n\n# Chekcing the lengths of our data\nlen(x_train), len(x_val), len(y_train), len(y_val)","metadata":{"id":"HmDDmgjKiJvV","outputId":"10531ec8-1273-4199-a2bb-7ac0acb159d7"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocessing (Turning images into Tensors)\n\n1. Take an filepath as an input\n2. use tensorflow to read the file and save it to a variable, 'image'\n3. turn the image into tensor\n4. resize the image to the size of (224, 224)\n5. return the modified image","metadata":{"id":"Q84kWhlUkJNu"}},{"cell_type":"code","source":"# Convert image to numpy array\n\nfrom matplotlib.pyplot import imread\nimages = imread(pathnames[42])\nimages.shape","metadata":{"id":"g0BvUAZijV6x","outputId":"5f834283-eac9-47a0-ae83-de9bb1cca475"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert image into tensor\n\ntf.constant(images[:2])","metadata":{"id":"R-zqJs5J3CaE","outputId":"1bcc1f54-8bbe-4eef-c732-8ab1cc777d49"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Create a function that turns an image into tensors","metadata":{"id":"kBKPRL4R3yZV"}},{"cell_type":"code","source":"# Define Image size\nIMG_SIZE = (224, 224)\n\n# Create a function\ndef preprocess_image(image_path, img_size=IMG_SIZE):\n  # Read an image file\n  image = tf.io.read_file(image_path)\n  # Turning images into numerical tensors\n  image = tf.image.decode_jpeg(image, channels=3)\n  # Convert the colur channel from 0-225 to 0-1\n  image = tf.image.convert_image_dtype(image, tf.float32)\n  # Resize the image to our desired value (224, 224)\n  image = tf.image.resize(image, size=IMG_SIZE)\n\n  return image","metadata":{"id":"TTdivq3qJIap"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n## Turn our data into batches\n\nWhy do we need  batches? Well, because even our GPU cannot process 10000+ images at a time\n\nSo, that is why we do 32 (default batch size) images in one go (this can also be adjusted manually)\n\nIn order to use Tensorflow effectively, we need the data in form of tuples:\n'(image, label)'\n","metadata":{"id":"2a8vGmX6MnJ6"}},{"cell_type":"code","source":"# Create a function that returns tuple (image, label)\n\ndef return_tuples(image_path, label):\n  \"\"\"\n  Takes an image, preprocess it and returns tuple\n  \"\"\"\n  image = preprocess_image(image_path)\n  return image, label","metadata":{"id":"jBV4JCj9R2yn"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Demo of the above\nreturn_tuples(pathnames[42], boolean_labels[42])","metadata":{"id":"yyk9J5UVTkms","outputId":"e33ea9c4-989b-42ce-acd3-fa2e83d694e8"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we have a way to turn our data into tuples, let's make a function to turn all of our data (x,y) into batches","metadata":{"id":"sKcp9rWgT1Un"}},{"cell_type":"markdown","source":"## Divide data into batches  ","metadata":{"id":"1zt-ZmFSUhBy"}},{"cell_type":"code","source":"# Define batch size\nBATCH_SIZE = 32\n\n# Create a function that turns data into batches\ndef create_data_batch(x, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False):\n  \"\"\"\n  Create batches of our data x and y\n  Shuffles if it is training data but does not shuffle if it is valid and test data\n  also accepts test data as input without labels (y)\n  \"\"\"\n  # If data is test data, we dont have a label\n  if test_data:\n    print(\"Creating test data batches...\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x))) # Only pathnames (no labels)\n    data_batch = data.map(preprocess_image).batch(BATCH_SIZE)\n    return data_batch\n  # If the data is validation set, we do not need to shuffle it\n  if valid_data:\n    print(\"Creating vaidation batches....\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x),  # Pathnames\n                                               tf.constant(y)))  # labels\n    data_batch = data.map(return_tuples).batch(BATCH_SIZE)\n    return data_batch\n\n  else:\n    print(\"Creating training batches...\")\n    # Turn pathnames into Tensors\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x),\n                                               tf.constant(y)))\n    # Shuffle pathnames and labels\n    data.shuffle(buffer_size=len(x))\n    data = data.map(return_tuples)\n    data_batch = data.batch(BATCH_SIZE)\n  return data_batch","metadata":{"id":"M1h5XoFcZn_N"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create train and validation data batches\n\ntrain_data = create_data_batch(x_train, y_train)\nvalid_data = create_data_batch(x_val, y_val, valid_data=True)","metadata":{"id":"KveIcFE4vYx0","outputId":"2239cc98-97e3-4854-de15-06c9d706ab4c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out different attributes of our data batches\ntrain_data.element_spec, valid_data.element_spec","metadata":{"id":"ITiooMEcv-yW","outputId":"cb551ad5-3bde-4645-9b39-6c3d3998a3da"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualizing data batches\n\nOur data is now in batches, however it is a little hard to visuzlize it. So, let's visuzlize them.","metadata":{"id":"D65D7uZXML1r"}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Create a function to view images in data batch\ndef show_25_images(images, labels):\n  \"\"\"\n  Displays a plot of 25 images and their labels from a data batch\n  \"\"\"\n  # Set up the figure\n  plt.figure(figsize=(10, 10))\n  # Loop through 25 (for displaying 25 images)\n  for i in range(25):\n    # Create subplots (5 columns, 5 rows)\n    ax = plt.subplot(5, 5, i+1)\n    # Dsiplay 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\")\n\n\n","metadata":{"id":"8A7_yNu3Nj_b"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images, train_labels = next(train_data.as_numpy_iterator())\ntrain_images, train_labels","metadata":{"id":"j4v4qCcjSRHD","outputId":"a8be9e77-c92c-4982-b8b1-2eff99588d17"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now lets visualize data in a traing batch\nshow_25_images(train_images, train_labels)","metadata":{"id":"zdA_9fV2Wq4Q","outputId":"ff2c67e4-20a2-4cb8-c2d6-024b237350ba"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lets visualize our validation data  as well\n\nval_images, val_labels = next(valid_data.as_numpy_iterator())\nval_images, val_labels\n\nshow_25_images(val_images, val_labels)","metadata":{"id":"Iq08WkUdXeEH","outputId":"5c665f6a-6816-4c75-df81-1fa9e47e663c"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Bulding a model\n\nBefore we build a model, we need to define:\n* The input shape\n* The output shape\n* The URL of the model that we are going to use","metadata":{"id":"8O576zfKaPlT"}},{"cell_type":"code","source":"# Set up input shape\nINPUT_SHAPE = [None, 224, 224, 3]\n# Set up output shape\nOUTPUT_SHAPE = len(unique_breeds)\n# URL\nMODEL_URL = \"https://kaggle.com/models/google/mobilenet-v2/frameworks/TensorFlow2/variations/130-224-classification/versions/1\"\n","metadata":{"id":"MlueSAb3ZtEK"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we have got our input shape, output shape and model we aer gonna use.\n\nKnowing this, let's build a function which does these below:\n\n* Takes input & output shape and model as its parameters;\n* Defines the layers in a Keras model in sequential fashion (do this first, then this and then this)\n* Compiles the model (says it should be evaluated and improved)\n* BUilds the model (tells the model the input shape it will be getting)\n* Returns the model","metadata":{"id":"J7ZhYWGx6Lvx"}},{"cell_type":"code","source":"# Lets create a function\n\ndef create_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, model_url=MODEL_URL):\n  print(\"Building model with:\", MODEL_URL)\n  # Set up model layers\n  model = tf.keras.Sequential([\n      hub.KerasLayer(MODEL_URL), # layer 1 (input)\n      tf.keras.layers.Dense(units=OUTPUT_SHAPE,\n                            activation=\"softmax\") #Layer 2 (output)\n  ])\n  # Compile the model\n  model.compile(\n      loss = tf.keras.losses.CategoricalFocalCrossentropy(),\n      optimizer = tf.keras.optimizers.Adam(),\n      metrics=[\"accuracy\"]\n  )\n  # Build the model\n  model.build(INPUT_SHAPE)\n  return model","metadata":{"id":"X2ZLeG5c-VjA"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = create_model()\nmodel.summary()","metadata":{"id":"DIEZfJC__03c","outputId":"a459fd77-06e2-470d-ab70-83d135d77931"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create a callbacks\n\nWe are going to create 2 callbacks, one for   Tensorboard which track the models progress and another one for early stopping which prevents our model from training for too long","metadata":{"id":"TyAKrY9PAPz0"}},{"cell_type":"markdown","source":"### TensorBoard\n\nTo set up TensorBoard callback, we need to do 3 things:\n* load the TensorBoard\n* Create a TensorBoard callback which is able to save logs to a directory and pas it to the 'fit()' model\n* Visualize our models training logs with '%tensorboard' magic function","metadata":{"id":"t299qvhxWawc"}},{"cell_type":"code","source":"# Load tensorboard  into the notebook\n%load_ext tensorboard","metadata":{"id":"HUkhgnayWaNa"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime\n\n# Create a function to build a TensorBoard callback\ndef create_tensor_callback():\n  # Create a log directory to save the models performance\n  logdir = os.path.join(\"Dog vision/logs\",\n                        # Make it so whenever the experiment is run the time should be tracked\n                        datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n\n  return tf.keras.callbacks.TensorBoard(logdir)\n","metadata":{"id":"rX3ZqXA_WwZq"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Early Stopping callback\n\nEarly stopping prevents model from overfitting by stopping training","metadata":{"id":"s-s3uGM0aCUo"}},{"cell_type":"code","source":"# Create a EarlyStopping callback\n\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                        patience = 3)","metadata":{"id":"SPCoXVx6bUXm"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train data (on a subset of images)\n\nOur first model will be trained on 1000 images to make sure everything is woeking\n\n","metadata":{"id":"IVoSiI3ybt9O"}},{"cell_type":"code","source":"NUM_EPOCHS = 100 #@param {type:\"slider\", min:10, max:100, step:10}","metadata":{"id":"DH3I_Wx3iAj1"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"  # Check to make sure that we are still using GPU\n  print(\"GPU\", \"available\" if tf.config.list_physical_devices(\"GPU\") else \"not available, unfortunately\")","metadata":{"id":"iXIFx8znipEt","outputId":"d501e679-ef07-4b2c-ade0-244b90510409"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Lets create a function which trains a model:\n\n* Create a model using 'create_model' function\n* Set up TensorBoard callback using create_tensor_callback\n* Call the 'fit' function on our model passing it traiining set, validation set number of epochs to train for\n* Return the model","metadata":{"id":"Dm5egB0KjgqH"}},{"cell_type":"code","source":"# Build a function to train and return trained model\n\ndef train_model():\n  \"\"\"\n  Trains the model and returns trained model\n  \"\"\"\n  model = create_model()\n  # Create new Tensorboard session everytime when the training is done\n  tensorboard = create_tensor_callback()\n  # Fit the data\n  model.fit(x=train_data,\n            epochs=NUM_EPOCHS,\n            validation_data = valid_data,\n            validation_freq=1,\n            callbacks=[tensorboard, early_stopping])\n  # Return the fitted model\n  return model","metadata":{"id":"hDjvvTQikl_3"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = train_model()","metadata":{"id":"4Q9o2bPWmsYH","outputId":"72a924f8-24cc-4b1c-b279-ca0bb8adbb90"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Checking the Tensorboard logs\n\n\n\nThe tensorboard magic function (%tesorboard) will access the logs directly and visualize its  contents.","metadata":{"id":"UD819VOOm6xY"}},{"cell_type":"code","source":"%tensorboard --logdir drive/MyDrive/Dog\\ vision/logs","metadata":{"id":"qjXdbVmJyGjQ","outputId":"d9832f4d-b92a-429c-c883-ea1f613e87e3"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Making and evaluating predictions","metadata":{"id":"X5q79LD9yfwQ"}},{"cell_type":"code","source":"valid_data","metadata":{"id":"MositMVA075g","outputId":"576c9b02-c4a7-4a73-fcb6-62a0e9322a07"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the validation data (not used on training)\n\npredictions = model.predict(valid_data, verbose=1)\npredictions","metadata":{"id":"odXgZS3e0fOJ","outputId":"69329d8e-5035-4fe2-b07c-9254f6530a97"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First prediction\nindex = 54\nprint(predictions[index])\nprint(f\"Max value (probability of the prediction): {np.max(predictions[index])}\")\nprint(f\"Sum: {np.sum(predictions[index])}\")\nprint(f\"Max index: {np.argmax(predictions[index])}\")\nprint(f\"Predicted label: {unique_breeds[np.argmax(predictions[index])]}\")","metadata":{"id":"m1CPeRb51VDZ","outputId":"2b5c2541-84ae-400a-dbcb-b844615d71f4"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn prediction probability into their respective label\ndef get_pred_label(prediction_probabilities):\n  \"\"\"\n  Turns an array of prediction probabilities into label\n  \"\"\"\n  return unique_breeds[np.argmax(prediction_probabilities)]\n","metadata":{"id":"XcBIe9BAB_Id"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function to unbatchify the batched data and to display actual images\n\ndef unbatchify(data):\n  \"\"\"\n  Unbatches the provided data\n  \"\"\"\n  images = []\n  labels = []\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\n# Unbatchify validation data\nval_images, val_labels = unbatchify(valid_data)\nval_images, val_labels","metadata":{"id":"pbfTFnAOHnCU","outputId":"c6911dc3-b595-47ee-e15d-b59354fefece"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_pred_label(val_labels[5])","metadata":{"id":"kLtcfV2RIXBS","outputId":"3d4226a0-42c2-4aca-b6c1-a75b2ff0bf3f"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We will create a function which does these:\n* Takes an array of prediction probabilities, an array of truth labels and an array of images and integers\n* Convert the prediction probabilities to a predicted label\n* Plot the predicted label, its predicted probability, the truth label and target image on a single plot.","metadata":{"id":"1HgNTag-IYFV"}},{"cell_type":"code","source":"def plot_pred(prediction_probabilities, labels, images, n=1):\n  \"\"\"\n  View the prediction, ground truth and image for sample n\n  \"\"\"\n  pred_probs, true_labels, image = prediction_probabilities[n], labels[n], images[n]\n\n  # Get pred labels\n  pred_label = get_pred_label(pred_probs)\n\n  # Plot the image and remove the ticks\n  plt.imshow(image)\n  plt.xticks([])\n  plt.yticks([])\n\n  if pred_label == true_labels:\n    color = \"green\"\n  else:\n    color = \"red\"\n  plt.title(\"{}, {:2.0f}%, {}\".format(pred_label,\n                                     np.max(pred_probs) * 100,\n                                     true_labels),\n            color = color)\n","metadata":{"id":"cnj5xCmhR0-V"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred(prediction_probabilities=predictions,\n          labels = val_labels,\n          images=val_images)","metadata":{"id":"0W8TBB1qTbnW","outputId":"0de19f1a-35a4-4627-fe1e-c9db97492270"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Saving and loading our model","metadata":{"id":"oSRsiHyGTuzw"}},{"cell_type":"code","source":"# Create a function to save a model\n\ndef save_model(model, suffix=None):\n  # Create a model directory pathname with current time\n  modeldir = os.path.join(\"Dog vision/models\",\n                          datetime.datetime.now().strftime(\"%Y%m%d-%H%M%s\"))\n  model_path = modeldir + \"-\" + suffix + \".h5\"\n  print(f\"Saving model to {model_path}... \")\n  model.save(model_path)\n  return model_path\n","metadata":{"id":"Lt3bHwCPbg6n"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save the model\nsave_model(model, suffix=\"1\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function to load a model\ndef load_model(model_path):\n  \"\"\"\n  LOads the model\n  \"\"\"\n  print(f\"Loading saved model from {model_path}\")\n  model = tf.keras.models.load_model(model_path,\n                                     custom_objects={\"KerasLayer\":hub.KerasLayer})\n","metadata":{"id":"TzjqJZQadMM-"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I have created a function to load the saved model whenever needed.","metadata":{"id":"fDYCoFc2etWY"}}]}