{"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":"# Getting started\nDataset consists of a collection of 10,000+ labelled images of 120 different dog breeds.\n\nWe are working on multi-class image classification.","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0"}},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub\n\nprint(\"TF version:\", tf.__version__)\nprint(\"Hub version:\", hub.__version__)\n\n# Check for GPU\nprint(\"GPU\", \"available (YESS!!!!)\" if tf.config.list_physical_devices(\"GPU\") else \"not available :(\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:14.102921Z","iopub.execute_input":"2022-04-20T19:24:14.103211Z","iopub.status.idle":"2022-04-20T19:24:20.42253Z","shell.execute_reply.started":"2022-04-20T19:24:14.10316Z","shell.execute_reply":"2022-04-20T19:24:20.421862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You might be wondering what a GPU is or why we need one. The short story is, a GPU is a computer chip which is faster at doing numerical computing. And since machine learning is all about finding patterns in numbers, that's what we're after. ","metadata":{}},{"cell_type":"markdown","source":"# Getting data ready ","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nlabels_csv = pd.read_csv(\"../input/dog-breed-identification/labels.csv\")\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:20.424768Z","iopub.execute_input":"2022-04-20T19:24:20.425277Z","iopub.status.idle":"2022-04-20T19:24:20.488786Z","shell.execute_reply.started":"2022-04-20T19:24:20.425228Z","shell.execute_reply":"2022-04-20T19:24:20.487812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are 10222 different images and 120 different breeds.\n\nLet's see how many images there are of each breed.","metadata":{}},{"cell_type":"code","source":"# How many images are there of each breed?\nlabels_csv[\"breed\"].value_counts().plot.bar(figsize=(20, 10));","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:20.49038Z","iopub.execute_input":"2022-04-20T19:24:20.49084Z","iopub.status.idle":"2022-04-20T19:24:22.755046Z","shell.execute_reply.started":"2022-04-20T19:24:20.490665Z","shell.execute_reply":"2022-04-20T19:24:22.754156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There's about 60+ images for each dog breed.","metadata":{}},{"cell_type":"code","source":"from IPython.display import display, Image\nImage(\"../input/dog-breed-identification/train/000bec180eb18c7604dcecc8fe0dba07.jpg\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:22.756578Z","iopub.execute_input":"2022-04-20T19:24:22.757088Z","iopub.status.idle":"2022-04-20T19:24:22.781976Z","shell.execute_reply.started":"2022-04-20T19:24:22.757035Z","shell.execute_reply":"2022-04-20T19:24:22.781292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Getting images and their labels","metadata":{}},{"cell_type":"code","source":"# Define the training file path \ntrain_path = \"../input/dog-breed-identification/train/\"","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:22.78506Z","iopub.execute_input":"2022-04-20T19:24:22.789506Z","iopub.status.idle":"2022-04-20T19:24:22.792683Z","shell.execute_reply.started":"2022-04-20T19:24:22.789454Z","shell.execute_reply":"2022-04-20T19:24:22.791981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create pathnames from image ID's\nfilenames = [train_path + fname + \".jpg\" for fname in labels_csv[\"id\"]]\n\n# Check the first 10 filenames\nfilenames[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:22.795471Z","iopub.execute_input":"2022-04-20T19:24:22.798537Z","iopub.status.idle":"2022-04-20T19:24:22.817775Z","shell.execute_reply.started":"2022-04-20T19:24:22.798486Z","shell.execute_reply":"2022-04-20T19:24:22.81713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check whether number of filenames matches number of actual image files\nimport os\nlen(os.listdir(train_path)) == len(filenames)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:22.821589Z","iopub.execute_input":"2022-04-20T19:24:22.823677Z","iopub.status.idle":"2022-04-20T19:24:23.163176Z","shell.execute_reply.started":"2022-04-20T19:24:22.823627Z","shell.execute_reply":"2022-04-20T19:24:23.162418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check an image directly from a filepath\nImage(filenames[9000])","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.164908Z","iopub.execute_input":"2022-04-20T19:24:23.165418Z","iopub.status.idle":"2022-04-20T19:24:23.179497Z","shell.execute_reply.started":"2022-04-20T19:24:23.165157Z","shell.execute_reply":"2022-04-20T19:24:23.178642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nlabels = labels_csv[\"breed\"].to_numpy() # convert labels column to NumPy array\nlabels[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.180996Z","iopub.execute_input":"2022-04-20T19:24:23.181393Z","iopub.status.idle":"2022-04-20T19:24:23.187647Z","shell.execute_reply.started":"2022-04-20T19:24:23.181228Z","shell.execute_reply":"2022-04-20T19:24:23.186925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# See if number of labels matches the number of filenames\nlen(labels) == len(filenames)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.18911Z","iopub.execute_input":"2022-04-20T19:24:23.18966Z","iopub.status.idle":"2022-04-20T19:24:23.196074Z","shell.execute_reply.started":"2022-04-20T19:24:23.189601Z","shell.execute_reply":"2022-04-20T19:24:23.195279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the unique label values\nunique_breeds = np.unique(labels)\nlen(unique_breeds)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.197522Z","iopub.execute_input":"2022-04-20T19:24:23.198139Z","iopub.status.idle":"2022-04-20T19:24:23.217013Z","shell.execute_reply.started":"2022-04-20T19:24:23.198088Z","shell.execute_reply":"2022-04-20T19:24:23.216271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The length of `unique_breeds` should be 120, cause we have 120 different breeds of dogs.\n","metadata":{}},{"cell_type":"code","source":"# Example: Turn one label into an array of booleans\nprint(labels[0])\nlabels[0] == unique_breeds # use comparison operator to create boolean array","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.218244Z","iopub.execute_input":"2022-04-20T19:24:23.218673Z","iopub.status.idle":"2022-04-20T19:24:23.22622Z","shell.execute_reply.started":"2022-04-20T19:24:23.218491Z","shell.execute_reply":"2022-04-20T19:24:23.225511Z"},"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[:2]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.227368Z","iopub.execute_input":"2022-04-20T19:24:23.227799Z","iopub.status.idle":"2022-04-20T19:24:23.335122Z","shell.execute_reply.started":"2022-04-20T19:24:23.22775Z","shell.execute_reply":"2022-04-20T19:24:23.334505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example: Turning a boolean array into integers\nprint(labels[0]) # original label\nprint(np.where(unique_breeds == labels[0])[0][0]) # index where label occurs\nprint(boolean_labels[0].argmax()) # index where label occurs in boolean array\nprint(boolean_labels[0].astype(int)) # there will be a 1 where the sample label occurs","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.337374Z","iopub.execute_input":"2022-04-20T19:24:23.337862Z","iopub.status.idle":"2022-04-20T19:24:23.345896Z","shell.execute_reply.started":"2022-04-20T19:24:23.337813Z","shell.execute_reply":"2022-04-20T19:24:23.344595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"we've converted our labels in a numeric format","metadata":{}},{"cell_type":"markdown","source":"# Creating validation set\n","metadata":{}},{"cell_type":"code","source":"# Setup X & y variables\nX = filenames\ny = boolean_labels\n\nprint(f\"Number of training images: {len(X)}\")\nprint(f\"Number of labels: {len(y)}\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.34808Z","iopub.execute_input":"2022-04-20T19:24:23.348721Z","iopub.status.idle":"2022-04-20T19:24:23.356947Z","shell.execute_reply.started":"2022-04-20T19:24:23.348445Z","shell.execute_reply":"2022-04-20T19:24:23.35574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since we're working with 10,000+ images, we should start training with a portion of dataset\n\nLet's start with 1000 and increase it as we need.","metadata":{}},{"cell_type":"code","source":"# Set number of images to use for experimenting\nNUM_IMAGES = 1000\nNUM_IMAGES","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.358362Z","iopub.execute_input":"2022-04-20T19:24:23.358863Z","iopub.status.idle":"2022-04-20T19:24:23.367685Z","shell.execute_reply.started":"2022-04-20T19:24:23.358813Z","shell.execute_reply":"2022-04-20T19:24:23.366773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's split our data into training and validation sets. We'll use and 80/20 split (80% training data, 20% validation data).","metadata":{}},{"cell_type":"code","source":"# Import train_test_split from Scikit-Learn\nfrom sklearn.model_selection import train_test_split\n\n# Split them 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)\n\nlen(X_train), len(y_train), len(X_val), len(y_val)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.369131Z","iopub.execute_input":"2022-04-20T19:24:23.36967Z","iopub.status.idle":"2022-04-20T19:24:23.715581Z","shell.execute_reply.started":"2022-04-20T19:24:23.3695Z","shell.execute_reply":"2022-04-20T19:24:23.714523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the training data (image file paths and labels)\nX_train[:5], y_train[:2]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.717045Z","iopub.execute_input":"2022-04-20T19:24:23.717525Z","iopub.status.idle":"2022-04-20T19:24:23.725258Z","shell.execute_reply.started":"2022-04-20T19:24:23.717473Z","shell.execute_reply":"2022-04-20T19:24:23.724406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocessing images (turning images into Tensors)","metadata":{}},{"cell_type":"code","source":"# Convert image to NumPy array\nfrom matplotlib.pyplot import imread\nimage = imread(filenames[42]) \nimage.shape","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:23.726885Z","iopub.execute_input":"2022-04-20T19:24:23.72762Z","iopub.status.idle":"2022-04-20T19:24:23.756483Z","shell.execute_reply.started":"2022-04-20T19:24:23.727568Z","shell.execute_reply":"2022-04-20T19:24:23.755648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Shape: (257, 350, 3). This is height, width, colour channel value. ","metadata":{}},{"cell_type":"code","source":"# Define image size\nIMG_SIZE = 224\n#  Converting an image into a Tensor\ndef process_image(image_path):\n  # Read in image file\n  image = tf.io.read_file(image_path)\n  # Turn the jpeg 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-225 values to 0-1 values\n  image = tf.image.convert_image_dtype(image, tf.float32)\n  # Resize the image to our desired size (224, 244)\n  image = tf.image.resize(image, size=[IMG_SIZE, IMG_SIZE])\n  return image","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:25.353263Z","iopub.execute_input":"2022-04-20T19:24:25.353826Z","iopub.status.idle":"2022-04-20T19:24:25.360902Z","shell.execute_reply.started":"2022-04-20T19:24:25.353519Z","shell.execute_reply":"2022-04-20T19:24:25.359721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating data batches","metadata":{}},{"cell_type":"code","source":"# a function to return a tuple (image: Tensor, label)\ndef get_image_label(image_path, label):\n  image = process_image(image_path)\n  return image, label","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:25.362466Z","iopub.execute_input":"2022-04-20T19:24:25.363072Z","iopub.status.idle":"2022-04-20T19:24:25.36967Z","shell.execute_reply.started":"2022-04-20T19:24:25.362778Z","shell.execute_reply":"2022-04-20T19:24:25.368581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the batch size\nBATCH_SIZE = 32\n\n# 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  # If the data is a test dataset, we won'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\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    data = data.shuffle(buffer_size=len(x))\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-20T19:24:25.371365Z","iopub.execute_input":"2022-04-20T19:24:25.371934Z","iopub.status.idle":"2022-04-20T19:24:25.382267Z","shell.execute_reply.started":"2022-04-20T19:24:25.371773Z","shell.execute_reply":"2022-04-20T19:24:25.381467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create 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-20T19:24:25.383649Z","iopub.execute_input":"2022-04-20T19:24:25.384136Z","iopub.status.idle":"2022-04-20T19:24:25.725762Z","shell.execute_reply.started":"2022-04-20T19:24:25.384087Z","shell.execute_reply":"2022-04-20T19:24:25.724967Z"},"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-04-20T19:24:25.727225Z","iopub.execute_input":"2022-04-20T19:24:25.72773Z","iopub.status.idle":"2022-04-20T19:24:25.73425Z","shell.execute_reply.started":"2022-04-20T19:24:25.72768Z","shell.execute_reply":"2022-04-20T19:24:25.733432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualizing data batches","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# a function for viewing images in a data batch\ndef show_25_images(images, labels):\n  \n  plt.figure(figsize=(10, 10))\n  \n  for i in range(25):\n    \n    ax = plt.subplot(5, 5, i+1)\n    \n    plt.imshow(images[i])\n    \n    # image label as title\n    plt.title(unique_breeds[labels[i].argmax()])\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:25.735796Z","iopub.execute_input":"2022-04-20T19:24:25.736338Z","iopub.status.idle":"2022-04-20T19:24:25.743998Z","shell.execute_reply.started":"2022-04-20T19:24:25.736286Z","shell.execute_reply":"2022-04-20T19:24:25.743198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualize training images from the training data batch\ntrain_images, train_labels = next(train_data.as_numpy_iterator())\nshow_25_images(train_images, train_labels)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:25.747102Z","iopub.execute_input":"2022-04-20T19:24:25.74736Z","iopub.status.idle":"2022-04-20T19:24:27.484489Z","shell.execute_reply.started":"2022-04-20T19:24:25.747316Z","shell.execute_reply":"2022-04-20T19:24:27.483725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualize validation images from the validation data batch\nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_25_images(val_images, val_labels)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:27.485732Z","iopub.execute_input":"2022-04-20T19:24:27.486094Z","iopub.status.idle":"2022-04-20T19:24:29.269532Z","shell.execute_reply.started":"2022-04-20T19:24:27.486053Z","shell.execute_reply":"2022-04-20T19:24:29.268777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building model","metadata":{}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3] # batch, height, width, colour channels\n\n# Setup output shape of the model\nOUTPUT_SHAPE = len(unique_breeds) # number of unique labels\n\n# Setup model URL from TensorFlow Hub\nMODEL_URL = \"https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4\"","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:29.270745Z","iopub.execute_input":"2022-04-20T19:24:29.271143Z","iopub.status.idle":"2022-04-20T19:24:29.275894Z","shell.execute_reply.started":"2022-04-20T19:24:29.271096Z","shell.execute_reply":"2022-04-20T19:24:29.275155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function which builds a 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), TensorFlow Hub layer, requires Kaggle internet setting turned on\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(), # Our model wants to reduce this (how wrong its guesses are)\n      optimizer=tf.keras.optimizers.Adam(), # A friend telling our model how to improve its guesses\n      metrics=[\"accuracy\"] # We'd like this to go up\n  )\n\n  # Build the model\n  model.build(INPUT_SHAPE) # Let the model know what kind of inputs it'll be getting\n  \n  return model","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:29.277314Z","iopub.execute_input":"2022-04-20T19:24:29.277815Z","iopub.status.idle":"2022-04-20T19:24:29.286466Z","shell.execute_reply.started":"2022-04-20T19:24:29.277767Z","shell.execute_reply":"2022-04-20T19:24:29.285514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Building the model","metadata":{}},{"cell_type":"code","source":"# Create a model\nmodel = create_model()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:29.287762Z","iopub.execute_input":"2022-04-20T19:24:29.288236Z","iopub.status.idle":"2022-04-20T19:24:35.558016Z","shell.execute_reply.started":"2022-04-20T19:24:29.288191Z","shell.execute_reply":"2022-04-20T19:24:35.557143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The non-trainable parameters are the patterns learned by `mobilenet_v2_130_224` and the trainable parameters are the ones in the dense layer we added.\n\nThis means the main bulk of the information in our model has already been learned and we're going to take that and adapt it to our own problem.","metadata":{}},{"cell_type":"markdown","source":"# Callbacks \n\nCallbacks are helper functions a model can use during training to do things such as save a models progress, check a models progress or stop training early if a model stops improving.\n\nThe two callbacks we're going to add are a TensorBoard callback and an Early Stopping callback.\n\n## TensorBoard Callback\n\nIt helps provide a visual way to monitor the progress of your model during and after training.","metadata":{}},{"cell_type":"code","source":"# Load the TensorBoard notebook extension\n%load_ext tensorboard","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.564499Z","iopub.execute_input":"2022-04-20T19:24:35.56472Z","iopub.status.idle":"2022-04-20T19:24:35.574358Z","shell.execute_reply.started":"2022-04-20T19:24:35.564677Z","shell.execute_reply":"2022-04-20T19:24:35.573315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime\n\n# Create a function to build a TensorBoard callback\ndef create_tensorboard_callback():\n  # Create a log directory for storing TensorBoard logs\n  logdir = os.path.join(\"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-04-20T19:24:35.575805Z","iopub.execute_input":"2022-04-20T19:24:35.576096Z","iopub.status.idle":"2022-04-20T19:24:35.581638Z","shell.execute_reply.started":"2022-04-20T19:24:35.576044Z","shell.execute_reply":"2022-04-20T19:24:35.580876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Early Stopping Callback\n\nIt helps prevent overfitting by stopping a model when a certain evaluation metric stops improving.","metadata":{}},{"cell_type":"code","source":"# Create early stopping \nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3) # stops after 3 rounds of no improvements","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.582962Z","iopub.execute_input":"2022-04-20T19:24:35.583461Z","iopub.status.idle":"2022-04-20T19:24:35.59012Z","shell.execute_reply.started":"2022-04-20T19:24:35.583413Z","shell.execute_reply":"2022-04-20T19:24:35.589117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training a model (on a subset of data)\nOur first model was trained on 1000 images. Or trained on 800 images and then validated on 200 images, meaning 1000 images total ~ about 10% of the total data.\n\nNow, We can train on the entire training dataset.","metadata":{}},{"cell_type":"code","source":"# Check again if GPU is available\nprint(\"GPU\", \"available\" if tf.config.list_physical_devices(\"GPU\") else \"not available\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.591738Z","iopub.execute_input":"2022-04-20T19:24:35.592252Z","iopub.status.idle":"2022-04-20T19:24:35.598535Z","shell.execute_reply.started":"2022-04-20T19:24:35.592044Z","shell.execute_reply":"2022-04-20T19:24:35.597681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_EPOCHS = 100","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.599998Z","iopub.execute_input":"2022-04-20T19:24:35.600566Z","iopub.status.idle":"2022-04-20T19:24:35.605546Z","shell.execute_reply.started":"2022-04-20T19:24:35.600517Z","shell.execute_reply":"2022-04-20T19:24:35.604521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model():\n  \n  model = create_model()\n\n  # create new TensorBoard session everytime we train a model\n  tensorboard = create_tensorboard_callback()\n  \n  model.fit(x=train_data,\n            epochs=NUM_EPOCHS,\n            validation_data=val_data,\n            validation_freq=1, #  it checks validation metrics every epoch\n            callbacks=[tensorboard, early_stopping])\n  \n  return model","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.606942Z","iopub.execute_input":"2022-04-20T19:24:35.607446Z","iopub.status.idle":"2022-04-20T19:24:35.614236Z","shell.execute_reply.started":"2022-04-20T19:24:35.60738Z","shell.execute_reply":"2022-04-20T19:24:35.613284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = train_model()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:24:35.615664Z","iopub.execute_input":"2022-04-20T19:24:35.616163Z","iopub.status.idle":"2022-04-20T19:25:16.660731Z","shell.execute_reply.started":"2022-04-20T19:24:35.615974Z","shell.execute_reply":"2022-04-20T19:25:16.66Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Checking the TensorBoard logs\n\nThe TensorBoard function (`%tensorboard`) will access the logs directory we created earlier and visualize its contents.","metadata":{}},{"cell_type":"code","source":"%tensorboard --logdir logs","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:16.662877Z","iopub.execute_input":"2022-04-20T19:25:16.663416Z","iopub.status.idle":"2022-04-20T19:25:20.72473Z","shell.execute_reply.started":"2022-04-20T19:25:16.663342Z","shell.execute_reply":"2022-04-20T19:25:20.723819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" `early_stopping` callback stopped training after 9 epochs. This is because the validation accuracy failed to improve for 3 epochs.","metadata":{}},{"cell_type":"markdown","source":"# Making and evaluating predictions using a trained model\n","metadata":{}},{"cell_type":"code","source":"# Make predictions on the validation data (not used to train on)\npredictions = model.predict(val_data, verbose=1) # verbose shows us how long there is to go\npredictions","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:20.726329Z","iopub.execute_input":"2022-04-20T19:25:20.726652Z","iopub.status.idle":"2022-04-20T19:25:21.862933Z","shell.execute_reply.started":"2022-04-20T19:25:20.726606Z","shell.execute_reply":"2022-04-20T19:25:21.862266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the shape of predictions\npredictions.shape","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:21.865351Z","iopub.execute_input":"2022-04-20T19:25:21.865812Z","iopub.status.idle":"2022-04-20T19:25:21.871218Z","shell.execute_reply.started":"2022-04-20T19:25:21.865757Z","shell.execute_reply":"2022-04-20T19:25:21.870481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First prediction\nprint(predictions[0])\nprint(f\"Max value (probability of prediction): {np.max(predictions[0])}\") # the max probability value predicted by the model\nprint(f\"Sum: {np.sum(predictions[0])}\") # because we used softmax activation in our model, this will be close to 1\nprint(f\"Max index: {np.argmax(predictions[0])}\") # the index of where the max value in predictions[0] occurs\nprint(f\"Predicted label: {unique_breeds[np.argmax(predictions[0])]}\") # the predicted label","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:21.872962Z","iopub.execute_input":"2022-04-20T19:25:21.873399Z","iopub.status.idle":"2022-04-20T19:25:21.88392Z","shell.execute_reply.started":"2022-04-20T19:25:21.873335Z","shell.execute_reply":"2022-04-20T19:25:21.883247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# converts prediction probabilities into label \ndef get_pred_label(prediction_probabilities):\n  \n  return unique_breeds[np.argmax(prediction_probabilities)]\n\n# predicted label of first row\npred_label = get_pred_label(predictions[0])\npred_label","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:21.886185Z","iopub.execute_input":"2022-04-20T19:25:21.886692Z","iopub.status.idle":"2022-04-20T19:25:21.894274Z","shell.execute_reply.started":"2022-04-20T19:25:21.886646Z","shell.execute_reply":"2022-04-20T19:25:21.89343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function to unbatch a batched dataset\n# Takes a batched dataset of (image, label) Tensors and returns separate arrays of images and labels.\ndef unbatchify(data):\n  images = []\n  labels = []\n    \n  # Loop through 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# Unbatchify the validation data\nval_images, val_labels = unbatchify(val_data)\nval_images[0], val_labels[0]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:21.895907Z","iopub.execute_input":"2022-04-20T19:25:21.89635Z","iopub.status.idle":"2022-04-20T19:25:22.540258Z","shell.execute_reply.started":"2022-04-20T19:25:21.896166Z","shell.execute_reply":"2022-04-20T19:25:22.539486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View the prediction, ground truth label and image for sample n\ndef plot_pred(prediction_probabilities, labels, images, n=1):\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.xticks([])\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\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-04-20T19:25:22.541623Z","iopub.execute_input":"2022-04-20T19:25:22.541893Z","iopub.status.idle":"2022-04-20T19:25:22.549299Z","shell.execute_reply.started":"2022-04-20T19:25:22.541848Z","shell.execute_reply":"2022-04-20T19:25:22.548574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View an example prediction, original image and truth label\nplot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:22.551088Z","iopub.execute_input":"2022-04-20T19:25:22.551443Z","iopub.status.idle":"2022-04-20T19:25:22.687526Z","shell.execute_reply.started":"2022-04-20T19:25:22.551345Z","shell.execute_reply":"2022-04-20T19:25:22.686763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plots the top 10 highest prediction confidences along with the truth label for sample n.\ndef plot_pred_conf(prediction_probabilities, labels, n=1):\n\n  pred_prob, true_label = prediction_probabilities[n], labels[n]\n\n  # Get the predicted label\n  pred_label = get_pred_label(pred_prob)\n\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\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\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-04-20T19:25:22.688856Z","iopub.execute_input":"2022-04-20T19:25:22.695299Z","iopub.status.idle":"2022-04-20T19:25:22.708507Z","shell.execute_reply.started":"2022-04-20T19:25:22.695234Z","shell.execute_reply":"2022-04-20T19:25:22.707484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,\n               labels=val_labels,\n               n=9)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:22.713301Z","iopub.execute_input":"2022-04-20T19:25:22.716021Z","iopub.status.idle":"2022-04-20T19:25:22.994756Z","shell.execute_reply.started":"2022-04-20T19:25:22.713746Z","shell.execute_reply":"2022-04-20T19:25:22.993776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's check a few predictions and their different values\ni_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-04-20T19:25:22.999545Z","iopub.execute_input":"2022-04-20T19:25:23.001854Z","iopub.status.idle":"2022-04-20T19:25:24.98033Z","shell.execute_reply.started":"2022-04-20T19:25:23.00178Z","shell.execute_reply":"2022-04-20T19:25:24.979648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Saving and reloading a model","metadata":{}},{"cell_type":"code","source":"def save_model(model, suffix=None):\n  # Create model directory with current time\n  if not os.path.isdir('models'):\n      os.mkdir(\"models\")\n    \n  modeldir = os.path.join(\"models\",\n                          datetime.datetime.now().strftime(\"%Y%m%d-%H%M%s\"))\n  model_path = modeldir + \"-\" + suffix + \".h5\" # save format of model\n  print(f\"Saving model to: {model_path}...\")\n  model.save(model_path)\n  return model_path","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:24.981504Z","iopub.execute_input":"2022-04-20T19:25:24.981877Z","iopub.status.idle":"2022-04-20T19:25:24.989161Z","shell.execute_reply.started":"2022-04-20T19:25:24.981831Z","shell.execute_reply":"2022-04-20T19:25:24.988214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(model_path):\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  return model","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:24.990626Z","iopub.execute_input":"2022-04-20T19:25:24.991223Z","iopub.status.idle":"2022-04-20T19:25:25.007479Z","shell.execute_reply.started":"2022-04-20T19:25:24.990889Z","shell.execute_reply":"2022-04-20T19:25:25.003616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save our model trained on 1000 images\nsaved_1000_image_model_path = save_model(model, suffix=\"1000-images\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:25.009232Z","iopub.execute_input":"2022-04-20T19:25:25.009982Z","iopub.status.idle":"2022-04-20T19:25:25.226039Z","shell.execute_reply.started":"2022-04-20T19:25:25.009932Z","shell.execute_reply":"2022-04-20T19:25:25.225284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load our model trained on 1000 images\nloaded_model_1000_images = load_model(saved_1000_image_model_path)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:25.227513Z","iopub.execute_input":"2022-04-20T19:25:25.227789Z","iopub.status.idle":"2022-04-20T19:25:27.763315Z","shell.execute_reply.started":"2022-04-20T19:25:25.227744Z","shell.execute_reply":"2022-04-20T19:25:27.762603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Compare the two models (the original one and loaded one). We can do so easily using the `evaluate()` method.","metadata":{}},{"cell_type":"code","source":"# Evaluate the pre-saved model\nmodel.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:27.764661Z","iopub.execute_input":"2022-04-20T19:25:27.764958Z","iopub.status.idle":"2022-04-20T19:25:28.696275Z","shell.execute_reply.started":"2022-04-20T19:25:27.764911Z","shell.execute_reply":"2022-04-20T19:25:28.695525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the loaded model\nloaded_model_1000_images.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:28.700599Z","iopub.execute_input":"2022-04-20T19:25:28.702843Z","iopub.status.idle":"2022-04-20T19:25:30.317146Z","shell.execute_reply.started":"2022-04-20T19:25:28.702786Z","shell.execute_reply":"2022-04-20T19:25:30.316511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training a model (on the full data)\n","metadata":{}},{"cell_type":"code","source":"# size of the full dataset\nlen(X), len(y)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:30.318596Z","iopub.execute_input":"2022-04-20T19:25:30.319086Z","iopub.status.idle":"2022-04-20T19:25:30.326151Z","shell.execute_reply.started":"2022-04-20T19:25:30.318876Z","shell.execute_reply":"2022-04-20T19:25:30.325137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn full training data in a data batch\nfull_data = create_data_batches(X, y)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:30.327875Z","iopub.execute_input":"2022-04-20T19:25:30.328481Z","iopub.status.idle":"2022-04-20T19:25:30.450226Z","shell.execute_reply.started":"2022-04-20T19:25:30.328433Z","shell.execute_reply":"2022-04-20T19:25:30.449637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Instantiate a new model for training on the full dataset\nfull_model = create_model()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:30.451458Z","iopub.execute_input":"2022-04-20T19:25:30.451713Z","iopub.status.idle":"2022-04-20T19:25:32.571392Z","shell.execute_reply.started":"2022-04-20T19:25:30.451669Z","shell.execute_reply":"2022-04-20T19:25:32.570504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create full model callbacks\n\n# TensorBoard callback\nfull_model_tensorboard = create_tensorboard_callback()\n\n# Early stopping callback\n# No validation set when training on all the data\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"accuracy\",\n                                                             patience=3)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:32.572885Z","iopub.execute_input":"2022-04-20T19:25:32.573197Z","iopub.status.idle":"2022-04-20T19:25:32.578374Z","shell.execute_reply.started":"2022-04-20T19:25:32.57315Z","shell.execute_reply":"2022-04-20T19:25:32.57741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%tensorboard --logdir logs","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:25:32.579929Z","iopub.execute_input":"2022-04-20T19:25:32.580486Z","iopub.status.idle":"2022-04-20T19:25:32.595496Z","shell.execute_reply.started":"2022-04-20T19:25:32.580398Z","shell.execute_reply":"2022-04-20T19:25:32.593322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the full model to the full training data\nfull_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-04-20T19:25:32.596804Z","iopub.execute_input":"2022-04-20T19:25:32.597287Z","iopub.status.idle":"2022-04-20T19:35:52.76765Z","shell.execute_reply.started":"2022-04-20T19:25:32.597239Z","shell.execute_reply":"2022-04-20T19:35:52.766983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Saving and reloading the full model\n","metadata":{}},{"cell_type":"code","source":"# Save model to file\nsaved_full_model_path = save_model(full_model, suffix=\"all-images\")","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:52.76936Z","iopub.execute_input":"2022-04-20T19:35:52.769816Z","iopub.status.idle":"2022-04-20T19:35:52.982688Z","shell.execute_reply.started":"2022-04-20T19:35:52.769766Z","shell.execute_reply":"2022-04-20T19:35:52.981861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load in the full model\nloaded_full_model = load_model(saved_full_model_path)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:52.984235Z","iopub.execute_input":"2022-04-20T19:35:52.984529Z","iopub.status.idle":"2022-04-20T19:35:55.542796Z","shell.execute_reply.started":"2022-04-20T19:35:52.984484Z","shell.execute_reply":"2022-04-20T19:35:55.542011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Making predictions on the test dataset","metadata":{}},{"cell_type":"code","source":"# Load test image filenames using os.listdir()\ntest_path = \"../input/dog-breed-identification/test/\"\ntest_filenames = [test_path + fname for fname in os.listdir(test_path)]\n\ntest_filenames[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:55.5442Z","iopub.execute_input":"2022-04-20T19:35:55.544502Z","iopub.status.idle":"2022-04-20T19:35:55.827562Z","shell.execute_reply.started":"2022-04-20T19:35:55.544455Z","shell.execute_reply":"2022-04-20T19:35:55.826755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(test_filenames)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:55.829003Z","iopub.execute_input":"2022-04-20T19:35:55.82929Z","iopub.status.idle":"2022-04-20T19:35:55.834949Z","shell.execute_reply.started":"2022-04-20T19:35:55.829248Z","shell.execute_reply":"2022-04-20T19:35:55.834109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create test data batch\ntest_data = create_data_batches(test_filenames, test_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:55.836727Z","iopub.execute_input":"2022-04-20T19:35:55.8374Z","iopub.status.idle":"2022-04-20T19:35:55.85806Z","shell.execute_reply.started":"2022-04-20T19:35:55.837335Z","shell.execute_reply":"2022-04-20T19:35:55.857466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on test data batch using the loaded full model\ntest_predictions = full_model.predict(test_data,\n                                      verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:35:55.860878Z","iopub.execute_input":"2022-04-20T19:35:55.861101Z","iopub.status.idle":"2022-04-20T19:37:20.387225Z","shell.execute_reply.started":"2022-04-20T19:35:55.861058Z","shell.execute_reply":"2022-04-20T19:37:20.386296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the test predictions\ntest_predictions[:10]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:20.393112Z","iopub.execute_input":"2022-04-20T19:37:20.393357Z","iopub.status.idle":"2022-04-20T19:37:20.401189Z","shell.execute_reply.started":"2022-04-20T19:37:20.393313Z","shell.execute_reply":"2022-04-20T19:37:20.40045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Converting test dataset predictions to .csv","metadata":{}},{"cell_type":"code","source":"# Create pandas DataFrame with empty columns\npreds_df = pd.DataFrame(columns=[\"id\"] + list(unique_breeds))\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:20.402962Z","iopub.execute_input":"2022-04-20T19:37:20.403417Z","iopub.status.idle":"2022-04-20T19:37:20.436221Z","shell.execute_reply.started":"2022-04-20T19:37:20.403218Z","shell.execute_reply":"2022-04-20T19:37:20.435366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Append test image ID's to predictions DataFrame\npreds_df[\"id\"] = [os.path.splitext(path)[0] for path in os.listdir(test_path)]\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:20.437923Z","iopub.execute_input":"2022-04-20T19:37:20.438314Z","iopub.status.idle":"2022-04-20T19:37:20.497829Z","shell.execute_reply.started":"2022-04-20T19:37:20.438157Z","shell.execute_reply":"2022-04-20T19:37:20.496817Z"},"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-04-20T19:37:20.499244Z","iopub.execute_input":"2022-04-20T19:37:20.499678Z","iopub.status.idle":"2022-04-20T19:37:20.660254Z","shell.execute_reply.started":"2022-04-20T19:37:20.499491Z","shell.execute_reply":"2022-04-20T19:37:20.659359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df.to_csv(\"final_model.csv\",\n                 index=False)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:20.661533Z","iopub.execute_input":"2022-04-20T19:37:20.66181Z","iopub.status.idle":"2022-04-20T19:37:23.250711Z","shell.execute_reply.started":"2022-04-20T19:37:20.661765Z","shell.execute_reply":"2022-04-20T19:37:23.249977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Making predictions on custom images\n\nTo make predictions on custom images, we've uploaded some pictures to https://www.kaggle.com/sahilchanglani/dogcustomimages. ","metadata":{}},{"cell_type":"code","source":"# Get custom image filepaths\ncustom_path = \"../input/dogcustomimages/\"\ncustom_image_paths = [custom_path + fname for fname in os.listdir(custom_path)]","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.252038Z","iopub.execute_input":"2022-04-20T19:37:23.252422Z","iopub.status.idle":"2022-04-20T19:37:23.259788Z","shell.execute_reply.started":"2022-04-20T19:37:23.252348Z","shell.execute_reply":"2022-04-20T19:37:23.258704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn custom image into batch \ncustom_data = create_data_batches(custom_image_paths, test_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.261453Z","iopub.execute_input":"2022-04-20T19:37:23.261919Z","iopub.status.idle":"2022-04-20T19:37:23.283461Z","shell.execute_reply.started":"2022-04-20T19:37:23.2617Z","shell.execute_reply":"2022-04-20T19:37:23.282614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the custom data\ncustom_preds = full_model.predict(custom_data)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.285052Z","iopub.execute_input":"2022-04-20T19:37:23.28547Z","iopub.status.idle":"2022-04-20T19:37:23.464725Z","shell.execute_reply.started":"2022-04-20T19:37:23.285294Z","shell.execute_reply":"2022-04-20T19:37:23.464019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get custom image prediction labels\ncustom_pred_labels = [get_pred_label(custom_preds[i]) for i in range(len(custom_preds))]\ncustom_pred_labels","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.466132Z","iopub.execute_input":"2022-04-20T19:37:23.466424Z","iopub.status.idle":"2022-04-20T19:37:23.475379Z","shell.execute_reply.started":"2022-04-20T19:37:23.466351Z","shell.execute_reply":"2022-04-20T19:37:23.473416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get custom images \ncustom_images = []\n# Loop through unbatched data\nfor image in custom_data.unbatch().as_numpy_iterator():\n  custom_images.append(image)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.477102Z","iopub.execute_input":"2022-04-20T19:37:23.477872Z","iopub.status.idle":"2022-04-20T19:37:23.503931Z","shell.execute_reply.started":"2022-04-20T19:37:23.477825Z","shell.execute_reply":"2022-04-20T19:37:23.503318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check custom image predictions\nplt.figure(figsize=(10, 10))\nfor i, image in enumerate(custom_images):\n  plt.subplot(1, 3, i+1)\n  plt.xticks([])\n  plt.yticks([])\n  plt.title(custom_pred_labels[i])\n  plt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2022-04-20T19:37:23.505318Z","iopub.execute_input":"2022-04-20T19:37:23.505725Z","iopub.status.idle":"2022-04-20T19:37:23.81391Z","shell.execute_reply.started":"2022-04-20T19:37:23.505681Z","shell.execute_reply":"2022-04-20T19:37:23.813131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Thankyou","metadata":{}}]}