{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"},{"sourceId":3412,"sourceType":"modelInstanceVersion","modelInstanceId":2511,"modelId":301},{"sourceId":3659,"sourceType":"modelInstanceVersion","modelInstanceId":2604,"modelId":301},{"sourceId":3660,"sourceType":"modelInstanceVersion","modelInstanceId":2604,"modelId":301}],"dockerImageVersionId":31090,"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:32:21.075705Z","iopub.execute_input":"2025-07-30T14:32:21.076431Z","iopub.status.idle":"2025-07-30T14:33:00.499555Z","shell.execute_reply.started":"2025-07-30T14:32:21.076402Z","shell.execute_reply":"2025-07-30T14:33:00.498755Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv=pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:00.500982Z","iopub.execute_input":"2025-07-30T14:33:00.501308Z","iopub.status.idle":"2025-07-30T14:33:00.537355Z","shell.execute_reply.started":"2025-07-30T14:33:00.50129Z","shell.execute_reply":"2025-07-30T14:33:00.536676Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:00.538038Z","iopub.execute_input":"2025-07-30T14:33:00.538215Z","iopub.status.idle":"2025-07-30T14:33:00.562434Z","shell.execute_reply.started":"2025-07-30T14:33:00.5382Z","shell.execute_reply":"2025-07-30T14:33:00.561797Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:00.563134Z","iopub.execute_input":"2025-07-30T14:33:00.563396Z","iopub.status.idle":"2025-07-30T14:33:00.572104Z","shell.execute_reply.started":"2025-07-30T14:33:00.563374Z","shell.execute_reply":"2025-07-30T14:33:00.571542Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_csv['breed'].value_counts().plot.bar(figsize=(15,8));","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:00.573543Z","iopub.execute_input":"2025-07-30T14:33:00.573758Z","iopub.status.idle":"2025-07-30T14:33:01.766224Z","shell.execute_reply.started":"2025-07-30T14:33:00.573744Z","shell.execute_reply":"2025-07-30T14:33:01.765292Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"filename = ['/kaggle/input/dog-breed-identification/train/' + fname for fname in labels_csv['id'] + '.jpg']\nfilename[:10]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.76703Z","iopub.execute_input":"2025-07-30T14:33:01.767242Z","iopub.status.idle":"2025-07-30T14:33:01.776743Z","shell.execute_reply.started":"2025-07-30T14:33:01.767224Z","shell.execute_reply":"2025-07-30T14:33:01.77613Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nif len(os.listdir('/kaggle/input/dog-breed-identification/train/')) == len(filename):\n  print('FileNames match actual amount of files!!! Proceed.')\nelse:\n  print('Filenames do not match actual amount of files,check the target dir')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.777409Z","iopub.execute_input":"2025-07-30T14:33:01.777659Z","iopub.status.idle":"2025-07-30T14:33:01.797176Z","shell.execute_reply.started":"2025-07-30T14:33:01.77764Z","shell.execute_reply":"2025-07-30T14:33:01.796556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels=labels_csv['breed'].to_numpy()\nlabels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:46:28.485876Z","iopub.execute_input":"2025-07-30T14:46:28.486158Z","iopub.status.idle":"2025-07-30T14:46:28.491354Z","shell.execute_reply.started":"2025-07-30T14:46:28.486138Z","shell.execute_reply":"2025-07-30T14:46:28.490769Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_breeds = np.unique(labels)\nunique_breeds","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.812512Z","iopub.execute_input":"2025-07-30T14:33:01.812666Z","iopub.status.idle":"2025-07-30T14:33:01.842316Z","shell.execute_reply.started":"2025-07-30T14:33:01.812652Z","shell.execute_reply":"2025-07-30T14:33:01.841681Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(unique_breeds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.842976Z","iopub.execute_input":"2025-07-30T14:33:01.843259Z","iopub.status.idle":"2025-07-30T14:33:01.86186Z","shell.execute_reply.started":"2025-07-30T14:33:01.843237Z","shell.execute_reply":"2025-07-30T14:33:01.861144Z"}},"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":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.862577Z","iopub.execute_input":"2025-07-30T14:33:01.862802Z","iopub.status.idle":"2025-07-30T14:33:01.929323Z","shell.execute_reply.started":"2025-07-30T14:33:01.862781Z","shell.execute_reply":"2025-07-30T14:33:01.928618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Example: Turning boolean array into integers\nprint(labels[0]) # original label\nprint(np.where(unique_breeds == labels[0])) # index where label occurs\nprint(boolean_labels[0].argmax()) # returns the index of the first True\nprint(boolean_labels[0].astype(int)) # there will be a 1 where the sample label occurs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.930027Z","iopub.execute_input":"2025-07-30T14:33:01.930716Z","iopub.status.idle":"2025-07-30T14:33:01.935375Z","shell.execute_reply.started":"2025-07-30T14:33:01.930696Z","shell.execute_reply":"2025-07-30T14:33:01.934874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X=filename\ny=boolean_labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.93607Z","iopub.execute_input":"2025-07-30T14:33:01.936292Z","iopub.status.idle":"2025-07-30T14:33:01.954175Z","shell.execute_reply.started":"2025-07-30T14:33:01.936268Z","shell.execute_reply":"2025-07-30T14:33:01.953667Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(filename))\nprint(len(boolean_labels))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.957232Z","iopub.execute_input":"2025-07-30T14:33:01.957416Z","iopub.status.idle":"2025-07-30T14:33:01.973443Z","shell.execute_reply.started":"2025-07-30T14:33:01.957402Z","shell.execute_reply":"2025-07-30T14:33:01.972952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set number of images to use for experimenting\nNUM_IMAGES = 1000 #@param {type:\"slider\", min:1000, max:10000, step:1000}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.974254Z","iopub.execute_input":"2025-07-30T14:33:01.974869Z","iopub.status.idle":"2025-07-30T14:33:01.990633Z","shell.execute_reply.started":"2025-07-30T14:33:01.974844Z","shell.execute_reply":"2025-07-30T14:33:01.990092Z"}},"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\n\n# Split them into training and validation of total size NUM_IMAGES\nX_train, X_val, y_train, y_val = train_test_split(X[:NUM_IMAGES],\n                                                  y[:NUM_IMAGES],\n                                                  test_size=0.2,\n                                                  random_state=42)\n\nlen(X_train), len(y_train), len(X_val), len(y_val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:01.991365Z","iopub.execute_input":"2025-07-30T14:33:01.991583Z","iopub.status.idle":"2025-07-30T14:33:02.717887Z","shell.execute_reply.started":"2025-07-30T14:33:01.991561Z","shell.execute_reply":"2025-07-30T14:33:02.716993Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from matplotlib.pyplot import imread\nimage = imread(filename[42])\nimage","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:02.718733Z","iopub.execute_input":"2025-07-30T14:33:02.719138Z","iopub.status.idle":"2025-07-30T14:33:02.736511Z","shell.execute_reply.started":"2025-07-30T14:33:02.71912Z","shell.execute_reply":"2025-07-30T14:33:02.735857Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:02.737294Z","iopub.execute_input":"2025-07-30T14:33:02.737513Z","iopub.status.idle":"2025-07-30T14:33:23.046413Z","shell.execute_reply.started":"2025-07-30T14:33:02.737497Z","shell.execute_reply":"2025-07-30T14:33:23.045624Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tf.constant(image)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:23.047246Z","iopub.execute_input":"2025-07-30T14:33:23.047627Z","iopub.status.idle":"2025-07-30T14:33:24.685917Z","shell.execute_reply.started":"2025-07-30T14:33:23.04761Z","shell.execute_reply":"2025-07-30T14:33:24.685116Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE = 224;\n\ndef process_img(image_path,img_size=IMG_SIZE):\n  \"\"\"\n  Takes an image file path and turns the image into a Tensor.\n  \"\"\"\n\n  # Read in an image file\n  image = tf.io.read_file(image_path)\n  # Turn the jpeg image into numerical Tensor with 3 colour channels (Red, Green, Blue)\n  image = tf.image.decode_jpeg(image, channels=3)\n  # Convert the colour channel values from 0-255 to 0-1 values\n  image = tf.image.convert_image_dtype(image, tf.float32)\n  # Resize the image to our desired value (224, 224)\n  image = tf.image.resize(image, size=[IMG_SIZE, IMG_SIZE])\n\n  return image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.686783Z","iopub.execute_input":"2025-07-30T14:33:24.687076Z","iopub.status.idle":"2025-07-30T14:33:24.702461Z","shell.execute_reply.started":"2025-07-30T14:33:24.687059Z","shell.execute_reply":"2025-07-30T14:33:24.701837Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a simple function to return a tuple (image, label)\ndef get_image_label(image_path, label):\n  \"\"\"\n  Takes an image file path name and the assosciated label,\n  processes the image and reutrns a typle of (image, label).\n  \"\"\"\n  image = process_img(image_path)\n  return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.703128Z","iopub.execute_input":"2025-07-30T14:33:24.703324Z","iopub.status.idle":"2025-07-30T14:33:24.720131Z","shell.execute_reply.started":"2025-07-30T14:33:24.703302Z","shell.execute_reply":"2025-07-30T14:33:24.719587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# Setup X & y variables\nX = filenames\ny = boolean_labels\n\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 32\n\ndef create_data_batchs(X, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False):\n  if test_data:\n    print('Creating test data...')\n    data = tf.data.Dataset.from_tensor_slices(tf.constant(X))\n    data_batch = data.map(process_img).batch(batch_size)\n    return data_batch\n\n  elif valid_data:\n    print('Creating valid data...')\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(X),\n                                              tf.constant(y)))\n    data_batch = data.map(get_image_label).batch(batch_size)\n    return data_batch\n\n  else:\n    print('Creating train data...')\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":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.720858Z","iopub.execute_input":"2025-07-30T14:33:24.721107Z","iopub.status.idle":"2025-07-30T14:33:24.74303Z","shell.execute_reply.started":"2025-07-30T14:33:24.721085Z","shell.execute_reply":"2025-07-30T14:33:24.742409Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_data_batchs(X_train, y_train)\nval_data = create_data_batchs(X_val, y_val, valid_data=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.743669Z","iopub.execute_input":"2025-07-30T14:33:24.743859Z","iopub.status.idle":"2025-07-30T14:33:24.874122Z","shell.execute_reply.started":"2025-07-30T14:33:24.743836Z","shell.execute_reply":"2025-07-30T14:33:24.873478Z"}},"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":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.874868Z","iopub.execute_input":"2025-07-30T14:33:24.87509Z","iopub.status.idle":"2025-07-30T14:33:24.879922Z","shell.execute_reply.started":"2025-07-30T14:33:24.875074Z","shell.execute_reply":"2025-07-30T14:33:24.87911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Create a function for viewing images in a data batch\ndef show_25_images(images, labels):\n  \"\"\"\n  Displays a plot of 25 images and their labels from a data batch.\n  \"\"\"\n  # Setup the figure\n  plt.figure(figsize=(10, 10))\n  # Loop through 25 (for displaying 25 images)\n  for i in range(25):\n    # Create subplots (5 rows, 5 columns)\n    ax = plt.subplot(5, 5, i+1)\n    # Display an image\n    plt.imshow(images[i])\n    # Add the image label as the title\n    plt.title(unique_breeds[labels[i].argmax()])\n    # Turn the grid lines off\n    plt.axis(\"off\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.880633Z","iopub.execute_input":"2025-07-30T14:33:24.880894Z","iopub.status.idle":"2025-07-30T14:33:24.897574Z","shell.execute_reply.started":"2025-07-30T14:33:24.88087Z","shell.execute_reply":"2025-07-30T14:33:24.896868Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Now let's visualize the data in a training batch\ntrain_images, train_labels = next(train_data.as_numpy_iterator())\nshow_25_images(train_images, train_labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:24.898289Z","iopub.execute_input":"2025-07-30T14:33:24.898555Z","iopub.status.idle":"2025-07-30T14:33:26.739696Z","shell.execute_reply.started":"2025-07-30T14:33:24.898535Z","shell.execute_reply":"2025-07-30T14:33:26.738738Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Now let's visualize our validation set\nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_25_images(val_images, val_labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:26.740429Z","iopub.execute_input":"2025-07-30T14:33:26.740626Z","iopub.status.idle":"2025-07-30T14:33:28.529587Z","shell.execute_reply.started":"2025-07-30T14:33:26.740612Z","shell.execute_reply":"2025-07-30T14:33:28.528865Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check to make sure we're still running on a GPU\nprint(\"GPU\", \"available (YESSS!!!!!!)\" if tf.config.list_physical_devices(\"GPU\") else \"not available :(\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:28.530396Z","iopub.execute_input":"2025-07-30T14:33:28.530619Z","iopub.status.idle":"2025-07-30T14:33:28.534957Z","shell.execute_reply.started":"2025-07-30T14:33:28.530603Z","shell.execute_reply":"2025-07-30T14:33:28.53415Z"}},"outputs":[],"execution_count":null},{"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 from TensorFlow Hub\nMODEL_URL = \"https://www.kaggle.com/models/google/mobilenet-v2/TensorFlow2/035-128-feature-vector/2\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:29:32.334543Z","iopub.execute_input":"2025-07-30T16:29:32.335241Z","iopub.status.idle":"2025-07-30T16:29:32.339185Z","shell.execute_reply.started":"2025-07-30T16:29:32.335214Z","shell.execute_reply":"2025-07-30T16:29:32.338268Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow import keras\nfrom tensorflow.keras.models import Sequential  # Fixed typo: 'model' → 'models'\nfrom tensorflow.keras.layers import Activation, Dense\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.metrics import categorical_crossentropy  # Fixed typo: 'catergorical' → 'categorical'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:28.554992Z","iopub.execute_input":"2025-07-30T14:33:28.555175Z","iopub.status.idle":"2025-07-30T14:33:28.583423Z","shell.execute_reply.started":"2025-07-30T14:33:28.55516Z","shell.execute_reply":"2025-07-30T14:33:28.582572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mobile = tf.keras.applications.mobilenet.MobileNet(include_top=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:28.584288Z","iopub.execute_input":"2025-07-30T14:33:28.584562Z","iopub.status.idle":"2025-07-30T14:33:30.840099Z","shell.execute_reply.started":"2025-07-30T14:33:28.584533Z","shell.execute_reply":"2025-07-30T14:33:30.839392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def create_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, ):\n#     print(\"Building model with:\", model_url)\n    \n#     model = Sequential([\n#         hub.KerasLayer(model_url,\n#                        input_shape=input_shape[1:],  # Remove batch dimension\n#                        trainable=True),              # Fine-tune the feature extractor\n#         Dense(units=output_shape, activation='softmax')\n#     ])\n\n#     model.compile(\n#         loss=tf.keras.losses.CategoricalCrossentropy(),\n#         optimizer=tf.keras.optimizers.Adam(),\n#         metrics=[\"accuracy\"]\n#     )\n\n#     return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:30.847541Z","iopub.status.idle":"2025-07-30T14:33:30.847757Z","shell.execute_reply.started":"2025-07-30T14:33:30.847654Z","shell.execute_reply":"2025-07-30T14:33:30.847663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mobile.compile(\n    loss=tf.keras.losses.CategoricalCrossentropy(),\n    optimizer=tf.keras.optimizers.Adam(),\n    metrics=[\"accuracy\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:34:13.743975Z","iopub.execute_input":"2025-07-30T16:34:13.744639Z","iopub.status.idle":"2025-07-30T16:34:13.754376Z","shell.execute_reply.started":"2025-07-30T16:34:13.744612Z","shell.execute_reply":"2025-07-30T16:34:13.753869Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# !pip install tensorflow==2.15.0 ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T14:33:30.848733Z","iopub.status.idle":"2025-07-30T14:33:30.848998Z","shell.execute_reply.started":"2025-07-30T14:33:30.848894Z","shell.execute_reply":"2025-07-30T14:33:30.848905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# model = create_model()\nmobile.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:25:56.861863Z","iopub.execute_input":"2025-07-30T16:25:56.862541Z","iopub.status.idle":"2025-07-30T16:25:56.923606Z","shell.execute_reply.started":"2025-07-30T16:25:56.862515Z","shell.execute_reply":"2025-07-30T16:25:56.922877Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = mobile.layers[-6].output\noutput = Dense(units=OUTPUT_SHAPE, activation='softmax')(X)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:25:59.429021Z","iopub.execute_input":"2025-07-30T16:25:59.429532Z","iopub.status.idle":"2025-07-30T16:25:59.441302Z","shell.execute_reply.started":"2025-07-30T16:25:59.429509Z","shell.execute_reply":"2025-07-30T16:25:59.440582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.applications import MobileNet\n\n# Step 1: Build the base MobileNet feature extractor\nbase_model = MobileNet(\n    input_shape=(224, 224, 3),\n    include_top=False,\n    weights='imagenet',    # Or load manually if offline\n    pooling='avg'          # Converts output to shape (None, 1024)\n)\n\n# Step 2: Freeze base_model for feature extraction\nbase_model.trainable = False  # Set to True later for fine-tuning\n\n# Step 3: Define your complete model\nmodel = Sequential([\n    base_model,\n    Dense(OUTPUT_SHAPE, activation='softmax')  # OUTPUT_SHAPE = number of classes\n])\n\n# Step 4: Compile the model\nmodel.compile(\n    optimizer=tf.keras.optimizers.Adam(),\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:01.342469Z","iopub.execute_input":"2025-07-30T16:26:01.342983Z","iopub.status.idle":"2025-07-30T16:26:01.711009Z","shell.execute_reply.started":"2025-07-30T16:26:01.34296Z","shell.execute_reply":"2025-07-30T16:26:01.710231Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:03.60465Z","iopub.execute_input":"2025-07-30T16:26:03.604935Z","iopub.status.idle":"2025-07-30T16:26:03.619128Z","shell.execute_reply.started":"2025-07-30T16:26:03.604916Z","shell.execute_reply":"2025-07-30T16:26:03.618423Z"}},"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  # Create a log directory for storing TensorBoard logs\n  logdir = os.path.join(\"/kaggle/working/logs/\",\n                        # Make it so the logs get tracked whenever we run an experiment\n                        datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n  return tf.keras.callbacks.TensorBoard(logdir)\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:04.938846Z","iopub.execute_input":"2025-07-30T16:26:04.939106Z","iopub.status.idle":"2025-07-30T16:26:04.943334Z","shell.execute_reply.started":"2025-07-30T16:26:04.939086Z","shell.execute_reply":"2025-07-30T16:26:04.942589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create early stopping callback\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:06.304318Z","iopub.execute_input":"2025-07-30T16:26:06.30458Z","iopub.status.idle":"2025-07-30T16:26:06.30829Z","shell.execute_reply.started":"2025-07-30T16:26:06.304561Z","shell.execute_reply":"2025-07-30T16:26:06.30775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"NUM_EPOCHS = 100 #@param {type:\"slider\", min:10, max:100, step:10}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:07.850125Z","iopub.execute_input":"2025-07-30T16:26:07.85041Z","iopub.status.idle":"2025-07-30T16:26:07.855031Z","shell.execute_reply.started":"2025-07-30T16:26:07.850369Z","shell.execute_reply":"2025-07-30T16:26:07.853936Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Build a function to train and return a trained model\ndef train_model():\n  \"\"\"\n  Trains a given model and returns the trained version.\n  \"\"\"\n\n  # Create new TensorBoard session everytime we train a model\n  tensorboard = create_tensorboard_callback()\n\n  # Fit the model to the data passing it the callbacks we created\n  model.fit(x=train_data,\n            epochs=NUM_EPOCHS,\n            validation_data=val_data,\n            validation_freq=1,\n            callbacks=[tensorboard, early_stopping])\n  # Return the fitted model\n  return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:09.761889Z","iopub.execute_input":"2025-07-30T16:26:09.76243Z","iopub.status.idle":"2025-07-30T16:26:09.766443Z","shell.execute_reply.started":"2025-07-30T16:26:09.762408Z","shell.execute_reply":"2025-07-30T16:26:09.765662Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Fit the model to the data\nmodel = train_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:12.692056Z","iopub.execute_input":"2025-07-30T16:26:12.6923Z","iopub.status.idle":"2025-07-30T16:26:32.233442Z","shell.execute_reply.started":"2025-07-30T16:26:12.692284Z","shell.execute_reply":"2025-07-30T16:26:32.232871Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:32.234789Z","iopub.execute_input":"2025-07-30T16:26:32.23509Z","iopub.status.idle":"2025-07-30T16:26:32.240147Z","shell.execute_reply.started":"2025-07-30T16:26:32.235072Z","shell.execute_reply":"2025-07-30T16:26:32.239445Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions = model.predict(val_data,verbose=1)\npredictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:32.240772Z","iopub.execute_input":"2025-07-30T16:26:32.24106Z","iopub.status.idle":"2025-07-30T16:26:35.891344Z","shell.execute_reply.started":"2025-07-30T16:26:32.241035Z","shell.execute_reply":"2025-07-30T16:26:35.89072Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.893428Z","iopub.execute_input":"2025-07-30T16:26:35.893646Z","iopub.status.idle":"2025-07-30T16:26:35.899651Z","shell.execute_reply.started":"2025-07-30T16:26:35.893624Z","shell.execute_reply":"2025-07-30T16:26:35.898998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions.shape,len(predictions[0]),np.sum(predictions[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.900324Z","iopub.execute_input":"2025-07-30T16:26:35.90058Z","iopub.status.idle":"2025-07-30T16:26:35.918481Z","shell.execute_reply.started":"2025-07-30T16:26:35.900562Z","shell.execute_reply":"2025-07-30T16:26:35.917884Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# First prediction\nindex = 21\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":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.919054Z","iopub.execute_input":"2025-07-30T16:26:35.919224Z","iopub.status.idle":"2025-07-30T16:26:35.93694Z","shell.execute_reply.started":"2025-07-30T16:26:35.919209Z","shell.execute_reply":"2025-07-30T16:26:35.936352Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_breeds[94]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.93753Z","iopub.execute_input":"2025-07-30T16:26:35.937731Z","iopub.status.idle":"2025-07-30T16:26:35.95779Z","shell.execute_reply.started":"2025-07-30T16:26:35.937711Z","shell.execute_reply":"2025-07-30T16:26:35.957247Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Turn prediction probabilities into their respective label (easier to understand)\ndef get_pred_label(prediction_probabilities):\n  \"\"\"\n  Turns an array of prediction probabilities into a label.\n  \"\"\"\n  return unique_breeds[np.argmax(prediction_probabilities)]\n\n# Get a predicted label based on an array of prediction probabilities\npred_label = get_pred_label(predictions[48])\npred_label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.958462Z","iopub.execute_input":"2025-07-30T16:26:35.958706Z","iopub.status.idle":"2025-07-30T16:26:35.976118Z","shell.execute_reply.started":"2025-07-30T16:26:35.958686Z","shell.execute_reply":"2025-07-30T16:26:35.97547Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.976719Z","iopub.execute_input":"2025-07-30T16:26:35.976999Z","iopub.status.idle":"2025-07-30T16:26:35.993949Z","shell.execute_reply.started":"2025-07-30T16:26:35.976983Z","shell.execute_reply":"2025-07-30T16:26:35.993324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a function to unbatch a batch dataset\ndef unbatchify(data):\n  \"\"\"\n  Takes a batched dataset of (image, label) Tensors and reutrns separate arrays\n  of images and labels.\n  \"\"\"\n  images = []\n  labels = []\n  # Loop through unbatched data\n  for image, label in data.unbatch().as_numpy_iterator():\n    images.append(image)\n    labels.append(unique_breeds[np.argmax(label)])\n  return images, labels\n\n# Unbatchify the validation data\nval_images, val_labels = unbatchify(val_data)\nval_images[0], val_labels[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:35.996135Z","iopub.execute_input":"2025-07-30T16:26:35.996434Z","iopub.status.idle":"2025-07-30T16:26:36.269703Z","shell.execute_reply.started":"2025-07-30T16:26:35.996417Z","shell.execute_reply":"2025-07-30T16:26:36.269047Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_labels[5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.270413Z","iopub.execute_input":"2025-07-30T16:26:36.270682Z","iopub.status.idle":"2025-07-30T16:26:36.275446Z","shell.execute_reply.started":"2025-07-30T16:26:36.270657Z","shell.execute_reply":"2025-07-30T16:26:36.274814Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"get_pred_label(predictions[5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.276198Z","iopub.execute_input":"2025-07-30T16:26:36.276424Z","iopub.status.idle":"2025-07-30T16:26:36.295396Z","shell.execute_reply.started":"2025-07-30T16:26:36.276401Z","shell.execute_reply":"2025-07-30T16:26:36.294813Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\ndef plot_pred(prediction_probabilities, labels, images, n=1):\n  \"\"\"\n  View the prediction, ground truth and image for sample n\n  \"\"\"\n  pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]\n\n  # Get the pred label\n  pred_label = get_pred_label(pred_prob)\n\n  # Plot image & remove ticks\n  plt.imshow(image)\n  plt.xticks([])\n  plt.yticks([])\n\n  # Change the colour 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 plot title to be predicted, probability of prediction and truth label\n  plt.title(\"{} {:2.0f}% {}\".format(pred_label,\n                                    np.max(pred_prob)*100,\n                                    true_label),\n                                    color=color)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.296109Z","iopub.execute_input":"2025-07-30T16:26:36.296347Z","iopub.status.idle":"2025-07-30T16:26:36.314313Z","shell.execute_reply.started":"2025-07-30T16:26:36.296331Z","shell.execute_reply":"2025-07-30T16:26:36.313553Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images,\n          n=77)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.315126Z","iopub.execute_input":"2025-07-30T16:26:36.315313Z","iopub.status.idle":"2025-07-30T16:26:36.477015Z","shell.execute_reply.started":"2025-07-30T16:26:36.315298Z","shell.execute_reply":"2025-07-30T16:26:36.476298Z"}},"outputs":[],"execution_count":null},{"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  # Find the top 10 prediction confidence values\n  top_10_pred_values = pred_prob[top_10_pred_indexes]\n  # Find the top 10 prediction labels\n  top_10_pred_labels = unique_breeds[top_10_pred_indexes]\n\n  # Setup plot\n  top_plot = plt.bar(np.arange(len(top_10_pred_labels)),\n                     top_10_pred_values,\n                     color=\"grey\")\n  plt.xticks(np.arange(len(top_10_pred_labels)),\n             labels=top_10_pred_labels,\n             rotation=\"vertical\")\n  \n  # Change color of true label\n  if np.isin(true_label, top_10_pred_labels):\n    top_plot[np.argmax(top_10_pred_labels == true_label)].set_color(\"green\")\n  else:\n    pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.478093Z","iopub.execute_input":"2025-07-30T16:26:36.4783Z","iopub.status.idle":"2025-07-30T16:26:36.483096Z","shell.execute_reply.started":"2025-07-30T16:26:36.478283Z","shell.execute_reply":"2025-07-30T16:26:36.482489Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,\n               labels=val_labels,\n               n=7)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.483773Z","iopub.execute_input":"2025-07-30T16:26:36.483982Z","iopub.status.idle":"2025-07-30T16:26:36.652846Z","shell.execute_reply.started":"2025-07-30T16:26:36.483967Z","shell.execute_reply":"2025-07-30T16:26:36.652169Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Let's check out a few predictions and their different values\ni_multiplier = 20\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,\n            labels=val_labels,\n            images=val_images,\n            n=i+i_multiplier)\n  plt.subplot(num_rows, 2*num_cols, 2*i+2)\n  plot_pred_conf(prediction_probabilities=predictions,\n                 labels=val_labels,\n                 n=i+i_multiplier)\nplt.tight_layout(h_pad=1.0)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:36.653641Z","iopub.execute_input":"2025-07-30T16:26:36.653847Z","iopub.status.idle":"2025-07-30T16:26:38.354086Z","shell.execute_reply.started":"2025-07-30T16:26:36.653808Z","shell.execute_reply":"2025-07-30T16:26:38.352891Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a function to save a model\ndef save_model(model, suffix=None):\n  \"\"\"\n  Saves a given model in a models directory and appends a suffix (string).\n  \"\"\"\n  # Create a model directory pathname with current time\n  modeldir = os.path.join(\"kaggle/input/models\",\n                          datetime.datetime.now().strftime(\"%Y%m%d-%H%M%s\"))\n  model_path = modeldir + \"-\" + suffix + \".h5\" # save format of model\n  print(f\"Saving model to: {model_path}...\")\n  model.save(model_path)\n  return model_path","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:38.355119Z","iopub.execute_input":"2025-07-30T16:26:38.355336Z","iopub.status.idle":"2025-07-30T16:26:38.359574Z","shell.execute_reply.started":"2025-07-30T16:26:38.35532Z","shell.execute_reply":"2025-07-30T16:26:38.358853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a function to load a trained model\ndef load_model(model_path):\n  \"\"\"\n  Loads a saved model from a specified path.\n  \"\"\"\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-07-30T16:26:38.360375Z","iopub.execute_input":"2025-07-30T16:26:38.360602Z","iopub.status.idle":"2025-07-30T16:26:38.384811Z","shell.execute_reply.started":"2025-07-30T16:26:38.360579Z","shell.execute_reply":"2025-07-30T16:26:38.384206Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# Save our model trained on 1000 images\nsave_model(model, suffix=\"1000-images-mobilenetv2-Adam\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:38.385618Z","iopub.execute_input":"2025-07-30T16:26:38.385842Z","iopub.status.idle":"2025-07-30T16:26:38.538713Z","shell.execute_reply.started":"2025-07-30T16:26:38.385807Z","shell.execute_reply":"2025-07-30T16:26:38.538107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loaded_1000_image_model = load_model('kaggle/input/models/20250730-16141753892097-1000-images-mobilenetv2-Adam.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:38.539473Z","iopub.execute_input":"2025-07-30T16:26:38.540222Z","iopub.status.idle":"2025-07-30T16:26:38.928209Z","shell.execute_reply.started":"2025-07-30T16:26:38.540196Z","shell.execute_reply":"2025-07-30T16:26:38.927641Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# Evaluate the pre-saved model\nmodel.evaluate(val_data)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:38.928893Z","iopub.execute_input":"2025-07-30T16:26:38.929081Z","iopub.status.idle":"2025-07-30T16:26:39.202044Z","shell.execute_reply.started":"2025-07-30T16:26:38.929066Z","shell.execute_reply":"2025-07-30T16:26:39.201377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# Evaluate the loaded model\nloaded_1000_image_model.evaluate(val_data)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:39.202791Z","iopub.execute_input":"2025-07-30T16:26:39.20313Z","iopub.status.idle":"2025-07-30T16:26:42.871413Z","shell.execute_reply.started":"2025-07-30T16:26:39.203105Z","shell.execute_reply":"2025-07-30T16:26:42.870497Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n# Setup X & y variables\nX = filenames\ny = boolean_labels\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:42.87238Z","iopub.execute_input":"2025-07-30T16:26:42.87266Z","iopub.status.idle":"2025-07-30T16:26:42.876405Z","shell.execute_reply.started":"2025-07-30T16:26:42.87264Z","shell.execute_reply":"2025-07-30T16:26:42.875765Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(X), len(y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:42.877251Z","iopub.execute_input":"2025-07-30T16:26:42.877513Z","iopub.status.idle":"2025-07-30T16:26:42.900246Z","shell.execute_reply.started":"2025-07-30T16:26:42.877484Z","shell.execute_reply":"2025-07-30T16:26:42.89973Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a data batch with the full data set\nfull_data = create_data_batchs(X, y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:42.901083Z","iopub.execute_input":"2025-07-30T16:26:42.901316Z","iopub.status.idle":"2025-07-30T16:26:42.989253Z","shell.execute_reply.started":"2025-07-30T16:26:42.901294Z","shell.execute_reply":"2025-07-30T16:26:42.98841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"full_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:42.990035Z","iopub.execute_input":"2025-07-30T16:26:42.990232Z","iopub.status.idle":"2025-07-30T16:26:42.995103Z","shell.execute_reply.started":"2025-07-30T16:26:42.990216Z","shell.execute_reply":"2025-07-30T16:26:42.994336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a model for full model\nfull_model = mobile","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:42.998742Z","iopub.execute_input":"2025-07-30T16:26:42.999035Z","iopub.status.idle":"2025-07-30T16:26:43.01033Z","shell.execute_reply.started":"2025-07-30T16:26:42.999018Z","shell.execute_reply":"2025-07-30T16:26:43.009684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    full_model.compile(\n        loss=tf.keras.losses.CategoricalCrossentropy(),\n        optimizer=tf.keras.optimizers.Adam(),\n        metrics=[\"accuracy\"]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:27:22.70621Z","iopub.execute_input":"2025-07-30T16:27:22.706481Z","iopub.status.idle":"2025-07-30T16:27:22.715632Z","shell.execute_reply.started":"2025-07-30T16:27:22.706461Z","shell.execute_reply":"2025-07-30T16:27:22.714918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create full model callbacks\nfull_model_tensorboard = create_tensorboard_callback()\n# No validation set when training on all the data, so we can't monitor validation accuracy\nfull_model_early_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"accuracy\",\n                                                             patience=3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:27:23.612724Z","iopub.execute_input":"2025-07-30T16:27:23.613461Z","iopub.status.idle":"2025-07-30T16:27:23.617143Z","shell.execute_reply.started":"2025-07-30T16:27:23.613434Z","shell.execute_reply":"2025-07-30T16:27:23.616259Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Fit the full model to the full data\nfull_model.fit(x=full_data,\n               epochs=NUM_EPOCHS,\n               callbacks=[full_model_tensorboard, full_model_early_stopping])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:34:23.682904Z","iopub.execute_input":"2025-07-30T16:34:23.683415Z","iopub.status.idle":"2025-07-30T16:34:24.9472Z","shell.execute_reply.started":"2025-07-30T16:34:23.683391Z","shell.execute_reply":"2025-07-30T16:34:24.946068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"save_model(full_model, suffix=\"full-image-set-mobilenetv2-Adam\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:43.053034Z","iopub.status.idle":"2025-07-30T16:26:43.053231Z","shell.execute_reply.started":"2025-07-30T16:26:43.053133Z","shell.execute_reply":"2025-07-30T16:26:43.053141Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load in the full model\nloaded_full_model = load_model('kaggle/input/models/20250730-16141753892097-1000-images-mobilenetv2-Adam.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T16:26:43.054216Z","iopub.status.idle":"2025-07-30T16:26:43.054428Z","shell.execute_reply.started":"2025-07-30T16:26:43.054325Z","shell.execute_reply":"2025-07-30T16:26:43.054333Z"}},"outputs":[],"execution_count":null}]}