{"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":"Transfer Learning and TensorFlow 2.0 to Classify Different Dog Breeds\n\n\n\n\nIn this project we're going to be using deep learning to help us identify different breeds of dogs.\n\nTo do this, we'll be using data from the [Kaggle dog breed identification competition](https://www.kaggle.com/c/dog-breed-identification/overview).\n\nIt is an example of multi class classification.\n\nSince the most important step in a deep learng problem is getting the data ready (turning it into numbers), that's what we're going to start with.\n\nWe're going to go through the following TensorFlow/Deep Learning workflow:\n1. Get data ready (download from Kaggle, store, import).\n2. Prepare the data (preprocessing, the 3 sets, X & y).\n3. Choosing a model.\n4. Evaluating a model.\n5. Improve the model through experimentation (start with 1000 images, make sure it works, increase the number of images).\n","metadata":{"id":"SZeHfjvj5xcp"}},{"cell_type":"code","source":"# import and check tensorflow\nimport tensorflow as tf\nprint(\"TF version:\", tf.__version__)","metadata":{"id":"YZUgBfHx6Vex","outputId":"02906eb6-8ed6-453c-e700-a34f31013128","execution":{"iopub.status.busy":"2021-07-03T13:56:13.215616Z","iopub.execute_input":"2021-07-03T13:56:13.216088Z","iopub.status.idle":"2021-07-03T13:56:19.442885Z","shell.execute_reply.started":"2021-07-03T13:56:13.215984Z","shell.execute_reply":"2021-07-03T13:56:19.441931Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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\nif tf.config.list_physical_devices(\"GPU\"):\n    print(\"GPU is available\")\nelse:\n    print(\"not available\")","metadata":{"id":"wJ325_fg7QZg","outputId":"bbc89338-c600-45cb-cf64-1468c2be105a","execution":{"iopub.status.busy":"2021-07-03T13:57:04.096734Z","iopub.execute_input":"2021-07-03T13:57:04.097073Z","iopub.status.idle":"2021-07-03T13:57:04.106722Z","shell.execute_reply.started":"2021-07-03T13:57:04.097043Z","shell.execute_reply":"2021-07-03T13:57:04.103362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n### Accessing the data\n\nImport the labels.csv file","metadata":{"id":"4jWoK2aBGmZI"}},{"cell_type":"code","source":"\nimport pandas as pd\nlabels = pd.read_csv(\"../input/dog-breed-identification/labels.csv\")\nprint(labels.head())","metadata":{"id":"lv1Ayf1qGrI6","outputId":"c5a97df7-3384-49a9-ed02-d63efc8ffd5f","execution":{"iopub.status.busy":"2021-07-03T13:57:27.345854Z","iopub.execute_input":"2021-07-03T13:57:27.346181Z","iopub.status.idle":"2021-07-03T13:57:27.383487Z","shell.execute_reply.started":"2021-07-03T13:57:27.346152Z","shell.execute_reply":"2021-07-03T13:57:27.382502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Looking at this, we can see there are 10222 different ID's (meaning 10222 different images) and 120 different breeds.\n\nLet's figure out how many images there are of each breed.","metadata":{"id":"04sOtsyUHduj"}},{"cell_type":"code","source":"#columns of the labels.csv file\nlabels.columns","metadata":{"id":"jfH_jx6lIZbF","outputId":"dfe33b4b-5855-493d-db32-e3b899ad9962","execution":{"iopub.status.busy":"2021-07-03T13:57:29.719782Z","iopub.execute_input":"2021-07-03T13:57:29.720136Z","iopub.status.idle":"2021-07-03T13:57:29.728575Z","shell.execute_reply.started":"2021-07-03T13:57:29.720105Z","shell.execute_reply":"2021-07-03T13:57:29.727197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#displaying an image from the data\nfrom IPython.display import display, Image\nImage(\"../input/dog-breed-identification/train/001cdf01b096e06d78e9e5112d419397.jpg\")","metadata":{"id":"0wt_Vy3BKfjI","execution":{"iopub.status.busy":"2021-07-03T13:57:52.850124Z","iopub.execute_input":"2021-07-03T13:57:52.850501Z","iopub.status.idle":"2021-07-03T13:57:52.868883Z","shell.execute_reply.started":"2021-07-03T13:57:52.850469Z","shell.execute_reply":"2021-07-03T13:57:52.867900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Images and labels\n\nCreating list of images from their label IDs ","metadata":{"id":"ZbYs5TX6L8hK"}},{"cell_type":"code","source":"# Creating pathnames\nfilenames = []\nfor name in labels[\"id\"]:\n    filenames.append(\"../input/dog-breed-identification/train/\" + name + \".jpg\")\n\n# Check the first 10 filenames\nfilenames[:10]","metadata":{"id":"v7fpANVoRnGr","outputId":"4b106483-5600-423d-fbd4-cc940527bbb5","execution":{"iopub.status.busy":"2021-07-03T13:58:05.470939Z","iopub.execute_input":"2021-07-03T13:58:05.471313Z","iopub.status.idle":"2021-07-03T13:58:05.484087Z","shell.execute_reply.started":"2021-07-03T13:58:05.471244Z","shell.execute_reply":"2021-07-03T13:58:05.483016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Check if all files are complete","metadata":{"id":"ZQa1N8cLSAMk"}},{"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(\"There are no missing files.\")\nelse:\n  print(\"Files missing\")","metadata":{"id":"zX1Ll_QbR9sF","outputId":"f3a2ed2b-86c6-40f3-a4b1-ef02de75b50c","execution":{"iopub.status.busy":"2021-07-03T13:58:17.464954Z","iopub.execute_input":"2021-07-03T13:58:17.465350Z","iopub.status.idle":"2021-07-03T13:58:17.644347Z","shell.execute_reply.started":"2021-07-03T13:58:17.465296Z","shell.execute_reply":"2021-07-03T13:58:17.643447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualizing one of the images from the created list","metadata":{"id":"NaMGkX_jSmTn"}},{"cell_type":"code","source":"# Check an image directly from a filepath\nImage(filenames[60])","metadata":{"id":"JbzZjkoKS9u0","outputId":"dd824271-8fe7-41f1-d61d-e7aaca2d03e0","execution":{"iopub.status.busy":"2021-07-03T13:58:20.318077Z","iopub.execute_input":"2021-07-03T13:58:20.318416Z","iopub.status.idle":"2021-07-03T13:58:20.331132Z","shell.execute_reply.started":"2021-07-03T13:58:20.318384Z","shell.execute_reply":"2021-07-03T13:58:20.330236Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Cute!\n\nNow we've got our image filepaths together, let's get the labels.\n\nWe'll take them from `labels_csv` and turn them into a NumPy array.","metadata":{"id":"lv7aNWb5TR-N"}},{"cell_type":"code","source":"import numpy as np\nlabel = labels[\"breed\"].to_numpy() # convert labels column to NumPy array\nlabel[:10]","metadata":{"id":"H9pYpJBpTD7w","outputId":"eb2113c4-4e21-453f-e96a-4379cf53e740","execution":{"iopub.status.busy":"2021-07-03T13:58:32.718751Z","iopub.execute_input":"2021-07-03T13:58:32.719099Z","iopub.status.idle":"2021-07-03T13:58:32.725585Z","shell.execute_reply.started":"2021-07-03T13:58:32.719067Z","shell.execute_reply":"2021-07-03T13:58:32.724350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Wonderful, now lets do the same thing as before, compare the amount of labels to number of filenames.","metadata":{"id":"pjXvS4nXTn10"}},{"cell_type":"code","source":"# See if number of labels matches the number of filenames\nif len(label) == len(filenames):\n  print(\"Exact number of files\")\nelse:\n  print(\"Some files are missing\")","metadata":{"id":"9P0InW71TmIQ","outputId":"8c4f854b-d79a-4f23-e791-df19d9eb8147","execution":{"iopub.status.busy":"2021-07-03T13:58:35.328856Z","iopub.execute_input":"2021-07-03T13:58:35.329209Z","iopub.status.idle":"2021-07-03T13:58:35.334342Z","shell.execute_reply.started":"2021-07-03T13:58:35.329170Z","shell.execute_reply":"2021-07-03T13:58:35.333297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the number of unique label\nunique = np.unique(label)\nlen(unique)","metadata":{"id":"5K6Oul0uUq4f","outputId":"0d9cdb73-d935-46eb-c5a3-98478a60b0ba","execution":{"iopub.status.busy":"2021-07-03T13:58:36.046923Z","iopub.execute_input":"2021-07-03T13:58:36.047403Z","iopub.status.idle":"2021-07-03T13:58:36.073009Z","shell.execute_reply.started":"2021-07-03T13:58:36.047355Z","shell.execute_reply":"2021-07-03T13:58:36.072094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Converting array of numbers to boolean array","metadata":{"id":"zF5MILPDU0ut"}},{"cell_type":"markdown","source":"That's for one example, let's do the whole thing.","metadata":{"id":"7DQhiXJ9VWeZ"}},{"cell_type":"code","source":"# Turn every label into a boolean array\nboolean_label = [element == np.array(unique) for element in label]\nboolean_label[:1]","metadata":{"id":"7Iq3n1SzVVk_","outputId":"c2ba05ac-e80b-4813-cc36-5f02ca59d0f0","execution":{"iopub.status.busy":"2021-07-03T13:58:38.963631Z","iopub.execute_input":"2021-07-03T13:58:38.963956Z","iopub.status.idle":"2021-07-03T13:58:39.070214Z","shell.execute_reply.started":"2021-07-03T13:58:38.963926Z","shell.execute_reply":"2021-07-03T13:58:39.069322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(label[0]) # original label\nprint(np.where(unique == label[0])[0][0]) # index where label occurs in the number array\nprint(boolean_label[0].argmax()) # index where label occurs in boolean array\nprint(boolean_label[0].astype(int))","metadata":{"id":"O4nTwfC9WDn7","outputId":"d1b771aa-814a-496a-9a47-a7d852cfe629","execution":{"iopub.status.busy":"2021-07-03T13:58:39.940916Z","iopub.execute_input":"2021-07-03T13:58:39.941251Z","iopub.status.idle":"2021-07-03T13:58:39.954235Z","shell.execute_reply.started":"2021-07-03T13:58:39.941221Z","shell.execute_reply":"2021-07-03T13:58:39.953066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating our own validation set\n\nUsing scikit learn train_test_split to split the data into train and validation set.","metadata":{"id":"jwsmgI0qUID4"}},{"cell_type":"code","source":"# Setup X & y variables\nx = filenames\ny = boolean_label","metadata":{"id":"ylTZ5QsV8jyX","execution":{"iopub.status.busy":"2021-07-03T13:58:42.419573Z","iopub.execute_input":"2021-07-03T13:58:42.419953Z","iopub.status.idle":"2021-07-03T13:58:42.423949Z","shell.execute_reply.started":"2021-07-03T13:58:42.419923Z","shell.execute_reply":"2021-07-03T13:58:42.422887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Starting with 1000 images","metadata":{"id":"87JOLRkX_qVI"}},{"cell_type":"code","source":"# Set number of images to use\nNUM_IMAGES = 1000\n","metadata":{"id":"-iUUiacU_8ey","outputId":"ca860055-f980-44e7-9685-ef3247cc92ef","execution":{"iopub.status.busy":"2021-07-03T13:58:44.251347Z","iopub.execute_input":"2021-07-03T13:58:44.251698Z","iopub.status.idle":"2021-07-03T13:58:44.255726Z","shell.execute_reply.started":"2021-07-03T13:58:44.251661Z","shell.execute_reply":"2021-07-03T13:58:44.254638Z"},"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":{"id":"lQ6nPdYdBHMs"}},{"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":{"id":"s6RNwMv3BD7N","outputId":"9984b352-f9f6-438f-e673-03d3182e194f","execution":{"iopub.status.busy":"2021-07-03T13:58:46.362509Z","iopub.execute_input":"2021-07-03T13:58:46.362848Z","iopub.status.idle":"2021-07-03T13:58:46.939643Z","shell.execute_reply.started":"2021-07-03T13:58:46.362818Z","shell.execute_reply":"2021-07-03T13:58:46.938559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Turning images into Tensors\n\nDefine a function that:\n1. Takes an image filename as input.\n2. Uses TensorFlow to read the file and save it to a variable, `image`.\n3. Turn our `image` into Tensors.\n4. Resize the `image` to be of shape (224, 224).\n5. Return the modified `image`.","metadata":{"id":"BrvNClHWUMPP"}},{"cell_type":"code","source":"# Convert image to NumPy array\nfrom matplotlib.pyplot import imread\nimage = imread(filenames[1])\nimage.shape# read in an image","metadata":{"id":"cvq4aLj8D_yX","outputId":"eb904f48-1e67-4cd0-ee8d-0f5101386e99","execution":{"iopub.status.busy":"2021-07-03T13:58:51.258350Z","iopub.execute_input":"2021-07-03T13:58:51.258705Z","iopub.status.idle":"2021-07-03T13:58:51.285074Z","shell.execute_reply.started":"2021-07-03T13:58:51.258673Z","shell.execute_reply":"2021-07-03T13:58:51.283949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"3 is the height of the image (red,green,blue)","metadata":{"id":"TONbcNvQGkbu"}},{"cell_type":"code","source":"tf.constant(image)[:1]","metadata":{"id":"4WvOdwIcG3eS","outputId":"876010f0-dacc-4b19-b93f-bfde1468b6dc","execution":{"iopub.status.busy":"2021-07-03T13:58:52.965419Z","iopub.execute_input":"2021-07-03T13:58:52.965743Z","iopub.status.idle":"2021-07-03T13:58:54.585802Z","shell.execute_reply.started":"2021-07-03T13:58:52.965712Z","shell.execute_reply":"2021-07-03T13:58:54.584708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define image dimension\nIMG_SIZE = 224\n\ndef process(image_path):\n  \n  # Read in image file\n  image = tf.io.read_file(image_path)\n\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\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\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":{"id":"ezyHapaOG48I","execution":{"iopub.status.busy":"2021-07-03T13:58:54.855798Z","iopub.execute_input":"2021-07-03T13:58:54.856156Z","iopub.status.idle":"2021-07-03T13:58:54.862468Z","shell.execute_reply.started":"2021-07-03T13:58:54.856124Z","shell.execute_reply":"2021-07-03T13:58:54.861210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating data batches\n\nIn deep learning, instead of finding patterns in an entire dataset at the same time, you often find them one batch at a time.\nHere we will create batches of size 32.","metadata":{"id":"KzAWUUFlPJMe"}},{"cell_type":"code","source":"# Creating function to return a tuple (image, label)\ndef image_label(path, label):\n \n  image = process(path)\n  return image, label","metadata":{"id":"KXSG48e9PCAX","execution":{"iopub.status.busy":"2021-07-03T13:58:57.168367Z","iopub.execute_input":"2021-07-03T13:58:57.168705Z","iopub.status.idle":"2021-07-03T13:58:57.173014Z","shell.execute_reply.started":"2021-07-03T13:58:57.168675Z","shell.execute_reply":"2021-07-03T13:58:57.171764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# defining batch dimensions\nBATCH = 32\n\n# Create a function to turn data into batches\ndef data_batches(x, y=None, batch_size=BATCH , valid_data=False, test_data=False):\n    \n  # If the data is a test dataset\n  if test_data:\n    print(\"Test data batches created\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x))) # only filepaths\n    data_batch = data.map(process).batch(BATCH)\n    return data_batch\n  \n  # If the data if a valid dataset\n  elif valid_data:\n    \n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                               tf.constant(y))) # labels\n    data_batch = data.map(image_label).batch(BATCH)\n    print(\"Validation data batches created\")\n    return data_batch\n\n  else:\n    # If the data is a training dataset, we shuffle it\n    \n    # Turn filepaths and labels into Tensors\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                              tf.constant(y))) # labels\n    \n    # Shuffling pathnames and labels\n    data = data.shuffle(buffer_size=len(x))\n\n    # Create (image, label) tuples\n    data = data.map(image_label)\n\n    # Turn the data into batches\n    data_batch = data.batch(BATCH)\n    print(\"Training data batches created\")\n  return data_batch","metadata":{"id":"VNACj1SO-RpY","execution":{"iopub.status.busy":"2021-07-03T13:58:57.943449Z","iopub.execute_input":"2021-07-03T13:58:57.943851Z","iopub.status.idle":"2021-07-03T13:58:57.952835Z","shell.execute_reply.started":"2021-07-03T13:58:57.943820Z","shell.execute_reply":"2021-07-03T13:58:57.951737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = data_batches(x_train, y_train)\nval_data = data_batches(x_val, y_val, valid_data=True)","metadata":{"id":"-K7GbSTZMFgL","outputId":"add04eed-e85b-4acc-98c5-1bd546f5f6bf","execution":{"iopub.status.busy":"2021-07-03T13:58:58.975620Z","iopub.execute_input":"2021-07-03T13:58:58.975948Z","iopub.status.idle":"2021-07-03T13:58:59.139097Z","shell.execute_reply.started":"2021-07-03T13:58:58.975918Z","shell.execute_reply":"2021-07-03T13:58:59.137422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# attributes of our data batches\ntrain_data.element_spec, val_data.element_spec","metadata":{"id":"ya6gI9ImMeBq","outputId":"8d8af45e-b185-4fc3-e4ba-387bc295d0a5","execution":{"iopub.status.busy":"2021-07-03T13:58:59.893444Z","iopub.execute_input":"2021-07-03T13:58:59.893771Z","iopub.status.idle":"2021-07-03T13:58:59.902575Z","shell.execute_reply.started":"2021-07-03T13:58:59.893736Z","shell.execute_reply":"2021-07-03T13:58:59.901539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualization","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Create a function for viewing images in a data batch\ndef show_images(images, labels):\n    \n  # Setup the figure\n  plt.figure(figsize=(20, 20))\n    \n  # Loop through 25 (for displaying 25 images)\n  for i in range(25):\n        \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[labels[i].argmax()])\n    # Turn gird lines off\n    plt.axis(\"off\")","metadata":{"id":"ou_fRHK2JMca","execution":{"iopub.status.busy":"2021-07-03T13:59:02.285461Z","iopub.execute_input":"2021-07-03T13:59:02.285807Z","iopub.status.idle":"2021-07-03T13:59:02.292179Z","shell.execute_reply.started":"2021-07-03T13:59:02.285777Z","shell.execute_reply":"2021-07-03T13:59:02.290863Z"},"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_images(train_images, train_labels)","metadata":{"id":"KpNpypPuL_IJ","outputId":"5720bb82-d547-4922-b7e4-070ed982c92d","execution":{"iopub.status.busy":"2021-07-03T13:59:03.333413Z","iopub.execute_input":"2021-07-03T13:59:03.333767Z","iopub.status.idle":"2021-07-03T13:59:05.945288Z","shell.execute_reply.started":"2021-07-03T13:59:03.333733Z","shell.execute_reply":"2021-07-03T13:59:05.944095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Since we have shuffled the train data in the function , everytime we run he function we will get a different set of pictures for the training data","metadata":{"id":"TvlNqUtlQBy5"}},{"cell_type":"code","source":"# Visualize validation images from the validation data batch\nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_images(val_images, val_labels)","metadata":{"id":"wlnzt9mkN4n5","outputId":"c9bffcb5-6361-4f25-da47-0eb437cc1552","execution":{"iopub.status.busy":"2021-07-03T13:59:26.103377Z","iopub.execute_input":"2021-07-03T13:59:26.103736Z","iopub.status.idle":"2021-07-03T13:59:28.527071Z","shell.execute_reply.started":"2021-07-03T13:59:26.103703Z","shell.execute_reply":"2021-07-03T13:59:28.525604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating and training a model\n\nUsing a pretrained machine learning model is often referred to as **transfer learning**.\n\n\n We will use [mobilenet_v2_130_224](https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4)\n","metadata":{"id":"7xJY5J5zPrVN"}},{"cell_type":"code","source":"# Setup input shape\nINPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3] # batch, height, width, colour channels\n\n# Setup output shape\nOUTPUT_SHAPE = len(unique) # number of unique labels\n\n# model URL from TensorFlow Hub\nMODEL_URL = \"https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4\"","metadata":{"id":"J90ZIz7ZUgej","execution":{"iopub.status.busy":"2021-07-03T13:59:38.160862Z","iopub.execute_input":"2021-07-03T13:59:38.161206Z","iopub.status.idle":"2021-07-03T13:59:38.165369Z","shell.execute_reply.started":"2021-07-03T13:59:38.161177Z","shell.execute_reply":"2021-07-03T13:59:38.164349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a function which builds a Keras model\ndef modelling(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, model_url=MODEL_URL):\n\n  # Setup the model layers\n  model = tf.keras.Sequential([\n    hub.KerasLayer(MODEL_URL), # Layer 1 (input layer)\n    tf.keras.layers.Dense(units=OUTPUT_SHAPE, \n                          activation=\"softmax\") # Layer 2 (output layer)\n  ])\n\n  # Compile the model\n  model.compile(\n      loss=tf.keras.losses.CategoricalCrossentropy(), # loss function to be reduced\n      optimizer=tf.keras.optimizers.Adam(), # Adam optimizer\n      metrics=[\"accuracy\"] \n  )\n\n  # Build the model\n  model.build(INPUT_SHAPE) \n  \n  return model","metadata":{"id":"sjYKUMTWSmbB","execution":{"iopub.status.busy":"2021-07-03T13:59:40.007788Z","iopub.execute_input":"2021-07-03T13:59:40.008128Z","iopub.status.idle":"2021-07-03T13:59:40.014371Z","shell.execute_reply.started":"2021-07-03T13:59:40.008098Z","shell.execute_reply":"2021-07-03T13:59:40.013254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a model and check its details\ncreated_model = modelling()\ncreated_model.summary()","metadata":{"id":"y3_vCn0ZSj5M","outputId":"5fbc3606-f65f-440d-db64-fb2f577c1d39","execution":{"iopub.status.busy":"2021-07-03T13:59:41.781756Z","iopub.execute_input":"2021-07-03T13:59:41.782092Z","iopub.status.idle":"2021-07-03T13:59:45.140905Z","shell.execute_reply.started":"2021-07-03T13:59:41.782062Z","shell.execute_reply":"2021-07-03T13:59:45.140019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Early Stopping Callback\n\nEarly stopping helps to maintain the quality of output of our model and if it starts to go down , it stops the model. \n\n","metadata":{"id":"o0XksOKh6ozR"}},{"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":{"id":"BD6bvwx26pE4","execution":{"iopub.status.busy":"2021-07-03T13:59:47.266869Z","iopub.execute_input":"2021-07-03T13:59:47.267191Z","iopub.status.idle":"2021-07-03T13:59:47.271555Z","shell.execute_reply.started":"2021-07-03T13:59:47.267160Z","shell.execute_reply":"2021-07-03T13:59:47.270226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Number of times our model passes through the data\nEPOCHS = 100 ","metadata":{"id":"GFe7tira73It","execution":{"iopub.status.busy":"2021-07-03T13:59:48.522716Z","iopub.execute_input":"2021-07-03T13:59:48.523048Z","iopub.status.idle":"2021-07-03T13:59:48.527399Z","shell.execute_reply.started":"2021-07-03T13:59:48.523018Z","shell.execute_reply":"2021-07-03T13:59:48.526066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Training model to fit training data and callback","metadata":{"id":"9bi-smYQBG5R"}},{"cell_type":"code","source":"# Build a function to train and return a trained model\ndef train_model():\n    \n  # Create a model\n  model = modelling()\n\n  # Fit the model to the data passing it the callbacks we created\n  model.fit(x=train_data,\n            epochs=EPOCHS,\n            validation_data=val_data,\n            validation_freq=1, # check validation metrics every epoch\n            callbacks=[early_stopping])\n  \n  return model","metadata":{"id":"sVG2q8Ep-ewd","execution":{"iopub.status.busy":"2021-07-03T13:59:50.259818Z","iopub.execute_input":"2021-07-03T13:59:50.260189Z","iopub.status.idle":"2021-07-03T13:59:50.267019Z","shell.execute_reply.started":"2021-07-03T13:59:50.260158Z","shell.execute_reply":"2021-07-03T13:59:50.265661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the model to the data\nmodel = train_model()","metadata":{"id":"jfhEe6Kd72_3","outputId":"631b5ae9-2d20-4d9d-d493-2b62ed6f6be3","execution":{"iopub.status.busy":"2021-07-03T13:59:51.506987Z","iopub.execute_input":"2021-07-03T13:59:51.507338Z","iopub.status.idle":"2021-07-03T14:00:47.296002Z","shell.execute_reply.started":"2021-07-03T13:59:51.507307Z","shell.execute_reply":"2021-07-03T14:00:47.294965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The model is clearly overfitting as it performs far better on the training data than on validation data","metadata":{"id":"LFFrMi6SCa0t"}},{"cell_type":"markdown","source":"## Predictions using the trained model\n","metadata":{"id":"RSPoRj3PRi6l"}},{"cell_type":"code","source":"# Make predictions on the validation data\npredictions = model.predict(val_data, verbose=1) # verbose shows us how long there is to go\npredictions","metadata":{"id":"AvgSpSjySqIz","outputId":"9128a4d0-bf4b-46b4-e5a8-4d0daaee878c","execution":{"iopub.status.busy":"2021-07-03T14:01:05.739432Z","iopub.execute_input":"2021-07-03T14:01:05.739786Z","iopub.status.idle":"2021-07-03T14:01:07.056028Z","shell.execute_reply.started":"2021-07-03T14:01:05.739752Z","shell.execute_reply":"2021-07-03T14:01:07.055187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions.shape","metadata":{"id":"S0v9awLqDtml","outputId":"7f043f4d-0cdc-415e-b192-41ada17b8c4e","execution":{"iopub.status.busy":"2021-07-03T14:01:11.946836Z","iopub.execute_input":"2021-07-03T14:01:11.947184Z","iopub.status.idle":"2021-07-03T14:01:11.955025Z","shell.execute_reply.started":"2021-07-03T14:01:11.947149Z","shell.execute_reply":"2021-07-03T14:01:11.953721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Making predictions with our model returns an array with a different value for each label.\n\nIn 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. The higher the value, the more likely the model thinks a given image is a specific breed of dog.\n\nLet's see how we'd convert an array of probabilities into an actual label.","metadata":{"id":"bhXvT9CeDzNE"}},{"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])}\")\nprint(f\"Max index: {np.argmax(predictions[0])}\") # the index of where the max value in predictions[0] occurs\nprint(f\"Predicted label: {unique[np.argmax(predictions[0])]}\") # the predicted label","metadata":{"id":"VUUDuXBlDy3i","outputId":"357a0a83-6a97-4380-c5d3-9d30ce6a61ed","execution":{"iopub.status.busy":"2021-07-03T14:01:14.643870Z","iopub.execute_input":"2021-07-03T14:01:14.644240Z","iopub.status.idle":"2021-07-03T14:01:14.653539Z","shell.execute_reply.started":"2021-07-03T14:01:14.644206Z","shell.execute_reply":"2021-07-03T14:01:14.652233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Predicting dog breed","metadata":{}},{"cell_type":"code","source":"\ndef pred_label(prediction_probabilities):\n\n  return unique[np.argmax(prediction_probabilities)]\n\nprediction_label = pred_label(predictions[0])\nprediction_label","metadata":{"id":"jEUEsrlvG6Z2","outputId":"9dc2d6f1-e6cb-4028-aef7-d16e5b6937ca","execution":{"iopub.status.busy":"2021-07-03T14:01:17.138269Z","iopub.execute_input":"2021-07-03T14:01:17.138640Z","iopub.status.idle":"2021-07-03T14:01:17.144728Z","shell.execute_reply.started":"2021-07-03T14:01:17.138609Z","shell.execute_reply":"2021-07-03T14:01:17.143713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Wonderful! Now we've got a list of all different predictions our model has made, we'll do the same for the validation images and validation labels.\n\nRemember, the model hasn't trained on the validation data, during the `fit()` function, it only used the validation data to evaluate itself. So we can use the validation images to visually compare our models predictions with the validation labels.\n\nSince 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()`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#unbatch)) and then turn it into an iterator using [`as_numpy_iterator()`](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#as_numpy_iterator).\n\nLet's make a small function to do so.","metadata":{"id":"kfjx3FPPHdQ7"}},{"cell_type":"code","source":"# function to unbatch a batched dataset\ndef unbatchify(data):\n  \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[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":{"id":"NEwoi7sjHdr_","outputId":"52e2d889-f402-4ff4-cd39-d14a945d18a7","execution":{"iopub.status.busy":"2021-07-03T14:01:21.828797Z","iopub.execute_input":"2021-07-03T14:01:21.829162Z","iopub.status.idle":"2021-07-03T14:01:22.637769Z","shell.execute_reply.started":"2021-07-03T14:01:21.829113Z","shell.execute_reply":"2021-07-03T14:01:22.636850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualizing the predictions","metadata":{}},{"cell_type":"code","source":"def plot_pred(prediction_probabilities, labels, images, n=1):\n \n  pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]\n  \n  # Get the pred label\n  prediction_label = 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 prediction_label == true_label:\n    color = \"green\"\n  else:\n    color = \"red\"\n\n  plt.title(\"{} {:2.0f}% ({})\".format(prediction_label,\n                                      np.max(pred_prob)*100,\n                                      true_label),\n                                      color=color)","metadata":{"id":"5YdcsHKlLMcW","execution":{"iopub.status.busy":"2021-07-03T14:01:26.120782Z","iopub.execute_input":"2021-07-03T14:01:26.121179Z","iopub.status.idle":"2021-07-03T14:01:26.127555Z","shell.execute_reply.started":"2021-07-03T14:01:26.121141Z","shell.execute_reply":"2021-07-03T14:01:26.126458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# example prediction, original image and truth label\nplot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images)","metadata":{"id":"RMHqjvroLuMD","outputId":"6e23c9a1-b1ac-48a2-f471-064f4a58609c","execution":{"iopub.status.busy":"2021-07-03T14:01:28.371823Z","iopub.execute_input":"2021-07-03T14:01:28.372162Z","iopub.status.idle":"2021-07-03T14:01:28.476990Z","shell.execute_reply.started":"2021-07-03T14:01:28.372126Z","shell.execute_reply":"2021-07-03T14:01:28.476035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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  prediction_label = pred_label(pred_prob)\n\n  # Find the top 7 prediction confidence indexes\n  pred_indexes_7 = pred_prob.argsort()[-7:][::-1]\n    \n  # Find the top 7 prediction confidence values\n  pred_values_7 = pred_prob[pred_indexes_7]\n    \n  # Find the top 7 prediction labels\n  pred_labels_7 = unique[pred_indexes_7]\n\n  # Setup plot\n  top_plot = plt.bar(np.arange(len(pred_labels_7)), \n                     pred_values_7, \n                     color=\"purple\")\n  plt.xticks(np.arange(len(pred_labels_7)),\n             labels=pred_labels_7,\n             rotation=\"vertical\")\n\n  # Change color of true label\n  if np.isin(true_label, pred_labels_7):\n    top_plot[np.argmax(pred_labels_7 == true_label)].set_color(\"orange\")\n  else:\n    pass","metadata":{"id":"IsWZOTMZNfha","execution":{"iopub.status.busy":"2021-07-03T14:01:31.375378Z","iopub.execute_input":"2021-07-03T14:01:31.375752Z","iopub.status.idle":"2021-07-03T14:01:31.385034Z","shell.execute_reply.started":"2021-07-03T14:01:31.375717Z","shell.execute_reply":"2021-07-03T14:01:31.383401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,\n               labels=val_labels,\n               n=10)","metadata":{"id":"2MgaCmh3Nkv0","outputId":"d9c28749-fa71-4846-c34c-5b4b8e7f45ed","execution":{"iopub.status.busy":"2021-07-03T14:01:32.663585Z","iopub.execute_input":"2021-07-03T14:01:32.663956Z","iopub.status.idle":"2021-07-03T14:01:32.815857Z","shell.execute_reply.started":"2021-07-03T14:01:32.663924Z","shell.execute_reply":"2021-07-03T14:01:32.814939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# few predictions and their different values\nmult = 0\nrows = 2\ncols = 2\nnum_images = rows*cols\nplt.figure(figsize=(5*1.5*cols, 5*rows))\nfor i in range(num_images):\n  plt.subplot(rows, 2*cols, 2*i+1)\n  plot_pred(prediction_probabilities=predictions,\n            labels=val_labels,\n            images=val_images,\n            n=i+mult)\n  plt.subplot(rows, 2*cols, 2*i+2)\n  plot_pred_conf(prediction_probabilities=predictions,\n                labels=val_labels,\n                n=i+mult)\nplt.tight_layout(h_pad=1.0)\nplt.show()","metadata":{"id":"H6Z-x-ZoOIzk","outputId":"f9b42793-eae3-4aca-a5ff-1fa90941edf5","execution":{"iopub.status.busy":"2021-07-03T14:01:34.967521Z","iopub.execute_input":"2021-07-03T14:01:34.967978Z","iopub.status.idle":"2021-07-03T14:01:36.204178Z","shell.execute_reply.started":"2021-07-03T14:01:34.967944Z","shell.execute_reply":"2021-07-03T14:01:36.203357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Thankyou","metadata":{"execution":{"iopub.status.busy":"2021-06-30T08:31:15.009625Z","iopub.execute_input":"2021-06-30T08:31:15.009999Z","iopub.status.idle":"2021-06-30T08:31:15.034702Z","shell.execute_reply.started":"2021-06-30T08:31:15.009967Z","shell.execute_reply":"2021-06-30T08:31:15.032663Z"}}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}