{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport tensorflow as tf\nimport tensorflow_hub as hub","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-13T15:39:20.588900Z","iopub.execute_input":"2022-03-13T15:39:20.589355Z","iopub.status.idle":"2022-03-13T15:39:20.594779Z","shell.execute_reply.started":"2022-03-13T15:39:20.589311Z","shell.execute_reply":"2022-03-13T15:39:20.593951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv = pd.read_csv(\"../input/dog-breed-identification/labels.csv\")\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:20.597167Z","iopub.execute_input":"2022-03-13T15:39:20.597676Z","iopub.status.idle":"2022-03-13T15:39:20.657815Z","shell.execute_reply.started":"2022-03-13T15:39:20.597638Z","shell.execute_reply":"2022-03-13T15:39:20.657107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# How many images are there of each breed?\nlabels_csv[\"breed\"].value_counts().plot.bar(figsize = (25,10));","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:20.659248Z","iopub.execute_input":"2022-03-13T15:39:20.659724Z","iopub.status.idle":"2022-03-13T15:39:22.581267Z","shell.execute_reply.started":"2022-03-13T15:39:20.659687Z","shell.execute_reply":"2022-03-13T15:39:22.580588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Getting images and their labels\n\nSince we've got the image ID's and their labels in a DataFrame (labels_csv), we'll use it to create:\n\n* A list a filepaths to training images\n* An array of all labels\n* An array of all unique labels\n\nWe'll only create a list of filepaths to images rather than importing them all to begin with. This is because working with filepaths (strings) is much efficient than working with images.","metadata":{}},{"cell_type":"code","source":"from IPython.display import display,Image\n#Image(\"../input/dog-breed-identification/train/000bec180eb18c7604dcecc8fe0dba07.jpg\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.582956Z","iopub.execute_input":"2022-03-13T15:39:22.583675Z","iopub.status.idle":"2022-03-13T15:39:22.588106Z","shell.execute_reply.started":"2022-03-13T15:39:22.583637Z","shell.execute_reply":"2022-03-13T15:39:22.587316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create pathnames from image ID's\nfilenames = [\"../input/dog-breed-identification/train/\"+fname+\".jpg\" for fname in labels_csv[\"id\"]]\n\n# Check the first 10 filenames\nfilenames[:10]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.589962Z","iopub.execute_input":"2022-03-13T15:39:22.590690Z","iopub.status.idle":"2022-03-13T15:39:22.604081Z","shell.execute_reply.started":"2022-03-13T15:39:22.590649Z","shell.execute_reply":"2022-03-13T15:39:22.603190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.listdir(\"../input/dog-breed-identification/train/\")[:5]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.605153Z","iopub.execute_input":"2022-03-13T15:39:22.607401Z","iopub.status.idle":"2022-03-13T15:39:22.619350Z","shell.execute_reply.started":"2022-03-13T15:39:22.607364Z","shell.execute_reply":"2022-03-13T15:39:22.618689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check whether number of filenames matches number of actual image files\nimport os\nif len(os.listdir(\"../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, check the target directory.\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.620667Z","iopub.execute_input":"2022-03-13T15:39:22.621147Z","iopub.status.idle":"2022-03-13T15:39:22.632379Z","shell.execute_reply.started":"2022-03-13T15:39:22.621108Z","shell.execute_reply":"2022-03-13T15:39:22.631009Z"},"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-03-13T15:39:22.635057Z","iopub.execute_input":"2022-03-13T15:39:22.635252Z","iopub.status.idle":"2022-03-13T15:39:22.648406Z","shell.execute_reply.started":"2022-03-13T15:39:22.635228Z","shell.execute_reply":"2022-03-13T15:39:22.647769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now we've got our image filepaths together, let's get the labels.\n# Take them from labels_csv and turn them into a NumPy array.\n\nlabels = np.array(labels_csv[\"breed\"])\nlabels[:10]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.649574Z","iopub.execute_input":"2022-03-13T15:39:22.650350Z","iopub.status.idle":"2022-03-13T15:39:22.656329Z","shell.execute_reply.started":"2022-03-13T15:39:22.650310Z","shell.execute_reply":"2022-03-13T15:39:22.655571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"we should have the same amount of images and labels.\nFinally, since a machine learning model can't take strings as input (what labels currently is), we'll have to convert our labels to numbers.\nTo begin with, we'll find all of the unique dog breed names.\nThen we'll go through the list of labels and compare them to unique breeds and create a list of booleans indicating which one is the real label (True) and which ones aren't (False).","metadata":{}},{"cell_type":"code","source":"# Find the unique label values\nunique_breeds = np.unique(labels_csv[\"breed\"])\nlen(unique_breeds)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.660834Z","iopub.execute_input":"2022-03-13T15:39:22.661639Z","iopub.status.idle":"2022-03-13T15:39:22.679117Z","shell.execute_reply.started":"2022-03-13T15:39:22.661604Z","shell.execute_reply":"2022-03-13T15:39:22.678205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn every label into a boolean array\n\nboolean_labels = [label == np.array(unique_breeds) for label in labels]\nboolean_labels[:2]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.680244Z","iopub.execute_input":"2022-03-13T15:39:22.681759Z","iopub.status.idle":"2022-03-13T15:39:22.770095Z","shell.execute_reply.started":"2022-03-13T15:39:22.681722Z","shell.execute_reply":"2022-03-13T15:39:22.769354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example: Turning a boolean array into integers\nprint(labels[0])\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))","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.771174Z","iopub.execute_input":"2022-03-13T15:39:22.771701Z","iopub.status.idle":"2022-03-13T15:39:22.779546Z","shell.execute_reply.started":"2022-03-13T15:39:22.771660Z","shell.execute_reply":"2022-03-13T15:39:22.778376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating our own validation set","metadata":{}},{"cell_type":"code","source":"X = filenames\nY = boolean_labels","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.781857Z","iopub.execute_input":"2022-03-13T15:39:22.782581Z","iopub.status.idle":"2022-03-13T15:39:22.788048Z","shell.execute_reply.started":"2022-03-13T15:39:22.782544Z","shell.execute_reply":"2022-03-13T15:39:22.787375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's start experimenting with 1000 and increase it as we need.\n# Set number of images to use for experimenting\nNUM_IMAGES = 1000 ","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.789560Z","iopub.execute_input":"2022-03-13T15:39:22.790041Z","iopub.status.idle":"2022-03-13T15:39:22.796949Z","shell.execute_reply.started":"2022-03-13T15:39:22.790005Z","shell.execute_reply":"2022-03-13T15:39:22.796237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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],Y[:NUM_IMAGES],test_size=0.2,random_state=42)\nlen(X_train) , len(X_val) , len(y_train) , len(y_val)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:22.798371Z","iopub.execute_input":"2022-03-13T15:39:22.798897Z","iopub.status.idle":"2022-03-13T15:39:23.353473Z","shell.execute_reply.started":"2022-03-13T15:39:22.798860Z","shell.execute_reply":"2022-03-13T15:39:23.352783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the training data (image file paths and labels)\nX_train[:2],y_train[:2]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:23.354750Z","iopub.execute_input":"2022-03-13T15:39:23.355140Z","iopub.status.idle":"2022-03-13T15:39:23.361942Z","shell.execute_reply.started":"2022-03-13T15:39:23.355103Z","shell.execute_reply":"2022-03-13T15:39:23.361217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocessing images (turning images into Tensors)\nTo preprocess our images into Tensors , write a function which does a few things:\n\n1. Takes an image filename as input.\n1. Uses TensorFlow to read the file and save it to a variable, image.\n1. Turn our image (a jpeg file) into Tensors.\n1. Resize the image to be of shape (224, 224).\n1. Return the modified image.","metadata":{}},{"cell_type":"code","source":"# Convert image to NumPy array\nfrom matplotlib.pyplot import imread\nimage = imread(filenames[42]) # read in an image\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:23.363333Z","iopub.execute_input":"2022-03-13T15:39:23.363808Z","iopub.status.idle":"2022-03-13T15:39:23.381083Z","shell.execute_reply.started":"2022-03-13T15:39:23.363731Z","shell.execute_reply":"2022-03-13T15:39:23.380462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# convert it to a Tensor using tf.constant().\ntf.constant(image)[:2]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:23.382353Z","iopub.execute_input":"2022-03-13T15:39:23.382828Z","iopub.status.idle":"2022-03-13T15:39:25.646186Z","shell.execute_reply.started":"2022-03-13T15:39:23.382794Z","shell.execute_reply":"2022-03-13T15:39:25.645469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define 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 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, 224)\n    image = tf.image.resize(image,size = [IMG_SIZE,IMG_SIZE])\n    return image","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:25.647395Z","iopub.execute_input":"2022-03-13T15:39:25.647805Z","iopub.status.idle":"2022-03-13T15:39:25.654442Z","shell.execute_reply.started":"2022-03-13T15:39:25.647767Z","shell.execute_reply":"2022-03-13T15:39:25.653707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating data batches","metadata":{}},{"cell_type":"code","source":"# Create a simple function to return a tuple (image, label)\ndef get_image_label(image_path,label):\n    \"\"\"\n  Takes an image file path name and the associated label,\n  processes the image and returns a tuple of (image, label).\n  \"\"\"\n    image = process_image(image_path)\n    return image,label","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:25.657633Z","iopub.execute_input":"2022-03-13T15:39:25.657833Z","iopub.status.idle":"2022-03-13T15:39:25.667421Z","shell.execute_reply.started":"2022-03-13T15:39:25.657809Z","shell.execute_reply":"2022-03-13T15:39:25.666428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the batch size\nBATCH_SIZE=32\n\n# Create a function to turn data into batches\ndef create_data_batches(x,y=None,batch_size=BATCH_SIZE,valid_data=False,test_data=False):\n    \"\"\"\n    create batches of data out of image (x),label (y) pairs\n    Shuffles the data if its training data but doesn't shuffle if its validation data.\n    Also accepts the data as inputs(no labels) \n    \"\"\"\n    \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    elif valid_data:\n        print(\"Creating valid data batches.....\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x), #only filepaths\n                                                  tf.constant(y))) #only labels\n        data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n        return data_batch\n    \n    else:\n        print(\"Creating train data batches\")\n        data = tf.data.Dataset.from_tensor_slices((tf.constant(x),tf.constant(y)))\n        # Shuffling pathnames and labels before mapping image processor function is faster than shuffling images\n        data = data.shuffle(buffer_size=len(x))\n        \n        data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n        return data_batch","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:25.668973Z","iopub.execute_input":"2022-03-13T15:39:25.669511Z","iopub.status.idle":"2022-03-13T15:39:25.679606Z","shell.execute_reply.started":"2022-03-13T15:39:25.669474Z","shell.execute_reply":"2022-03-13T15:39:25.678792Z"},"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-03-13T15:39:25.681070Z","iopub.execute_input":"2022-03-13T15:39:25.681388Z","iopub.status.idle":"2022-03-13T15:39:25.842060Z","shell.execute_reply.started":"2022-03-13T15:39:25.681353Z","shell.execute_reply":"2022-03-13T15:39:25.841337Z"},"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-03-13T15:39:25.843229Z","iopub.execute_input":"2022-03-13T15:39:25.843651Z","iopub.status.idle":"2022-03-13T15:39:25.850408Z","shell.execute_reply.started":"2022-03-13T15:39:25.843615Z","shell.execute_reply":"2022-03-13T15:39:25.849451Z"},"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# Create a function for viewing images in a data batch\n\ndef show_25_images(images,labels):\n    plt.figure(figsize=(10,10))\n    # Loop through 25 \n    for i in range(25):\n        # Create subplots (5 rows, 5 columns)\n        ax=plt.subplot(5,5,i+1)\n        # Display an image\n        plt.imshow(images[i])\n        # Add the image label as the title\n        plt.title(unique_breeds[labels[i].argmax()])\n        # Turn gird lines off\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:25.852124Z","iopub.execute_input":"2022-03-13T15:39:25.852494Z","iopub.status.idle":"2022-03-13T15:39:25.860809Z","shell.execute_reply.started":"2022-03-13T15:39:25.852455Z","shell.execute_reply":"2022-03-13T15:39:25.860038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So to view data in a batch, we've got to unwind it.\n\nWe can do so by calling the `as_numpy_iterator()` method on a data batch.\n\nThis will turn our a data batch into something which can be iterated over.\n\nPassing an iterable to `next()` will return the next item in the iterator.","metadata":{}},{"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-03-13T15:39:25.862266Z","iopub.execute_input":"2022-03-13T15:39:25.862590Z","iopub.status.idle":"2022-03-13T15:39:27.774980Z","shell.execute_reply.started":"2022-03-13T15:39:25.862557Z","shell.execute_reply":"2022-03-13T15:39:27.774369Z"},"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-03-13T15:39:27.776287Z","iopub.execute_input":"2022-03-13T15:39:27.776781Z","iopub.status.idle":"2022-03-13T15:39:29.194981Z","shell.execute_reply.started":"2022-03-13T15:39:27.776734Z","shell.execute_reply":"2022-03-13T15:39:29.194384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating and training a model\n\n* We'll use an existing model from TensorFlow Hub.\n* Using a pretrained machine learning model is often referred to as `transfer learning`.\n*  mobilenet_v2_130_224 model,this model takes an input of images in the shape 224, 224 .The model has been trained in the domain of image classification.\n\n## Building a model\n\nBefore we build a model, there are a few things we need to define:\n\n* The input shape (images, in the form of Tensors) to our model.\n* The output shape (image labels, in the form of Tensors) of our model.\n* The URL of the model we want to use.","metadata":{}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None,IMG_SIZE,IMG_SIZE,3] #batch,height,width,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/5\"","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:29.196289Z","iopub.execute_input":"2022-03-13T15:39:29.196762Z","iopub.status.idle":"2022-03-13T15:39:29.201394Z","shell.execute_reply.started":"2022-03-13T15:39:29.196721Z","shell.execute_reply":"2022-03-13T15:39:29.200574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's create a function which:\n\n* Takes the input shape, output shape and the model we've chosen's URL as parameters.\n* Defines the layers in a Keras model in a sequential fashion (do this first, then this, then that).\n* Compiles the model (says how it should be evaluated and improved).\n* Builds the model (tells it what kind of input shape it'll be getting).\n* Returns the model.","metadata":{}},{"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 a model with:\",MODEL_URL)\n    \n    # Setup the model layers\n    model = tf.keras.Sequential([\n        hub.KerasLayer(MODEL_URL), #Layer1 (input layer)\n        tf.keras.layers.Dense(units=OUTPUT_SHAPE,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-03-13T15:39:29.207646Z","iopub.execute_input":"2022-03-13T15:39:29.208128Z","iopub.status.idle":"2022-03-13T15:39:29.215624Z","shell.execute_reply.started":"2022-03-13T15:39:29.208081Z","shell.execute_reply":"2022-03-13T15:39:29.214906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"What's happening here?\n### Setting up the model layers\n\nThe first layer we use is the model from TensorFlow Hub `hub.KerasLayer(MODEL_URL)`. So our first layer is actually an entire model (many more layers). This **input layer** takes in our images and finds patterns in them based on the patterns `mobilenet_v2_130_224` has found.\n\nThe next layer (`tf.keras.layers.Dense()`) is the **output layer** of our model. It brings all of the information discovered in the input layer together and outputs it in the shape we're after, 120 (the number of unique labels we have).\n\nThe `activation=\"softmax\"` parameter tells the output layer, we'd like to assign a probability value to each of the 120 labels somewhere between 0 & 1. The higher the value, the more the model believes the input image should have that label. If we were working on a binary classification problem, we'd use `activation=\"sigmoid\"`.\n\n### Compiling the model\n\n* **loss** - Getting to 0 means the model is learning perfectly.\n* **optimizer** -Adam is the optimizer,the one telling you how to lower the loss function.Other optimizers include RMSprop and Stochastic Gradient Descent.\n* **metrics** - Giving the accuracy of how well our model is predicting the correct image label.\n\n### Building the model\n\nWe use `model.build()` whenever we're using a layer from TensorFlow Hub to tell our model what input shape it can expect.\n\nIn this case, the input shape is **[None, IMG_SIZE, IMG_SIZE, 3] or [None, 224, 224, 3] or [batch_size, img_height, img_width, color_channels]**.\n\nBatch size is left as `None` as this is inferred from the data we pass the model. In our case, it'll be 32.\n\nWe can call `summary()` on our model to get idea of what our model looks like.\n\nThe non-trainable parameters are the patterns learned by `mobilenet_v2_130_224` and the trainable parameters are the ones in the dense layer.","metadata":{}},{"cell_type":"code","source":"# Create a model and check its details\nmodel = create_model()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:29.217047Z","iopub.execute_input":"2022-03-13T15:39:29.217514Z","iopub.status.idle":"2022-03-13T15:39:36.185964Z","shell.execute_reply.started":"2022-03-13T15:39:29.217477Z","shell.execute_reply":"2022-03-13T15:39:36.185192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating 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\n### Early Stopping Callback\n\nEarly stopping helps prevent overfitting by stopping a model when a certain evaluation metric stops improving. If a model trains for too long, it can do so well at finding patterns in a certain dataset that it's not able to use those patterns on another dataset it hasn't seen before (doesn't generalize).","metadata":{}},{"cell_type":"code","source":"# Create early stopping (once our model stops improving, stop training)\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-03-13T15:39:36.187170Z","iopub.execute_input":"2022-03-13T15:39:36.187539Z","iopub.status.idle":"2022-03-13T15:39:36.194599Z","shell.execute_reply.started":"2022-03-13T15:39:36.187484Z","shell.execute_reply":"2022-03-13T15:39:36.193861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training a model(subset of 1000 images)","metadata":{}},{"cell_type":"code","source":"# How many rounds should we get the model to look through the data?\nNUM_EPOCHS = 100","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:36.195991Z","iopub.execute_input":"2022-03-13T15:39:36.196264Z","iopub.status.idle":"2022-03-13T15:39:36.204778Z","shell.execute_reply.started":"2022-03-13T15:39:36.196227Z","shell.execute_reply":"2022-03-13T15:39:36.204018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Build a function to train and return a trained model\ndef train_model():\n    \"\"\"\n  Trains a given model and returns the trained version.\n  \"\"\"\n    # create a model\n    model = create_model()\n    \n    # Fit the model to the data passing it the callbacks we created\n    \n    model.fit(x=train_data,\n             epochs=NUM_EPOCHS,\n             validation_data=val_data,\n             validation_freq=1, # check validation metrics every epoch\n             callbacks = [early_stopping])\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:36.206316Z","iopub.execute_input":"2022-03-13T15:39:36.207027Z","iopub.status.idle":"2022-03-13T15:39:36.214580Z","shell.execute_reply.started":"2022-03-13T15:39:36.206917Z","shell.execute_reply":"2022-03-13T15:39:36.213844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the model to the data\nmodel = train_model()","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:39:36.216211Z","iopub.execute_input":"2022-03-13T15:39:36.216844Z","iopub.status.idle":"2022-03-13T15:40:43.203156Z","shell.execute_reply.started":"2022-03-13T15:39:36.216803Z","shell.execute_reply":"2022-03-13T15:40:43.202382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making and evaluating predictions using a trained model","metadata":{}},{"cell_type":"code","source":"# Make predictions on the validation data\n\npredictions = model.predict(val_data,verbose=1) # verbose shows us how long there is to go\npredictions","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:43.204846Z","iopub.execute_input":"2022-03-13T15:40:43.205103Z","iopub.status.idle":"2022-03-13T15:40:44.457168Z","shell.execute_reply.started":"2022-03-13T15:40:43.205068Z","shell.execute_reply":"2022-03-13T15:40:44.456515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the shape of predictions\npredictions.shape","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:44.458448Z","iopub.execute_input":"2022-03-13T15:40:44.458738Z","iopub.status.idle":"2022-03-13T15:40:44.464356Z","shell.execute_reply.started":"2022-03-13T15:40:44.458702Z","shell.execute_reply":"2022-03-13T15:40:44.463584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In this case, making predictions on the validation data (200 images) returns an array (predictions) of arrays, each containing 120 different values (one for each unique dog breed).\n\nThese different values are the probabilities or the likelihood the model has predicted a certain image being a certain breed of dog. ","metadata":{}},{"cell_type":"code","source":"# First prediction\nprint(predictions[0])\nprint(f\",max value (probability of predictions): {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])]}\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:44.465805Z","iopub.execute_input":"2022-03-13T15:40:44.466370Z","iopub.status.idle":"2022-03-13T15:40:44.477737Z","shell.execute_reply.started":"2022-03-13T15:40:44.466334Z","shell.execute_reply":"2022-03-13T15:40:44.476855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn prediction probabilities into their respective label (easier to understand)\ndef get_pred_label(prediction_probabilities):\n    \"\"\"\n  Turns an array of prediction probabilities into a label.\n  \"\"\"\n    return unique_breeds[np.argmax(prediction_probabilities)]\n\n# Get a predicted label based on an array of prediction probabilities\n\npred_label = get_pred_label(predictions[0])\npred_label","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:44.479210Z","iopub.execute_input":"2022-03-13T15:40:44.479541Z","iopub.status.idle":"2022-03-13T15:40:44.488557Z","shell.execute_reply.started":"2022-03-13T15:40:44.479486Z","shell.execute_reply":"2022-03-13T15:40:44.487673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since our validation data (`val_data`) is in batch form, to get a list of validation images and labels, we'll have to unbatch it (`using unbatch()`) and then turn it into an iterator using `as_numpy_iterator()`","metadata":{}},{"cell_type":"code","source":"# Create a function to unbatch a batched dataset\ndef unbatchify(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    # Loop through unbatched data\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                  \n                      \n# Unbatchify the validation data\n    \nval_images,val_labels = unbatchify(val_data)\nval_images[0],val_labels[0]                      ","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:44.489860Z","iopub.execute_input":"2022-03-13T15:40:44.490342Z","iopub.status.idle":"2022-03-13T15:40:44.966504Z","shell.execute_reply.started":"2022-03-13T15:40:44.490304Z","shell.execute_reply":"2022-03-13T15:40:44.965852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The first function will:\n\n* Take an array of prediction probabilities, an array of truth labels, an array of images and an integer.\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":{}},{"cell_type":"code","source":"def plot_pred(prediction_probabilities, labels, images, n=8):\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.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-03-13T15:40:44.967964Z","iopub.execute_input":"2022-03-13T15:40:44.968262Z","iopub.status.idle":"2022-03-13T15:40:44.974872Z","shell.execute_reply.started":"2022-03-13T15:40:44.968227Z","shell.execute_reply":"2022-03-13T15:40:44.974069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View an example prediction, original image and truth label\nplot_pred(prediction_probabilities=predictions,labels=val_labels,images=val_images)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:44.976584Z","iopub.execute_input":"2022-03-13T15:40:44.976928Z","iopub.status.idle":"2022-03-13T15:40:45.100018Z","shell.execute_reply.started":"2022-03-13T15:40:44.976889Z","shell.execute_reply":"2022-03-13T15:40:45.099350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The function will:\n\n* Take an input of a prediction probabilities array, a ground truth labels array and an integer.\n* Find the predicted label using get_pred_label().\n* Find the top 10:\n  * Prediction probabilities indexes\n  * Prediction probabilities values\n  * Prediction labels\n* Plot the top 10 prediction probability values and labels, coloring the true label green.","metadata":{}},{"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    \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    \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\n    ","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:45.101654Z","iopub.execute_input":"2022-03-13T15:40:45.102222Z","iopub.status.idle":"2022-03-13T15:40:45.112661Z","shell.execute_reply.started":"2022-03-13T15:40:45.102188Z","shell.execute_reply":"2022-03-13T15:40:45.111921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities = predictions,labels=val_labels,n=9)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:45.114016Z","iopub.execute_input":"2022-03-13T15:40:45.114498Z","iopub.status.idle":"2022-03-13T15:40:45.346871Z","shell.execute_reply.started":"2022-03-13T15:40:45.114461Z","shell.execute_reply":"2022-03-13T15:40:45.346177Z"},"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    \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-03-13T15:40:45.347958Z","iopub.execute_input":"2022-03-13T15:40:45.348497Z","iopub.status.idle":"2022-03-13T15:40:47.091005Z","shell.execute_reply.started":"2022-03-13T15:40:45.348457Z","shell.execute_reply":"2022-03-13T15:40:47.090397Z"},"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    print(\"Saving model...\")\n    model.save(\"model_\"+suffix+\".h5\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:47.092163Z","iopub.execute_input":"2022-03-13T15:40:47.094684Z","iopub.status.idle":"2022-03-13T15:40:47.099175Z","shell.execute_reply.started":"2022-03-13T15:40:47.094635Z","shell.execute_reply":"2022-03-13T15:40:47.098375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(model_path):\n    print(\"Loading saved model......\")\n    model = tf.keras.models.load_model(model_path,\n                                      custom_objects={\"KerasLayer\":hub.KerasLayer})\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:47.100745Z","iopub.execute_input":"2022-03-13T15:40:47.101797Z","iopub.status.idle":"2022-03-13T15:40:47.109930Z","shell.execute_reply.started":"2022-03-13T15:40:47.101754Z","shell.execute_reply":"2022-03-13T15:40:47.109032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save our model trained on 1000 images\nsave_model(model,suffix=\"1000-images-Adam\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:47.111630Z","iopub.execute_input":"2022-03-13T15:40:47.112704Z","iopub.status.idle":"2022-03-13T15:40:47.337658Z","shell.execute_reply.started":"2022-03-13T15:40:47.112666Z","shell.execute_reply":"2022-03-13T15:40:47.336956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load our model trained on 1000 images\nmodel_1000_images = load_model(\"./model_1000-images-Adam.h5\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:47.340375Z","iopub.execute_input":"2022-03-13T15:40:47.340693Z","iopub.status.idle":"2022-03-13T15:40:49.168887Z","shell.execute_reply.started":"2022-03-13T15:40:47.340661Z","shell.execute_reply":"2022-03-13T15:40:49.168003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the pre-saved model\nmodel.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:49.170355Z","iopub.execute_input":"2022-03-13T15:40:49.170605Z","iopub.status.idle":"2022-03-13T15:40:49.688058Z","shell.execute_reply.started":"2022-03-13T15:40:49.170570Z","shell.execute_reply":"2022-03-13T15:40:49.687372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the loaded model\nmodel_1000_images.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:49.689484Z","iopub.execute_input":"2022-03-13T15:40:49.689747Z","iopub.status.idle":"2022-03-13T15:40:50.779236Z","shell.execute_reply.started":"2022-03-13T15:40:49.689713Z","shell.execute_reply":"2022-03-13T15:40:50.778414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training a model (on the full data)","metadata":{}},{"cell_type":"code","source":"len(X), len(Y)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:50.781482Z","iopub.execute_input":"2022-03-13T15:40:50.782006Z","iopub.status.idle":"2022-03-13T15:40:50.787079Z","shell.execute_reply.started":"2022-03-13T15:40:50.781964Z","shell.execute_reply":"2022-03-13T15:40:50.786333Z"},"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-03-13T15:40:50.788539Z","iopub.execute_input":"2022-03-13T15:40:50.789061Z","iopub.status.idle":"2022-03-13T15:40:50.902906Z","shell.execute_reply.started":"2022-03-13T15:40:50.789025Z","shell.execute_reply":"2022-03-13T15:40:50.902219Z"},"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-03-13T15:40:50.904129Z","iopub.execute_input":"2022-03-13T15:40:50.904356Z","iopub.status.idle":"2022-03-13T15:40:52.588191Z","shell.execute_reply.started":"2022-03-13T15:40:50.904326Z","shell.execute_reply":"2022-03-13T15:40:52.587454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create full model callbacks\n# Early stopping callback\n# Note: No validation set when training on all the data, therefore can't monitor validation accruacy\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"accuracy\",patience=3)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:52.589421Z","iopub.execute_input":"2022-03-13T15:40:52.589693Z","iopub.status.idle":"2022-03-13T15:40:52.595119Z","shell.execute_reply.started":"2022-03-13T15:40:52.589649Z","shell.execute_reply":"2022-03-13T15:40:52.594312Z"},"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_early_stopping])","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:40:52.596578Z","iopub.execute_input":"2022-03-13T15:40:52.596859Z","iopub.status.idle":"2022-03-13T15:52:45.064069Z","shell.execute_reply.started":"2022-03-13T15:40:52.596822Z","shell.execute_reply":"2022-03-13T15:52:45.063369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving and reloading the full model","metadata":{}},{"cell_type":"code","source":"# Save model to file\nsave_model(full_model,suffix=\"all-image-Adam\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:52:45.065374Z","iopub.execute_input":"2022-03-13T15:52:45.065722Z","iopub.status.idle":"2022-03-13T15:52:45.275072Z","shell.execute_reply.started":"2022-03-13T15:52:45.065678Z","shell.execute_reply":"2022-03-13T15:52:45.274350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load in the full model\nloaded_full_model = load_model(\"./model_all-image-Adam.h5\")","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:52:45.276652Z","iopub.execute_input":"2022-03-13T15:52:45.276907Z","iopub.status.idle":"2022-03-13T15:52:47.153182Z","shell.execute_reply.started":"2022-03-13T15:52:45.276871Z","shell.execute_reply":"2022-03-13T15:52:47.152372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making predictions on the test dataset\n\nTo make predictions on the test data, we'll:\n\n* Get the test image filenames.\n* Convert the filenames into test data batches using `create_data_batches()` and setting the `test_data` parameter to True (since there are no labels with the test images).\n* Make a predictions array by passing the test data batches to the `predict()` function.","metadata":{}},{"cell_type":"code","source":"test_filenames = [\"../input/dog-breed-identification/test/\"+fname for fname in os.listdir(\"../input/dog-breed-identification/test\")]\ntest_filenames[:10]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:52:47.154615Z","iopub.execute_input":"2022-03-13T15:52:47.154909Z","iopub.status.idle":"2022-03-13T15:52:47.695159Z","shell.execute_reply.started":"2022-03-13T15:52:47.154873Z","shell.execute_reply":"2022-03-13T15:52:47.694416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# How many test images are there?\nlen(test_filenames)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:52:47.696458Z","iopub.execute_input":"2022-03-13T15:52:47.696738Z","iopub.status.idle":"2022-03-13T15:52:47.701795Z","shell.execute_reply.started":"2022-03-13T15:52:47.696701Z","shell.execute_reply":"2022-03-13T15:52:47.701116Z"},"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-03-13T15:52:47.703234Z","iopub.execute_input":"2022-03-13T15:52:47.703636Z","iopub.status.idle":"2022-03-13T15:52:47.725206Z","shell.execute_reply.started":"2022-03-13T15:52:47.703599Z","shell.execute_reply":"2022-03-13T15:52:47.724496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on test data batch using the loaded full model\ntest_predictions = loaded_full_model.predict(test_data,\n                                             verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:52:47.726487Z","iopub.execute_input":"2022-03-13T15:52:47.726912Z","iopub.status.idle":"2022-03-13T15:54:10.012041Z","shell.execute_reply.started":"2022-03-13T15:52:47.726874Z","shell.execute_reply":"2022-03-13T15:54:10.011258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the test predictions\ntest_predictions[:1]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T15:54:10.013457Z","iopub.execute_input":"2022-03-13T15:54:10.013728Z","iopub.status.idle":"2022-03-13T15:54:10.021573Z","shell.execute_reply.started":"2022-03-13T15:54:10.013693Z","shell.execute_reply":"2022-03-13T15:54:10.020731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making predictions on custom images\n\nIf we want to make predictions on our own custom images, we have to pass them to the model in the same format the model was trained on.\n\nTo do so, we'll:\n\nGet the filepaths of our own images.\nTurn the filepaths into data batches using `create_data_batches()`. And since our custom images won't have labels, we set the `test_data` parameter to `True`.\nPass the custom image data batch to our model's `predict()` method.\nConvert the prediction output probabilities to prediction labels.\nCompare the predicted labels to the custom images.","metadata":{}},{"cell_type":"code","source":"# Get custom image filepaths\ncustom_filenames = [\"../input/dogimages2/\"+fname for fname in os.listdir(\"../input/dogimages2\")]\ncustom_filenames[:3]","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:02:46.953664Z","iopub.execute_input":"2022-03-13T16:02:46.953966Z","iopub.status.idle":"2022-03-13T16:02:46.961281Z","shell.execute_reply.started":"2022-03-13T16:02:46.953933Z","shell.execute_reply":"2022-03-13T16:02:46.960412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn custom image into batch (set to test data because there are no labels)\ncustom_data = create_data_batches(custom_filenames, test_data=True)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:02:48.215662Z","iopub.execute_input":"2022-03-13T16:02:48.216253Z","iopub.status.idle":"2022-03-13T16:02:48.233479Z","shell.execute_reply.started":"2022-03-13T16:02:48.216216Z","shell.execute_reply":"2022-03-13T16:02:48.232749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the custom data\ncustom_preds = loaded_full_model.predict(custom_data)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:02:49.435044Z","iopub.execute_input":"2022-03-13T16:02:49.435682Z","iopub.status.idle":"2022-03-13T16:02:49.659202Z","shell.execute_reply.started":"2022-03-13T16:02:49.435641Z","shell.execute_reply":"2022-03-13T16:02:49.658447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get custom image prediction labels\ncustom_preds_labels = [get_pred_label(custom_preds[i]) for i in range(len(custom_preds))] ","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:02:59.743933Z","iopub.execute_input":"2022-03-13T16:02:59.744186Z","iopub.status.idle":"2022-03-13T16:02:59.748571Z","shell.execute_reply.started":"2022-03-13T16:02:59.744158Z","shell.execute_reply":"2022-03-13T16:02:59.747309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get custom images\ncustom_images=[]\n# Loop through unbatched data\nfor images in custom_data.unbatch().as_numpy_iterator():\n    custom_images.append(images)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:05:35.201977Z","iopub.execute_input":"2022-03-13T16:05:35.202259Z","iopub.status.idle":"2022-03-13T16:05:35.292018Z","shell.execute_reply.started":"2022-03-13T16:05:35.202227Z","shell.execute_reply":"2022-03-13T16:05:35.291140Z"},"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_preds_labels[i])\n    plt.imshow(image)","metadata":{"execution":{"iopub.status.busy":"2022-03-13T16:05:35.772431Z","iopub.execute_input":"2022-03-13T16:05:35.772711Z","iopub.status.idle":"2022-03-13T16:05:36.033098Z","shell.execute_reply.started":"2022-03-13T16:05:35.772681Z","shell.execute_reply":"2022-03-13T16:05:36.032455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}