diff --git "a/Sneakers_Transfer_Learning.ipynb" "b/Sneakers_Transfer_Learning.ipynb"
new file mode 100644--- /dev/null
+++ "b/Sneakers_Transfer_Learning.ipynb"
@@ -0,0 +1,1202 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "provenance": [],
+ "toc_visible": true,
+ "authorship_tag": "ABX9TyMy6eJcO6tG5bz/ZoOCzLY4",
+ "include_colab_link": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ },
+ "language_info": {
+ "name": "python"
+ },
+ "accelerator": "GPU",
+ "gpuClass": "standard"
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "view-in-github",
+ "colab_type": "text"
+ },
+ "source": [
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Becoming one with data"
+ ],
+ "metadata": {
+ "id": "s6TgLDGj0Tgs"
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "id": "FJT3_4AWzvrS"
+ },
+ "outputs": [],
+ "source": [
+ "import zipfile\n",
+ "\n",
+ "# Unzip the downloaded file from github or kaggle \"https://www.kaggle.com/datasets/die9origephit/nike-adidas-and-converse-imaged?resource=download\"\n",
+ "zip_ref = zipfile.ZipFile(\"Sneakers_CNN.zip\", \"r\")\n",
+ "zip_ref.extractall()\n",
+ "zip_ref.close()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import os\n",
+ "\n",
+ "# Walk through directory and list number of files\n",
+ "print(\"TRAIN---\")\n",
+ "for dirpath, dirnames, filenames in os.walk(\"train\"):\n",
+ " print(f\"There are {len(dirnames)} directories and {len(filenames)} images in '{dirpath}'.\")\n",
+ "print(\"TEST---\")\n",
+ "for dirpath, dirnames, filenames in os.walk(\"test\"):\n",
+ " print(f\"There are {len(dirnames)} directories and {len(filenames)} images in '{dirpath}'.\")"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "L-BIxhaw0ATB",
+ "outputId": "b313a9a6-1ea9-49ca-81e1-8454f60a0da1"
+ },
+ "execution_count": 6,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "TRAIN---\n",
+ "There are 3 directories and 0 images in 'train'.\n",
+ "There are 0 directories and 237 images in 'train/nike'.\n",
+ "There are 0 directories and 237 images in 'train/converse'.\n",
+ "There are 0 directories and 237 images in 'train/adidas'.\n",
+ "TEST---\n",
+ "There are 3 directories and 0 images in 'test'.\n",
+ "There are 0 directories and 38 images in 'test/nike'.\n",
+ "There are 0 directories and 38 images in 'test/converse'.\n",
+ "There are 0 directories and 38 images in 'test/adidas'.\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Preprocessing Data"
+ ],
+ "metadata": {
+ "id": "CNka9U0d1d1g"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# Setup data inputs\n",
+ "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
+ "\n",
+ "IMAGE_SHAPE = (224, 224)\n",
+ "BATCH_SIZE = 32\n",
+ "\n",
+ "train_dir = \"/content/train\"\n",
+ "test_dir = \"/content/test\"\n",
+ "\n",
+ "train_datagen = ImageDataGenerator(rescale=1/255.)\n",
+ "test_datagen = ImageDataGenerator(rescale=1/255.)\n",
+ "\n",
+ "print(\"Training images:\")\n",
+ "train_data_10_percent = train_datagen.flow_from_directory(train_dir,\n",
+ " target_size=IMAGE_SHAPE,\n",
+ " batch_size=BATCH_SIZE,\n",
+ " class_mode=\"categorical\")\n",
+ "\n",
+ "print(\"Testing images:\")\n",
+ "test_data = train_datagen.flow_from_directory(test_dir,\n",
+ " target_size=IMAGE_SHAPE,\n",
+ " batch_size=BATCH_SIZE,\n",
+ " class_mode=\"categorical\")"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "cEymnz7a1l71",
+ "outputId": "3facc161-d4da-4665-afa2-0008318b41ac"
+ },
+ "execution_count": 7,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Training images:\n",
+ "Found 711 images belonging to 3 classes.\n",
+ "Testing images:\n",
+ "Found 114 images belonging to 3 classes.\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Setting Callbacks"
+ ],
+ "metadata": {
+ "id": "Tf84Dlox1v-U"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# Create tensorboard callback (functionized because need to create a new one for each model)\n",
+ "import datetime\n",
+ "def create_tensorboard_callback(dir_name, experiment_name):\n",
+ " log_dir = dir_name + \"/\" + experiment_name + \"/\" + datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
+ " tensorboard_callback = tf.keras.callbacks.TensorBoard(\n",
+ " log_dir=log_dir\n",
+ " )\n",
+ " print(f\"Saving TensorBoard log files to: {log_dir}\")\n",
+ " return tensorboard_callback\n",
+ " "
+ ],
+ "metadata": {
+ "id": "LhzWxCb112ee"
+ },
+ "execution_count": 8,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "# Plot the validation and training data separately\n",
+ "def plot_loss_curves(history):\n",
+ " \"\"\"\n",
+ " Returns separate loss curves for training and validation metrics.\n",
+ " \"\"\" \n",
+ " loss = history.history['loss']\n",
+ " val_loss = history.history['val_loss']\n",
+ "\n",
+ " accuracy = history.history['accuracy']\n",
+ " val_accuracy = history.history['val_accuracy']\n",
+ "\n",
+ " epochs = range(len(history.history['loss']))\n",
+ "\n",
+ " # Plot loss\n",
+ " plt.plot(epochs, loss, label='training_loss')\n",
+ " plt.plot(epochs, val_loss, label='val_loss')\n",
+ " plt.title('Loss')\n",
+ " plt.xlabel('Epochs')\n",
+ " plt.legend()\n",
+ "\n",
+ " # Plot accuracy\n",
+ " plt.figure()\n",
+ " plt.plot(epochs, accuracy, label='training_accuracy')\n",
+ " plt.plot(epochs, val_accuracy, label='val_accuracy')\n",
+ " plt.title('Accuracy')\n",
+ " plt.xlabel('Epochs')\n",
+ " plt.legend();"
+ ],
+ "metadata": {
+ "id": "k6gmZ13mpAo7"
+ },
+ "execution_count": 14,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Creating models using Tensorflow Hub"
+ ],
+ "metadata": {
+ "id": "X579fHUS15Fe"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import tensorflow as tf\n",
+ "import tensorflow_hub as hub\n",
+ "from tensorflow.keras import layers"
+ ],
+ "metadata": {
+ "id": "DeM4Iedx1_WM"
+ },
+ "execution_count": 9,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "Models used :\n",
+ "* Resnet V2 50\n",
+ "* EfficientNet B0 (version 1)\n",
+ "* EfficientNet B0 (version 2)\n",
+ "* MobileNet V2"
+ ],
+ "metadata": {
+ "id": "WJaJre0q2CiA"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# Resnet 50 V2 feature vector\n",
+ "resnet_url = \"https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/4\"\n",
+ "\n",
+ "# Original: EfficientNetB0 feature vector (version 1)\n",
+ "efficientnet_url = \"https://tfhub.dev/tensorflow/efficientnet/b0/feature-vector/1\"\n",
+ "\n",
+ "# New: EfficientNetB0 feature vector (version 2)\n",
+ "efficientnet_2_url = \"https://tfhub.dev/google/imagenet/efficientnet_v2_imagenet1k_b0/feature_vector/2\"\n",
+ "\n",
+ "# MobileNet V2 feature vector\n",
+ "mobilenet_url=\"https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/5\""
+ ],
+ "metadata": {
+ "id": "6xagt0Uj2epB"
+ },
+ "execution_count": 24,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "def create_model(model_url, num_classes=10):\n",
+ " \"\"\"Takes a TensorFlow Hub URL and creates a Keras Sequential model with it.\n",
+ " \n",
+ " Args:\n",
+ " model_url (str): A TensorFlow Hub feature extraction URL.\n",
+ " num_classes (int): Number of output neurons in output layer,\n",
+ " should be equal to number of target classes, default 10.\n",
+ "\n",
+ " Returns:\n",
+ " An uncompiled Keras Sequential model with model_url as feature\n",
+ " extractor layer and Dense output layer with num_classes outputs.\n",
+ " \"\"\"\n",
+ " # Download the pretrained model and save it as a Keras layer\n",
+ " feature_extractor_layer = hub.KerasLayer(model_url,\n",
+ " trainable=False, # freeze the underlying patterns\n",
+ " name='feature_extraction_layer',\n",
+ " input_shape=IMAGE_SHAPE+(3,)) # define the input image shape\n",
+ " \n",
+ " # Create our own model\n",
+ " model = tf.keras.Sequential([\n",
+ " feature_extractor_layer, # use the feature extraction layer as the base\n",
+ " layers.Dense(num_classes, activation='softmax', name='output_layer') # create our own output layer \n",
+ " ])\n",
+ "\n",
+ " return model"
+ ],
+ "metadata": {
+ "id": "7RaajEUabHT9"
+ },
+ "execution_count": 11,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "#### Resnet"
+ ],
+ "metadata": {
+ "id": "Zcywxx0sbQgw"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# Create model\n",
+ "resnet_model = create_model(resnet_url, num_classes=train_data_10_percent.num_classes)\n",
+ "\n",
+ "# Compile model\n",
+ "resnet_model.compile(loss='categorical_crossentropy',\n",
+ " optimizer=tf.keras.optimizers.Adam(),\n",
+ " metrics=['accuracy'])"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "6J6F8t5ebcnz",
+ "outputId": "881f05a0-5055-4bc0-941f-66c94e13848b"
+ },
+ "execution_count": 12,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stderr",
+ "text": [
+ "WARNING:tensorflow:Please fix your imports. Module tensorflow.python.training.tracking.data_structures has been moved to tensorflow.python.trackable.data_structures. The old module will be deleted in version 2.11.\n",
+ "WARNING:tensorflow:From /usr/local/lib/python3.8/dist-packages/tensorflow/python/autograph/pyct/static_analysis/liveness.py:83: Analyzer.lamba_check (from tensorflow.python.autograph.pyct.static_analysis.liveness) is deprecated and will be removed after 2023-09-23.\n",
+ "Instructions for updating:\n",
+ "Lambda fuctions will be no more assumed to be used in the statement where they are used, or at least in the same block. https://github.com/tensorflow/tensorflow/issues/56089\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# Fit the model\n",
+ "resnet_history = resnet_model.fit(train_data_10_percent,\n",
+ " epochs=5,\n",
+ " steps_per_epoch=len(train_data_10_percent),\n",
+ " validation_data=test_data,\n",
+ " validation_steps=len(test_data),\n",
+ " # Add TensorBoard callback to model (callbacks parameter takes a list)\n",
+ " callbacks=[create_tensorboard_callback(dir_name=\"tensorflow_hub\", # save experiment logs here\n",
+ " experiment_name=\"resnet50V2\")]) # name of log files"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "8rs8hNWObeWJ",
+ "outputId": "6756abd2-abcc-41b6-ab67-7859d812085e"
+ },
+ "execution_count": 13,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Saving TensorBoard log files to: tensorflow_hub/resnet50V2/20230228-152728\n",
+ "Epoch 1/5\n",
+ "23/23 [==============================] - 19s 219ms/step - loss: 0.9993 - accuracy: 0.5091 - val_loss: 0.8047 - val_accuracy: 0.6491\n",
+ "Epoch 2/5\n",
+ "23/23 [==============================] - 2s 106ms/step - loss: 0.6376 - accuracy: 0.7356 - val_loss: 0.6863 - val_accuracy: 0.7018\n",
+ "Epoch 3/5\n",
+ "23/23 [==============================] - 3s 108ms/step - loss: 0.5183 - accuracy: 0.8115 - val_loss: 0.6317 - val_accuracy: 0.7018\n",
+ "Epoch 4/5\n",
+ "23/23 [==============================] - 2s 105ms/step - loss: 0.4382 - accuracy: 0.8664 - val_loss: 0.6110 - val_accuracy: 0.7368\n",
+ "Epoch 5/5\n",
+ "23/23 [==============================] - 3s 131ms/step - loss: 0.3842 - accuracy: 0.8790 - val_loss: 0.5968 - val_accuracy: 0.7456\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "plot_loss_curves(resnet_history)"
+ ],
+ "metadata": {
+ "id": "TWetSQXzl6IJ",
+ "outputId": "d7b9d426-410f-40ed-d121-c63e7f109496",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 573
+ }
+ },
+ "execution_count": 15,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ "