{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3W9PPXC4r5bl"
   },
   "source": [
    "## Training with Small Datasets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "eD42RODSVk5Z"
   },
   "source": [
    "### Preliminaries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "1Zil0bIDr5bp",
    "tags": []
   },
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "plt.rcParams[\"figure.figsize\"] = (3,2)  # default figure width, height in inches"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "kKKAa30Y8NvM",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# generalized version of plot_history that plots validation data if available\n",
    "\n",
    "def plot_history(history):\n",
    "    loss_values = history.history['loss']\n",
    "    accuracy_values = history.history['accuracy']\n",
    "    validation = 'val_loss' in history.history\n",
    "    if validation:\n",
    "        val_loss_values = history.history['val_loss']\n",
    "        val_accuracy_values = history.history['val_accuracy']\n",
    "    epoch_nums = range(1, len(loss_values)+1)\n",
    "    plt.figure(figsize=(12,4)) # width, height in inches\n",
    "    plt.subplot(1, 2, 1)\n",
    "    if validation:\n",
    "        plt.plot(epoch_nums, loss_values, 'r', label=\"Training loss\")\n",
    "        plt.plot(epoch_nums, val_loss_values, 'r--', label=\"Validation loss\")\n",
    "        plt.title(\"Training/validation loss\")\n",
    "        plt.legend()\n",
    "    else:\n",
    "        plt.plot(epoch_nums, loss_values, 'r', label=\"Training loss\")\n",
    "        plt.title(\"Training loss\")\n",
    "    plt.xlabel(\"Epochs\")\n",
    "    plt.ylabel(\"Loss\")\n",
    "    plt.subplot(1, 2, 2)\n",
    "    if validation:\n",
    "        plt.plot(epoch_nums, accuracy_values, 'b', label='Training accuracy')\n",
    "        plt.plot(epoch_nums, val_accuracy_values, 'b--', label='Validation accuracy')\n",
    "        plt.title(\"Training/validation accuracy\")\n",
    "        plt.legend()\n",
    "    else:\n",
    "        plt.plot(epoch_nums, accuracy_values, 'b', label='Training accuracy')\n",
    "        plt.title(\"Training accuracy\")\n",
    "    plt.xlabel(\"Epochs\")\n",
    "    plt.ylabel(\"Accuracy\")\n",
    "    plt.ylim(0, 1)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WnqESWFbr5b0"
   },
   "source": [
    "### Loading Dataset Files From a Directory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "TACUbSseVk5b",
    "outputId": "cd6fcd1a-28e5-476a-97bd-384f1343d7a8"
   },
   "outputs": [],
   "source": [
    "!curl -O science.slc.edu/jmarshall/bioai/data/cats_and_dogs_tiny.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "BHjIi6uEVk5c"
   },
   "outputs": [],
   "source": [
    "!unzip -q cats_and_dogs_tiny.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "-2FWkfCzXWIK",
    "outputId": "c0960822-917a-4aa6-b914-0bb20f94dab1"
   },
   "outputs": [],
   "source": [
    "!ls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "KzspfM3wVk5c",
    "outputId": "0901ae1c-87ad-4ff3-b4de-69b04e4316eb",
    "tags": []
   },
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny/train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "E0toGKk4Xiou",
    "outputId": "6f059120-ccaf-41ae-c252-fd48ad66bdd5"
   },
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny/train/dogs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny/validation/dogs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny/test/dogs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_tiny/train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "omHaqF-Hr5b0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from keras.utils import image_dataset_from_directory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "6WGn5go5r5b0",
    "outputId": "b147730b-8440-444e-c2fc-70607848dc48",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_dataset = image_dataset_from_directory('cats_and_dogs_tiny/train',\n",
    "                                             image_size=(180,180),\n",
    "                                             batch_size=6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "7ZCwgVuJr5b1",
    "outputId": "a7d4f652-c38e-4823-8b45-2c0c7e69760b",
    "tags": []
   },
   "outputs": [],
   "source": [
    "val_dataset = image_dataset_from_directory('cats_and_dogs_tiny/validation',\n",
    "                                           image_size=(180,180),\n",
    "                                           batch_size=6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "i9DRtmCur5b1",
    "outputId": "ee5a56c0-44f3-4898-a92a-5084a4378804",
    "tags": []
   },
   "outputs": [],
   "source": [
    "test_dataset = image_dataset_from_directory('cats_and_dogs_tiny/test',\n",
    "                                            image_size=(180,180),\n",
    "                                            batch_size=6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "eiGuU0oEr5b1",
    "outputId": "6678acb8-edcc-401e-bf22-615cf5161e73",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pbZT9go4r5b1"
   },
   "source": [
    "These dataset objects return images of type 'float32' in the range 0.0 to 255.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "RxiMhrl6r5b1",
    "tags": []
   },
   "outputs": [],
   "source": [
    "for image_batch, label_batch in train_dataset:\n",
    "    images = image_batch\n",
    "    labels = label_batch\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Txu9ad3XVk5f",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "z1HO-j9DVk5f",
    "outputId": "d3f3f82e-aa19-433c-96fd-0647c9c0c7f5",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "ykr7-xLjVk5g",
    "outputId": "b4b8ebf9-1488-442f-be3b-d40f11567664",
    "tags": []
   },
   "outputs": [],
   "source": [
    "labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "49tEO8n2Vk5g",
    "outputId": "25f17e49-6837-4039-9bf6-7d1485d166da",
    "tags": []
   },
   "outputs": [],
   "source": [
    "labels.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "9UGF5HOjr5b2",
    "jupyter": {
     "source_hidden": true
    },
    "outputId": "4e9204e6-8ca4-4156-f7d5-ed16f04aecf3",
    "tags": []
   },
   "outputs": [],
   "source": [
    "for image_batch, label_batch in train_dataset:\n",
    "    # image_batch and label_batch are of type EagerTensor\n",
    "    print(\"image_batch.shape =\", image_batch.shape)\n",
    "    print(\"image_batch.dtype =\", image_batch.dtype,\n",
    "          \"min =\", image_batch.numpy().min(),\n",
    "          \"max =\", image_batch.numpy().max())\n",
    "    print(\"label_batch.shape =\", label_batch.shape)\n",
    "    print(\"label_batch.dtype =\", label_batch.dtype)\n",
    "    print('------------------------------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "1-iA0kU9r5b1",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator = train_dataset.as_numpy_iterator()\n",
    "val_iterator = val_dataset.as_numpy_iterator()\n",
    "test_iterator = test_dataset.as_numpy_iterator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "f7Yf5XZkVk5h",
    "outputId": "99c1fa0a-3981-4590-a59c-d07774759900",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "I1Dd-ke9bBNx",
    "outputId": "1e7aef1c-5981-4c5a-8a2b-1b315fd41e3e"
   },
   "outputs": [],
   "source": [
    "type(train_iterator.next())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Dc-SIOupVk5h",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator.next()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "FQKe2JVrbN7H"
   },
   "outputs": [],
   "source": [
    "images, labels = train_iterator.next()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "THe-P7ojbSYj",
    "outputId": "cb921484-36c8-4132-9d2d-7455d6c669d9"
   },
   "outputs": [],
   "source": [
    "type(images)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "iOBxYcIqr5b2",
    "tags": []
   },
   "outputs": [],
   "source": [
    "def get_next_batch(iterator):\n",
    "    images, labels = iterator.next()\n",
    "    images = images.astype('float32') / 255\n",
    "    labels = labels.astype('uint8')\n",
    "    return images, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "2eTJX8P-r5b2",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images, labels = get_next_batch(train_iterator)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "fF4WBW3Cr5b2",
    "outputId": "892f195b-e853-46bf-dfbd-1e860146c281",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "lb0BJssYr5b2",
    "outputId": "891d54ef-f823-4434-bcb9-250f506ad583",
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(images.dtype, images.min(), images.max())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "zaUh1RD7r5b2",
    "outputId": "78ad8fb9-77de-4156-9e60-70ff9c85efc4",
    "tags": []
   },
   "outputs": [],
   "source": [
    "labels.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "oEuTA8-Dr5b3",
    "outputId": "782ca6e5-0d67-4897-d9ba-ccae10c45828",
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(labels.dtype, labels.min(), labels.max())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "dxW6mTAVVk5i",
    "outputId": "6a4b78f5-9e95-4f54-e693-6b0981ff87e0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images, labels = get_next_batch(train_iterator)\n",
    "print(\"images:\", type(images))\n",
    "print(\"labels:\", type(labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Mf_nXxPeVk5i",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def get_next_batch(iterator):\n",
    "    try:\n",
    "        images, labels = iterator.next()\n",
    "    except:\n",
    "        return None, None\n",
    "    images = images.astype('float32') / 255\n",
    "    labels = labels.astype('uint8')\n",
    "    return images, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "lwbzCY6aVk5i",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator = train_dataset.as_numpy_iterator()\n",
    "val_iterator = val_dataset.as_numpy_iterator()\n",
    "test_iterator = test_dataset.as_numpy_iterator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "7J3aywzHVk5i",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images, labels = get_next_batch(train_iterator)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "EVA5NeTNr5b3",
    "outputId": "86a501fc-2ab4-4dc0-b839-47e676ec89f8",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(images[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "51lX2w-Gr5b3",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def show_next_batch(iterator):\n",
    "    images, labels = get_next_batch(iterator)\n",
    "    if images is None:\n",
    "        print('out of data')\n",
    "        return\n",
    "    print('class labels:', labels)\n",
    "    rows, columns = int(np.ceil(len(images)/8)), 8\n",
    "    plt.figure(figsize=(12,rows*1.5))  # (width, height) in inches\n",
    "    k = 0\n",
    "    for i in range(1, columns*rows+1):\n",
    "        if k >= len(images): break\n",
    "        img = images[k]\n",
    "        k += 1\n",
    "        plt.subplot(rows, columns, i)\n",
    "        plt.axis('off')\n",
    "        plt.imshow(img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "BsswFmsur5b3",
    "outputId": "ec05cf98-1e37-4c3b-c722-f0c2d533d2eb",
    "tags": []
   },
   "outputs": [],
   "source": [
    "show_next_batch(train_iterator)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8PJyZVQ3Vk5j"
   },
   "source": [
    "### Creating a Single Numpy Array from a Dataset\n",
    "\n",
    "Let's first recreate the Dataset objects from our image folders:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "9uimwy-sVk5j",
    "outputId": "10aff2d3-281d-4383-f7d1-0a3e65928ba2",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_dataset = image_dataset_from_directory('cats_and_dogs_tiny/train',\n",
    "                                             image_size=(180,180),\n",
    "                                             batch_size=6)\n",
    "\n",
    "val_dataset = image_dataset_from_directory('cats_and_dogs_tiny/validation',\n",
    "                                           image_size=(180,180),\n",
    "                                           batch_size=6)\n",
    "\n",
    "test_dataset = image_dataset_from_directory('cats_and_dogs_tiny/test',\n",
    "                                            image_size=(180,180),\n",
    "                                            batch_size=6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "g44Ngh9zVk5j"
   },
   "source": [
    "Now we will concatenate the images in each batch into a single Numpy array, and do the same with the labels:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "jIC_UsT3Vk5k",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "all_image_batches = []\n",
    "all_label_batches = []\n",
    "for image_batch, label_batch in train_dataset:\n",
    "    image_batch = image_batch.numpy()\n",
    "    label_batch = label_batch.numpy()\n",
    "    all_image_batches.append(image_batch)\n",
    "    all_label_batches.append(label_batch)\n",
    "images = np.concatenate(all_image_batches)\n",
    "labels = np.concatenate(all_label_batches)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "rRmIDSlrVk5k",
    "outputId": "1b554315-33be-4419-821c-327cf6dd2dbc",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "lqkamgKvVk5k",
    "outputId": "08b961c7-dc8d-45fa-f8d7-774ad2b54f75",
    "tags": []
   },
   "outputs": [],
   "source": [
    "print(images.dtype, images.min(), images.max())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ja0k6BwnVk5k",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 256
    },
    "id": "kH2VxLjTVk5k",
    "outputId": "6b931980-877f-4337-803f-f819dedd96e9",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(images[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "TEXEHtvbVk5l",
    "tags": []
   },
   "outputs": [],
   "source": [
    "np.round(images[0]).astype('uint8')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "JfeKU7poVk5l",
    "outputId": "8509676b-2748-467e-eb6c-4b614757cd66",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(np.round(images[0]).astype('uint8'));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "-Xo5UO5mVk5l",
    "outputId": "bb28f7ab-8e2d-46c1-9648-5ccae3057d02",
    "tags": []
   },
   "outputs": [],
   "source": [
    "labels.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "qtzIDqRiVk5l",
    "outputId": "88d8c7b8-b2ea-413c-d0e2-a85d49941cfc",
    "tags": []
   },
   "outputs": [],
   "source": [
    "labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Bc0v0Ub7Vk5l",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def read_images(folder_name, height, width):\n",
    "    dataset = image_dataset_from_directory(folder_name, image_size=(height, width))\n",
    "    all_image_batches = []\n",
    "    all_label_batches = []\n",
    "    for image_batch, label_batch in dataset:\n",
    "      image_batch = np.round(image_batch.numpy()).astype('uint8')\n",
    "      label_batch = label_batch.numpy().astype('uint8')\n",
    "      all_image_batches.append(image_batch)\n",
    "      all_label_batches.append(label_batch)\n",
    "    images = np.concatenate(all_image_batches)\n",
    "    labels = np.concatenate(all_label_batches)\n",
    "    return images, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "5j40xFcKVk5l",
    "outputId": "36eec718-ff4e-4d61-c932-f8c7b1c84a33",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_images, train_labels = read_images('cats_and_dogs_tiny/train', 200, 400)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "bnPHDzNvVk5l",
    "outputId": "237cb4b3-8132-4e91-d304-60e8f16f7bcd",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 182
    },
    "id": "RBI_ztRbVk5l",
    "outputId": "f67d0587-4e70-448c-ca29-5daa5e3c5167",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(train_images[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "1UXLtoq_Vk5m",
    "outputId": "29b530cc-6172-468f-855e-a55b0816d872",
    "tags": []
   },
   "outputs": [],
   "source": [
    "val_images, val_labels = read_images('cats_and_dogs_tiny/validation', 200, 400)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "eKJhqJCdVk5m",
    "outputId": "175cd357-831a-4509-fc77-fd4e3ddf7ba6",
    "tags": []
   },
   "outputs": [],
   "source": [
    "test_images, test_labels = read_images('cats_and_dogs_tiny/test', 200, 400)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "SmzyENFMVk5m",
    "tags": []
   },
   "outputs": [],
   "source": [
    "all_images = np.concatenate([train_images, val_images, test_images])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "knIxtH_uVk5m",
    "tags": []
   },
   "outputs": [],
   "source": [
    "all_labels = np.concatenate([train_labels, val_labels, test_labels])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "2hUJpkjmVk5m",
    "outputId": "31508964-7b74-4292-9bce-e2772557e12b",
    "tags": []
   },
   "outputs": [],
   "source": [
    "all_images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "HPTxgcfVVk5m",
    "outputId": "b332efda-f2ce-4314-c76a-3eb0c52a2476",
    "tags": []
   },
   "outputs": [],
   "source": [
    "all_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "xnERZy9fVk5m",
    "tags": []
   },
   "outputs": [],
   "source": [
    "np.savez_compressed('tiny_stretched.npz', images=all_images, labels=all_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "51l885gKVk5m",
    "outputId": "7f4aa963-0cbb-48a7-9b3b-d67f7c1c59a4",
    "tags": []
   },
   "outputs": [],
   "source": [
    "!ls -lh tiny_stretched.npz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "7cg682z7Vk5n",
    "tags": []
   },
   "outputs": [],
   "source": [
    "npz = np.load('tiny_stretched.npz')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "a8nMRxNkVk5n",
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_images = npz['images']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "zyxk2wv0Vk5n",
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_labels = npz['labels']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Ohtr9nldVk5n",
    "outputId": "7a53efd8-df44-42b3-d4a4-dc3aca4df8d0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_images.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "mnyWVFcAVk5n",
    "outputId": "d86c4769-15bd-4d47-dc2e-d35556a41ab6",
    "tags": []
   },
   "outputs": [],
   "source": [
    "new_labels.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 182
    },
    "id": "qOLmeeZFVk5n",
    "outputId": "3aa6684b-a278-416f-c049-22e42e9ede41",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(new_images[0]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WLM6tpM5Vk5n"
   },
   "source": [
    "### The (Small) Cats and Dogs Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "DGhVDVtnr5bz",
    "outputId": "86b5946e-b4a3-4522-84f8-be4cc3add290"
   },
   "outputs": [],
   "source": [
    "!curl -O science.slc.edu/jmarshall/bioai/data/cats_and_dogs_small.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "txCMOAHMr5bz"
   },
   "outputs": [],
   "source": [
    "!unzip -q cats_and_dogs_small.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "PUdARBzbVk5o",
    "tags": []
   },
   "outputs": [],
   "source": [
    "!ls cats_and_dogs_small/train/cats"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "1bAawQtoVk5o",
    "outputId": "77a913d8-f254-4bfc-c219-0b47118d1158",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_dataset = image_dataset_from_directory('cats_and_dogs_small/train',\n",
    "                                             image_size=(180,180),\n",
    "                                             batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "PZniMDVcVk5o",
    "outputId": "4e3d0ef1-3ef8-4828-8e4d-c8a97319fe02",
    "tags": []
   },
   "outputs": [],
   "source": [
    "val_dataset = image_dataset_from_directory('cats_and_dogs_small/validation',\n",
    "                                           image_size=(180,180),\n",
    "                                           batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Z1d49dZrVk5o",
    "outputId": "8e741351-ea09-4e75-e6c1-3d20ee4813f2",
    "tags": []
   },
   "outputs": [],
   "source": [
    "test_dataset = image_dataset_from_directory('cats_and_dogs_small/test',\n",
    "                                            image_size=(180,180),\n",
    "                                            batch_size=32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "nqkdvOjbVk5o",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator = train_dataset.as_numpy_iterator()\n",
    "val_iterator = val_dataset.as_numpy_iterator()\n",
    "test_iterator = test_dataset.as_numpy_iterator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 458
    },
    "id": "a4zaAYRMVk5o",
    "outputId": "5c7a08ca-c7a9-454f-d419-26019b906391",
    "tags": []
   },
   "outputs": [],
   "source": [
    "show_next_batch(train_iterator)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1OoYDDxFr5bz",
    "tags": []
   },
   "source": [
    "### A Convolutional Network for Classifying Cats vs. Dogs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "b6T25b_or5bz",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "lptaR6Rer5bz",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from keras.layers import Rescaling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "J1a4MIj6r5b0",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def build_convnet():\n",
    "    network = Sequential()\n",
    "    network.add(Input(shape=(180,180,3)))\n",
    "    network.add(Rescaling(1/255, name='rescale'))\n",
    "    network.add(Conv2D(32, (3,3), activation='relu', name='conv1'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool1'))\n",
    "    network.add(Conv2D(64, (3,3), activation='relu', name='conv2'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool2'))\n",
    "    network.add(Conv2D(128, (3,3), activation='relu', name='conv3'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool3'))\n",
    "    network.add(Conv2D(256, (3,3), activation='relu', name='conv4'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool4'))\n",
    "    network.add(Conv2D(256, (3,3), activation='relu', name='conv5'))\n",
    "    network.add(Flatten(name='flatten'))\n",
    "    network.add(Dense(1, activation='sigmoid', name='output'))\n",
    "    \n",
    "    network.compile(loss='binary_crossentropy',\n",
    "                    optimizer='rmsprop',\n",
    "                    metrics=['accuracy'])\n",
    "    return network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "q-FfO63Br5b0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "petnet = build_convnet()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "vZEbIxeRr5b0",
    "outputId": "62e6949d-f7bb-49f4-8d56-b367e14564be",
    "tags": []
   },
   "outputs": [],
   "source": [
    "petnet.summary(print_fn=print)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "wGoKD-CLr5b3",
    "outputId": "15435ef9-0a7b-43b1-e4a1-10fc3b438a52",
    "tags": []
   },
   "outputs": [],
   "source": [
    "history = petnet.fit(train_dataset, epochs=30, validation_data=val_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 346
    },
    "id": "Qd5DpENpr5b3",
    "outputId": "439a8cf9-0fc9-413b-a076-4573bc25ab97"
   },
   "outputs": [],
   "source": [
    "plot_history(history)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "9ie2K20iug6V",
    "outputId": "6025f502-4a10-4e89-9169-f4870cca654d"
   },
   "outputs": [],
   "source": [
    "petnet.evaluate(test_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4MKEiqv8r5b3"
   },
   "outputs": [],
   "source": [
    "petnet = build_convnet()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "LwJ9EagBr5b3",
    "outputId": "3425e329-a2c2-4046-a448-4fb77b0097d8"
   },
   "outputs": [],
   "source": [
    "history = petnet.fit(train_dataset, epochs=7, validation_data=val_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 343
    },
    "id": "sIXHc9hZr5b3",
    "outputId": "3b3cae0e-e36a-4591-a387-0acc47ccfde4"
   },
   "outputs": [],
   "source": [
    "plot_history(history)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "-50hn_NduGTM",
    "outputId": "60e385f6-0292-471d-c562-87e3da71e1cb"
   },
   "outputs": [],
   "source": [
    "petnet.evaluate(test_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "By-rvuj_uHgS",
    "outputId": "c4d5599f-721c-410c-ab83-ea04257a501d"
   },
   "outputs": [],
   "source": [
    "petnet.summary(print_fn=print)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "85uoDAZiVk5q"
   },
   "source": [
    "### Data Augmentation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ONtxp1HhVk5r",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from keras.layers import RandomFlip, RandomRotation, RandomZoom"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "inkqBcIPVk5r",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "data_augmentation_layers = [\n",
    "    RandomFlip('horizontal'),\n",
    "    RandomFlip('vertical'),\n",
    "    RandomRotation(0.90),\n",
    "    RandomZoom(0.50)\n",
    "]\n",
    "\n",
    "def transform(image):\n",
    "    for layer in data_augmentation_layers:\n",
    "        image = layer(image)\n",
    "    return image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.imshow(transform(images[0]));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "yO3A0YXEl8Pr",
    "tags": []
   },
   "outputs": [],
   "source": [
    "train_iterator = train_dataset.as_numpy_iterator()\n",
    "val_iterator = val_dataset.as_numpy_iterator()\n",
    "test_iterator = test_dataset.as_numpy_iterator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Eb3z7-6YVk5r",
    "tags": []
   },
   "outputs": [],
   "source": [
    "images, labels = get_next_batch(train_iterator)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "EPeWtKvTl_bh",
    "outputId": "f2cc71bc-7abc-47b2-9cc6-a55a14814f28"
   },
   "outputs": [],
   "source": [
    "plt.imshow(images[0]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "P0p_0RxHmDVc",
    "outputId": "f48bd16b-01b9-4409-cfd5-5c842bafcddc"
   },
   "outputs": [],
   "source": [
    "plt.imshow(transform(images[0]));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "ZDbAb2gVVk5r",
    "outputId": "bd8423c0-57d2-4e0a-ec90-29880c15b03e",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(random.choice(images));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 219
    },
    "id": "2NWNegVRVk5r",
    "outputId": "d0a13472-f389-4714-8b76-0389890bc343",
    "tags": []
   },
   "outputs": [],
   "source": [
    "plt.imshow(transform(random.choice(images)));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "6N7xqPekVk5r",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def show_transforms(images):\n",
    "    image = random.choice(images)\n",
    "    plt.axis('off')\n",
    "    plt.imshow(image)\n",
    "    plt.figure(figsize=(15,12))  # (width, height) in inches\n",
    "    rows, columns = 5, 6\n",
    "    for k in range(1, columns*rows+1):\n",
    "        plt.subplot(rows, columns, k)\n",
    "        plt.axis('off')\n",
    "        plt.imshow(transform(image))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 865
    },
    "id": "-NhAoTHFVk5s",
    "outputId": "03f20426-fff3-4196-d740-b79aca8f8b58",
    "tags": []
   },
   "outputs": [],
   "source": [
    "show_transforms(images)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "QYqbrtKcVk5s",
    "tags": []
   },
   "outputs": [],
   "source": [
    "from keras.layers import Lambda, Dropout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "GQNe98edVk5s",
    "jupyter": {
     "source_hidden": true
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "def build_convnet():\n",
    "    network = Sequential()\n",
    "    network.add(Input(shape=(180,180,3)))\n",
    "    network.add(Rescaling(1/255, name='rescale')) #, input_shape=(180,180,3)))\n",
    "    # added data augmentation layer\n",
    "    network.add(Lambda(transform, name='data_aug'))\n",
    "    network.add(Conv2D(32, (3,3), activation='relu', name='conv1'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool1'))\n",
    "    network.add(Conv2D(64, (3,3), activation='relu', name='conv2'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool2'))\n",
    "    network.add(Conv2D(128, (3,3), activation='relu', name='conv3'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool3'))\n",
    "    network.add(Conv2D(256, (3,3), activation='relu', name='conv4'))\n",
    "    network.add(MaxPooling2D((2,2), name='pool4'))\n",
    "    network.add(Conv2D(256, (3,3), activation='relu', name='conv5'))\n",
    "    network.add(Flatten(name='flatten'))\n",
    "    # added dropout layer\n",
    "    network.add(Dropout(0.5))\n",
    "    network.add(Dense(1, activation='sigmoid', name='output'))\n",
    "    \n",
    "    network.compile(loss='binary_crossentropy',\n",
    "                    optimizer='rmsprop',\n",
    "                    metrics=['accuracy'])\n",
    "    return network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "yFqiL98xumiR",
    "tags": []
   },
   "outputs": [],
   "source": [
    "petnet2 = build_convnet()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "4-ezeZHTum7M",
    "outputId": "5df81d4a-1020-45ee-a529-eb3dbe506ad0",
    "tags": []
   },
   "outputs": [],
   "source": [
    "petnet2.summary(print_fn=print)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "h1ceaZQFum93",
    "outputId": "e3556ab3-3ea4-4f93-fafe-5d1076d8530c",
    "tags": []
   },
   "outputs": [],
   "source": [
    "history2 = petnet2.fit(train_dataset, epochs=100, validation_data=val_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 343
    },
    "id": "m5XDyYk4Vk5s",
    "outputId": "e6f56cac-d42a-47e0-9b67-242c3615d83a",
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "plot_history(history2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "-_LtxQkQVk5t",
    "outputId": "d043b5e1-a795-401e-dc1e-08081002b002",
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "petnet2.evaluate(test_dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "provenance": []
  },
  "gpuClass": "standard",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
