{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":3676,"sourceType":"modelInstanceVersion","modelInstanceId":2610}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom tensorflow import keras\nfrom keras import Sequential\nfrom keras.layers import Input, Dense,Conv2D , MaxPooling2D, Flatten,BatchNormalization,Dropout\nfrom tensorflow.keras.preprocessing import image_dataset_from_directory\nimport tensorflow_hub as hub","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:08.621004Z","iopub.execute_input":"2024-03-22T16:44:08.621248Z","iopub.status.idle":"2024-03-22T16:44:31.648457Z","shell.execute_reply.started":"2024-03-22T16:44:08.621225Z","shell.execute_reply":"2024-03-22T16:44:31.647453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nfrom keras.layers import Dense","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:31.650140Z","iopub.execute_input":"2024-03-22T16:44:31.650659Z","iopub.status.idle":"2024-03-22T16:44:31.654728Z","shell.execute_reply.started":"2024-03-22T16:44:31.650634Z","shell.execute_reply":"2024-03-22T16:44:31.653922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"  # Run this cell if TensorFlow 2.x isn't the default in Colab\ntry:\n  # %tensorflow_version only exists in Colab\n    %tensorflow_version 2.x\nexcept Exception:\n    pass","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:31.660169Z","iopub.execute_input":"2024-03-22T16:44:31.660448Z","iopub.status.idle":"2024-03-22T16:44:31.665584Z","shell.execute_reply.started":"2024-03-22T16:44:31.660425Z","shell.execute_reply":"2024-03-22T16:44:31.664661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"TF version:\", tf.__version__)\nprint(\"TF Hub version:\", hub.__version__)\n\n# Check for GPU availability\nprint(\"GPU\", \"available (YESSSS!!!!!)\" if tf.config.list_physical_devices(\"GPU\") else \"not available :(\")","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:31.666633Z","iopub.execute_input":"2024-03-22T16:44:31.666957Z","iopub.status.idle":"2024-03-22T16:44:32.121910Z","shell.execute_reply.started":"2024-03-22T16:44:31.666926Z","shell.execute_reply":"2024-03-22T16:44:32.120936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checkout the labels of our data\nimport pandas as pd\nlabels_csv = pd.read_csv(\"/kaggle/input/dog-breed-identification/labels.csv\")\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:32.123211Z","iopub.execute_input":"2024-03-22T16:44:32.123560Z","iopub.status.idle":"2024-03-22T16:44:32.211307Z","shell.execute_reply.started":"2024-03-22T16:44:32.123528Z","shell.execute_reply":"2024-03-22T16:44:32.210459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# How many images are there of each breed?\nlabels_csv[\"breed\"].value_counts().plot.bar(figsize=(20, 10))","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:32.212339Z","iopub.execute_input":"2024-03-22T16:44:32.212589Z","iopub.status.idle":"2024-03-22T16:44:33.802937Z","shell.execute_reply.started":"2024-03-22T16:44:32.212567Z","shell.execute_reply":"2024-03-22T16:44:33.802003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# What's the median number of images per class?\nlabels_csv[\"breed\"].value_counts().median()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:33.804077Z","iopub.execute_input":"2024-03-22T16:44:33.804358Z","iopub.status.idle":"2024-03-22T16:44:33.815567Z","shell.execute_reply.started":"2024-03-22T16:44:33.804334Z","shell.execute_reply":"2024-03-22T16:44:33.814692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's view an image\nfrom IPython.display import Image\nImage(\"/kaggle/input/dog-breed-identification/train/001513dfcb2ffafc82cccf4d8bbaba97.jpg\")","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:33.816821Z","iopub.execute_input":"2024-03-22T16:44:33.817701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create pathnames from image ID's\nfilenames = [\"/kaggle/input/dog-breed-identification/train/\" + fname + \".jpg\" for fname in labels_csv[\"id\"]]\n\n# Check the first 10\nfilenames[:10]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = labels_csv[\"breed\"].to_numpy() \n# labels = np.array(labels) # does same thing as above\nlabels","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# See if number of labels matches the number of filenames\nif len(labels) == len(filenames):\n  print(\"Number of labels matches number of filenames!\")\nelse:\n  print(\"Number of labels does not match number of filenames, check data directories!\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the unique label values\nunique_breeds = np.unique(labels)\nlen(unique_breeds)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"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()) # index where label occurs in boolean array\nprint(boolean_labels[0].astype(int)) # there will be a 1 where the sample label occurs","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setup X & y variables\nX = filenames\ny = boolean_labels","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's split our data into train and validation sets\nfrom sklearn.model_selection import train_test_split\n\n# Split them into training and validation of total size NUM_IMAGES\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":{"execution":{"iopub.status.idle":"2024-03-22T16:44:35.550772Z","shell.execute_reply.started":"2024-03-22T16:44:34.046180Z","shell.execute_reply":"2024-03-22T16:44:35.549741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert image to NumPy array\nfrom matplotlib.pyplot import imread\nimage = imread(filenames[42])\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:35.552296Z","iopub.execute_input":"2024-03-22T16:44:35.552864Z","iopub.status.idle":"2024-03-22T16:44:35.578453Z","shell.execute_reply.started":"2024-03-22T16:44:35.552836Z","shell.execute_reply":"2024-03-22T16:44:35.577608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define image size\nIMG_SIZE = 224\n\n# Create a function for preprocessing images\ndef process_image(image_path, img_size=IMG_SIZE):\n  \"\"\"\n  Takes an image file path and turns the image into a Tensor.\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":{"execution":{"iopub.status.busy":"2024-03-22T16:44:35.579644Z","iopub.execute_input":"2024-03-22T16:44:35.580071Z","iopub.status.idle":"2024-03-22T16:44:35.586599Z","shell.execute_reply.started":"2024-03-22T16:44:35.580041Z","shell.execute_reply":"2024-03-22T16:44:35.585570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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_image(image_path)\n  return image, label","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:35.587827Z","iopub.execute_input":"2024-03-22T16:44:35.588177Z","iopub.status.idle":"2024-03-22T16:44:35.596613Z","shell.execute_reply.started":"2024-03-22T16:44:35.588148Z","shell.execute_reply":"2024-03-22T16:44:35.595772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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 if it's validation data.\n  Also accepts test data as input (no labels).\n  \"\"\"\n  # If the data is a test dataset, we probably don't have have labels\n  if test_data:\n    print(\"Creating 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  # If the data is a valid dataset, we don't need to shuffle it\n  elif valid_data:\n    print(\"Creating validation data batches...\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(X), # filepaths\n                                               tf.constant(y))) # labels\n    data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n    return data_batch\n\n  else:\n    print(\"Creating training data batches...\")\n    # Turn filepaths and labels into Tensors\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(X),\n                                               tf.constant(y)))\n    # Shuffling pathnames and labels before mapping image processor function is faster than shuffling images\n    data = data.shuffle(buffer_size=len(X))\n\n    # Create (image, label) tuples (this also turns the iamge path into a preprocessed image)\n    data = data.map(get_image_label)\n\n    # Turn the training data into batches\n    data_batch = data.batch(BATCH_SIZE)\n  return data_batch","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:35.597755Z","iopub.execute_input":"2024-03-22T16:44:35.598507Z","iopub.status.idle":"2024-03-22T16:44:35.613511Z","shell.execute_reply.started":"2024-03-22T16:44:35.598474Z","shell.execute_reply":"2024-03-22T16:44:35.612658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_data_batches(X_train, y_train)\nval_data = create_data_batches(X_val, y_val, valid_data=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:35.614535Z","iopub.execute_input":"2024-03-22T16:44:35.614769Z","iopub.status.idle":"2024-03-22T16:44:36.310808Z","shell.execute_reply.started":"2024-03-22T16:44:35.614749Z","shell.execute_reply":"2024-03-22T16:44:36.309780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the different attributes of our data batches\ntrain_data.element_spec, val_data.element_spec","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:36.312078Z","iopub.execute_input":"2024-03-22T16:44:36.312412Z","iopub.status.idle":"2024-03-22T16:44:36.318762Z","shell.execute_reply.started":"2024-03-22T16:44:36.312381Z","shell.execute_reply":"2024-03-22T16:44:36.317896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:44:36.319848Z","iopub.execute_input":"2024-03-22T16:44:36.320146Z","iopub.status.idle":"2024-03-22T16:44:36.331204Z","shell.execute_reply.started":"2024-03-22T16:44:36.320124Z","shell.execute_reply":"2024-03-22T16:44:36.330282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:44:36.332469Z","iopub.execute_input":"2024-03-22T16:44:36.333058Z","iopub.status.idle":"2024-03-22T16:44:38.618614Z","shell.execute_reply.started":"2024-03-22T16:44:36.333025Z","shell.execute_reply":"2024-03-22T16:44:38.617538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [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 = \"/kaggle/input/mobilenet-v2/tensorflow2/140-224-classification/2\"","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:38.619786Z","iopub.execute_input":"2024-03-22T16:44:38.620117Z","iopub.status.idle":"2024-03-22T16:44:38.624792Z","shell.execute_reply.started":"2024-03-22T16:44:38.620090Z","shell.execute_reply":"2024-03-22T16:44:38.623827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"from tensorflow.keras.models import Sequential\n\nmodel_hub = hub.KerasLayer(MODEL_URL, input_shape=INPUT_SHAPE, trainable=False)\n# Create a function which builds a Keras model\ndef create_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, model_url=MODEL_URL):\n    model = keras.Sequential([\n    model_url,\n    keraslayers.Dense(units=OUTPUT_SHAPE,\n                activation=\"softmax\")])\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\n","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:44:38.631392Z","iopub.execute_input":"2024-03-22T16:44:38.631659Z","iopub.status.idle":"2024-03-22T16:44:41.058278Z","shell.execute_reply.started":"2024-03-22T16:44:38.631637Z","shell.execute_reply":"2024-03-22T16:44:41.057264Z"}}},{"cell_type":"code","source":"from tensorflow.keras import layers as tfl","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:48:55.392893Z","iopub.execute_input":"2024-03-22T16:48:55.393639Z","iopub.status.idle":"2024-03-22T16:48:55.397685Z","shell.execute_reply.started":"2024-03-22T16:48:55.393603Z","shell.execute_reply":"2024-03-22T16:48:55.396748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Input shape to the model\nINPUT_SHAPE = [IMG_SIZE, IMG_SIZE, 3] #height, width, colour channels\n\n# Output shape of the model\nOUTPUT_SHAPE = len(unique_breeds)\n\ndef data_augmenter():\n    '''\n    Create a Sequential model composed of 2 layers\n    Returns:\n        tf.keras.Sequential\n    '''\n    data_augmentation = tf.keras.models.Sequential()\n    data_augmentation.add(tfl.RandomFlip('horizontal'))\n    data_augmentation.add(tfl.RandomRotation(0.2))\n    \n    return data_augmentation\n\ndef custom_MobileNetV2_model(input_shape=INPUT_SHAPE, output_shape=OUTPUT_SHAPE, data_augmentation=None):\n    base_model = tf.keras.applications.mobilenet_v2.MobileNetV2(input_shape=input_shape,\n                                                   include_top=False,\n                                                   weights=\"imagenet\")\n    \n    base_model.trainable = False\n    \n    inputs = tf.keras.Input(shape=input_shape)\n    \n    if data_augmentation:\n        X = data_augmentation(inputs)\n    else:\n        X = inputs\n    \n    X = base_model(X, training=False) \n        \n    X = tfl.GlobalAveragePooling2D()(X) \n    \n    X = tfl.Dropout(.5)(X)\n    \n    outputs = tfl.Dense(output_shape)(X)\n    \n    return tf.keras.Model(inputs = inputs, outputs=outputs)\n\n\ndef create_model(model=custom_MobileNetV2_model(), learning_rate=1e-3):\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),  # Update this line\n        loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),\n        metrics=[\n            tf.keras.metrics.CategoricalAccuracy(name='accuracy', dtype=np.float32)\n        ]\n    )\n    return model\n","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:53:44.012420Z","iopub.execute_input":"2024-03-22T16:53:44.013230Z","iopub.status.idle":"2024-03-22T16:53:44.760138Z","shell.execute_reply.started":"2024-03-22T16:53:44.013198Z","shell.execute_reply":"2024-03-22T16:53:44.759207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_learning_rate = 1e-2\nmodel = create_model(custom_MobileNetV2_model(data_augmentation=data_augmenter()), base_learning_rate)\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:53:48.073898Z","iopub.execute_input":"2024-03-22T16:53:48.074772Z","iopub.status.idle":"2024-03-22T16:53:48.875084Z","shell.execute_reply.started":"2024-03-22T16:53:48.074739Z","shell.execute_reply":"2024-03-22T16:53:48.874201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load TensorBoard notebook extension\n%load_ext tensorboard","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:54:03.474233Z","iopub.execute_input":"2024-03-22T16:54:03.475068Z","iopub.status.idle":"2024-03-22T16:54:03.499559Z","shell.execute_reply.started":"2024-03-22T16:54:03.475034Z","shell.execute_reply":"2024-03-22T16:54:03.498825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime\nimport os\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(\"drive/My Drive/Dog Vision/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)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:54:05.448267Z","iopub.execute_input":"2024-03-22T16:54:05.448973Z","iopub.status.idle":"2024-03-22T16:54:05.453836Z","shell.execute_reply.started":"2024-03-22T16:54:05.448930Z","shell.execute_reply":"2024-03-22T16:54:05.452953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create early stopping callback\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:54:06.842087Z","iopub.execute_input":"2024-03-22T16:54:06.842781Z","iopub.status.idle":"2024-03-22T16:54:06.847045Z","shell.execute_reply.started":"2024-03-22T16:54:06.842748Z","shell.execute_reply":"2024-03-22T16:54:06.846036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nNUM_EPOCHS = 100 #@param {type:\"slider\", min:10, max:100, step:10}","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:54:08.232370Z","iopub.execute_input":"2024-03-22T16:54:08.232781Z","iopub.status.idle":"2024-03-22T16:54:08.237681Z","shell.execute_reply.started":"2024-03-22T16:54:08.232755Z","shell.execute_reply":"2024-03-22T16:54:08.236727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:54:09.524102Z","iopub.execute_input":"2024-03-22T16:54:09.524441Z","iopub.status.idle":"2024-03-22T16:54:09.529756Z","shell.execute_reply.started":"2024-03-22T16:54:09.524416Z","shell.execute_reply":"2024-03-22T16:54:09.528837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Build a function to train and return a trained model\ndef train_model():\n  \"\"\"\n  Trains a given model and returns the trained version.\n  \"\"\"\n  # Create a model\n  model = create_model()\n  tensorboard = create_tensorboard_callback()\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":{"execution":{"iopub.status.busy":"2024-03-22T16:54:10.975097Z","iopub.execute_input":"2024-03-22T16:54:10.975787Z","iopub.status.idle":"2024-03-22T16:54:10.980812Z","shell.execute_reply.started":"2024-03-22T16:54:10.975758Z","shell.execute_reply":"2024-03-22T16:54:10.979933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fit the model to the data\nmodel = train_model()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:54:13.966385Z","iopub.execute_input":"2024-03-22T16:54:13.967260Z","iopub.status.idle":"2024-03-22T16:54:55.110612Z","shell.execute_reply.started":"2024-03-22T16:54:13.967202Z","shell.execute_reply":"2024-03-22T16:54:55.109798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the validation data (not used to train on)\npredictions = model.predict(val_data, verbose=1)\npredictions","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:57:26.931429Z","iopub.execute_input":"2024-03-22T16:57:26.932398Z","iopub.status.idle":"2024-03-22T16:57:33.015839Z","shell.execute_reply.started":"2024-03-22T16:57:26.932362Z","shell.execute_reply":"2024-03-22T16:57:33.014845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# First prediction\nindex = 42\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":{"execution":{"iopub.status.busy":"2024-03-22T16:57:33.018006Z","iopub.execute_input":"2024-03-22T16:57:33.018417Z","iopub.status.idle":"2024-03-22T16:57:33.026001Z","shell.execute_reply.started":"2024-03-22T16:57:33.018380Z","shell.execute_reply":"2024-03-22T16:57:33.025163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn prediction probabilities into their respective label (easier to understand)\ndef get_pred_label(prediction_probabilities):\n  \"\"\"\n  Turns an array of prediction probabilities into a label.\n  \"\"\"\n  return unique_breeds[np.argmax(prediction_probabilities)]\n\n# Get a predicted label based on an array of prediction probabilities\npred_label = get_pred_label(predictions[81])\npred_label","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:57:33.027181Z","iopub.execute_input":"2024-03-22T16:57:33.027441Z","iopub.status.idle":"2024-03-22T16:57:33.044333Z","shell.execute_reply.started":"2024-03-22T16:57:33.027420Z","shell.execute_reply":"2024-03-22T16:57:33.043477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:57:33.046188Z","iopub.execute_input":"2024-03-22T16:57:33.047122Z","iopub.status.idle":"2024-03-22T16:57:33.356544Z","shell.execute_reply.started":"2024-03-22T16:57:33.047092Z","shell.execute_reply":"2024-03-22T16:57:33.355483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:57:36.539501Z","iopub.execute_input":"2024-03-22T16:57:36.540180Z","iopub.status.idle":"2024-03-22T16:57:36.546410Z","shell.execute_reply.started":"2024-03-22T16:57:36.540148Z","shell.execute_reply":"2024-03-22T16:57:36.545553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images,\n          n=77)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:57:36.859094Z","iopub.execute_input":"2024-03-22T16:57:36.859466Z","iopub.status.idle":"2024-03-22T16:57:37.115974Z","shell.execute_reply.started":"2024-03-22T16:57:36.859437Z","shell.execute_reply":"2024-03-22T16:57:37.114617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:57:40.900943Z","iopub.execute_input":"2024-03-22T16:57:40.901311Z","iopub.status.idle":"2024-03-22T16:57:40.909065Z","shell.execute_reply.started":"2024-03-22T16:57:40.901284Z","shell.execute_reply":"2024-03-22T16:57:40.908079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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()\n","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:57:41.246299Z","iopub.execute_input":"2024-03-22T16:57:41.246602Z","iopub.status.idle":"2024-03-22T16:57:43.500775Z","shell.execute_reply.started":"2024-03-22T16:57:41.246577Z","shell.execute_reply":"2024-03-22T16:57:43.499578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the pre-saved model\nmodel.evaluate(val_data)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:58:03.014190Z","iopub.execute_input":"2024-03-22T16:58:03.014556Z","iopub.status.idle":"2024-03-22T16:58:03.324770Z","shell.execute_reply.started":"2024-03-22T16:58:03.014525Z","shell.execute_reply":"2024-03-22T16:58:03.323910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a data batch with the full data set\nfull_data = create_data_batches(X, y)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:58:10.767630Z","iopub.execute_input":"2024-03-22T16:58:10.768539Z","iopub.status.idle":"2024-03-22T16:58:10.898223Z","shell.execute_reply.started":"2024-03-22T16:58:10.768506Z","shell.execute_reply":"2024-03-22T16:58:10.897370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a model for full model\nfull_model = create_model()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T16:58:13.552218Z","iopub.execute_input":"2024-03-22T16:58:13.552963Z","iopub.status.idle":"2024-03-22T16:58:13.562413Z","shell.execute_reply.started":"2024-03-22T16:58:13.552913Z","shell.execute_reply":"2024-03-22T16:58:13.561497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:58:15.564798Z","iopub.execute_input":"2024-03-22T16:58:15.565553Z","iopub.status.idle":"2024-03-22T16:58:15.570221Z","shell.execute_reply.started":"2024-03-22T16:58:15.565520Z","shell.execute_reply":"2024-03-22T16:58:15.569232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-03-22T16:58:16.831454Z","iopub.execute_input":"2024-03-22T16:58:16.832074Z","iopub.status.idle":"2024-03-22T17:03:59.707262Z","shell.execute_reply.started":"2024-03-22T16:58:16.832043Z","shell.execute_reply":"2024-03-22T17:03:59.706300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load test image filenames\ntest_path = \"/kaggle/input/dog-breed-identification/test/\"\ntest_filenames = [test_path + fname for fname in os.listdir(test_path)]\ntest_filenames[:10]","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:25:05.778873Z","iopub.execute_input":"2024-03-22T17:25:05.779613Z","iopub.status.idle":"2024-03-22T17:25:06.254090Z","shell.execute_reply.started":"2024-03-22T17:25:05.779578Z","shell.execute_reply":"2024-03-22T17:25:06.253201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(test_filenames)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:25:10.723745Z","iopub.execute_input":"2024-03-22T17:25:10.724631Z","iopub.status.idle":"2024-03-22T17:25:10.730167Z","shell.execute_reply.started":"2024-03-22T17:25:10.724593Z","shell.execute_reply":"2024-03-22T17:25:10.729227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create test data batch\ntest_data = create_data_batches(test_filenames, test_data=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:25:11.210614Z","iopub.execute_input":"2024-03-22T17:25:11.211564Z","iopub.status.idle":"2024-03-22T17:25:11.236121Z","shell.execute_reply.started":"2024-03-22T17:25:11.211517Z","shell.execute_reply":"2024-03-22T17:25:11.235199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on test data batch using the loaded full model\ntest_predictions = full_model.predict(test_data,\n                                             verbose=1)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:25:14.459639Z","iopub.execute_input":"2024-03-22T17:25:14.460136Z","iopub.status.idle":"2024-03-22T17:26:04.181685Z","shell.execute_reply.started":"2024-03-22T17:25:14.460104Z","shell.execute_reply":"2024-03-22T17:26:04.180840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a pandas DataFrame with empty columns\npreds_df = pd.DataFrame(columns=[\"id\"] + list(unique_breeds))\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:04.183530Z","iopub.execute_input":"2024-03-22T17:26:04.183829Z","iopub.status.idle":"2024-03-22T17:26:04.215891Z","shell.execute_reply.started":"2024-03-22T17:26:04.183785Z","shell.execute_reply":"2024-03-22T17:26:04.215011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:04.217193Z","iopub.execute_input":"2024-03-22T17:26:04.217971Z","iopub.status.idle":"2024-03-22T17:26:04.283326Z","shell.execute_reply.started":"2024-03-22T17:26:04.217936Z","shell.execute_reply":"2024-03-22T17:26:04.282582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:04.285742Z","iopub.execute_input":"2024-03-22T17:26:04.286310Z","iopub.status.idle":"2024-03-22T17:26:04.310847Z","shell.execute_reply.started":"2024-03-22T17:26:04.286273Z","shell.execute_reply":"2024-03-22T17:26:04.309971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Add the prediction probabilities to each dog breed column\npreds_df[list(unique_breeds)] = test_predictions\npreds_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:04.312008Z","iopub.execute_input":"2024-03-22T17:26:04.312285Z","iopub.status.idle":"2024-03-22T17:26:04.364596Z","shell.execute_reply.started":"2024-03-22T17:26:04.312262Z","shell.execute_reply":"2024-03-22T17:26:04.363629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:04.365727Z","iopub.execute_input":"2024-03-22T17:26:04.366004Z","iopub.status.idle":"2024-03-22T17:26:05.901698Z","shell.execute_reply.started":"2024-03-22T17:26:04.365981Z","shell.execute_reply":"2024-03-22T17:26:05.900633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_predictions.shape","metadata":{"execution":{"iopub.status.busy":"2024-03-22T17:26:05.902989Z","iopub.execute_input":"2024-03-22T17:26:05.903270Z","iopub.status.idle":"2024-03-22T17:26:05.909280Z","shell.execute_reply.started":"2024-03-22T17:26:05.903246Z","shell.execute_reply":"2024-03-22T17:26:05.908388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}