Skip to content
Snippets Groups Projects
Jupyter Notebook Block 4 - Convolutional Neural Networks.ipynb 1.89 MiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 1 - Convolutional Neural Networks for CIFAR-10\n",
    "\n",
    "\n",
    "In this notebook chapter, we'll build, train and optimize a neural network to classify images of the CIFAR-10 dataset using convolutional neural networks.\n",
    "\n",
    "This guide uses [tf.keras](https://www.tensorflow.org/guide/keras), a high-level API to build and train models in TensorFlow.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.7.1\n",
      "Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz\n",
      "170500096/170498071 [==============================] - 7s 0us/step\n",
      "170508288/170498071 [==============================] - 7s 0us/step\n",
      "Train: X=(50000, 32, 32, 3), y=(50000, 1)\n",
      "Test: X=(10000, 32, 32, 3), y=(10000, 1)\n",
      "(50000, 1)\n",
      "(10000, 1)\n",
      "(50000, 10)\n",
      "(10000, 10)\n"
     ]
    }
   ],
   "source": [
    "from __future__ import absolute_import, division, print_function, unicode_literals\n",
    "\n",
    "# Import TensorFlow and TensorFlow Datasets\n",
    "import tensorflow as tf\n",
    "print(tf.__version__)\n",
    "\n",
    "# Helper libraries\n",
    "import math\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from tensorflow.keras.datasets import cifar10\n",
    "from tensorflow.keras.utils import to_categorical\n",
Simon van Hemert's avatar
Simon van Hemert committed
    "\n",
    "# load dataset\n",
    "(X_train, y_train), (X_test, y_test) = cifar10.load_data()\n",
    "X_train = X_train.astype('float32')\n",
    "X_test = X_test.astype('float32')\n",
    "\n",
    "class_names = ['airplanes', 'cars', 'birds', 'cats', 'deer',\n",
    "               'dogs',      'frogs',   'horses',  'ships',   'trucks']\n",
    "num_classes = len(class_names)\n",
    "\n",
    "\n",
    "# summarize loaded dataset\n",
    "print('Train: X=%s, y=%s' % (X_train.shape, y_train.shape))\n",
    "print('Test: X=%s, y=%s' % (X_test.shape, y_test.shape))\n",
    "y_train_cat = to_categorical(y_train, 10)\n",
    "y_test_cat  = to_categorical(y_test, 10)\n",
    "print(y_train.shape)\n",
    "print(y_test.shape)\n",
    "print(y_train_cat.shape)\n",
    "print(y_test_cat.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Preprocess the data\n",
    "\n",
    "### 1.1 Zero-Centered Images\n",
    "\n",
    "The value of each pixel in the image data is an integer in the range `[0,255]`. For the model to work properly, these values need to be zero-centered to the range. So here we compute the mean value per colour channel over all training images and subtract the mean value per colour channel from every image in the training and test set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[125.3069  122.95015 113.866  ]\n",
      "[-25.327402 -39.670845 -56.451923]\n",
      "(32, 32, 3)\n",
      "(50000, 32, 32, 3)\n",
      "(10000, 32, 32, 3)\n",
      "float32\n"
     ]
    }
   ],
   "source": [
    "train_mean = X_train.mean(axis=(0,1,2))\n",
    "train_std =  X_train.std(axis=(0,1,2))\n",
    "print(train_mean)\n",
    "X_train_zc = X_train - train_mean\n",
    "X_test_zc  = X_test - train_mean\n",
    "\n",
    "\n",
    "print(X_train_zc[3].mean(axis=(0,1)))\n",
    "print(X_train_zc[3].shape)\n",
    "print(X_train_zc.shape)\n",
    "print(X_test_zc.shape)\n",
    "print(X_train_zc.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 Data Augmentation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "from tensorflow.keras.preprocessing import image\n",
    "\n",
    "\n",
    "train_datagen = ImageDataGenerator(\n",
    "        # set input mean to 0 over the dataset\n",
    "        featurewise_center=False, \n",
    "        # set each sample mean to 0\n",
    "        samplewise_center=False,  \n",
    "        # divide inputs by std of the dataset\n",
    "        featurewise_std_normalization=False, \n",
    "        # divide each input by its std\n",
    "        samplewise_std_normalization=False,  \n",
    "        # apply ZCA whitening\n",
    "        zca_whitening=False, \n",
    "        # epsilon for ZCA whitening\n",
    "        zca_epsilon=1e-06,  \n",
    "        # randomly rotate images in the range (degrees, 0 to 180)\n",
    "        rotation_range=0,  \n",
    "        # randomly shift images horizontally (fraction of total width)\n",
    "        width_shift_range=0.1,\n",
    "        # randomly shift images vertically (fraction of total height)\n",
    "        height_shift_range=0.1,\n",
    "        # set range for random shear\n",
    "        shear_range=0., \n",
    "        # set range for random zoom\n",
    "        zoom_range=0.,  \n",
    "        # set range for random channel shifts\n",
    "        # set mode for filling points outside the input boundaries\n",
    "        channel_shift_range=0.,  \n",
    "        # value used for fill_mode = \"constant\"\n",
    "        fill_mode='nearest',\n",
    "        cval=0.,  \n",
    "        # randomly flip images\n",
    "        horizontal_flip=True, \n",
    "        # randomly flip images\n",
    "        vertical_flip=False,  \n",
    "        # set rescaling factor (applied before any other transformation)\n",
    "        rescale=None,\n",
    "        # set function that will be applied on each input\n",
    "        preprocessing_function=None,\n",
    "        # image data format, either \"channels_first\" or \"channels_last\"\n",
    "        data_format=None,\n",
    "        # fraction of images reserved for validation (strictly between 0 and 1)\n",
    "        validation_split=0.0)\n",
    "\n",
    "validation_datagen = ImageDataGenerator( \n",
    "      # rescale the pixel values (between 0 and 255) to the [0,1] interval \n",
    "      # rescale=1./255\n",
    ")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Build the model\n",
    "\n",
    "Building the neural network requires configuring the layers of the model, then compiling the model."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 Define the network\n",
    "\n",
    "The basic building block of a neural network is the *layer*. A layer extracts a representation from the data fed into it. Hopefully, a series of connected layers results in a representation that is meaningful for the problem at hand.\n",
    "\n",
    "Much of deep learning consists of chaining together simple layers. Most layers, like `tf.keras.layers.Dense`, have internal parameters which are adjusted (\"learned\") during training."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = tf.keras.Sequential()\n",
    "model.add(tf.keras.layers.Conv2D(32, (3, 3), padding='same',\n",
    "                 input_shape=X_train_zc.shape[1:]))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('relu'))\n",
    "model.add(tf.keras.layers.Conv2D(32, (3, 3)))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('relu'))\n",
    "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(tf.keras.layers.Dropout(0.25))\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(64, (3, 3), padding='same'))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('relu'))\n",
    "model.add(tf.keras.layers.Conv2D(64, (3, 3)))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('relu'))\n",
    "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(tf.keras.layers.Dropout(0.25))\n",
    "\n",
    "model.add(tf.keras.layers.Flatten())\n",
    "model.add(tf.keras.layers.Dense(512))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('relu'))\n",
    "model.add(tf.keras.layers.Dropout(0.5))\n",
    "model.add(tf.keras.layers.Dense(num_classes))\n",
    "model.add(tf.keras.layers.BatchNormalization())\n",
    "model.add(tf.keras.layers.Activation('softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`tf.keras.layers.Conv2D(32, (3, 3)))` implies the following parameter settings:\n",
    "\n",
    "\n",
    "- `filters` : Integer, the dimensionality of the output space (i.e. the number of output filters in the \n",
    "convolution). In this case, the number of filters is $32$.\n",
    "\n",
    "- `kernel_size` : An integer or tuple/list of 2 integers, specifying the height and width of the 2D convolution window (receptive field). Can be a single integer to specify the same value for all spatial dimensions. In this \n",
    "case, the receptive field of the filters are $3\\times3$.\n",
    "\n",
    "- `strides` : An integer or tuple/list of 2 integers, specifying the strides of the convolution along the height and width. Can be a single integer to specify the same value for all spatial dimensions. Default strides : $(1, 1)$\n",
    "\n",
    "- `padding`: one of `valid` or `same`. In this case, the size of the output volume won't be changed.\n",
    "\n",
    "`tf.keras.layers.MaxPooling2D(pool_size=(2, 2))` implies the following parameter settings:\n",
    "\n",
    "- `pool_size`: integer or tuple of 2 integers, factors by which to downscale (vertical, horizontal). $(2, 2)$ will halve the input in both spatial dimension. If only one integer is specified, the same window length will be used for both dimensions.\n",
    "- `strides`: Integer, tuple of 2 integers, or `None`. `strides` values. If `None`, it will default to `pool_size`. In this case $(2,2)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " conv2d (Conv2D)             (None, 32, 32, 32)        896       \n",
      "                                                                 \n",
      " batch_normalization (BatchN  (None, 32, 32, 32)       128       \n",
      " ormalization)                                                   \n",
      "                                                                 \n",
      " activation (Activation)     (None, 32, 32, 32)        0         \n",
      "                                                                 \n",
      " conv2d_1 (Conv2D)           (None, 30, 30, 32)        9248      \n",
      "                                                                 \n",
      " batch_normalization_1 (Batc  (None, 30, 30, 32)       128       \n",
      " hNormalization)                                                 \n",
      "                                                                 \n",
      " activation_1 (Activation)   (None, 30, 30, 32)        0         \n",
      "                                                                 \n",
      " max_pooling2d (MaxPooling2D  (None, 15, 15, 32)       0         \n",
      " )                                                               \n",
      "                                                                 \n",
      " dropout (Dropout)           (None, 15, 15, 32)        0         \n",
      "                                                                 \n",
      " conv2d_2 (Conv2D)           (None, 15, 15, 64)        18496     \n",
      "                                                                 \n",
      " batch_normalization_2 (Batc  (None, 15, 15, 64)       256       \n",
      " hNormalization)                                                 \n",
      "                                                                 \n",
      " activation_2 (Activation)   (None, 15, 15, 64)        0         \n",
      "                                                                 \n",
      " conv2d_3 (Conv2D)           (None, 13, 13, 64)        36928     \n",
      "                                                                 \n",
      " batch_normalization_3 (Batc  (None, 13, 13, 64)       256       \n",
      " hNormalization)                                                 \n",
      "                                                                 \n",
      " activation_3 (Activation)   (None, 13, 13, 64)        0         \n",
      "                                                                 \n",
      " max_pooling2d_1 (MaxPooling  (None, 6, 6, 64)         0         \n",
      " 2D)                                                             \n",
      "                                                                 \n",
      " dropout_1 (Dropout)         (None, 6, 6, 64)          0         \n",
      "                                                                 \n",
      " flatten (Flatten)           (None, 2304)              0         \n",
      "                                                                 \n",
      " dense (Dense)               (None, 512)               1180160   \n",
      "                                                                 \n",
      " batch_normalization_4 (Batc  (None, 512)              2048      \n",
      " hNormalization)                                                 \n",
      "                                                                 \n",
      " activation_4 (Activation)   (None, 512)               0         \n",
      "                                                                 \n",
      " dropout_2 (Dropout)         (None, 512)               0         \n",
      "                                                                 \n",
      " dense_1 (Dense)             (None, 10)                5130      \n",
      "                                                                 \n",
      " batch_normalization_5 (Batc  (None, 10)               40        \n",
      " hNormalization)                                                 \n",
      "                                                                 \n",
      " activation_5 (Activation)   (None, 10)                0         \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 1,253,714\n",
      "Trainable params: 1,252,286\n",
      "Non-trainable params: 1,428\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 Compile and Fit the Network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:26: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "125/125 [==============================] - 40s 304ms/step - loss: 2.2280 - accuracy: 0.2125 - val_loss: 1.8853 - val_accuracy: 0.3190\n",
      "Epoch 2/100\n",
      "125/125 [==============================] - 37s 296ms/step - loss: 1.9369 - accuracy: 0.2790 - val_loss: 1.7425 - val_accuracy: 0.3870\n",
      "Epoch 3/100\n",
      "125/125 [==============================] - 37s 294ms/step - loss: 1.8355 - accuracy: 0.3377 - val_loss: 1.6886 - val_accuracy: 0.4130\n",
      "Epoch 4/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.8057 - accuracy: 0.3500 - val_loss: 1.6520 - val_accuracy: 0.4290\n",
      "Epoch 5/100\n",
      "125/125 [==============================] - 36s 286ms/step - loss: 1.7602 - accuracy: 0.3598 - val_loss: 1.6384 - val_accuracy: 0.4260\n",
      "Epoch 6/100\n",
      "125/125 [==============================] - 36s 291ms/step - loss: 1.7119 - accuracy: 0.3875 - val_loss: 1.6166 - val_accuracy: 0.4370\n",
      "Epoch 7/100\n",
      "125/125 [==============================] - 36s 290ms/step - loss: 1.7023 - accuracy: 0.3900 - val_loss: 1.5716 - val_accuracy: 0.4480\n",
      "Epoch 8/100\n",
      "125/125 [==============================] - 36s 290ms/step - loss: 1.6751 - accuracy: 0.4020 - val_loss: 1.5516 - val_accuracy: 0.4480\n",
      "Epoch 9/100\n",
      "125/125 [==============================] - 36s 290ms/step - loss: 1.6369 - accuracy: 0.4235 - val_loss: 1.5129 - val_accuracy: 0.4700\n",
      "Epoch 10/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.6150 - accuracy: 0.4270 - val_loss: 1.5484 - val_accuracy: 0.4510\n",
      "Epoch 11/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.5958 - accuracy: 0.4392 - val_loss: 1.5497 - val_accuracy: 0.4490\n",
      "Epoch 12/100\n",
      "125/125 [==============================] - 36s 288ms/step - loss: 1.5693 - accuracy: 0.4588 - val_loss: 1.5169 - val_accuracy: 0.4640\n",
      "Epoch 13/100\n",
      "125/125 [==============================] - 36s 289ms/step - loss: 1.5640 - accuracy: 0.4563 - val_loss: 1.4527 - val_accuracy: 0.5000\n",
      "Epoch 14/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.5460 - accuracy: 0.4550 - val_loss: 1.4747 - val_accuracy: 0.4910\n",
      "Epoch 15/100\n",
      "125/125 [==============================] - 37s 294ms/step - loss: 1.5309 - accuracy: 0.4688 - val_loss: 1.4892 - val_accuracy: 0.4800\n",
      "Epoch 16/100\n",
      "125/125 [==============================] - 37s 294ms/step - loss: 1.5052 - accuracy: 0.4755 - val_loss: 1.4476 - val_accuracy: 0.4960\n",
      "Epoch 17/100\n",
      "125/125 [==============================] - 37s 293ms/step - loss: 1.4891 - accuracy: 0.4803 - val_loss: 1.5067 - val_accuracy: 0.4670\n",
      "Epoch 18/100\n",
      "125/125 [==============================] - 37s 300ms/step - loss: 1.4939 - accuracy: 0.4890 - val_loss: 1.3816 - val_accuracy: 0.5070\n",
      "Epoch 19/100\n",
      "125/125 [==============================] - 37s 294ms/step - loss: 1.4847 - accuracy: 0.4818 - val_loss: 1.4077 - val_accuracy: 0.5050\n",
      "Epoch 20/100\n",
      "125/125 [==============================] - 36s 289ms/step - loss: 1.4667 - accuracy: 0.4938 - val_loss: 1.4425 - val_accuracy: 0.4900\n",
      "Epoch 21/100\n",
      "125/125 [==============================] - 36s 291ms/step - loss: 1.4660 - accuracy: 0.4952 - val_loss: 1.4399 - val_accuracy: 0.4860\n",
      "Epoch 22/100\n",
      "125/125 [==============================] - 37s 296ms/step - loss: 1.4420 - accuracy: 0.5102 - val_loss: 1.3517 - val_accuracy: 0.5300\n",
      "Epoch 23/100\n",
      "125/125 [==============================] - 37s 297ms/step - loss: 1.4317 - accuracy: 0.5205 - val_loss: 1.5031 - val_accuracy: 0.4560\n",
      "Epoch 24/100\n",
      "125/125 [==============================] - 36s 291ms/step - loss: 1.4237 - accuracy: 0.5182 - val_loss: 1.4334 - val_accuracy: 0.5000\n",
      "Epoch 25/100\n",
      "125/125 [==============================] - 36s 290ms/step - loss: 1.4117 - accuracy: 0.5250 - val_loss: 1.4227 - val_accuracy: 0.4940\n",
      "Epoch 26/100\n",
      "125/125 [==============================] - 38s 304ms/step - loss: 1.3872 - accuracy: 0.5228 - val_loss: 1.4280 - val_accuracy: 0.4880\n",
      "Epoch 27/100\n",
      "125/125 [==============================] - 36s 289ms/step - loss: 1.3957 - accuracy: 0.5378 - val_loss: 1.3953 - val_accuracy: 0.5030\n",
      "Epoch 28/100\n",
      "125/125 [==============================] - 36s 285ms/step - loss: 1.3733 - accuracy: 0.5405 - val_loss: 1.4223 - val_accuracy: 0.5070\n",
      "Epoch 29/100\n",
      "125/125 [==============================] - 35s 281ms/step - loss: 1.3632 - accuracy: 0.5405 - val_loss: 1.3442 - val_accuracy: 0.5220\n",
      "Epoch 30/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.3535 - accuracy: 0.5415 - val_loss: 1.4933 - val_accuracy: 0.4800\n",
      "Epoch 31/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.3360 - accuracy: 0.5502 - val_loss: 1.3711 - val_accuracy: 0.5090\n",
      "Epoch 32/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.3287 - accuracy: 0.5562 - val_loss: 1.3496 - val_accuracy: 0.5270\n",
      "Epoch 33/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.3301 - accuracy: 0.5565 - val_loss: 1.3474 - val_accuracy: 0.5220\n",
      "Epoch 34/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.3037 - accuracy: 0.5705 - val_loss: 1.2509 - val_accuracy: 0.5670\n",
      "Epoch 35/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.3104 - accuracy: 0.5585 - val_loss: 1.3048 - val_accuracy: 0.5350\n",
      "Epoch 36/100\n",
      "125/125 [==============================] - 34s 275ms/step - loss: 1.2998 - accuracy: 0.5610 - val_loss: 1.2407 - val_accuracy: 0.5770\n",
      "Epoch 37/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.2916 - accuracy: 0.5773 - val_loss: 1.2704 - val_accuracy: 0.5530\n",
      "Epoch 38/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.2829 - accuracy: 0.5810 - val_loss: 1.2211 - val_accuracy: 0.5730\n",
      "Epoch 39/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.2529 - accuracy: 0.5825 - val_loss: 1.2493 - val_accuracy: 0.5710\n",
      "Epoch 40/100\n",
      "125/125 [==============================] - 35s 279ms/step - loss: 1.2578 - accuracy: 0.5782 - val_loss: 1.2544 - val_accuracy: 0.5570\n",
      "Epoch 41/100\n",
      "125/125 [==============================] - 34s 275ms/step - loss: 1.2443 - accuracy: 0.5943 - val_loss: 1.2345 - val_accuracy: 0.5610\n",
      "Epoch 42/100\n",
      "125/125 [==============================] - 35s 283ms/step - loss: 1.2466 - accuracy: 0.5857 - val_loss: 1.2378 - val_accuracy: 0.5670\n",
      "Epoch 43/100\n",
      "125/125 [==============================] - 36s 285ms/step - loss: 1.2358 - accuracy: 0.5820 - val_loss: 1.2974 - val_accuracy: 0.5480\n",
      "Epoch 44/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.2546 - accuracy: 0.5753 - val_loss: 1.2483 - val_accuracy: 0.5580\n",
      "Epoch 45/100\n",
      "125/125 [==============================] - 34s 277ms/step - loss: 1.2363 - accuracy: 0.5975 - val_loss: 1.1611 - val_accuracy: 0.5930\n",
      "Epoch 46/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.1954 - accuracy: 0.6137 - val_loss: 1.1885 - val_accuracy: 0.5710\n",
      "Epoch 50/100\n",
      "125/125 [==============================] - 36s 285ms/step - loss: 1.1885 - accuracy: 0.6155 - val_loss: 1.2232 - val_accuracy: 0.5730\n",
      "Epoch 51/100\n",
      "125/125 [==============================] - 35s 279ms/step - loss: 1.1859 - accuracy: 0.6045 - val_loss: 1.1790 - val_accuracy: 0.5950\n",
      "Epoch 52/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 1.1797 - accuracy: 0.6158 - val_loss: 1.1768 - val_accuracy: 0.5870\n",
      "Epoch 53/100\n",
      "125/125 [==============================] - 36s 287ms/step - loss: 1.1939 - accuracy: 0.6043 - val_loss: 1.2470 - val_accuracy: 0.5760\n",
      "Epoch 54/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.1705 - accuracy: 0.6102 - val_loss: 1.2323 - val_accuracy: 0.5620\n",
      "Epoch 55/100\n",
      "125/125 [==============================] - 34s 269ms/step - loss: 1.1530 - accuracy: 0.6298 - val_loss: 1.1293 - val_accuracy: 0.6200\n",
      "Epoch 56/100\n",
      "125/125 [==============================] - 34s 276ms/step - loss: 1.1574 - accuracy: 0.6252 - val_loss: 1.1976 - val_accuracy: 0.5780\n",
      "Epoch 57/100\n",
      "125/125 [==============================] - 35s 281ms/step - loss: 1.1436 - accuracy: 0.6220 - val_loss: 1.1925 - val_accuracy: 0.5810\n",
      "Epoch 58/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.1303 - accuracy: 0.6332 - val_loss: 1.1210 - val_accuracy: 0.6150\n",
      "Epoch 59/100\n",
      "125/125 [==============================] - 34s 272ms/step - loss: 1.1353 - accuracy: 0.6308 - val_loss: 1.0928 - val_accuracy: 0.6260\n",
      "Epoch 60/100\n",
      "125/125 [==============================] - 34s 272ms/step - loss: 1.1494 - accuracy: 0.6137 - val_loss: 1.1149 - val_accuracy: 0.6130\n",
      "Epoch 61/100\n",
      "125/125 [==============================] - 34s 270ms/step - loss: 1.1328 - accuracy: 0.6273 - val_loss: 1.1124 - val_accuracy: 0.6070\n",
      "Epoch 62/100\n",
      "125/125 [==============================] - 36s 285ms/step - loss: 1.1132 - accuracy: 0.6432 - val_loss: 1.1760 - val_accuracy: 0.5900\n",
      "Epoch 63/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.1047 - accuracy: 0.6510 - val_loss: 1.1410 - val_accuracy: 0.5930\n",
      "Epoch 64/100\n",
      "125/125 [==============================] - 34s 275ms/step - loss: 1.0979 - accuracy: 0.6455 - val_loss: 1.1152 - val_accuracy: 0.6210\n",
      "Epoch 65/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.1033 - accuracy: 0.6405 - val_loss: 1.1486 - val_accuracy: 0.6110\n",
      "Epoch 66/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.0901 - accuracy: 0.6572 - val_loss: 1.1168 - val_accuracy: 0.6200\n",
      "Epoch 67/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.0882 - accuracy: 0.6435 - val_loss: 1.1408 - val_accuracy: 0.6240\n",
      "Epoch 68/100\n",
      "125/125 [==============================] - 35s 276ms/step - loss: 1.0776 - accuracy: 0.6587 - val_loss: 1.1729 - val_accuracy: 0.6090\n",
      "Epoch 69/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.0829 - accuracy: 0.6482 - val_loss: 1.1495 - val_accuracy: 0.6120\n",
      "Epoch 70/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.0607 - accuracy: 0.6605 - val_loss: 1.1804 - val_accuracy: 0.6030\n",
      "Epoch 71/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.0642 - accuracy: 0.6610 - val_loss: 1.0661 - val_accuracy: 0.6400\n",
      "Epoch 72/100\n",
      "125/125 [==============================] - 36s 286ms/step - loss: 1.0620 - accuracy: 0.6600 - val_loss: 1.0767 - val_accuracy: 0.6330\n",
      "Epoch 73/100\n",
      "125/125 [==============================] - 34s 269ms/step - loss: 1.0440 - accuracy: 0.6670 - val_loss: 1.0811 - val_accuracy: 0.6350\n",
      "Epoch 74/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.0738 - accuracy: 0.6532 - val_loss: 1.0731 - val_accuracy: 0.6310\n",
      "Epoch 75/100\n",
      "125/125 [==============================] - 35s 278ms/step - loss: 1.0568 - accuracy: 0.6540 - val_loss: 1.0869 - val_accuracy: 0.6300\n",
      "Epoch 76/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.0530 - accuracy: 0.6615 - val_loss: 1.0482 - val_accuracy: 0.6480\n",
      "Epoch 77/100\n",
      "125/125 [==============================] - 34s 275ms/step - loss: 1.0606 - accuracy: 0.6475 - val_loss: 1.1287 - val_accuracy: 0.6090\n",
      "Epoch 78/100\n",
      "125/125 [==============================] - 34s 275ms/step - loss: 1.0373 - accuracy: 0.6640 - val_loss: 1.0355 - val_accuracy: 0.6510\n",
      "Epoch 79/100\n",
      "125/125 [==============================] - 35s 282ms/step - loss: 1.0275 - accuracy: 0.6715 - val_loss: 1.1656 - val_accuracy: 0.6040\n",
      "Epoch 80/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.0189 - accuracy: 0.6675 - val_loss: 1.0925 - val_accuracy: 0.6200\n",
      "Epoch 81/100\n",
      "125/125 [==============================] - 36s 285ms/step - loss: 1.0285 - accuracy: 0.6690 - val_loss: 1.0356 - val_accuracy: 0.6410\n",
      "Epoch 82/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.0155 - accuracy: 0.6647 - val_loss: 1.0605 - val_accuracy: 0.6280\n",
      "Epoch 83/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 1.0036 - accuracy: 0.6837 - val_loss: 1.0332 - val_accuracy: 0.6510\n",
      "Epoch 84/100\n",
      "125/125 [==============================] - 33s 269ms/step - loss: 0.9994 - accuracy: 0.6787 - val_loss: 1.0366 - val_accuracy: 0.6510\n",
      "Epoch 85/100\n",
      "125/125 [==============================] - 34s 273ms/step - loss: 1.0105 - accuracy: 0.6780 - val_loss: 1.0304 - val_accuracy: 0.6530\n",
      "Epoch 86/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 1.0105 - accuracy: 0.6730 - val_loss: 1.0589 - val_accuracy: 0.6410\n",
      "Epoch 87/100\n",
      "125/125 [==============================] - 34s 272ms/step - loss: 1.0017 - accuracy: 0.6740 - val_loss: 1.0851 - val_accuracy: 0.6310\n",
      "Epoch 88/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 1.0078 - accuracy: 0.6645 - val_loss: 1.0116 - val_accuracy: 0.6620\n",
      "Epoch 89/100\n",
      "125/125 [==============================] - 35s 282ms/step - loss: 0.9698 - accuracy: 0.6902 - val_loss: 1.0451 - val_accuracy: 0.6480\n",
      "Epoch 90/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 0.9889 - accuracy: 0.6798 - val_loss: 1.0839 - val_accuracy: 0.6320\n",
      "Epoch 91/100\n",
      "125/125 [==============================] - 35s 276ms/step - loss: 0.9768 - accuracy: 0.6855 - val_loss: 1.0349 - val_accuracy: 0.6530\n",
      "Epoch 92/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 0.9862 - accuracy: 0.6820 - val_loss: 0.9886 - val_accuracy: 0.6680\n",
      "Epoch 93/100\n",
      "125/125 [==============================] - 35s 279ms/step - loss: 0.9789 - accuracy: 0.6752 - val_loss: 1.0975 - val_accuracy: 0.6310\n",
      "Epoch 94/100\n",
      "125/125 [==============================] - 36s 286ms/step - loss: 0.9726 - accuracy: 0.6740 - val_loss: 0.9940 - val_accuracy: 0.6730\n",
      "Epoch 95/100\n",
      "125/125 [==============================] - 35s 277ms/step - loss: 0.9706 - accuracy: 0.6892 - val_loss: 1.0154 - val_accuracy: 0.6640\n",
      "Epoch 96/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 0.9629 - accuracy: 0.6798 - val_loss: 1.1028 - val_accuracy: 0.6220\n",
      "Epoch 97/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 0.9535 - accuracy: 0.6925 - val_loss: 1.0176 - val_accuracy: 0.6670\n",
      "Epoch 98/100\n",
      "125/125 [==============================] - 34s 274ms/step - loss: 0.9639 - accuracy: 0.6817 - val_loss: 0.9908 - val_accuracy: 0.6590\n",
      "Epoch 99/100\n",
      "125/125 [==============================] - 34s 277ms/step - loss: 0.9392 - accuracy: 0.7035 - val_loss: 1.0175 - val_accuracy: 0.6500\n",
      "Epoch 100/100\n",
      "125/125 [==============================] - 35s 280ms/step - loss: 0.9376 - accuracy: 0.6965 - val_loss: 0.9891 - val_accuracy: 0.6750\n"
    },
    {
     "data": {
      "text/plain": [
       "<bound method Model.evaluate of <keras.engine.sequential.Sequential object at 0x7fa2a3377190>>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import datetime, os\n",
    "logdir = os.path.join(\"logs\", datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\"))\n",
    "tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)\n",
    "\n",
    "# Compile Network \n",
    "model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001, decay=1e-6),\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])\n",
    "\n",
    "num_validation_examples = 1000\n",
    "num_train_examples = 5000\n",
    "\n",
    "\n",
    "train_iterator = train_datagen.flow(X_train_zc[num_validation_examples:num_train_examples], \n",
    "                                    y_train_cat[num_validation_examples:num_train_examples], \n",
    "                                    batch_size=32)\n",
    "validation_iterator = validation_datagen.flow(X_train_zc[:num_validation_examples:], \n",
    "                                              y_train_cat[:num_validation_examples:], \n",
    "                                              batch_size=32)\n",
    "\n",
    "# Fit Network\n",
    "history = model.fit_generator(generator= train_iterator,  \n",
    "                              validation_data = validation_iterator, \n",
Mirko Birbaumer's avatar
Mirko Birbaumer committed
    "                              epochs=100, \n",
    "                              steps_per_epoch=len(train_iterator),\n",
    "                              callbacks=[tensorboard_callback])\n",
    "\n",
    "# Determine \n",
    "model.evaluate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 Evaluate the Network on the test dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "313/313 [==============================] - 17s 54ms/step - loss: 1.0072 - accuracy: 0.6684\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[1.007246494293213, 0.66839998960495]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.evaluate(X_test_zc, y_test_cat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot training and validation accuracy\n",
    "acc = history.history['accuracy']\n",
    "val_acc = history.history['val_accuracy']\n",
    "\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs_range = range(100)\n",
    "\n",
    "plt.figure(figsize=(8, 8))\n",
    "plt.subplot(1, 2, 1)\n",
    "plt.plot(epochs_range, acc, label='Training Accuracy')\n",
    "plt.plot(epochs_range, val_acc, label='Validation Accuracy')\n",
    "plt.legend(loc='lower right')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(epochs_range, loss, label='Training Loss')\n",
    "plt.plot(epochs_range, val_loss, label='Validation Loss')\n",
    "plt.legend(loc='upper right')\n",
    "plt.title('Training and Validation Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load the TensorBoard notebook extension\n",
    "%load_ext tensorboard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ERROR: Failed to launch TensorBoard (exited with 1).\n",
       "Contents of stderr:\n",
       "Traceback (most recent call last):\n",
       "  File \"/opt/conda/bin/tensorboard\", line 5, in <module>\n",
       "    from tensorboard.main import run_main\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/tensorboard/main.py\", line 27, in <module>\n",
       "    from tensorboard import default\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/tensorboard/default.py\", line 33, in <module>\n",
       "    from tensorboard.plugins.audio import audio_plugin\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/tensorboard/plugins/audio/audio_plugin.py\", line 23, in <module>\n",
       "    from tensorboard import plugin_util\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/tensorboard/plugin_util.py\", line 24, in <module>\n",
       "    import markdown\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/markdown/__init__.py\", line 29, in <module>\n",
       "    from .core import Markdown, markdown, markdownFromFile  # noqa: E402\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/markdown/core.py\", line 26, in <module>\n",
       "    from . import util\n",
       "  File \"/opt/conda/lib/python3.7/site-packages/markdown/util.py\", line 88, in <module>\n",
       "    INSTALLED_EXTENSIONS = metadata.entry_points(group='markdown.extensions')\n",
       "TypeError: entry_points() got an unexpected keyword argument 'group'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "os.makedirs(logdir, exist_ok=True)\n",
    "%tensorboard --logdir logs\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
Mirko Birbaumer's avatar
Mirko Birbaumer committed
   "outputs": [],
   "source": [
    "model.save('./Daten/cifar_10_convnets_1.h5')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FE7KNzPPVrVV"
   },
   "source": [
    "# Part 2 - Dogs vs Cats Image Classification : Visualizing what ConvNets learn?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "gN7G9GFmVrVY"
   },
   "source": [
    "In this notebook chapter, we will discuss how to classify images into pictures of cats or pictures of dogs. We'll build an image classifier using `tf.keras.Sequential` model and load data using `tf.keras.preprocessing.image.ImageDataGenerator`. At the end, we will visualize filters and intermediate activation layers.\n",
    "\n",
Mirko Birbaumer's avatar
Mirko Birbaumer committed
    "### Specific concepts that will be covered:\n",
    "In the process, we will build practical experience and develop intuition around the following concepts\n",
    "\n",
    "* Building _data input pipelines_ using the `tf.keras.preprocessing.image.ImageDataGenerator` class — How can we efficiently work with data on disk to interface with our model?\n",
    "* _Overfitting_ - what is it, how to identify it, and how can we prevent it?\n",
    "* _Data Augmentation_ and _Dropout_ - Key techniques to fight overfitting in computer vision tasks that we will incorporate into our data pipeline and image classifier model.\n",
    "* _Visualizing ConvNet filters_\n",
    "* _Visualizing intermediate activations_\n",
    "\n",
    "\n",
Mirko Birbaumer's avatar
Mirko Birbaumer committed
    "### We will follow the general machine learning workflow:\n",
    "\n",
    "1. Examine and understand data\n",
    "2. Build an input pipeline\n",
    "3. Build our model\n",
    "4. Train our model\n",
    "5. Test our model\n",
    "6. Improve our model/Repeat the process\n",
    "\n",
    "<hr>\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "zF9uvbXNVrVY"
   },
   "source": [
Mirko Birbaumer's avatar
Mirko Birbaumer committed
    "### Importing packages"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "VddxeYBEVrVZ"
   },
   "source": [
    "Let's start by importing required packages:\n",
    "\n",
    "*   os — to read files and directory structure\n",
    "*   numpy — for some matrix math outside of TensorFlow\n",
    "*   matplotlib.pyplot — to plot the graph and display images in our training and validation data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "rtPGh2MAVrVa"
   },
   "outputs": [],
   "source": [
    "from __future__ import absolute_import, division, print_function, unicode_literals\n",
    "\n",
    "import os\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "L1WtoaOHVrVh"
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UZZI6lNkVrVm"
   },
   "source": [
Mirko Birbaumer's avatar
Mirko Birbaumer committed
    "### Data Loading"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DPHx8-t-VrVo"
   },
   "source": [
    "To build our image classifier, we begin by downloading the dataset. The dataset we are using is a filtered version of <a href=\"https://www.kaggle.com/c/dogs-vs-cats/data\" target=\"_blank\">Dogs vs. Cats</a> dataset from Kaggle (ultimately, this dataset is provided by Microsoft Research).\n",
    "\n",
    "In this Jupyter Notebook however, we will make use of the class `tf.keras.preprocessing.image.ImageDataGenerator` which will read data from disk. We therefore need to directly download *Dogs vs. Cats* from a URL and unzip it to your computers filesystem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "OYmOylPlVrVt"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip\n",
      "68608000/68606236 [==============================] - 1s 0us/step\n",
      "68616192/68606236 [==============================] - 1s 0us/step\n"
     ]
    }
   ],
   "source": [
    "_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'\n",
    "\n",
    "zip_dir = tf.keras.utils.get_file('cats_and_dogs_filterted.zip', origin=_URL, extract=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Giv0wMQzVrVw"
   },
   "source": [
    "The dataset we have downloaded has following directory structure.\n",
    "\n",
    "<pre style=\"font-size: 10.0pt; font-family: Arial; line-height: 2; letter-spacing: 1.0pt;\" >\n",
    "<b>cats_and_dogs_filtered</b>\n",
    "|__ <b>train</b>\n",
    "    |______ <b>cats</b>: [cat.0.jpg, cat.1.jpg, cat.2.jpg ....]\n",
    "    |______ <b>dogs</b>: [dog.0.jpg, dog.1.jpg, dog.2.jpg ...]\n",
    "|__ <b>validation</b>\n",
    "    |______ <b>cats</b>: [cat.2000.jpg, cat.2001.jpg, cat.2002.jpg ....]\n",
    "    |______ <b>dogs</b>: [dog.2000.jpg, dog.2001.jpg, dog.2002.jpg ...]\n",
    "</pre>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "VpmywIlsVrVx"
   },
   "source": [
    "We'll now assign variables with the proper file path for the training and validation sets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "sRucI3QqVrVy"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/jovyan/.keras/datasets\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/train\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/validation\n"
     ]
    }
   ],
   "source": [
    "print(os.path.dirname(zip_dir))\n",
    "base_dir = os.path.join(os.path.dirname(zip_dir), 'cats_and_dogs_filtered')\n",
    "print(base_dir)\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "print(train_dir)\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "print(validation_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Utv3nryxVrV0"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/train/cats\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/train/dogs\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/validation/cats\n",
      "/home/jovyan/.keras/datasets/cats_and_dogs_filtered/validation/dogs\n"
     ]
    }
   ],
   "source": [
    "train_cats_dir = os.path.join(train_dir, 'cats')  # directory with our training cat pictures\n",
    "print(train_cats_dir)\n",
    "train_dogs_dir = os.path.join(train_dir, 'dogs')  # directory with our training dog pictures\n",
    "print(train_dogs_dir)\n",
    "validation_cats_dir = os.path.join(validation_dir, 'cats')  # directory with our validation cat pictures\n",
    "print(validation_cats_dir)\n",
    "validation_dogs_dir = os.path.join(validation_dir, 'dogs')  # directory with our validation dog pictures\n",
    "print(validation_dogs_dir)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "ZdrHHTy2VrV3"
   },
   "source": [
    "### Understanding our data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {