{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[],"gpuType":"T4","authorship_tag":"ABX9TyOVuDKXkqwjSaaALfWrv6Pl"},"accelerator":"GPU","kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":31041,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"id":"mdjOkmkQ625b","executionInfo":{"status":"ok","timestamp":1751003846568,"user_tz":240,"elapsed":829,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"6e3cffab-3288-4b53-e553-5db1caf103d1","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:11.051135Z","iopub.execute_input":"2025-06-27T06:34:11.051786Z","iopub.status.idle":"2025-06-27T06:34:19.147845Z","shell.execute_reply.started":"2025-06-27T06:34:11.051764Z","shell.execute_reply":"2025-06-27T06:34:19.146829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#!unzip '/content/drive/MyDrive/Colab Notebooks/Zero-to-Mastery/machinelearning-ai/dog-vision-deep-learning-project/dog-breed-identification.zip' -d '/content/drive/MyDrive/Colab Notebooks/Zero-to-Mastery/machinelearning-ai/dog-vision-deep-learning-project/dog-breed-identification'","metadata":{"id":"En5fSnVr9zkf","executionInfo":{"status":"ok","timestamp":1751003846571,"user_tz":240,"elapsed":22,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.149334Z","iopub.execute_input":"2025-06-27T06:34:19.149882Z","iopub.status.idle":"2025-06-27T06:34:19.153840Z","shell.execute_reply.started":"2025-06-27T06:34:19.149858Z","shell.execute_reply":"2025-06-27T06:34:19.152964Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# End-to-end Multi-class Dog Breed Classification\n\nThis notebook builds anend-to-end multi-classimage classifier using TensorFlow 2.0 and TensorFlow hub.\n\n## 1. Problem\nIdentifying 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.\nhttps://www.kaggle.com/c/dog-breed-identification/data\n\n## 3. Evaluation\nThe evaluation is a filewith prediction probabilities for each dog breed of each test image.\n\n## 4. Features\nSome information about 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 classes)","metadata":{"id":"X33JmmMBBjFw"}},{"cell_type":"code","source":"import zipfile,h5py\nimport pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\nfrom PIL import Image,ImageFilter\n\n# Consider making a class that pulls the data from the zip, allows for EDA, then download sets into h5 datasets.\n# Taken from a class project I completed recently\nclass ZipImageDatasetBuilder:\n  def __init__(self,zip_path,ext,label_map=None,split='train'):\n    self.split = split\n    self.zip_path = zip_path\n    self.zf = zipfile.ZipFile(zip_path,'r')\n    self.label_map = self._read_label_map(label_map) if label_map else None\n    self.image_index = self._index_images(ext)\n    self.label_set = set()\n    print(\"Zipfile open, be sure to close once done\")\n\n  def _read_label_map(self,label_map):\n    with self.zf.open(label_map) as f:\n      return pd.read_csv(f)\n\n  def _index_images(self,ext):\n    if self.split == 'train':\n      image_files = [f for f in self.zf.namelist() if f.lower().endswith(ext) and f.split('/')[0] == 'train']\n      return[(\n          f,\n          f.split('/')[0],\n          self.label_map.loc[self.label_map['id'] == (f.split('/')[1]).replace(f'.{ext}',''),'breed'].tolist()[0],\n          f.split('/')[1]) for f in image_files]\n\n\n  def iterate_images(self):\n    for filepath,split,label,image_key in self.image_index:\n      yield filepath,split,label,image_key\n\n  def extract_metadata_row(self,filepath,label,split,image_key):\n    try:\n      with self.zf.open(filepath) as file:\n        img = Image.open(file)\n        width,height = img.size\n        channels = len(img.getbands())\n        size_bytes = self.zf.getinfo(filepath).file_size\n      return {\n          \"image_key\":image_key,\n          \"filepath\":filepath,\n          \"split\":split,\n          \"label\":label,\n          \"width\":width,\n          \"height\":height,\n          \"channels\":channels,\n          \"size_bytes\":size_bytes\n      }\n    except Exception as e:\n      print(f\"Error processing {filepath}: {e}\")\n      return None\n\n  def extract_metadata(self,metadata_output_path):\n    metadata = []\n    for (filepath,split,label,image_key) in tqdm(self.iterate_images(),desc=\"Extracting metadata\"):\n      self.label_set.add(label)\n      row = self.extract_metadata_row(filepath,label,split,image_key)\n      if row:\n        metadata.append(row)\n\n    df = pd.DataFrame(metadata)\n    df.to_csv(metadata_output_path,index=False)\n    print(f\"{metadata_output_path} exported.\")\n\n  def width_height_kde_plot(self,metadata_output_path):\n    # read the data and setup the plots\n    df = pd.read_csv(pwd+'/metadata.csv')\n    fig = plt.figure(figsize=(12,5))\n\n    # draw kde 2d plot for image analysis\n    sns.kdeplot(data=df,x='width',y='height')\n    H,xedges,yedges = np.histogram2d(df['width'],df['height'],bins=50)\n    for x,y in np.argwhere(H==H.max()):\n      xi,yi = np.average(xedges[x:x+2]),np.average(yedges[y:y+2])\n      plt.scatter(x=xi,y=yi,color='red')\n      plt.annotate(f'({xi:.2f},{yi:.2f})',xy=(xi,yi),\n                   xytext=(xi+0.5,yi+0.5),\n                   fontsize=12,fontweight='bold',color='red')\n\n    plt.tight_layout()\n    plt.show()\n\n  def build_h5_dataset(self,hd5_path,conver_string,resize):\n    image_data = {'train':{'X':[],'y':[]},'test':{'X':[],'y':[]}}\n\n    for filepath,split,label,_ in tqdm(self.iterate_images(),desc=\"Processing images\"):\n      self.label_set.add(label)\n\n      try:\n        with self.zf.open(filepath) as file:\n          img = Image.open(file)\n          img = img.convert(conver_string).resize(resize)\n          img_arr = np.array(img,dtype=np.uint8)\n      except Exception as e:\n        print(f\"Error processing {filepath}: {e}\")\n        continue\n\n      image_data[split]['X'].append(img_arr)\n      image_data[split]['y'].append(label)\n\n    label_list = sorted(self.label_set)\n    label_to_index = {label:idx for idx,label in enumerate(label_list)}\n\n    with h5py.File(hd5_path,'w') as f:\n      for split in ['train','test']:\n        X = np.array(image_data[split]['X'],dtype=np.uint8)\n        y = np.array([label_to_index[label] for label in image_data[split]['y']],dtype=np.uint8)\n\n        f.create_dataset(f\"{split}_X\",data=X,compression=\"gzip\")\n        f.create_dataset(f\"{split}_y\",data=y)\n\n      f.create_dataset(\"label_list\",data=np.array(label_list,dtype=h5py.string_dtype(encoding='utf-8')))\n      print(f\"{hd5_path} exported.\")\n\n  def close(self):\n    self.zf.close()\n    print(\"Zipfile closed.\")","metadata":{"id":"rmqvoYRL-FQ_","executionInfo":{"status":"ok","timestamp":1751003847402,"user_tz":240,"elapsed":842,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.154734Z","iopub.execute_input":"2025-06-27T06:34:19.155263Z","iopub.status.idle":"2025-06-27T06:34:19.180300Z","shell.execute_reply.started":"2025-06-27T06:34:19.155241Z","shell.execute_reply":"2025-06-27T06:34:19.179535Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# define the directory variable\npwd = '/kaggle/input/dog-breed-identification/'","metadata":{"id":"Q9-NfPhjYLyK","executionInfo":{"status":"ok","timestamp":1751003847465,"user_tz":240,"elapsed":52,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.181009Z","iopub.execute_input":"2025-06-27T06:34:19.181372Z","iopub.status.idle":"2025-06-27T06:34:19.200785Z","shell.execute_reply.started":"2025-06-27T06:34:19.181326Z","shell.execute_reply":"2025-06-27T06:34:19.200134Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#z = ZipImageDatasetBuilder(pwd+'/dog-breed-identification.zip',ext='jpg',label_map='labels.csv')\n#z.extract_metadata(pwd+'/metadata.csv')","metadata":{"id":"j5oVi5QbXyCd","executionInfo":{"status":"ok","timestamp":1751003847483,"user_tz":240,"elapsed":8,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.202621Z","iopub.execute_input":"2025-06-27T06:34:19.203158Z","iopub.status.idle":"2025-06-27T06:34:19.216615Z","shell.execute_reply.started":"2025-06-27T06:34:19.203135Z","shell.execute_reply":"2025-06-27T06:34:19.216047Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#z.width_height_kde_plot(pwd+'/metadata.csv')","metadata":{"id":"5vKHhb0lYU_w","executionInfo":{"status":"ok","timestamp":1751003847491,"user_tz":240,"elapsed":3,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.217305Z","iopub.execute_input":"2025-06-27T06:34:19.217692Z","iopub.status.idle":"2025-06-27T06:34:19.231811Z","shell.execute_reply.started":"2025-06-27T06:34:19.217675Z","shell.execute_reply":"2025-06-27T06:34:19.231081Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#z.build_h5_dataset(pwd+'/dataset_224.h5',conver_string='RGB',resize=(128,128))\n#z.close()","metadata":{"id":"0m2FWPlyyNhy","executionInfo":{"status":"ok","timestamp":1751003847497,"user_tz":240,"elapsed":4,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.232797Z","iopub.execute_input":"2025-06-27T06:34:19.233025Z","iopub.status.idle":"2025-06-27T06:34:19.246625Z","shell.execute_reply.started":"2025-06-27T06:34:19.233010Z","shell.execute_reply":"2025-06-27T06:34:19.246043Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Get workspace ready","metadata":{"id":"rX46-TTQDBva"}},{"cell_type":"code","source":"!pip install tensorflow==2.15.0 tensorflow-hub keras==2.15.0\nimport tensorflow as tf\nimport tensorflow_hub as hub\nprint(\"TF version:\",tf.__version__)\nprint(\"TF-Hub version:\",hub.__version__)\n\n# Check for GPU availability\nprint(\"GPU\", \"available\" if tf.config.list_physical_devices(\"GPU\") else \"not available\")","metadata":{"id":"oRFP2dbIztka","executionInfo":{"status":"ok","timestamp":1751003850173,"user_tz":240,"elapsed":2673,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"8ff38a54-69cc-48f2-c009-6d57dd1da088","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:19.247300Z","iopub.execute_input":"2025-06-27T06:34:19.247539Z","iopub.status.idle":"2025-06-27T06:34:22.343387Z","shell.execute_reply.started":"2025-06-27T06:34:19.247518Z","shell.execute_reply":"2025-06-27T06:34:22.342595Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Getting our data ready (turning into tensors)","metadata":{"id":"8aCWMebQIaT-"}},{"cell_type":"code","source":"# Checkout the labels.csv file\nlabels_csv = pd.read_csv(pwd+'labels.csv')\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"id":"Krgkvt5YIXf-","executionInfo":{"status":"ok","timestamp":1751003850219,"user_tz":240,"elapsed":40,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"189d6f68-1641-4cf4-d254-8f4fa89fc98e","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:22.344454Z","iopub.execute_input":"2025-06-27T06:34:22.344734Z","iopub.status.idle":"2025-06-27T06:34:22.371837Z","shell.execute_reply.started":"2025-06-27T06:34:22.344706Z","shell.execute_reply":"2025-06-27T06:34:22.371234Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# How many images are there of each breed\nlabels_csv['breed'].value_counts().plot.bar(figsize=(20,10))","metadata":{"id":"DlMDA4BbI2qk","executionInfo":{"status":"ok","timestamp":1751003851274,"user_tz":240,"elapsed":1034,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"287f1392-7a8f-48be-a62d-00c4c3ca06c8","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:22.372534Z","iopub.execute_input":"2025-06-27T06:34:22.372814Z","iopub.status.idle":"2025-06-27T06:34:23.338531Z","shell.execute_reply.started":"2025-06-27T06:34:22.372796Z","shell.execute_reply":"2025-06-27T06:34:23.337679Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv['breed'].value_counts().median(),labels_csv['breed'].value_counts().mean()","metadata":{"id":"wY83scu3JXs4","executionInfo":{"status":"ok","timestamp":1751003851290,"user_tz":240,"elapsed":13,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"ae0ac100-6537-428e-e9df-23e101a2035a","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.339403Z","iopub.execute_input":"2025-06-27T06:34:23.339850Z","iopub.status.idle":"2025-06-27T06:34:23.349418Z","shell.execute_reply.started":"2025-06-27T06:34:23.339827Z","shell.execute_reply":"2025-06-27T06:34:23.348648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Let's view an image\nfrom IPython.display import Image\nImage(pwd+'train/001513dfcb2ffafc82cccf4d8bbaba97.jpg')","metadata":{"id":"qeHUJJt2JxHi","executionInfo":{"status":"ok","timestamp":1751003851318,"user_tz":240,"elapsed":24,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"2d69dc88-6f13-4a74-b714-6262cf204003","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.350189Z","iopub.execute_input":"2025-06-27T06:34:23.350448Z","iopub.status.idle":"2025-06-27T06:34:23.367070Z","shell.execute_reply.started":"2025-06-27T06:34:23.350426Z","shell.execute_reply":"2025-06-27T06:34:23.366393Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Getting images and their labels","metadata":{"id":"6z-ORaUyKw-K"}},{"cell_type":"code","source":"filenames = [f'{pwd}train/{fname}.jpg' for fname in labels_csv['id']]\nfilenames[:10]","metadata":{"id":"7vU7inHqKh5N","executionInfo":{"status":"ok","timestamp":1751003851320,"user_tz":240,"elapsed":16,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"c2d7a6db-099c-406b-8b10-3c42ca9c17d4","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.367789Z","iopub.execute_input":"2025-06-27T06:34:23.368070Z","iopub.status.idle":"2025-06-27T06:34:23.381288Z","shell.execute_reply.started":"2025-06-27T06:34:23.368048Z","shell.execute_reply":"2025-06-27T06:34:23.380695Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check whether number of filenames matches number of actual image files\nimport os\nif len(os.listdir(pwd+'train/')) == len(filenames):\n  print(\"Number of filenames matches the number of image files.\")","metadata":{"id":"dFJndkaZLCus","executionInfo":{"status":"ok","timestamp":1751003853576,"user_tz":240,"elapsed":2255,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"a60d8453-789b-48ad-a024-67de5f79d4d0","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.384203Z","iopub.execute_input":"2025-06-27T06:34:23.384401Z","iopub.status.idle":"2025-06-27T06:34:23.398613Z","shell.execute_reply.started":"2025-06-27T06:34:23.384387Z","shell.execute_reply":"2025-06-27T06:34:23.398015Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Image(filenames[9000])","metadata":{"id":"SRdhxnBRLogP","executionInfo":{"status":"ok","timestamp":1751003853622,"user_tz":240,"elapsed":39,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"3e555eec-a6d5-4e23-e131-670595271cf9","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.399376Z","iopub.execute_input":"2025-06-27T06:34:23.399596Z","iopub.status.idle":"2025-06-27T06:34:23.422250Z","shell.execute_reply.started":"2025-06-27T06:34:23.399576Z","shell.execute_reply":"2025-06-27T06:34:23.421561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv['breed'][9000]","metadata":{"id":"UpgaVyWFMX8Z","executionInfo":{"status":"ok","timestamp":1751003853635,"user_tz":240,"elapsed":10,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"9e691509-9c0d-4f95-d066-88bd2f16b35b","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.423006Z","iopub.execute_input":"2025-06-27T06:34:23.423239Z","iopub.status.idle":"2025-06-27T06:34:23.427895Z","shell.execute_reply.started":"2025-06-27T06:34:23.423219Z","shell.execute_reply":"2025-06-27T06:34:23.427359Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Since we've now got out training image filepaths in a list, Let's prepare our labels","metadata":{"id":"VD16z1epMqdx"}},{"cell_type":"code","source":"labels = labels_csv['breed'].to_numpy()\nlabels","metadata":{"id":"jRArLKSGMffO","executionInfo":{"status":"ok","timestamp":1751003853663,"user_tz":240,"elapsed":32,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"a9746951-cda8-490a-b08d-13f004d01038","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.428449Z","iopub.execute_input":"2025-06-27T06:34:23.428704Z","iopub.status.idle":"2025-06-27T06:34:23.444718Z","shell.execute_reply.started":"2025-06-27T06:34:23.428682Z","shell.execute_reply":"2025-06-27T06:34:23.444042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(labels)","metadata":{"id":"YglTyETZMxc4","executionInfo":{"status":"ok","timestamp":1751003853680,"user_tz":240,"elapsed":16,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"6dad1865-f550-4906-b986-7620c0845368","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.445597Z","iopub.execute_input":"2025-06-27T06:34:23.445808Z","iopub.status.idle":"2025-06-27T06:34:23.462178Z","shell.execute_reply.started":"2025-06-27T06:34:23.445789Z","shell.execute_reply":"2025-06-27T06:34:23.461621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# See if number of labels matches the number of filenames\nif len(labels) == len(filenames):\n  print(\"Number of labels matches the number of filenames.\")","metadata":{"id":"XOgYwVGHM7sw","executionInfo":{"status":"ok","timestamp":1751003853694,"user_tz":240,"elapsed":17,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"b1ce5f31-638c-447b-ca00-621406ba0082","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.462926Z","iopub.execute_input":"2025-06-27T06:34:23.463422Z","iopub.status.idle":"2025-06-27T06:34:23.478957Z","shell.execute_reply.started":"2025-06-27T06:34:23.463399Z","shell.execute_reply":"2025-06-27T06:34:23.478417Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Find the unique label values\nunique_breeds = np.unique(labels)\nlen(unique_breeds)","metadata":{"id":"a8hZSCEVNNhG","executionInfo":{"status":"ok","timestamp":1751003853758,"user_tz":240,"elapsed":62,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"d4c6ac35-a915-4375-8c4b-9a57198b17d4","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.479609Z","iopub.execute_input":"2025-06-27T06:34:23.479781Z","iopub.status.idle":"2025-06-27T06:34:23.502812Z","shell.execute_reply.started":"2025-06-27T06:34:23.479766Z","shell.execute_reply":"2025-06-27T06:34:23.502319Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Turn a single label into an array of booleans\nprint(labels[0])\nlabels[0] == unique_breeds","metadata":{"id":"f2ucAEgJNZt5","executionInfo":{"status":"ok","timestamp":1751003853758,"user_tz":240,"elapsed":19,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"c17e7f51-dfdd-4732-8820-acf115ed44d4","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.503426Z","iopub.execute_input":"2025-06-27T06:34:23.503612Z","iopub.status.idle":"2025-06-27T06:34:23.519681Z","shell.execute_reply.started":"2025-06-27T06:34:23.503592Z","shell.execute_reply":"2025-06-27T06:34:23.519154Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Turn every label into a boolean array\nboolean_labels = [label == unique_breeds for label in labels]\nboolean_labels[:2]","metadata":{"id":"egP-YYSHNs-K","executionInfo":{"status":"ok","timestamp":1751003853881,"user_tz":240,"elapsed":128,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"fead09ef-2a1f-4b2b-d7cf-e854a4053f0b","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.520379Z","iopub.execute_input":"2025-06-27T06:34:23.520635Z","iopub.status.idle":"2025-06-27T06:34:23.586478Z","shell.execute_reply.started":"2025-06-27T06:34:23.520620Z","shell.execute_reply":"2025-06-27T06:34:23.585939Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(boolean_labels)","metadata":{"id":"abpfJs6tN5z7","executionInfo":{"status":"ok","timestamp":1751003853883,"user_tz":240,"elapsed":72,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"15f7b606-eb3c-4c47-f000-d33781a758e1","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.587251Z","iopub.execute_input":"2025-06-27T06:34:23.587487Z","iopub.status.idle":"2025-06-27T06:34:23.592399Z","shell.execute_reply.started":"2025-06-27T06:34:23.587466Z","shell.execute_reply":"2025-06-27T06:34:23.591540Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Example: Turning boolean array into integers\nprint(labels[0])\nprint(np.where(unique_breeds == labels[0]))\nprint(boolean_labels[0].argmax())\nboolean_labels[0].argmax()","metadata":{"id":"hGyKvxkhOAdx","executionInfo":{"status":"ok","timestamp":1751003853883,"user_tz":240,"elapsed":19,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"677b2df0-a5fb-433d-a1b6-291a5b3d5e21","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.593265Z","iopub.execute_input":"2025-06-27T06:34:23.593596Z","iopub.status.idle":"2025-06-27T06:34:23.609637Z","shell.execute_reply.started":"2025-06-27T06:34:23.593573Z","shell.execute_reply":"2025-06-27T06:34:23.609063Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating our own validation set","metadata":{"id":"vPdNyWO3O4-D"}},{"cell_type":"code","source":"# Setup X and y variables\nX = filenames\ny = boolean_labels","metadata":{"id":"52tZ2kSsOPpc","executionInfo":{"status":"ok","timestamp":1751003853888,"user_tz":240,"elapsed":4,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.610425Z","iopub.execute_input":"2025-06-27T06:34:23.610702Z","iopub.status.idle":"2025-06-27T06:34:23.626182Z","shell.execute_reply.started":"2025-06-27T06:34:23.610686Z","shell.execute_reply":"2025-06-27T06:34:23.625654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(filenames)","metadata":{"id":"ywhpLjJxPO9C","executionInfo":{"status":"ok","timestamp":1751003853904,"user_tz":240,"elapsed":13,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"5bb9db53-e3c1-4032-e2ec-96926fd5415c","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.627017Z","iopub.execute_input":"2025-06-27T06:34:23.627238Z","iopub.status.idle":"2025-06-27T06:34:23.641980Z","shell.execute_reply.started":"2025-06-27T06:34:23.627221Z","shell.execute_reply":"2025-06-27T06:34:23.641365Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"We're going to start off experimenting with ~1000 images and increase as needed.","metadata":{"id":"L3GJhOK3PaRQ"}},{"cell_type":"code","source":"# Set number of images to use for experimenting\nNUM_IMAGES = 1000 #@param {type:\"slider\",min:1000,max:10000}","metadata":{"id":"c4Fa0G6fPRc1","executionInfo":{"status":"ok","timestamp":1751003853910,"user_tz":240,"elapsed":4,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.642680Z","iopub.execute_input":"2025-06-27T06:34:23.642866Z","iopub.status.idle":"2025-06-27T06:34:23.655034Z","shell.execute_reply.started":"2025-06-27T06:34:23.642852Z","shell.execute_reply":"2025-06-27T06:34:23.654428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Let's split our data into train and validation sets\nfrom sklearn.model_selection import train_test_split\nX_train,X_val,y_train,y_val = train_test_split(X[:NUM_IMAGES],y[:NUM_IMAGES],test_size=0.2,random_state=42)\n\nlen(X_train),len(y_train),len(X_val),len(y_val)","metadata":{"id":"XLd-7h3IPw21","executionInfo":{"status":"ok","timestamp":1751003854050,"user_tz":240,"elapsed":138,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"0520346b-d765-49fe-a9bc-4bcd7de7bf4d","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.655624Z","iopub.execute_input":"2025-06-27T06:34:23.655785Z","iopub.status.idle":"2025-06-27T06:34:23.675099Z","shell.execute_reply.started":"2025-06-27T06:34:23.655768Z","shell.execute_reply":"2025-06-27T06:34:23.674558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Let's have a geez at the training data\nX_train[:5],y_train[:2]","metadata":{"id":"bg8lSDawQKKk","executionInfo":{"status":"ok","timestamp":1751003854051,"user_tz":240,"elapsed":31,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"9f78902c-e23d-4fac-d518-ef00c3fb2497","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.675931Z","iopub.execute_input":"2025-06-27T06:34:23.676158Z","iopub.status.idle":"2025-06-27T06:34:23.690318Z","shell.execute_reply.started":"2025-06-27T06:34:23.676141Z","shell.execute_reply":"2025-06-27T06:34:23.689751Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Preprocessing Images (turning images into Tensors)\n\nTo preprocess our images into Tensors we're going to write a function which does a few things:\n1. Take an image filepath as input\n2. Use TensorFlow to read a file and save it to a variable `image`\n3. Turn our `image` (a jpg) into Tensors\n4. Resize the `image` to be a shape (224,224)\n5. Return the modified `image`","metadata":{"id":"NZomDwzLQk18"}},{"cell_type":"code","source":"from matplotlib.pyplot import imread\nimage = imread(filenames[42])\nimage.shape","metadata":{"id":"40DSWd6SQUdy","executionInfo":{"status":"ok","timestamp":1751003854051,"user_tz":240,"elapsed":22,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"f0889de8-2df3-42f2-a8f5-d910bd54f3b7","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.690992Z","iopub.execute_input":"2025-06-27T06:34:23.691208Z","iopub.status.idle":"2025-06-27T06:34:23.708032Z","shell.execute_reply.started":"2025-06-27T06:34:23.691193Z","shell.execute_reply":"2025-06-27T06:34:23.707492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image","metadata":{"id":"6FXbt3v8Rtp3","executionInfo":{"status":"ok","timestamp":1751003854111,"user_tz":240,"elapsed":66,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"d0f8a5f6-5942-4585-edb2-dac1b9e1a616","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.708705Z","iopub.execute_input":"2025-06-27T06:34:23.708880Z","iopub.status.idle":"2025-06-27T06:34:23.721465Z","shell.execute_reply.started":"2025-06-27T06:34:23.708858Z","shell.execute_reply":"2025-06-27T06:34:23.720866Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tf.constant(image)","metadata":{"id":"IIUCcFJzR4yx","executionInfo":{"status":"ok","timestamp":1751003854147,"user_tz":240,"elapsed":33,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"80b297ac-02c1-48ae-8cfc-6b64e462481d","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.722058Z","iopub.execute_input":"2025-06-27T06:34:23.722307Z","iopub.status.idle":"2025-06-27T06:34:23.738212Z","shell.execute_reply.started":"2025-06-27T06:34:23.722287Z","shell.execute_reply":"2025-06-27T06:34:23.737586Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Now we've seenwhat an image looks like as a tensor, let's make a function to preprocess them.","metadata":{"id":"Fl-2Fn01SeS-"}},{"cell_type":"code","source":"# Define image size\nIMG_SIZE = 224 #@param {type:\"slider\",min:128,max:512,step:64}\n\n#Create a function for preprocessing images\ndef process_image(image_path):\n  image = tf.io.read_file(image_path)\n  image = tf.image.decode_jpeg(image,channels=3)\n  image = tf.image.convert_image_dtype(image,tf.float32)\n  image = tf.image.resize(image,size=[IMG_SIZE,IMG_SIZE])\n  return image","metadata":{"id":"0VOz5WHiSEIO","executionInfo":{"status":"ok","timestamp":1751003854149,"user_tz":240,"elapsed":5,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.738875Z","iopub.execute_input":"2025-06-27T06:34:23.739080Z","iopub.status.idle":"2025-06-27T06:34:23.751470Z","shell.execute_reply.started":"2025-06-27T06:34:23.739056Z","shell.execute_reply":"2025-06-27T06:34:23.750804Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Turning our data into batches","metadata":{"id":"QBMCBe6sU81K"}},{"cell_type":"code","source":"# Create a simple function that returns a tuple of tensors\ndef get_image_label(image_path,label):\n  return process_image(image_path),label","metadata":{"id":"6sGYG6ztUKko","executionInfo":{"status":"ok","timestamp":1751003854196,"user_tz":240,"elapsed":14,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.752214Z","iopub.execute_input":"2025-06-27T06:34:23.752433Z","iopub.status.idle":"2025-06-27T06:34:23.764984Z","shell.execute_reply.started":"2025-06-27T06:34:23.752409Z","shell.execute_reply":"2025-06-27T06:34:23.764432Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Now we've got a way to turn our data into tuples of tensors in the form: `(image,label)`, let's make a function to turn all of our data (`X` & `y`) into batches","metadata":{"id":"vmIobNC3WVFx"}},{"cell_type":"code","source":"# Define the batch size, 32 is a good start\nBATCH_SIZE = 32\n\n# Create a function to turn data into batches\ndef create_data_batches(X,y=None,batch_size=BATCH_SIZE,valid_data=False,test_data=False):\n  \"\"\"\n  Creates batches of data out of image (X) and label (y) pairs.\n  Shuffles the data if it's training data but doesn't shuffle it if it's validation data.\n  Also accepts test data as input (no labels).\n  \"\"\"\n\n  if test_data:\n    print(\"Create test data batches...\")\n    data = tf.data.Dataset.from_tensor_slices(tf.constant(X)) # Only filepaths, no labels\n    data_batch = data.map(process_image).batch(BATCH_SIZE)\n    return data_batch\n\n  elif valid_data:\n    print(\"Create validation data batches...\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(X),tf.constant(y)))\n    data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n    return data_batch\n\n  print(\"Create training data batches...\")\n  # Turn filepaths and labels into Tensors\n  data = tf.data.Dataset.from_tensor_slices((tf.constant(X),tf.constant(y)))\n  data = data.shuffle(buffer_size=len(X))\n  data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n  return data_batch","metadata":{"id":"vhXhQHrCV3BQ","executionInfo":{"status":"ok","timestamp":1751003854198,"user_tz":240,"elapsed":10,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.765601Z","iopub.execute_input":"2025-06-27T06:34:23.765765Z","iopub.status.idle":"2025-06-27T06:34:23.778847Z","shell.execute_reply.started":"2025-06-27T06:34:23.765752Z","shell.execute_reply":"2025-06-27T06:34:23.778237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_data_batches(X_train,y_train)\nval_data = create_data_batches(X_val,y_val,valid_data=True)","metadata":{"id":"m7ljo5gTY4Lh","executionInfo":{"status":"ok","timestamp":1751003854314,"user_tz":240,"elapsed":121,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"ad80deef-01a3-4147-cf9c-27ecd69a0db1","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.779456Z","iopub.execute_input":"2025-06-27T06:34:23.779678Z","iopub.status.idle":"2025-06-27T06:34:23.881453Z","shell.execute_reply.started":"2025-06-27T06:34:23.779659Z","shell.execute_reply":"2025-06-27T06:34:23.880904Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check out the different attributes of our data batches\ntrain_data.element_spec,val_data.element_spec","metadata":{"id":"zlZbHPDvZBg0","executionInfo":{"status":"ok","timestamp":1751003854364,"user_tz":240,"elapsed":49,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"8abcb6f5-188f-4623-9103-eaa38591c9c7","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.882163Z","iopub.execute_input":"2025-06-27T06:34:23.882352Z","iopub.status.idle":"2025-06-27T06:34:23.886652Z","shell.execute_reply.started":"2025-06-27T06:34:23.882337Z","shell.execute_reply":"2025-06-27T06:34:23.886067Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Visualizing Data Batches","metadata":{"id":"z4b6IvUXZ1ab"}},{"cell_type":"code","source":"# Create a function for viewing images in a data batch\ndef show_25_images(images,labels):\n  \"\"\"\n  Displays 25 images from a data batch.\n  \"\"\"\n  # Setup the figure\n  plt.figure(figsize=(10,10))\n  for i in range(25):\n    ax = plt.subplot(5,5,i+1)\n    plt.imshow(images[i])\n    plt.axis(\"off\")\n    plt.title(unique_breeds[labels[i].argmax()])\n\ntrain_images,train_labels = next(train_data.as_numpy_iterator())\nshow_25_images(train_images,train_labels)","metadata":{"id":"pSWlNBG4ZYZB","executionInfo":{"status":"ok","timestamp":1751003867164,"user_tz":240,"elapsed":12797,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"be07c469-71a6-4a13-d14a-9892c7a6517a","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:23.887270Z","iopub.execute_input":"2025-06-27T06:34:23.887488Z","iopub.status.idle":"2025-06-27T06:34:25.859987Z","shell.execute_reply.started":"2025-06-27T06:34:23.887465Z","shell.execute_reply":"2025-06-27T06:34:25.859109Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Building a model\n\nBefore we build a model, there are a few things we need to define:\n* The input shape\n* The output shape\n* The URL of the model we want to use","metadata":{"id":"4p35_BqvcW9e"}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None,IMG_SIZE,IMG_SIZE,3] # Batch, Height, Width, Colour channels\n\n# Setup output shape of our model\nOUTPUT_SHAPE = len(unique_breeds)\n\n# Setup model URL\nMODEL_URL = \"https://tfhub.dev/google/imagenet/mobilenet_v2_130_224/classification/4\"","metadata":{"id":"IP6RWN_eaOE2","executionInfo":{"status":"ok","timestamp":1751003867202,"user_tz":240,"elapsed":5,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:25.860799Z","iopub.execute_input":"2025-06-27T06:34:25.861029Z","iopub.status.idle":"2025-06-27T06:34:25.865425Z","shell.execute_reply.started":"2025-06-27T06:34:25.861012Z","shell.execute_reply":"2025-06-27T06:34:25.864667Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Now we've got our inputs, outputs, and model ready to go.\nLet's put them together into a Keras deep learning model","metadata":{"id":"wYD0F8FMf_dO"}},{"cell_type":"code","source":"# Create a function which builds a Keras model\ndef create_model(input_shape=INPUT_SHAPE,output_shape=OUTPUT_SHAPE,model_url=MODEL_URL):\n  print(\"Building model with:\",MODEL_URL)\n\n  # Setup the model layers\n  model = tf.keras.Sequential([\n      hub.KerasLayer(MODEL_URL),\n      tf.keras.layers.Dense(units=OUTPUT_SHAPE,activation=\"softmax\")\n  ])\n\n  # Compile the model\n  model.compile(\n      loss=tf.keras.losses.CategoricalCrossentropy(),\n      optimizer=tf.keras.optimizers.Adam(),\n      metrics=[\"accuracy\"]\n  )\n\n  # Build the model\n  model.build(INPUT_SHAPE)\n  return model","metadata":{"id":"j8T1wuVbfZ14","executionInfo":{"status":"ok","timestamp":1751003867220,"user_tz":240,"elapsed":6,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:25.866193Z","iopub.execute_input":"2025-06-27T06:34:25.866398Z","iopub.status.idle":"2025-06-27T06:34:25.885455Z","shell.execute_reply.started":"2025-06-27T06:34:25.866383Z","shell.execute_reply":"2025-06-27T06:34:25.884646Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = create_model()\nmodel.summary()","metadata":{"id":"XXmV2mcohQ46","executionInfo":{"status":"ok","timestamp":1751003868884,"user_tz":240,"elapsed":1662,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"a3cf25c2-12c2-4ea3-c7f6-b747b5a10df7","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:25.891150Z","iopub.execute_input":"2025-06-27T06:34:25.891337Z","iopub.status.idle":"2025-06-27T06:34:29.368473Z","shell.execute_reply.started":"2025-06-27T06:34:25.891324Z","shell.execute_reply":"2025-06-27T06:34:29.367865Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating Callbacks\n1. Tensorboard\n2. Early stopping","metadata":{"id":"9AUvKTlBoikw"}},{"cell_type":"code","source":"# Load Tensorboard notebook extension\n#%load_ext tensorboard","metadata":{"id":"nOW0glIPhUeD","executionInfo":{"status":"ok","timestamp":1751003869003,"user_tz":240,"elapsed":98,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:29.369094Z","iopub.execute_input":"2025-06-27T06:34:29.369320Z","iopub.status.idle":"2025-06-27T06:34:29.372690Z","shell.execute_reply.started":"2025-06-27T06:34:29.369305Z","shell.execute_reply":"2025-06-27T06:34:29.372000Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import datetime\n\n# Create a function to build a Tensorboard callback\ndef create_tensorboard_callback():\n  logdir = os.path.join(\"logs\",datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n  print(f\"Saving TensorBoard log files to: {pwd+logdir}\")\n  return tf.keras.callbacks.TensorBoard(pwd+logdir)","metadata":{"id":"Og9DArV5pHFh","executionInfo":{"status":"ok","timestamp":1751003869004,"user_tz":240,"elapsed":75,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:29.373520Z","iopub.execute_input":"2025-06-27T06:34:29.373794Z","iopub.status.idle":"2025-06-27T06:34:29.391176Z","shell.execute_reply.started":"2025-06-27T06:34:29.373778Z","shell.execute_reply":"2025-06-27T06:34:29.390593Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Early Stopping Callback","metadata":{"id":"v7k079lXqkIx"}},{"cell_type":"code","source":"# Create early stopping callback\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3)","metadata":{"id":"uZOo4qWBp1wk","executionInfo":{"status":"ok","timestamp":1751003869005,"user_tz":240,"elapsed":42,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:29.391970Z","iopub.execute_input":"2025-06-27T06:34:29.392225Z","iopub.status.idle":"2025-06-27T06:34:29.406021Z","shell.execute_reply.started":"2025-06-27T06:34:29.392205Z","shell.execute_reply":"2025-06-27T06:34:29.405470Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Training a model (on a subset of data)","metadata":{"id":"2t22EaGkrKNQ"}},{"cell_type":"code","source":"NUM_EPOCHS = 100 #@param {type:\"slider\",min:10,max:100}","metadata":{"id":"1ji3dEIYq7zU","executionInfo":{"status":"ok","timestamp":1751003869007,"user_tz":240,"elapsed":35,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:29.406676Z","iopub.execute_input":"2025-06-27T06:34:29.406886Z","iopub.status.idle":"2025-06-27T06:34:29.420805Z","shell.execute_reply.started":"2025-06-27T06:34:29.406871Z","shell.execute_reply":"2025-06-27T06:34:29.420229Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check to make sure we'restill running on a GPU\nprint(\"GPU\",\"available\" if tf.config.list_physical_devices(\"GPU\") else \"not available\")","metadata":{"id":"E8zKJakVrvRR","executionInfo":{"status":"ok","timestamp":1751003869008,"user_tz":240,"elapsed":31,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"16881a38-e6f0-4910-af1a-80aad6bcb792","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:29.421474Z","iopub.execute_input":"2025-06-27T06:34:29.421691Z","iopub.status.idle":"2025-06-27T06:34:29.437557Z","shell.execute_reply.started":"2025-06-27T06:34:29.421676Z","shell.execute_reply":"2025-06-27T06:34:29.436864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# BUild a function to train and return a trained model\ndef train_model():\n  model = create_model()\n  tensorboard = create_tensorboard_callback()\n  model.fit(x=train_data,\n            epochs=NUM_EPOCHS,\n            validation_data=val_data,\n            validation_freq=1,\n            callbacks=[early_stopping])\n  return model","metadata":{"id":"ABd8Te5mr6KA","executionInfo":{"status":"ok","timestamp":1751003869008,"user_tz":240,"elapsed":17,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:41.111025Z","iopub.execute_input":"2025-06-27T06:34:41.111597Z","iopub.status.idle":"2025-06-27T06:34:41.115603Z","shell.execute_reply.started":"2025-06-27T06:34:41.111574Z","shell.execute_reply":"2025-06-27T06:34:41.114756Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fit the model to the data\nmodel = train_model()","metadata":{"id":"dO5ebrPotfP_","executionInfo":{"status":"ok","timestamp":1751004737191,"user_tz":240,"elapsed":868194,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"c76b98c8-dad1-4480-8493-f1b5cee33736","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:34:41.478229Z","iopub.execute_input":"2025-06-27T06:34:41.478444Z","iopub.status.idle":"2025-06-27T06:39:19.711598Z","shell.execute_reply.started":"2025-06-27T06:34:41.478427Z","shell.execute_reply":"2025-06-27T06:39:19.711019Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Checking the Tensorboard logs","metadata":{"id":"8O-jHl-2vkGg"}},{"cell_type":"code","source":"#%tensorboard --logdir '/content/drive/MyDrive/Colab Notebooks/Zero-to-Mastery/machinelearning-ai/dog-vision-deep-learning-project/logs'","metadata":{"id":"1Z0sU1Dqvm5H","executionInfo":{"status":"ok","timestamp":1751004743206,"user_tz":240,"elapsed":5987,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"c4edfd0d-6a2d-47cd-9ea4-d580c1b09d1f","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:19.735971Z","iopub.execute_input":"2025-06-27T06:39:19.736222Z","iopub.status.idle":"2025-06-27T06:39:19.739626Z","shell.execute_reply.started":"2025-06-27T06:39:19.736204Z","shell.execute_reply":"2025-06-27T06:39:19.738907Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Making and evaluating predictions using a trained model","metadata":{"id":"nGy5HfdBw4sW"}},{"cell_type":"code","source":"# Make predictions on the validation data (not used to train on)\npredictions = model.predict(val_data,verbose=1)\npredictions","metadata":{"id":"AJTB4PhmwCR6","executionInfo":{"status":"ok","timestamp":1751004754981,"user_tz":240,"elapsed":11748,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"0bd1c025-2ee7-4bcd-b275-d6269744947e","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:19.740486Z","iopub.execute_input":"2025-06-27T06:39:19.740732Z","iopub.status.idle":"2025-06-27T06:39:24.855839Z","shell.execute_reply.started":"2025-06-27T06:39:19.740710Z","shell.execute_reply":"2025-06-27T06:39:24.855139Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions.shape","metadata":{"id":"V0llmDyLxSUX","executionInfo":{"status":"ok","timestamp":1751004755047,"user_tz":240,"elapsed":55,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"e83df70e-6307-46f7-f534-060ed9741a57","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:24.857693Z","iopub.execute_input":"2025-06-27T06:39:24.857894Z","iopub.status.idle":"2025-06-27T06:39:24.862670Z","shell.execute_reply.started":"2025-06-27T06:39:24.857879Z","shell.execute_reply":"2025-06-27T06:39:24.862058Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"index = 0\nprint(predictions[index])\nprint(f\"Max value (probability of prediction): {np.max(predictions[index])}\")\nprint(f\"Sum: {np.sum(predictions[index])}\")\nprint(f\"Max index: {np.argmax(predictions[index])}\")\nprint(f\"Predicted label: {unique_breeds[np.argmax(predictions[index])]}\")","metadata":{"id":"tHGXOkAYxay4","executionInfo":{"status":"ok","timestamp":1751004755139,"user_tz":240,"elapsed":76,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"e21583a1-73fd-4e45-bf22-7c08ff5af49f","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:24.863343Z","iopub.execute_input":"2025-06-27T06:39:24.863512Z","iopub.status.idle":"2025-06-27T06:39:24.880837Z","shell.execute_reply.started":"2025-06-27T06:39:24.863499Z","shell.execute_reply":"2025-06-27T06:39:24.880073Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Having the above functionality is great but we want to be able to do it at scale.","metadata":{"id":"mCJx5VkwzqmK"}},{"cell_type":"code","source":"# Turn prediction probabilities into thei rrespective label (easier to understand)\ndef get_pred_label(prediction_probabilities):\n  return unique_breeds[np.argmax(prediction_probabilities)]\n\n# Get a predicted label based on array of prediction probabilities\npred_label = get_pred_label(predictions[0])\npred_label","metadata":{"id":"LQXL23Lpy41g","executionInfo":{"status":"ok","timestamp":1751004755190,"user_tz":240,"elapsed":56,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"8d3cdd07-9cde-4fe9-9e1f-2333f321b8da","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:24.881777Z","iopub.execute_input":"2025-06-27T06:39:24.882441Z","iopub.status.idle":"2025-06-27T06:39:24.898255Z","shell.execute_reply.started":"2025-06-27T06:39:24.882423Z","shell.execute_reply":"2025-06-27T06:39:24.897598Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a function to unbatch a batch dataset\ndef unbatchify(data):\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\nval_images,val_labels = unbatchify(val_data)\nval_images[0],val_labels[0]","metadata":{"id":"k32MACmJ0OZi","executionInfo":{"status":"ok","timestamp":1751004755240,"user_tz":240,"elapsed":46,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"ba2c262c-5342-4c36-9dc8-d5a2a58f7ab7","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:24.898984Z","iopub.execute_input":"2025-06-27T06:39:24.899319Z","iopub.status.idle":"2025-06-27T06:39:25.188981Z","shell.execute_reply.started":"2025-06-27T06:39:24.899302Z","shell.execute_reply":"2025-06-27T06:39:25.188304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"get_pred_label(val_labels[0])","metadata":{"id":"WZTYT5nH26II","executionInfo":{"status":"ok","timestamp":1751004755261,"user_tz":240,"elapsed":30,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"4c5f02af-b86e-4851-e84f-23e17ea9aea6","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:25.189765Z","iopub.execute_input":"2025-06-27T06:39:25.190023Z","iopub.status.idle":"2025-06-27T06:39:25.194572Z","shell.execute_reply.started":"2025-06-27T06:39:25.190007Z","shell.execute_reply":"2025-06-27T06:39:25.193983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_pred(prediction_probabilities,labels,images,n=1):\n  pred_prob,true_label,image = prediction_probabilities[n],labels[n],images[n]\n  pred_label = get_pred_label(pred_prob)\n\n  plt.imshow(image)\n  if pred_label == true_label:\n    color = \"green\"\n  else:\n    color = \"red\"\n  plt.title(f\"Prediction: {pred_label} \\n Probability: {np.max(pred_prob):.2f} \\n True label: {true_label}\",color=color)\n  plt.axis(False)","metadata":{"id":"QxqMSE6y3BrW","executionInfo":{"status":"ok","timestamp":1751004755279,"user_tz":240,"elapsed":10,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:25.195298Z","iopub.execute_input":"2025-06-27T06:39:25.195521Z","iopub.status.idle":"2025-06-27T06:39:25.209966Z","shell.execute_reply.started":"2025-06-27T06:39:25.195506Z","shell.execute_reply":"2025-06-27T06:39:25.209418Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_pred(predictions,val_labels,val_images,n=0)","metadata":{"id":"AQltasll4u4S","executionInfo":{"status":"ok","timestamp":1751004755448,"user_tz":240,"elapsed":151,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"4e21b84f-8bed-40c9-f3ef-6c94bc3f1152","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:39:25.211795Z","iopub.execute_input":"2025-06-27T06:39:25.211978Z","iopub.status.idle":"2025-06-27T06:39:25.411816Z","shell.execute_reply.started":"2025-06-27T06:39:25.211964Z","shell.execute_reply":"2025-06-27T06:39:25.411151Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_pred_conf(prediction_probabilities,labels,n=1):\n  pred_prob,true_label = prediction_probabilities[n],labels[n]\n  pred_label = get_pred_label(pred_prob)\n  top_10_pred_indexes = pred_prob.argsort()[-10:][::-1]\n  top_10_pred_values = pred_prob[top_10_pred_indexes]\n  top_10_pred_labels = unique_breeds[top_10_pred_indexes]\n\n  top_plot = plt.bar(np.arange(len(top_10_pred_labels)),top_10_pred_values,color=\"grey\")\n  plt.xticks(np.arange(len(top_10_pred_labels)),labels=top_10_pred_labels,rotation='vertical')\n\n  if np.isin(true_label,top_10_pred_labels):\n    top_plot[np.argmax(top_10_pred_labels == true_label)].set_color(\"green\")","metadata":{"id":"NAQG8Jsw42Sh","executionInfo":{"status":"ok","timestamp":1751004755463,"user_tz":240,"elapsed":7,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:47:04.697882Z","iopub.execute_input":"2025-06-27T06:47:04.698195Z","iopub.status.idle":"2025-06-27T06:47:04.703418Z","shell.execute_reply.started":"2025-06-27T06:47:04.698171Z","shell.execute_reply":"2025-06-27T06:47:04.702691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,labels=labels,n=64)","metadata":{"id":"t_Fsitvp8hee","executionInfo":{"status":"error","timestamp":1751004755512,"user_tz":240,"elapsed":37,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"outputId":"11250c78-cd3b-48c0-f56b-6fd0c3a4943c","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:47:18.975638Z","iopub.execute_input":"2025-06-27T06:47:18.975909Z","iopub.status.idle":"2025-06-27T06:47:19.133272Z","shell.execute_reply.started":"2025-06-27T06:47:18.975889Z","shell.execute_reply":"2025-06-27T06:47:19.132341Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Let's check out a few prediction and their different values\ni_multiplier = 0\nnum_rows = 3\nnum_cols = 2\nnum_images = num_rows*num_cols\nplt.figure(figsize=(10*num_cols,5*num_rows))\nfor i in range(num_images):\n  plt.subplot(num_rows,2*num_cols,2*i+1)\n  plot_pred(prediction_probabilities=predictions,labels=val_labels,images=val_images,n=i+i_multiplier)\n  plt.subplot(num_rows,2*num_cols,2*i+2)\n  plot_pred_conf(prediction_probabilities=predictions,labels=val_labels,n=i+i_multiplier)\nplt.tight_layout(h_pad=1.0)\nplt.show()","metadata":{"id":"AHAFpWHO8qxK","executionInfo":{"status":"aborted","timestamp":1751004755497,"user_tz":240,"elapsed":909861,"user":{"displayName":"Brian Vilnrotter","userId":"14318513860280514101"}},"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:47:51.018228Z","iopub.execute_input":"2025-06-27T06:47:51.018500Z","iopub.status.idle":"2025-06-27T06:47:52.474757Z","shell.execute_reply.started":"2025-06-27T06:47:51.018481Z","shell.execute_reply":"2025-06-27T06:47:52.473913Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Saving and reloading a trained model","metadata":{}},{"cell_type":"code","source":"# Create a function to save a model\ndef save_model(model,suffix=None):\n    modeldir = os.path.join(pwd+'models',datetime.datetime.now().strftime(\"%Y%m%d-%H%M%s\"))\n    model_path = modeldir+\"-\"+suffix+\".h5\"\n    print(f\"Saving model to: {model_path}...\")\n    model.save(model_path)\n    return model_path","metadata":{"id":"65wsB2tP-whb","trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:53:32.794543Z","iopub.execute_input":"2025-06-27T06:53:32.795238Z","iopub.status.idle":"2025-06-27T06:53:32.799261Z","shell.execute_reply.started":"2025-06-27T06:53:32.795215Z","shell.execute_reply":"2025-06-27T06:53:32.798374Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a function to load a saved mode\ndef load_model(model_path):\n    print(f\"Loading saved model from: {model_path}\")\n    model = tf.keras.models.load_model(model_path,\n                                      custom_objects={\"KerasLayer\":hub.KerasLayer})\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:53:33.154579Z","iopub.execute_input":"2025-06-27T06:53:33.154846Z","iopub.status.idle":"2025-06-27T06:53:33.159099Z","shell.execute_reply.started":"2025-06-27T06:53:33.154825Z","shell.execute_reply":"2025-06-27T06:53:33.158387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#save_model(model,suffix=\"1000-images-mobilenetv2-Adam\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:53:45.880598Z","iopub.execute_input":"2025-06-27T06:53:45.881336Z","iopub.status.idle":"2025-06-27T06:53:45.884527Z","shell.execute_reply.started":"2025-06-27T06:53:45.881310Z","shell.execute_reply":"2025-06-27T06:53:45.883627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load atrained model\n#loaded_1000_image_model = load_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:54:29.385701Z","iopub.execute_input":"2025-06-27T06:54:29.386278Z","iopub.status.idle":"2025-06-27T06:54:29.389251Z","shell.execute_reply.started":"2025-06-27T06:54:29.386253Z","shell.execute_reply":"2025-06-27T06:54:29.388461Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.evaluate(val_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:55:29.844461Z","iopub.execute_input":"2025-06-27T06:55:29.845196Z","iopub.status.idle":"2025-06-27T06:55:34.378350Z","shell.execute_reply.started":"2025-06-27T06:55:29.845172Z","shell.execute_reply":"2025-06-27T06:55:34.377630Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Training a big dog model (on the full data)","metadata":{}},{"cell_type":"code","source":"len(X), len(y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:57:24.417977Z","iopub.execute_input":"2025-06-27T06:57:24.418616Z","iopub.status.idle":"2025-06-27T06:57:24.423305Z","shell.execute_reply.started":"2025-06-27T06:57:24.418592Z","shell.execute_reply":"2025-06-27T06:57:24.422585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a data batch with the full data set\nfull_data = create_data_batches(X,y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:59:04.892874Z","iopub.execute_input":"2025-06-27T06:59:04.893500Z","iopub.status.idle":"2025-06-27T06:59:04.978855Z","shell.execute_reply.started":"2025-06-27T06:59:04.893475Z","shell.execute_reply":"2025-06-27T06:59:04.978280Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"full_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T06:59:16.752725Z","iopub.execute_input":"2025-06-27T06:59:16.753329Z","iopub.status.idle":"2025-06-27T06:59:16.758332Z","shell.execute_reply.started":"2025-06-27T06:59:16.753305Z","shell.execute_reply":"2025-06-27T06:59:16.757503Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a model for full model\nfull_model = create_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T07:00:15.716490Z","iopub.execute_input":"2025-06-27T07:00:15.717227Z","iopub.status.idle":"2025-06-27T07:00:19.944780Z","shell.execute_reply.started":"2025-06-27T07:00:15.717200Z","shell.execute_reply":"2025-06-27T07:00:19.944261Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create full model callbacks\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"accuracy\",patience=3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T07:02:31.967678Z","iopub.execute_input":"2025-06-27T07:02:31.968422Z","iopub.status.idle":"2025-06-27T07:02:31.971904Z","shell.execute_reply.started":"2025-06-27T07:02:31.968397Z","shell.execute_reply":"2025-06-27T07:02:31.971170Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check for GPU availability\nprint(\"GPU\", \"available\" if tf.config.list_physical_devices(\"GPU\") else \"not available\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T07:04:35.054246Z","iopub.execute_input":"2025-06-27T07:04:35.054825Z","iopub.status.idle":"2025-06-27T07:04:35.058997Z","shell.execute_reply.started":"2025-06-27T07:04:35.054799Z","shell.execute_reply":"2025-06-27T07:04:35.058092Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"full_model.fit(x=full_data,\n               epochs=NUM_EPOCHS,\n               callbacks=[full_model_early_stopping])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T07:04:48.123182Z","iopub.execute_input":"2025-06-27T07:04:48.123419Z","iopub.status.idle":"2025-06-27T08:20:49.543065Z","shell.execute_reply.started":"2025-06-27T07:04:48.123402Z","shell.execute_reply":"2025-06-27T08:20:49.542484Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Save model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.544354Z","iopub.execute_input":"2025-06-27T08:20:49.544596Z","iopub.status.idle":"2025-06-27T08:20:49.547777Z","shell.execute_reply.started":"2025-06-27T08:20:49.544578Z","shell.execute_reply":"2025-06-27T08:20:49.547156Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Making predictions on the test dataset","metadata":{}},{"cell_type":"code","source":"# Load test image filenames\ntest_path = pwd+\"test/\"\ntest_filenames = [test_path + fname for fname in os.listdir(test_path)]\ntest_filenames[:10]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.548413Z","iopub.execute_input":"2025-06-27T08:20:49.548632Z","iopub.status.idle":"2025-06-27T08:20:49.570017Z","shell.execute_reply.started":"2025-06-27T08:20:49.548613Z","shell.execute_reply":"2025-06-27T08:20:49.569511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(test_filenames)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.571600Z","iopub.execute_input":"2025-06-27T08:20:49.571805Z","iopub.status.idle":"2025-06-27T08:20:49.576185Z","shell.execute_reply.started":"2025-06-27T08:20:49.571789Z","shell.execute_reply":"2025-06-27T08:20:49.575664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create test data batch\ntest_data = create_data_batches(test_filenames,test_data=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.576761Z","iopub.execute_input":"2025-06-27T08:20:49.576929Z","iopub.status.idle":"2025-06-27T08:20:49.609697Z","shell.execute_reply.started":"2025-06-27T08:20:49.576915Z","shell.execute_reply":"2025-06-27T08:20:49.609015Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.610463Z","iopub.execute_input":"2025-06-27T08:20:49.610675Z","iopub.status.idle":"2025-06-27T08:20:49.614877Z","shell.execute_reply.started":"2025-06-27T08:20:49.610653Z","shell.execute_reply":"2025-06-27T08:20:49.614331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Make predictions on test data batch using the loaded full model\ntest_predictions = full_model.predict(test_data,verbose=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:20:49.615512Z","iopub.execute_input":"2025-06-27T08:20:49.615686Z","iopub.status.idle":"2025-06-27T08:25:12.109912Z","shell.execute_reply.started":"2025-06-27T08:20:49.615672Z","shell.execute_reply":"2025-06-27T08:25:12.109336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Save predictions (NumPy array) to csv file (for access later)\nnp.savetxt(pwd+'preds_array.csv',test_predictions,delimiter=\",\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:49:12.613401Z","iopub.execute_input":"2025-06-27T08:49:12.613695Z","iopub.status.idle":"2025-06-27T08:49:12.632260Z","shell.execute_reply.started":"2025-06-27T08:49:12.613674Z","shell.execute_reply":"2025-06-27T08:49:12.631440Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_predictions = np.loadtxt(pwd+'preds_array.csv',delimiter=',')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.128574Z","iopub.status.idle":"2025-06-27T08:25:12.128811Z","shell.execute_reply.started":"2025-06-27T08:25:12.128693Z","shell.execute_reply":"2025-06-27T08:25:12.128705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_predictions[:10]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.129377Z","iopub.status.idle":"2025-06-27T08:25:12.129679Z","shell.execute_reply.started":"2025-06-27T08:25:12.129523Z","shell.execute_reply":"2025-06-27T08:25:12.129537Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_predictions.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.130952Z","iopub.status.idle":"2025-06-27T08:25:12.131207Z","shell.execute_reply.started":"2025-06-27T08:25:12.131072Z","shell.execute_reply":"2025-06-27T08:25:12.131081Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Preparing test dataset predictions for Kaggle","metadata":{}},{"cell_type":"code","source":"# Create a pandas DataFrame with empty columns\npreds_df = pd.DataFrame(columns=['id'] + list(unique_breeds))\npreds_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.133471Z","iopub.status.idle":"2025-06-27T08:25:12.133707Z","shell.execute_reply.started":"2025-06-27T08:25:12.133608Z","shell.execute_reply":"2025-06-27T08:25:12.133618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Append test image ID's to predictions DataFrame\ntest_ids = [os.path.splitext(path)[0] for path in os.listdir(test_path)]\npreds_df['id'] = test_ids\npreds_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.141526Z","iopub.status.idle":"2025-06-27T08:25:12.141783Z","shell.execute_reply.started":"2025-06-27T08:25:12.141673Z","shell.execute_reply":"2025-06-27T08:25:12.141685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Add the prediction probabilities to each dog breed column\npreds_df[list(unique_breeds)] = test_predictions\npreds_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.142614Z","iopub.status.idle":"2025-06-27T08:25:12.142840Z","shell.execute_reply.started":"2025-06-27T08:25:12.142726Z","shell.execute_reply":"2025-06-27T08:25:12.142738Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds_df.to_csv(pwd+'full_model_predictions_submission_.csv',index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-27T08:25:12.145436Z","iopub.status.idle":"2025-06-27T08:25:12.145738Z","shell.execute_reply.started":"2025-06-27T08:25:12.145581Z","shell.execute_reply":"2025-06-27T08:25:12.145594Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}