{"metadata":{"colab":{"provenance":[],"collapsed_sections":["sY4_7IPf7O3A"],"gpuType":"T4"},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"accelerator":"GPU","kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":7327,"databundleVersionId":861871},{"sourceType":"modelInstanceVersion","sourceId":3660,"databundleVersionId":5075746,"modelInstanceId":2604}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#  End-to-end Multi class Dog Breed Classification\n\n## 1. Problem\n\n- Identifying the breed of a dog given an image of a dog\n\n## 2. Data\nThe data we're using is from kaggle's dog breed Identification competition\n\n\nhttps://www.kaggle.com/competitions/dog-breed-identification/data\n\n## 3. Evaluation\n\nThe Evaluation is a file with prediction probabilities for each dog breed of each test image\n\n## 4. Features\n**Some info abou the data :**\n- We're Dealing with Images (Unstructured data), so it's probably best we use deep learning / transfer learning .\n- There are 120 breeds of dogs (this means there are 120 different classes )\n- There are around 10,000+ images in the training set  (have labels)\n- there are around 10,000+ images in the test set  (have no labels 'cause we'll want to predict them)\n\n","metadata":{"id":"ULWnp2C88omX"}},{"cell_type":"markdown","source":"## Get our Workspace ready","metadata":{"id":"YKMOWqYhgdCk"}},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub\n\nprint(tf.__version__)\nprint(hub.__version__)\n\n","metadata":{"id":"rECLc_gG9hu3","outputId":"78f8edd8-6de6-4705-aa62-57186317837a","execution":{"iopub.status.busy":"2024-10-17T15:01:20.324912Z","iopub.execute_input":"2024-10-17T15:01:20.325786Z","iopub.status.idle":"2024-10-17T15:01:34.104256Z","shell.execute_reply.started":"2024-10-17T15:01:20.32574Z","shell.execute_reply":"2024-10-17T15:01:34.103321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Getting our data ready (Turning into Tensors)\n\nwith all ML models, our data has to be numerical format\n\nso that's what we'll doing first ==> turning our images into Tensors (Numercial Representation)","metadata":{"id":"KAG8kgLnmxC9"}},{"cell_type":"code","source":"# Check out the labels of our data\nimport pandas as pd\nlabels_csv= pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\n\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"id":"5ID3B9aVgv6A","outputId":"d18d4d1d-371b-4580-c2bd-e7d7822cd0c9","execution":{"iopub.status.busy":"2024-10-17T15:01:34.106225Z","iopub.execute_input":"2024-10-17T15:01:34.107167Z","iopub.status.idle":"2024-10-17T15:01:34.172456Z","shell.execute_reply.started":"2024-10-17T15:01:34.107114Z","shell.execute_reply":"2024-10-17T15:01:34.17158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv.head()","metadata":{"id":"A3kaUitRnqRW","outputId":"a92e845d-7cb2-4bbb-dd63-a1ea9cdfefa4","execution":{"iopub.status.busy":"2024-10-17T15:01:34.17349Z","iopub.execute_input":"2024-10-17T15:01:34.173823Z","iopub.status.idle":"2024-10-17T15:01:34.185193Z","shell.execute_reply.started":"2024-10-17T15:01:34.17379Z","shell.execute_reply":"2024-10-17T15:01:34.184307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# how many iamge\nlabels_csv['breed'].value_counts().plot.bar(figsize=(20,10));","metadata":{"id":"Bk59maFjoPlr","outputId":"6a0f92be-e303-4ed3-a70c-2bd0926fb3a6","execution":{"iopub.status.busy":"2024-10-17T15:01:34.18724Z","iopub.execute_input":"2024-10-17T15:01:34.187592Z","iopub.status.idle":"2024-10-17T15:01:35.855426Z","shell.execute_reply.started":"2024-10-17T15:01:34.187549Z","shell.execute_reply":"2024-10-17T15:01:35.854409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_csv['breed'].value_counts().median()","metadata":{"id":"rZbBaI1yon8B","outputId":"4898e2e1-fc64-4946-c752-a9d1efb2e34c","execution":{"iopub.status.busy":"2024-10-17T15:01:35.85701Z","iopub.execute_input":"2024-10-17T15:01:35.858083Z","iopub.status.idle":"2024-10-17T15:01:35.870596Z","shell.execute_reply.started":"2024-10-17T15:01:35.858033Z","shell.execute_reply":"2024-10-17T15:01:35.869413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import Image\nImage('/kaggle/input/dog-breed-identification/train/0075dc49dab4024d12fafe67074d8a81.jpg')","metadata":{"id":"wYnlkwvSpGqA","outputId":"dc5d45f7-1b95-4c77-b17b-daa8b76bc876","execution":{"iopub.status.busy":"2024-10-17T15:01:35.872048Z","iopub.execute_input":"2024-10-17T15:01:35.872427Z","iopub.status.idle":"2024-10-17T15:01:35.892186Z","shell.execute_reply.started":"2024-10-17T15:01:35.872365Z","shell.execute_reply":"2024-10-17T15:01:35.891335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Getting images and their labels\n\n- Let's get a list of all of our image file pathnames","metadata":{"id":"5Z0mlCX3q_Rj"}},{"cell_type":"code","source":"# Create path name from images ID's\nfilenames= [\"/kaggle/input/dog-breed-identification/train/\"+fname + \".jpg\" for fname in labels_csv['id']]\n# Check the first 10\nfilenames[:10]","metadata":{"id":"lAJick73qnXw","outputId":"34ce4508-e0f4-4c67-c100-f795ecfd29b4","execution":{"iopub.status.busy":"2024-10-17T15:01:35.893199Z","iopub.execute_input":"2024-10-17T15:01:35.893476Z","iopub.status.idle":"2024-10-17T15:01:35.904943Z","shell.execute_reply.started":"2024-10-17T15:01:35.893445Z","shell.execute_reply":"2024-10-17T15:01:35.904036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check whether number of filenames matches number of actual image file\n\nimport os\nif len(os.listdir(\"/kaggle/input/dog-breed-identification/train/\"))== len(filenames):\n  print(\"Filename match actual amount of files!!! Proceed. \")\nelse:\n  print(\"Filename NOT match actual amount of files, Check the target directory \")\n","metadata":{"id":"cbrpYk0brnad","outputId":"ce824112-2235-43a7-a8eb-6ce062e04c89","execution":{"iopub.status.busy":"2024-10-17T15:01:35.906042Z","iopub.execute_input":"2024-10-17T15:01:35.906351Z","iopub.status.idle":"2024-10-17T15:01:36.161907Z","shell.execute_reply.started":"2024-10-17T15:01:35.906319Z","shell.execute_reply":"2024-10-17T15:01:36.160938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# one more check\nImage(filenames[404])","metadata":{"id":"dk7dx6kBtG1h","outputId":"ca081451-e876-4847-8f7d-623b7363877d","execution":{"iopub.status.busy":"2024-10-17T15:01:36.163177Z","iopub.execute_input":"2024-10-17T15:01:36.163602Z","iopub.status.idle":"2024-10-17T15:01:36.175155Z","shell.execute_reply.started":"2024-10-17T15:01:36.163546Z","shell.execute_reply":"2024-10-17T15:01:36.174196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nSince we've now got our training images filepaths in a list, let's prepare our labels","metadata":{"id":"ZmfU6Qfnuv16"}},{"cell_type":"code","source":"import numpy as np\n\nlabels= labels_csv['breed'].to_numpy()\n#labels= np.array(labels)\nlabels","metadata":{"id":"_t4eBKz0t8E7","outputId":"2f1936a0-d2d7-41b2-cb4e-b9eaac2505a3","execution":{"iopub.status.busy":"2024-10-17T15:01:36.179516Z","iopub.execute_input":"2024-10-17T15:01:36.179875Z","iopub.status.idle":"2024-10-17T15:01:36.186618Z","shell.execute_reply.started":"2024-10-17T15:01:36.179842Z","shell.execute_reply":"2024-10-17T15:01:36.185764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(labels)","metadata":{"id":"2GgipRvNvB3R","outputId":"3ff91f3a-11a5-4f51-e2ef-2d667b85214a","execution":{"iopub.status.busy":"2024-10-17T15:01:36.187934Z","iopub.execute_input":"2024-10-17T15:01:36.18836Z","iopub.status.idle":"2024-10-17T15:01:36.196982Z","shell.execute_reply.started":"2024-10-17T15:01:36.188318Z","shell.execute_reply":"2024-10-17T15:01:36.196046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# See if number of labels matches the number of filenames\nif len(labels)== len(filenames):\n  print(\"Number of labeles matches number of filenames!\")\nelse:\n  print(\"NUmber of Labels doesn't match number of filename, check data Dirs\")","metadata":{"id":"WZKY3AXdvULe","outputId":"894373d9-7423-4612-b1c8-5f27ef1150ba","execution":{"iopub.status.busy":"2024-10-17T15:01:36.199932Z","iopub.execute_input":"2024-10-17T15:01:36.20061Z","iopub.status.idle":"2024-10-17T15:01:36.206989Z","shell.execute_reply.started":"2024-10-17T15:01:36.200576Z","shell.execute_reply":"2024-10-17T15:01:36.206073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the Unique label values\nunique_breeds= np.unique(labels)\nunique_breeds","metadata":{"id":"7c05PFhnwLmN","outputId":"4c1618d9-73a4-45b2-d32b-4be1d508c9e5","execution":{"iopub.status.busy":"2024-10-17T15:01:36.208074Z","iopub.execute_input":"2024-10-17T15:01:36.208688Z","iopub.status.idle":"2024-10-17T15:01:36.228738Z","shell.execute_reply.started":"2024-10-17T15:01:36.208654Z","shell.execute_reply":"2024-10-17T15:01:36.227794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn a single label into an array of booleans\nprint(labels[0])\nlabels[0]== unique_breeds","metadata":{"id":"fW9FlicO5Yvw","outputId":"a08c0d2d-6948-4b16-a747-e01851e195bb","execution":{"iopub.status.busy":"2024-10-17T15:01:36.229968Z","iopub.execute_input":"2024-10-17T15:01:36.230322Z","iopub.status.idle":"2024-10-17T15:01:36.241842Z","shell.execute_reply.started":"2024-10-17T15:01:36.230275Z","shell.execute_reply":"2024-10-17T15:01:36.240925Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn every label into a boolean array\n\nboolean_labels= [label== unique_breeds for label in labels]\nboolean_labels","metadata":{"id":"BKHE1oql5rFT","outputId":"156c9f76-1e06-46bb-a5e6-dff7b00279a4","execution":{"iopub.status.busy":"2024-10-17T15:01:36.243994Z","iopub.execute_input":"2024-10-17T15:01:36.244289Z","iopub.status.idle":"2024-10-17T15:01:36.75341Z","shell.execute_reply.started":"2024-10-17T15:01:36.244257Z","shell.execute_reply":"2024-10-17T15:01:36.752596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(boolean_labels)","metadata":{"id":"RhfCx3Sg6Xyv","outputId":"281f06cf-aaf6-40fb-b46b-28e73b3f7405","execution":{"iopub.status.busy":"2024-10-17T15:01:36.754641Z","iopub.execute_input":"2024-10-17T15:01:36.754989Z","iopub.status.idle":"2024-10-17T15:01:36.761126Z","shell.execute_reply.started":"2024-10-17T15:01:36.754952Z","shell.execute_reply":"2024-10-17T15:01:36.760271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example: Turning boolean array into int\nprint(labels[0]) # Original label\nprint(np.where(unique_breeds==labels[0])) # index of the labels occurs\n\nprint(boolean_labels[0].argmax()) # index where label occurs in boolean array\n\nprint(boolean_labels[0].astype(int)) # There will be a 1 where the sample label occurs","metadata":{"id":"jfjwH5dx6aIn","outputId":"fa58a0e8-edb3-416d-a16d-d561e10c1a19","execution":{"iopub.status.busy":"2024-10-17T15:01:36.762209Z","iopub.execute_input":"2024-10-17T15:01:36.762548Z","iopub.status.idle":"2024-10-17T15:01:36.771854Z","shell.execute_reply.started":"2024-10-17T15:01:36.762496Z","shell.execute_reply":"2024-10-17T15:01:36.770958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating our Own Validation Dataset\n\nSince the dataset from kaggle dones't come with a validation set . we're going to create our own","metadata":{"id":"GlqMYa6374l1"}},{"cell_type":"code","source":"# Setup X & Y Variables\n\nx= filenames\ny= boolean_labels","metadata":{"id":"kmumJd1I7QNo","execution":{"iopub.status.busy":"2024-10-17T15:01:36.772981Z","iopub.execute_input":"2024-10-17T15:01:36.773275Z","iopub.status.idle":"2024-10-17T15:01:36.78619Z","shell.execute_reply.started":"2024-10-17T15:01:36.773239Z","shell.execute_reply":"2024-10-17T15:01:36.785339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We're going to start off experimenting with ~1000 images and increase as needed","metadata":{"id":"4lwh31nl8yA0"}},{"cell_type":"code","source":"# Set number of image to use for experminting\n\nNUM_IMAGES=1000 # @param{type:'slider',min:1000,max:10000,step:100}","metadata":{"id":"43GeYL0b8kQL","execution":{"iopub.status.busy":"2024-10-17T15:01:36.787272Z","iopub.execute_input":"2024-10-17T15:01:36.78762Z","iopub.status.idle":"2024-10-17T15:01:36.796072Z","shell.execute_reply.started":"2024-10-17T15:01:36.787588Z","shell.execute_reply":"2024-10-17T15:01:36.79515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# let's split our data into train and validation sets\nfrom sklearn.model_selection import train_test_split\n\n# split them into training and validation of total size NUM_IMAGES\n\nX_train, X_val , Y_tarin, 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_tarin) , len(X_val) , len(Y_val)","metadata":{"id":"gM2B_Pyb9lOU","outputId":"6ffa3ecf-172d-4d89-b1f8-8b765c80d614","execution":{"iopub.status.busy":"2024-10-17T15:01:36.797213Z","iopub.execute_input":"2024-10-17T15:01:36.797543Z","iopub.status.idle":"2024-10-17T15:01:37.225694Z","shell.execute_reply.started":"2024-10-17T15:01:36.797483Z","shell.execute_reply":"2024-10-17T15:01:37.22479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# let's have a geez at the training data\n\nX_train[:3] , Y_tarin[:3]","metadata":{"id":"NzagXzOR-bW-","outputId":"7d5ef506-ee3f-4f05-c41d-afce7d00aefb","execution":{"iopub.status.busy":"2024-10-17T15:01:37.226707Z","iopub.execute_input":"2024-10-17T15:01:37.227221Z","iopub.status.idle":"2024-10-17T15:01:37.234708Z","shell.execute_reply.started":"2024-10-17T15:01:37.227188Z","shell.execute_reply":"2024-10-17T15:01:37.233782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preprocessing Images (Turning images into tensors)\n\n* To Preprocess our images into Tensors we're going to write a function whitch does a few things:\n 1. Take an image filepath as input\n 2. Use TansorFlow to read the file and save it to a var `image`\n 3. Turn our `image` into Tensors\n 4. Resize the `image` to be a shape (244,244)\n 5. Return the modified `image`","metadata":{"id":"gCi_mQHi_G-z"}},{"cell_type":"code","source":"# Convert an image into Numpy Array\n\nfrom matplotlib.pyplot import imread\n\nimage = imread(filenames[42])\nimage.shape","metadata":{"id":"zhEZnccd-rcw","outputId":"196f009e-31cf-4ed0-ca0e-06f8036d8ae1","execution":{"iopub.status.busy":"2024-10-17T15:01:37.235844Z","iopub.execute_input":"2024-10-17T15:01:37.236171Z","iopub.status.idle":"2024-10-17T15:01:37.25706Z","shell.execute_reply.started":"2024-10-17T15:01:37.23613Z","shell.execute_reply":"2024-10-17T15:01:37.256032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image","metadata":{"id":"gAQEnOIbA_yT","outputId":"510a9ad0-1779-4699-d4cf-6bcc6dd30e86","execution":{"iopub.status.busy":"2024-10-17T15:01:37.258114Z","iopub.execute_input":"2024-10-17T15:01:37.258398Z","iopub.status.idle":"2024-10-17T15:01:37.265226Z","shell.execute_reply.started":"2024-10-17T15:01:37.258368Z","shell.execute_reply":"2024-10-17T15:01:37.264356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# turn image into Tensor\ntf.constant(image)","metadata":{"id":"aUbMw0JdBRqD","outputId":"7c47b1cc-6b8b-48ef-af63-393e9f50b499","execution":{"iopub.status.busy":"2024-10-17T15:01:37.266335Z","iopub.execute_input":"2024-10-17T15:01:37.26664Z","iopub.status.idle":"2024-10-17T15:01:37.878847Z","shell.execute_reply.started":"2024-10-17T15:01:37.266609Z","shell.execute_reply":"2024-10-17T15:01:37.877864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define image size\nIMG_SIZE= 224\n\n# Create a function for preprocessing images\n\ndef process_image(image_path, image_size=IMG_SIZE):\n  \"\"\"\n  Takes an images filepath and turns the image into a Tensor.\n  \"\"\"\n  # Read an image file\n  image= tf.io.read_file(image_path)\n  # Trun the image into numerical Tensor with 3 color channels (red ,green,blue)\n  image= tf.image.decode_jpeg(image,channels=3)\n  # Convert the color channel values from 0-255 to 0-1 values (Normalization)\n  image= tf.image.convert_image_dtype(image,tf.float32)\n  # Rsize the image to our desired value (244,244)\n  image= tf.image.resize(image,size=[image_size,image_size])\n  return image\n\n","metadata":{"id":"hmGMSF9GBj2z","execution":{"iopub.status.busy":"2024-10-17T15:01:37.879917Z","iopub.execute_input":"2024-10-17T15:01:37.880207Z","iopub.status.idle":"2024-10-17T15:01:37.886468Z","shell.execute_reply.started":"2024-10-17T15:01:37.880177Z","shell.execute_reply":"2024-10-17T15:01:37.885484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Turning our data into batches\n\nWhy turn our data into batches ??\n\nLet's say you're trying to process 10,000+ images in one go..\nthey all might be fit into memory\n\nso that's why we do about 32 (batch side) images at a time (You can manually adjust the batch size if need be)\n\nIn Order to use TensorFlow Effectively, we need our data in the form of Tensors tuples .(`image`,`label`)","metadata":{"id":"VP9Im8tCTkqs"}},{"cell_type":"code","source":"# Create a simple function to return a tuple (image,label)\ndef get_image_label(image_path,label):\n  \"\"\"\n  Take an image file path name and the assoicated label,\n  processes the image and returns a tuble of image label\n  \"\"\"\n  image= process_image(image_path)\n  return image , label\n","metadata":{"id":"QAse8K4LUW4W","execution":{"iopub.status.busy":"2024-10-17T15:01:37.887515Z","iopub.execute_input":"2024-10-17T15:01:37.887846Z","iopub.status.idle":"2024-10-17T15:01:37.896961Z","shell.execute_reply.started":"2024-10-17T15:01:37.887813Z","shell.execute_reply":"2024-10-17T15:01:37.89611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(process_image(x[42]),y[42])","metadata":{"id":"Jc17GCXcVfPH","outputId":"733acdbb-2e3a-45f4-8951-64d298cbdaf2","execution":{"iopub.status.busy":"2024-10-17T15:01:37.898131Z","iopub.execute_input":"2024-10-17T15:01:37.898577Z","iopub.status.idle":"2024-10-17T15:01:37.948329Z","shell.execute_reply.started":"2024-10-17T15:01:37.898519Z","shell.execute_reply":"2024-10-17T15:01:37.947478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we've got a way to turn our data into tubles of tensors\nin the form : (`image`,`label`) let's make a function to turn all of our data (`x` & `y` ) into batches","metadata":{"id":"3BW2hqAdWmXl"}},{"cell_type":"code","source":"# Define the batch size , 32 is a good start\n\nBATCH_SIZE= 32\n\n# Lets Create a function to turn data into batches\n\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 images (x) and label (y) paris.\n  Shuffle the data if it's training data but doesn't shuffle it's validation data.\n  Also accespts test data as input (no label) .\n  \"\"\"\n  # If the data is test data set, we Probably don'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 filepath (no labels)\n    data_batch= data.map(process_image).batch(batch_size)\n    return data_batch\n  elif valid_data:\n    print(\"Creating valid data batches.....\")\n    data= tf.data.Dataset.from_tensor_slices((tf.constant(x), # file path\n                                             tf.constant(y)))  # labels\n\n    data_batch= data.map(get_image_label).batch(batch_size)\n    return data_batch\n  else:\n    print(\"Creating data batche......\")\n    # Turn file path and labels into Tensors\n    data= tf.data.Dataset.from_tensor_slices((tf.constant(x), # file path\n                                             tf.constant(y)))  # labels\n    # Shuffling the pathnames and labels before mapping image processor function is faster than shuffing images\n    data= data.shuffle(buffer_size=len(x))\n    # Create (image,labels) tubles (this also turns the image path into a pre-processd image)\n    data= data.map(get_image_label)\n    # Turn the training data into batches\n    data_batch= data.batch(batch_size)\n    return data_batch","metadata":{"id":"AODj5nXmVrOj","execution":{"iopub.status.busy":"2024-10-17T15:01:37.953929Z","iopub.execute_input":"2024-10-17T15:01:37.954484Z","iopub.status.idle":"2024-10-17T15:01:37.962931Z","shell.execute_reply.started":"2024-10-17T15:01:37.954449Z","shell.execute_reply":"2024-10-17T15:01:37.96206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training data  and validation data batches\n\ntrain_data= create_data_batches(X_train,Y_tarin)\nval_data= create_data_batches(X_val,Y_val,valid_data=True)","metadata":{"id":"8Two0yEab6Ov","outputId":"8e77666e-e244-4dc0-e263-a183beef60cf","execution":{"iopub.status.busy":"2024-10-17T15:01:37.964209Z","iopub.execute_input":"2024-10-17T15:01:37.964496Z","iopub.status.idle":"2024-10-17T15:01:38.120256Z","shell.execute_reply.started":"2024-10-17T15:01:37.964465Z","shell.execute_reply":"2024-10-17T15:01:38.119234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the different attributes of our data batches\n\ntrain_data.element_spec, val_data.element_spec","metadata":{"id":"UoQvfZ6Fcaxb","outputId":"827e64d0-e849-40c5-8c7c-d6e394f0c3d9","execution":{"iopub.status.busy":"2024-10-17T15:01:38.121347Z","iopub.execute_input":"2024-10-17T15:01:38.12165Z","iopub.status.idle":"2024-10-17T15:01:38.127371Z","shell.execute_reply.started":"2024-10-17T15:01:38.121618Z","shell.execute_reply":"2024-10-17T15:01:38.126413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"id":"wuZGUE6EcsCj"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visulaizing Data Batches\n\nour data is now in batches , however, these can be a little hard to understand/comprehend, Let's Visualize them!\n","metadata":{"id":"gUTiFjUWw5fZ"}},{"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  \"\"\"\n  Displays a plot of 25 images and there lables from a data batch\n\n  \"\"\"\n  # Setup a figure\n  plt.figure(figsize=(10,10))\n  # Loop thorw 25 (for displaying 25 images)\n  for i in range(25):\n    # Create a subplots\n    ax=plt.subplot(5,5,i+1)\n    # Display an images\n    plt.imshow(images[i])\n    # Add the image label as a title\n    plt.title(unique_breeds[labels[i].argmax()])\n    # Trun the grid line off\n    plt.axis('off')\n\n\n","metadata":{"id":"-W2B7D7yxLbA","execution":{"iopub.status.busy":"2024-10-17T15:01:38.128405Z","iopub.execute_input":"2024-10-17T15:01:38.128739Z","iopub.status.idle":"2024-10-17T15:01:38.137233Z","shell.execute_reply.started":"2024-10-17T15:01:38.128707Z","shell.execute_reply":"2024-10-17T15:01:38.136441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images, train_labels= next(train_data.as_numpy_iterator())\ntrain_images, train_labels","metadata":{"id":"_mBf3nYwy9rg","outputId":"3051df2d-d3e1-465c-d601-3ac29c8bcec9","execution":{"iopub.status.busy":"2024-10-17T15:01:38.138335Z","iopub.execute_input":"2024-10-17T15:01:38.138644Z","iopub.status.idle":"2024-10-17T15:01:38.32414Z","shell.execute_reply.started":"2024-10-17T15:01:38.138613Z","shell.execute_reply":"2024-10-17T15:01:38.323258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_images), len(train_labels)","metadata":{"id":"_s_8IOJmznl3","outputId":"18005a0b-aef0-4fed-d3ba-cf2f779b5e70","execution":{"iopub.status.busy":"2024-10-17T15:01:38.325133Z","iopub.execute_input":"2024-10-17T15:01:38.325409Z","iopub.status.idle":"2024-10-17T15:01:38.33137Z","shell.execute_reply.started":"2024-10-17T15:01:38.325379Z","shell.execute_reply":"2024-10-17T15:01:38.330577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_25_images(train_images,train_labels)","metadata":{"id":"dap5wE_dztZ7","outputId":"64b3d3fb-5599-42f9-976c-696d47249e15","execution":{"iopub.status.busy":"2024-10-17T15:01:38.332501Z","iopub.execute_input":"2024-10-17T15:01:38.332876Z","iopub.status.idle":"2024-10-17T15:01:40.308489Z","shell.execute_reply.started":"2024-10-17T15:01:38.332836Z","shell.execute_reply":"2024-10-17T15:01:40.307405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now Let's Visualize our validation data set\nval_image, val_labels= next(val_data.as_numpy_iterator())\nshow_25_images(val_image,val_labels)","metadata":{"id":"RIe39bTZzzIp","outputId":"f0d4cbe2-a7b1-49c9-8418-7a0c6bac0f66","execution":{"iopub.status.busy":"2024-10-17T15:01:40.309827Z","iopub.execute_input":"2024-10-17T15:01:40.310193Z","iopub.status.idle":"2024-10-17T15:01:42.589286Z","shell.execute_reply.started":"2024-10-17T15:01:40.310155Z","shell.execute_reply":"2024-10-17T15:01:42.588408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Building a model\n\nBefore we build a model, there are few things we need to define:\n\n* The Input shape (Our image shape, in the form of Tensors) to our model\n* The Output (image labels in the form of Tensors) of our mode.\n* The URL of the model we want to use ('cause we use Transfer learning/ Fine-Tuning)","metadata":{"id":"4PDPoChj2oLh"}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE= [None, IMG_SIZE,IMG_SIZE,3] # Batch , hight , width , color channels\n\n# Setup the output shape\nOUTPUT_SHAPE= len(unique_breeds)\n\n# Setup model Url from Tensorflow hub\nMODEL_URL= \"https://www.kaggle.com/models/google/mobilenet-v2/TensorFlow2/130-224-classification/2\"\n\n","metadata":{"id":"j8XCsiT-1rHf","execution":{"iopub.status.busy":"2024-10-17T15:01:42.590468Z","iopub.execute_input":"2024-10-17T15:01:42.590847Z","iopub.status.idle":"2024-10-17T15:01:42.595941Z","shell.execute_reply.started":"2024-10-17T15:01:42.590808Z","shell.execute_reply":"2024-10-17T15:01:42.59512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We've got our inputs, outputs and model ready to go .\n\nlet's put them together into keras deep learning model\n\nKnowing this , let's create a function which:\n* Takes the input shape , output shape and the model as parameter\n*  Define the layers in a keras model in squential fashion\n(do this first , then this , then that)..\n* Compiles the model (says how it should be evaluated and Improved)\n* Build the model (tells the model the input shape it'll be getting )\n* Returns the model","metadata":{"id":"Y9c0vSzv9NJQ"}},{"cell_type":"code","source":"import tf_keras as tfk\n\n# Create a function to build 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  # Setup the model Layers\n  model= tfk.Sequential([\n        hub.KerasLayer(model_url),\n                       tfk.layers.Dense(units=output_shape, activation='softmax')\n                       ])\n\n    # compile the model\n  model.compile(\n        loss=tfk.losses.CategoricalCrossentropy(),\n        optimizer=tfk.optimizers.Adam(),\n        metrics=['accuracy']\n    )\n\n    # build the model\n  model.build(input_shape)\n\n  return model","metadata":{"id":"vD0HOe1n-Fi7","execution":{"iopub.status.busy":"2024-10-17T15:01:42.59708Z","iopub.execute_input":"2024-10-17T15:01:42.597401Z","iopub.status.idle":"2024-10-17T15:01:42.609247Z","shell.execute_reply.started":"2024-10-17T15:01:42.597363Z","shell.execute_reply":"2024-10-17T15:01:42.608366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = create_model()\nmodel.summary()","metadata":{"id":"xJFeJKH6AD39","outputId":"1ef6e583-463c-4099-c850-ca12ae8b9d27","execution":{"iopub.status.busy":"2024-10-17T15:01:42.610375Z","iopub.execute_input":"2024-10-17T15:01:42.610674Z","iopub.status.idle":"2024-10-17T15:01:53.049106Z","shell.execute_reply.started":"2024-10-17T15:01:42.610643Z","shell.execute_reply":"2024-10-17T15:01:53.048163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Createing Callbacks\n\ncallbacks are helper functions a model can use during training to do such things as save it's progress, check it's prograss or stop training early if the model stop improving\n\nWe'll Create two callbacks, one for TensorBoard which helps track our model progress and another for early stopping","metadata":{"id":"XUIWhQvK6DvV"}},{"cell_type":"markdown","source":"### TensorBoard Callback\n\nWe need to do 3 things :\n1. Load The TensorBoard notebook Extension.\n2. Create a TensorBoard callback which able to save logs to a directory\nand pass it to our model `fit()` function\n3. Visualize our model training logs with `%TensorBoard` Magic function","metadata":{"id":"lPsWEnIi7VG9"}},{"cell_type":"code","source":"# Load TensorBoard\n%load_ext tensorboard","metadata":{"id":"qx9X06sBzj6-","execution":{"iopub.status.busy":"2024-10-17T15:01:53.050172Z","iopub.execute_input":"2024-10-17T15:01:53.050454Z","iopub.status.idle":"2024-10-17T15:01:53.07659Z","shell.execute_reply.started":"2024-10-17T15:01:53.050423Z","shell.execute_reply":"2024-10-17T15:01:53.075577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime\nimport tf_keras\nimport os\n# Create a funciton to Bulild a TensorBoard callback\n\ndef create_tensorboard_callback():\n  # Create a log dir for storing tensorboard\n  logdir=os.path.join('/kaggle/working/dogify/logs',\n                      datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n  return tf_keras.callbacks.TensorBoard(log_dir=logdir)","metadata":{"id":"8C96D16E7hMM","execution":{"iopub.status.busy":"2024-10-17T15:01:53.078041Z","iopub.execute_input":"2024-10-17T15:01:53.078737Z","iopub.status.idle":"2024-10-17T15:01:53.1562Z","shell.execute_reply.started":"2024-10-17T15:01:53.078691Z","shell.execute_reply":"2024-10-17T15:01:53.15524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Early stopping Callback\n\nstop our model from overfitting by stopping training if a certain evaluation metric stops improving","metadata":{"id":"9vznVS-7-Iq8"}},{"cell_type":"code","source":"# Create early stopping call back\nearly_stopping= tf_keras.callbacks.EarlyStopping(monitor='val_accuracy',patience=3)\n","metadata":{"id":"8IQGK1Bg8uUb","execution":{"iopub.status.busy":"2024-10-17T15:01:53.157513Z","iopub.execute_input":"2024-10-17T15:01:53.15793Z","iopub.status.idle":"2024-10-17T15:01:53.166097Z","shell.execute_reply.started":"2024-10-17T15:01:53.157884Z","shell.execute_reply":"2024-10-17T15:01:53.165318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training a model (on a subset of data)\n\nOur first model is only going to train a 1000 images, to make sure everthing is working","metadata":{"id":"IaPSxQuC_Nqk"}},{"cell_type":"code","source":"NUM_EPOCHS = 100 # @param {type:'slider',step:10,min:10,max:100}","metadata":{"id":"o_4mPBPU-0KL","execution":{"iopub.status.busy":"2024-10-17T15:01:53.167145Z","iopub.execute_input":"2024-10-17T15:01:53.167551Z","iopub.status.idle":"2024-10-17T15:01:53.178078Z","shell.execute_reply.started":"2024-10-17T15:01:53.167496Z","shell.execute_reply":"2024-10-17T15:01:53.177162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's Create a function to train our model\n\n* Create a model using `create_model()`\n* Setup TensorBoard callbacks using `create_tensorboard_callback()`\n* call the `fit()` function on our model passing it the training data, validation data, number of epochs to train for\n* Return a model","metadata":{"id":"9QiPEyKfA4Ek"}},{"cell_type":"code","source":"def train_model():\n  \"\"\"\n  Trains a given model and returns the trained version\n  \"\"\"\n  # Create a model\n  model= create_model()\n  # Create New Tensorborad every time we train a model\n  tensorbaorad= create_tensorboard_callback()\n\n  # Fit the model to the data passing it the callbacks\n  model.fit(x=train_data,\n            epochs=NUM_EPOCHS,\n            validation_data=val_data,\n            validation_freq=1,\n            callbacks=[tensorbaorad,early_stopping]\n            )\n  # Return the fitted model\n\n  return model\n","metadata":{"id":"MtMGpswLAEo9","execution":{"iopub.status.busy":"2024-10-17T15:01:53.179252Z","iopub.execute_input":"2024-10-17T15:01:53.179644Z","iopub.status.idle":"2024-10-17T15:01:53.187896Z","shell.execute_reply.started":"2024-10-17T15:01:53.1796Z","shell.execute_reply":"2024-10-17T15:01:53.186866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the model to the data\nmodel = train_model()","metadata":{"id":"ecugvqTeBdww","outputId":"3f5aea25-f59b-4968-f521-3d0572de1fc3","execution":{"iopub.status.busy":"2024-10-17T15:01:53.18911Z","iopub.execute_input":"2024-10-17T15:01:53.189451Z","iopub.status.idle":"2024-10-17T15:02:40.022732Z","shell.execute_reply.started":"2024-10-17T15:01:53.189413Z","shell.execute_reply":"2024-10-17T15:02:40.021695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Its look like our model is overfitting because it's performing far better on the training set than the validation set\n\n**NOTE**: overfitting to begin with is a good thing. it means our model is learning!! 📗","metadata":{"id":"wv7BfkPAo1FX"}},{"cell_type":"markdown","source":"### check the tensorboard logs\n\nThe Tensorboard Magic function (`%tensorboard`) will access the logs directory we created earlier and Visulaize it's content","metadata":{"id":"_7RtT79IqSTv"}},{"cell_type":"code","source":"### check the tensorboard\n%tensorboard --logdir /content/drive/MyDrive/Dog-Vision/logs","metadata":{"id":"i3jaWdzipDaU","outputId":"4b050ee7-1aa1-4941-f6ee-fca7dda001f8","execution":{"iopub.status.busy":"2024-10-17T15:02:46.283676Z","iopub.execute_input":"2024-10-17T15:02:46.284116Z","iopub.status.idle":"2024-10-17T15:02:52.305237Z","shell.execute_reply.started":"2024-10-17T15:02:46.284075Z","shell.execute_reply":"2024-10-17T15:02:52.304284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making and Evaluation prediction using a trained model","metadata":{"id":"8gjwnPt8sJbm"}},{"cell_type":"code","source":"# make perdiction on the validation data\npredicitons= model.predict(val_data,verbose=1)\npredicitons","metadata":{"id":"cdMDn0_5qxhg","outputId":"2c1dd6be-346e-454d-b427-9db0170822a9","execution":{"iopub.status.busy":"2024-10-17T15:02:52.307113Z","iopub.execute_input":"2024-10-17T15:02:52.307431Z","iopub.status.idle":"2024-10-17T15:02:53.324686Z","shell.execute_reply.started":"2024-10-17T15:02:52.307398Z","shell.execute_reply":"2024-10-17T15:02:53.323688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predicitons.shape","metadata":{"id":"0exFWrOtstkY","outputId":"43ac39a8-bd54-461f-fa31-adec6837d7d5","execution":{"iopub.status.busy":"2024-10-17T15:02:53.325918Z","iopub.execute_input":"2024-10-17T15:02:53.326241Z","iopub.status.idle":"2024-10-17T15:02:53.332448Z","shell.execute_reply.started":"2024-10-17T15:02:53.326205Z","shell.execute_reply":"2024-10-17T15:02:53.33157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First predictions\nindex=0\nprint(predicitons[0])\nprint(f\"Max value (probablity of prediction ):{np.max(predicitons[index])}\")\nprint(f\"sum :{np.sum(predicitons[index])}\")\nprint(f\"max value : {np.argmax(predicitons[index])}\")\nprint(f\"Predicted label:{unique_breeds[np.argmax(predicitons[index])]}\")","metadata":{"id":"xmd4mMC7s1Bo","outputId":"e5fa6b47-e294-4d55-d908-ad4d6cd2f7b0","execution":{"iopub.status.busy":"2024-10-17T15:02:53.333783Z","iopub.execute_input":"2024-10-17T15:02:53.3344Z","iopub.status.idle":"2024-10-17T15:02:53.345915Z","shell.execute_reply.started":"2024-10-17T15:02:53.334357Z","shell.execute_reply":"2024-10-17T15:02:53.345033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Having the above functionality is greet but we want to be able to do it at scale.\n\nAnd it would be even better if we could see the image , the prediction is being make on\n\n**NOTE:** prediction probabitlity are also known as confidence level","metadata":{"id":"fce-x56u4aIU"}},{"cell_type":"code","source":"# Trun probabilities into their respective label (eaier 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\npred_label= get_pred_label(predicitons[0])\npred_label","metadata":{"id":"FlBShhm04r-Q","outputId":"aade4ab7-fb3d-4304-8e34-591738bd18a4","execution":{"iopub.status.busy":"2024-10-17T15:02:53.348863Z","iopub.execute_input":"2024-10-17T15:02:53.349193Z","iopub.status.idle":"2024-10-17T15:02:53.358848Z","shell.execute_reply.started":"2024-10-17T15:02:53.349161Z","shell.execute_reply":"2024-10-17T15:02:53.357968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now since our validation data is still in a batch dataset, we'll have to un-batch it to make predictions on a validation images and then compare those predictions to the validation labels","metadata":{"id":"bpvorK4d6RkF"}},{"cell_type":"code","source":"# Create a function to un-batch\ndef unbatchify(data):\n  \"\"\"\n  Takes a batch datasets of (image, label) Tensors and returns seperate arrays\n   of images and labels\n  \"\"\"\n  images=[]\n  labels=[]\n  for image, label in data.unbatch().as_numpy_iterator():\n    images.append(image)\n    labels.append(unique_breeds[np.argmax(label)])\n  return images, labels\n# Unbatch the validation\nval_image , val_label= unbatchify(val_data)\nval_image[0], val_label[0]","metadata":{"id":"j0uj2j2B59lw","outputId":"61ac2a23-efb5-4802-d1fd-08ea6735fab6","execution":{"iopub.status.busy":"2024-10-17T15:02:53.359908Z","iopub.execute_input":"2024-10-17T15:02:53.36022Z","iopub.status.idle":"2024-10-17T15:02:53.643177Z","shell.execute_reply.started":"2024-10-17T15:02:53.360189Z","shell.execute_reply":"2024-10-17T15:02:53.642261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_pred_label(val_label[0])","metadata":{"id":"tlcjyktu7tzW","outputId":"cd3b6d00-538a-4e3a-ea63-d9fd1b89b609","execution":{"iopub.status.busy":"2024-10-17T15:02:53.644569Z","iopub.execute_input":"2024-10-17T15:02:53.644968Z","iopub.status.idle":"2024-10-17T15:02:53.651419Z","shell.execute_reply.started":"2024-10-17T15:02:53.644922Z","shell.execute_reply":"2024-10-17T15:02:53.650571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we've got way to get :\n* Prediction labels\n* Validation labels (Truth labels)\n* validation images\n\nlet's make some functions to make these all a bit more visualize\n\n---\n\nWe'll Create a function which:\n* Take an array of predicitons probabilities, an array of truth labels and and array of images into integer.\n\n* convert the perdiction probabilites to a predicted label\n* plot the predicted label, it's predicted probability, the truth label and the target image on a single plot","metadata":{"id":"Acrb6Ux2-PAn"}},{"cell_type":"code","source":"def plot_pred(prediction_prob,labels,images,n=1):\n  \"\"\"\n  View the prediction, ground truth and image for sample n\n  \"\"\"\n\n  pred_prob, true_label, image = prediction_prob[n], labels[n], images[n]\n  # Get the pred label\n  pred_label = get_pred_label(pred_prob)\n  # plot image & remove ticks\n  plt.imshow(image)\n\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  # change the plot title to be predicted, probability of predictions and truth label\n  plt.title(f\"{pred_label} { np.max(pred_prob)*100:2.0f}%  {true_label}\",color=color)\n\n\n\n","metadata":{"id":"gRiIyrbW9zln","execution":{"iopub.status.busy":"2024-10-17T15:02:53.652836Z","iopub.execute_input":"2024-10-17T15:02:53.653245Z","iopub.status.idle":"2024-10-17T15:02:53.661769Z","shell.execute_reply.started":"2024-10-17T15:02:53.653197Z","shell.execute_reply":"2024-10-17T15:02:53.660923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred(predicitons, labels=val_label,images=val_image,n=1)","metadata":{"id":"exop9dp0A602","outputId":"4595f9ea-055f-48bb-ea3d-4e9494b11f45","execution":{"iopub.status.busy":"2024-10-17T15:02:53.662993Z","iopub.execute_input":"2024-10-17T15:02:53.663352Z","iopub.status.idle":"2024-10-17T15:02:53.850286Z","shell.execute_reply.started":"2024-10-17T15:02:53.663311Z","shell.execute_reply":"2024-10-17T15:02:53.849429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we've got one function to visualize our models top predictions, let's make another to view our model top 10 predictions\n\nThis function will:\n* Take an input of predictions probabilities array and a ground truth array and an int\n* Find the predicted label using `get_pred_label()`\n* find the top 10 :\n  * Predictions Probabilities indexes\n  * Predictions Probabilities values\n  * Predictions labels\n* Plot the top 10 predictions probabilities values and labels, Coloring the True labe with green🟢","metadata":{"id":"__Nqf-gL0uf1"}},{"cell_type":"code","source":"def plot_pred_conf(prediction_probabilities, labels, n=1):\n  \"\"\"\n  Plus the top 10 highest prediction confidences along with 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  # finr the top 10 prediction confidence values\n  top_10_pred_values = pred_prob[top_10_pred_indexes]\n\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 the colour 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":{"id":"cYtUhLDt1nMB","execution":{"iopub.status.busy":"2024-10-17T15:02:53.851903Z","iopub.execute_input":"2024-10-17T15:02:53.85254Z","iopub.status.idle":"2024-10-17T15:02:53.86212Z","shell.execute_reply.started":"2024-10-17T15:02:53.852481Z","shell.execute_reply":"2024-10-17T15:02:53.861017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_pred_conf(prediction_probabilities, labels,  n=1):\n    \"\"\"\n    Plots the top 10 highest prediction confidences along with the true label for sample n.\n    \"\"\"\n    pred_prob = prediction_probabilities[n]\n\n    # Convert one-hot encoded `true_label` to class index\n    true_label = np.argmax(labels[n])  # This assumes `labels` is one-hot encoded\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\n    # Find the top 10 prediction confidence values\n    top_10_pred_values = pred_prob[top_10_pred_indexes]\n\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 the color of the bar corresponding to the true label\n    true_label_name = unique_breeds[true_label]  # Convert class index to label name\n    if true_label_name in top_10_pred_labels:\n        true_label_index = np.where(top_10_pred_labels == true_label_name)[0][0]\n        top_plot[true_label_index].set_color('green')\n","metadata":{"id":"LRi9l9ZXBMIU","execution":{"iopub.status.busy":"2024-10-17T15:02:53.863807Z","iopub.execute_input":"2024-10-17T15:02:53.864183Z","iopub.status.idle":"2024-10-17T15:02:53.876782Z","shell.execute_reply.started":"2024-10-17T15:02:53.86414Z","shell.execute_reply":"2024-10-17T15:02:53.875663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predicitons,\n               labels=val_labels,\n               n=9)","metadata":{"id":"T7id6gLE5ial","outputId":"16279bb6-5ff0-44c2-eae0-983bdcb4551c","execution":{"iopub.status.busy":"2024-10-17T15:02:53.878312Z","iopub.execute_input":"2024-10-17T15:02:53.878736Z","iopub.status.idle":"2024-10-17T15:02:54.155883Z","shell.execute_reply.started":"2024-10-17T15:02:53.878692Z","shell.execute_reply":"2024-10-17T15:02:54.154966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we've got some function to help use visualize our predictions and evalute our model\nlet's check out a few  ","metadata":{"id":"8RK3Ob749Me1"}},{"cell_type":"code","source":"# Let's check out a few predictions and their different values\ni_multiplier= 1\nnum_rows= 3\nnum_cols= 2\nnum_images= num_rows*num_cols\nplt.figure(figsize=(10*num_cols,5*num_rows))\n\nfor i in range(num_images):\n  plt.subplot(num_rows, 2 * num_cols, 2 * i +1)\n  plot_pred(predicitons, labels=val_label,images=val_image,n=i + i_multiplier)\n\n  plt.subplot(num_rows,2*num_cols , 2*i+2)\n  plot_pred_conf(prediction_probabilities=predicitons,\n                 labels=val_labels,\n                 n= i+i_multiplier\n                 )\n\n  plt.tight_layout(h_pad=2)\n\nplt.show()","metadata":{"id":"27_RIp0v-Nmu","outputId":"7c904957-d6a0-44f0-b6f1-ac8aab19cd39","execution":{"iopub.status.busy":"2024-10-17T15:02:54.157421Z","iopub.execute_input":"2024-10-17T15:02:54.15778Z","iopub.status.idle":"2024-10-17T15:02:56.367752Z","shell.execute_reply.started":"2024-10-17T15:02:54.157747Z","shell.execute_reply":"2024-10-17T15:02:56.36679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Saving and reloading a trained model\n","metadata":{"id":"w2vJLdjlDALT"}},{"cell_type":"code","source":"os.mkdir('/kaggle/working/dogify/models')","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:09:08.286401Z","iopub.execute_input":"2024-10-17T15:09:08.28732Z","iopub.status.idle":"2024-10-17T15:09:08.291805Z","shell.execute_reply.started":"2024-10-17T15:09:08.287277Z","shell.execute_reply":"2024-10-17T15:09:08.290832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_model(model, suffix=None):\n  \"\"\"\n  Saves a given model in a models dir\n  and append a suffix (string)\n  \"\"\"\n  # Create a model directory pathname with current time\n  modeldir= os.path.join(\"/kaggle/working/dogify/models/\",datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n  model_path= modeldir + \"-\"+ suffix + \".keras\"\n  print(f\"saving  model to : {model_path}....\")\n  model.save(model_path)\n  return model_path\n","metadata":{"id":"AKj4H7MWBPic","execution":{"iopub.status.busy":"2024-10-17T15:09:13.865951Z","iopub.execute_input":"2024-10-17T15:09:13.866612Z","iopub.status.idle":"2024-10-17T15:09:13.872041Z","shell.execute_reply.started":"2024-10-17T15:09:13.866574Z","shell.execute_reply":"2024-10-17T15:09:13.871139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we've got functions to save and load a trained model\nlet's make sure there are work\n","metadata":{"id":"bSyHBB-5F2jM"}},{"cell_type":"code","source":"# Save our model trained on 1000 images\nsave_model(model,suffix=\"1000-images-mobilenetv2-Adam\")","metadata":{"id":"4G6uIoPdF-sL","outputId":"28afd426-28ae-4bed-ea86-1e1a45d619ea","execution":{"iopub.status.busy":"2024-10-17T15:09:21.59114Z","iopub.execute_input":"2024-10-17T15:09:21.591505Z","iopub.status.idle":"2024-10-17T15:09:21.857366Z","shell.execute_reply.started":"2024-10-17T15:09:21.591472Z","shell.execute_reply":"2024-10-17T15:09:21.856426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load a trained model\npath=\"/kaggle/working/dogify/models/20241017-150921-1000-images-mobilenetv2-Adam.keras\"\nloaded_1000_image_model=tfk.models.load_model(path,\n                      custom_objects={\"KerasLayer\":hub.KerasLayer},\n                      )","metadata":{"id":"e5ilhuDKGThy","execution":{"iopub.status.busy":"2024-10-17T15:10:30.107128Z","iopub.execute_input":"2024-10-17T15:10:30.107864Z","iopub.status.idle":"2024-10-17T15:10:34.541694Z","shell.execute_reply.started":"2024-10-17T15:10:30.10782Z","shell.execute_reply":"2024-10-17T15:10:34.540608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(val_data)","metadata":{"id":"0-2RITwoJdRc","outputId":"4772f6ab-5bed-458c-8838-d8fa6f8a3bbc","execution":{"iopub.status.busy":"2024-10-17T15:10:34.543758Z","iopub.execute_input":"2024-10-17T15:10:34.544704Z","iopub.status.idle":"2024-10-17T15:10:34.927366Z","shell.execute_reply.started":"2024-10-17T15:10:34.544656Z","shell.execute_reply":"2024-10-17T15:10:34.926497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loaded_1000_image_model.evaluate(val_data)","metadata":{"id":"TI-RV0f-Gop8","outputId":"9d2d6cfc-d7c3-4cbb-9b83-71331e2463ee","execution":{"iopub.status.busy":"2024-10-17T15:10:34.928683Z","iopub.execute_input":"2024-10-17T15:10:34.929073Z","iopub.status.idle":"2024-10-17T15:10:36.313309Z","shell.execute_reply.started":"2024-10-17T15:10:34.92903Z","shell.execute_reply":"2024-10-17T15:10:36.312392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train a model in FULL data","metadata":{"id":"uIJymJERJtP2"}},{"cell_type":"code","source":"len(x), len(y)","metadata":{"id":"m8idDtbSIvlx","outputId":"64dc8861-e3ff-4cf9-9fba-2e8f7847b5ad","execution":{"iopub.status.busy":"2024-10-17T15:10:50.711388Z","iopub.execute_input":"2024-10-17T15:10:50.711803Z","iopub.status.idle":"2024-10-17T15:10:50.718058Z","shell.execute_reply.started":"2024-10-17T15:10:50.711764Z","shell.execute_reply":"2024-10-17T15:10:50.717103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Create a data batch with the full dataset\nfull_data= create_data_batches(x,y)\n","metadata":{"id":"ezfa8eL2J9-g","outputId":"8d64b0f1-dd3e-4bc7-82e4-a6212cddd2df","execution":{"iopub.status.busy":"2024-10-17T15:10:51.220056Z","iopub.execute_input":"2024-10-17T15:10:51.220438Z","iopub.status.idle":"2024-10-17T15:10:51.352208Z","shell.execute_reply.started":"2024-10-17T15:10:51.220402Z","shell.execute_reply":"2024-10-17T15:10:51.351273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_data","metadata":{"id":"e3qJX54FKe3t","outputId":"dd60a598-3678-4631-9f97-53a60c9e5dac","execution":{"iopub.status.busy":"2024-10-17T15:10:52.420982Z","iopub.execute_input":"2024-10-17T15:10:52.421391Z","iopub.status.idle":"2024-10-17T15:10:52.42755Z","shell.execute_reply.started":"2024-10-17T15:10:52.421352Z","shell.execute_reply":"2024-10-17T15:10:52.426592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"full_model=create_model()","metadata":{"id":"-_9PEUlQKhom","outputId":"211c35bc-584f-4724-92a5-478b1e64b5a7","execution":{"iopub.status.busy":"2024-10-17T15:10:52.980941Z","iopub.execute_input":"2024-10-17T15:10:52.981708Z","iopub.status.idle":"2024-10-17T15:10:55.753069Z","shell.execute_reply.started":"2024-10-17T15:10:52.981668Z","shell.execute_reply":"2024-10-17T15:10:55.752036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create full model callback\nfull_model_tensorboard= create_tensorboard_callback()\n# No validation set when training on all the data, so we can't moitor validation accuracy\nfull_model_early_stopping= tf_keras.callbacks.EarlyStopping(monitor=\"accuracy\",patience=3)","metadata":{"id":"YgBNzGHuK3Kt","execution":{"iopub.status.busy":"2024-10-17T15:10:55.754955Z","iopub.execute_input":"2024-10-17T15:10:55.75545Z","iopub.status.idle":"2024-10-17T15:10:55.760557Z","shell.execute_reply.started":"2024-10-17T15:10:55.755403Z","shell.execute_reply":"2024-10-17T15:10:55.759635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the full-model to the full data\n\nfull_model.fit(x=full_data,\n               epochs=NUM_EPOCHS,\n               callbacks=[full_model_tensorboard,full_model_early_stopping]\n               )","metadata":{"id":"FKqK6c2NLrTS","outputId":"5892d42e-c777-4c13-89b3-ee3bd9ae7ca5","execution":{"iopub.status.busy":"2024-10-17T15:10:57.397987Z","iopub.execute_input":"2024-10-17T15:10:57.39839Z","iopub.status.idle":"2024-10-17T15:14:29.952517Z","shell.execute_reply.started":"2024-10-17T15:10:57.398353Z","shell.execute_reply":"2024-10-17T15:14:29.951582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"save_model(full_model,suffix=\"full-image-set-mobilenetv2-Adam\")","metadata":{"id":"5GYjXl7SMZ4C","outputId":"bf4ca5f1-1ca2-4149-ba63-8dad2f4ebaca","execution":{"iopub.status.busy":"2024-10-17T15:14:29.953969Z","iopub.execute_input":"2024-10-17T15:14:29.954283Z","iopub.status.idle":"2024-10-17T15:14:30.158348Z","shell.execute_reply.started":"2024-10-17T15:14:29.954249Z","shell.execute_reply":"2024-10-17T15:14:30.15741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path=\"/kaggle/working/dogify/models/20241017-151429-full-image-set-mobilenetv2-Adam.keras\"\nloaded_full_model=tfk.models.load_model(path,\n                      custom_objects={\"KerasLayer\":hub.KerasLayer},\n                      )","metadata":{"id":"ftaeldo3Npb6","execution":{"iopub.status.busy":"2024-10-17T15:14:50.663761Z","iopub.execute_input":"2024-10-17T15:14:50.664497Z","iopub.status.idle":"2024-10-17T15:14:54.963596Z","shell.execute_reply.started":"2024-10-17T15:14:50.664456Z","shell.execute_reply":"2024-10-17T15:14:54.962585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Making predictions on a test dataset\n\nsince our model has beed trained on images in the form of Tensors batches, to make predictions on a test data . we'll have got it into the same format\n\nTo make predictions on the test data , we'll:\n* Get the test images filenames.\n* Convert the filenames into test data batch\n* Make a Predictions array","metadata":{"id":"phJxHsBjR5MJ"}},{"cell_type":"code","source":"# Load test image filenames\ntest_path='/kaggle/input/dog-breed-identification/test/'\ntest_filename= [test_path + fname for fname in os.listdir(test_path)]\ntest_filename[:10]","metadata":{"id":"r6UaWnFSRrGN","outputId":"4b1c7821-e7db-4947-be28-fa502af01c86","execution":{"iopub.status.busy":"2024-10-17T15:15:01.328209Z","iopub.execute_input":"2024-10-17T15:15:01.329095Z","iopub.status.idle":"2024-10-17T15:15:01.657483Z","shell.execute_reply.started":"2024-10-17T15:15:01.329052Z","shell.execute_reply":"2024-10-17T15:15:01.656497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create test data batch\ntest_data= create_data_batches(test_filename,test_data=True)\n","metadata":{"id":"MqBMNIaDThDS","outputId":"1de295a9-7f9c-4e9a-f7c5-5131829a1757","execution":{"iopub.status.busy":"2024-10-17T15:15:04.722586Z","iopub.execute_input":"2024-10-17T15:15:04.722949Z","iopub.status.idle":"2024-10-17T15:15:04.745514Z","shell.execute_reply.started":"2024-10-17T15:15:04.722917Z","shell.execute_reply":"2024-10-17T15:15:04.744654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data","metadata":{"id":"tVZtLEXST1RP","outputId":"eec0de09-3824-4438-b360-462842fd73c7","execution":{"iopub.status.busy":"2024-10-17T15:15:06.749414Z","iopub.execute_input":"2024-10-17T15:15:06.749789Z","iopub.status.idle":"2024-10-17T15:15:06.756127Z","shell.execute_reply.started":"2024-10-17T15:15:06.749755Z","shell.execute_reply":"2024-10-17T15:15:06.755162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"⛔ **Note:** calling `predict()` on our full model and passing it the test data batch will take a long time to run (about 30 min in GPU)","metadata":{"id":"PfM280FYUfMq"}},{"cell_type":"code","source":"# Make predictions on test data batch using the loaded full model\ntest_predictions= loaded_full_model.predict(test_data,verbose=1)","metadata":{"id":"6a16PhTgUFkC","outputId":"7f5111e2-4ddb-4a40-ba35-a2def961e80b","execution":{"iopub.status.busy":"2024-10-17T15:15:10.684296Z","iopub.execute_input":"2024-10-17T15:15:10.685211Z","iopub.status.idle":"2024-10-17T15:15:39.64897Z","shell.execute_reply.started":"2024-10-17T15:15:10.685167Z","shell.execute_reply":"2024-10-17T15:15:39.648082Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predictions.shape","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:19:10.61234Z","iopub.execute_input":"2024-10-17T15:19:10.612741Z","iopub.status.idle":"2024-10-17T15:19:10.619236Z","shell.execute_reply.started":"2024-10-17T15:19:10.612703Z","shell.execute_reply":"2024-10-17T15:19:10.618346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Preparing test dataset prediction for kaggle\nLooking at the kaggle sample submission, we find that it wants  our model predictions probability output in a dataframe with an id column and a column for each different dog breed\n\n- To get the data in this format , we'll\n    - Create a pandas dataframe with an id column as will as a column for each dogbreed \n    - Add data to the ID column by extracting the test image ID's from their file path \n    - Add data ( the prediction probabilities to each of the dog breed columns \n    - Export the Dataframe as a csv to submit it to kaggle","metadata":{}},{"cell_type":"code","source":"# Create a dataframe\npred_df= pd.DataFrame(columns=['id']+list(unique_breeds))\npred_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:28:55.060134Z","iopub.execute_input":"2024-10-17T15:28:55.06051Z","iopub.status.idle":"2024-10-17T15:28:55.080339Z","shell.execute_reply.started":"2024-10-17T15:28:55.060471Z","shell.execute_reply":"2024-10-17T15:28:55.079392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Append test image ID's to prediction dataframe\ntest_ids=[os.path.splitext(path)[0] for path in os.listdir(test_path)]\npred_df[\"id\"]= test_ids","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:33:25.472452Z","iopub.execute_input":"2024-10-17T15:33:25.473349Z","iopub.status.idle":"2024-10-17T15:33:25.514325Z","shell.execute_reply.started":"2024-10-17T15:33:25.473307Z","shell.execute_reply":"2024-10-17T15:33:25.513584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:33:35.730763Z","iopub.execute_input":"2024-10-17T15:33:35.731652Z","iopub.status.idle":"2024-10-17T15:33:35.754157Z","shell.execute_reply.started":"2024-10-17T15:33:35.731613Z","shell.execute_reply":"2024-10-17T15:33:35.7532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Add the prediction probability to each column\npred_df[list(unique_breeds)] = test_predictions\npred_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:35:03.979193Z","iopub.execute_input":"2024-10-17T15:35:03.979893Z","iopub.status.idle":"2024-10-17T15:35:04.041183Z","shell.execute_reply.started":"2024-10-17T15:35:03.979849Z","shell.execute_reply":"2024-10-17T15:35:04.040123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# export to csv\npred_df.to_csv('/kaggle/working/dogify/full_model_predictions_submission_1_mobilenetv2.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2024-10-17T15:36:55.761914Z","iopub.execute_input":"2024-10-17T15:36:55.762324Z","iopub.status.idle":"2024-10-17T15:36:57.682805Z","shell.execute_reply.started":"2024-10-17T15:36:55.762284Z","shell.execute_reply":"2024-10-17T15:36:57.681896Z"},"trusted":true},"execution_count":null,"outputs":[]}]}