{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cad950d4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "D:/cats-v-dogs created\n",
      "D:/cats-v-dogs/training created\n",
      "D:/cats-v-dogs/testing created\n",
      "D:/cats-v-dogs/training/cats created\n",
      "D:/cats-v-dogs/training/dogs created\n",
      "D:/cats-v-dogs/testing/cats created\n",
      "D:/cats-v-dogs/testing/dogs created\n",
      "666.jpg is zero length, so ignoring\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "import os\n",
    "import random\n",
    "from shutil import copyfile\n",
    "\n",
    "\n",
    "\n",
    "def split_data(SOURCE, TRAINING, TESTING, SPLIT_SIZE):\n",
    "    all_files = []\n",
    "    \n",
    "    for file_name in os.listdir(SOURCE):\n",
    "        file_path = SOURCE + file_name\n",
    "\n",
    "        if os.path.getsize(file_path):\n",
    "            all_files.append(file_name)\n",
    "        else:\n",
    "            print('{} is zero length, so ignoring'.format(file_name))\n",
    "    \n",
    "    n_files = len(all_files)\n",
    "    split_point = int(n_files * SPLIT_SIZE)\n",
    "    \n",
    "    shuffled = random.sample(all_files, n_files)\n",
    "    \n",
    "    train_set = shuffled[:split_point]\n",
    "    test_set = shuffled[split_point:]\n",
    "    \n",
    "    for file_name in train_set:\n",
    "        copyfile(SOURCE + file_name, TRAINING + file_name)\n",
    "        \n",
    "    for file_name in test_set:\n",
    "        copyfile(SOURCE + file_name, TESTING + file_name)\n",
    "\n",
    "to_create = [\n",
    "    'D:/cats-v-dogs',\n",
    "    'D:/cats-v-dogs/training',\n",
    "    'D:/cats-v-dogs/testing',\n",
    "    'D:/cats-v-dogs/training/cats',\n",
    "    'D:/cats-v-dogs/training/dogs',\n",
    "    'D:/cats-v-dogs/testing/cats',\n",
    "    'D:/cats-v-dogs/testing/dogs'\n",
    "]\n",
    "\n",
    "for directory in to_create:\n",
    "    try:\n",
    "        os.mkdir(directory)\n",
    "        print(directory, 'created')\n",
    "    except:\n",
    "        print(directory, 'failed')\n",
    "\n",
    "CAT_SOURCE_DIR = r\"D:/PettImages/Cat/\"\n",
    "TRAINING_CATS_DIR = r\"D:/cats-v-dogs/training/cats/\"\n",
    "TESTING_CATS_DIR = r\"D:/cats-v-dogs/testing/cats/\"\n",
    "DOG_SOURCE_DIR = r\"D:/PettImages/Dog/\"\n",
    "TRAINING_DOGS_DIR = r\"D:/cats-v-dogs/training/dogs/\"\n",
    "TESTING_DOGS_DIR = r\"D:/cats-v-dogs/testing/dogs/\"\n",
    "\n",
    "split_size = .7\n",
    "split_data(CAT_SOURCE_DIR, TRAINING_CATS_DIR, TESTING_CATS_DIR, split_size)\n",
    "split_data(DOG_SOURCE_DIR, TRAINING_DOGS_DIR, TESTING_DOGS_DIR, split_size)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aa6a7fa8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2801 images belonging to 2 classes.\n",
      "Found 1202 images belonging to 2 classes.\n",
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d (Conv2D)              (None, 148, 148, 32)      896       \n",
      "_________________________________________________________________\n",
      "max_pooling2d (MaxPooling2D) (None, 74, 74, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 72, 72, 64)        18496     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 36, 36, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_2 (Conv2D)            (None, 34, 34, 64)        36928     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_2 (MaxPooling2 (None, 17, 17, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_3 (Conv2D)            (None, 15, 15, 128)       73856     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_3 (MaxPooling2 (None, 7, 7, 128)         0         \n",
      "_________________________________________________________________\n",
      "flatten (Flatten)            (None, 6272)              0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 512)               3211776   \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 64)                32832     \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 1)                 65        \n",
      "=================================================================\n",
      "Total params: 3,374,849\n",
      "Trainable params: 3,374,849\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "Epoch 1/50\n",
      "29/29 [==============================] - 167s 6s/step - loss: 0.6929 - accuracy: 0.5112 - val_loss: 0.6913 - val_accuracy: 0.5300\n",
      "Epoch 2/50\n",
      "29/29 [==============================] - 135s 5s/step - loss: 0.6916 - accuracy: 0.5095 - val_loss: 0.6901 - val_accuracy: 0.5549\n",
      "Epoch 3/50\n",
      "29/29 [==============================] - 136s 5s/step - loss: 0.6901 - accuracy: 0.5562 - val_loss: 0.6896 - val_accuracy: 0.5699\n",
      "Epoch 4/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6894 - accuracy: 0.5619 - val_loss: 0.6882 - val_accuracy: 0.5524\n",
      "Epoch 5/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6876 - accuracy: 0.5612 - val_loss: 0.6881 - val_accuracy: 0.5100\n",
      "Epoch 6/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6869 - accuracy: 0.5477 - val_loss: 0.6867 - val_accuracy: 0.5932\n",
      "Epoch 7/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6873 - accuracy: 0.5441 - val_loss: 0.6854 - val_accuracy: 0.5158\n",
      "Epoch 8/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6862 - accuracy: 0.5602 - val_loss: 0.6843 - val_accuracy: 0.5349\n",
      "Epoch 9/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6862 - accuracy: 0.5659 - val_loss: 0.6831 - val_accuracy: 0.5632\n",
      "Epoch 10/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6855 - accuracy: 0.5787 - val_loss: 0.6820 - val_accuracy: 0.5699\n",
      "Epoch 11/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6830 - accuracy: 0.5652 - val_loss: 0.6813 - val_accuracy: 0.5998\n",
      "Epoch 12/50\n",
      "29/29 [==============================] - 132s 5s/step - loss: 0.6818 - accuracy: 0.5869 - val_loss: 0.6849 - val_accuracy: 0.5574\n",
      "Epoch 13/50\n",
      "29/29 [==============================] - 133s 5s/step - loss: 0.6821 - accuracy: 0.5698 - val_loss: 0.6790 - val_accuracy: 0.5857\n",
      "Epoch 14/50\n",
      "29/29 [==============================] - 3630s 125s/step - loss: 0.6798 - accuracy: 0.5801 - val_loss: 0.6772 - val_accuracy: 0.5899\n",
      "Epoch 15/50\n",
      "29/29 [==============================] - 168s 6s/step - loss: 0.6802 - accuracy: 0.5930 - val_loss: 0.6764 - val_accuracy: 0.5699\n",
      "Epoch 16/50\n",
      "29/29 [==============================] - 179s 6s/step - loss: 0.6768 - accuracy: 0.6026 - val_loss: 0.6751 - val_accuracy: 0.5849\n",
      "Epoch 17/50\n",
      "29/29 [==============================] - 154s 5s/step - loss: 0.6770 - accuracy: 0.5837 - val_loss: 0.6761 - val_accuracy: 0.5599\n",
      "Epoch 18/50\n",
      "29/29 [==============================] - 171s 6s/step - loss: 0.6750 - accuracy: 0.5866 - val_loss: 0.6723 - val_accuracy: 0.5899\n",
      "Epoch 19/50\n",
      "29/29 [==============================] - 185s 6s/step - loss: 0.6746 - accuracy: 0.5869 - val_loss: 0.6716 - val_accuracy: 0.5882\n",
      "Epoch 20/50\n",
      "29/29 [==============================] - 168s 6s/step - loss: 0.6743 - accuracy: 0.5884 - val_loss: 0.6702 - val_accuracy: 0.5965\n",
      "Epoch 21/50\n",
      "29/29 [==============================] - 163s 6s/step - loss: 0.6728 - accuracy: 0.5994 - val_loss: 0.6727 - val_accuracy: 0.5566\n",
      "Epoch 22/50\n",
      "29/29 [==============================] - 158s 5s/step - loss: 0.6694 - accuracy: 0.5987 - val_loss: 0.6696 - val_accuracy: 0.5807\n",
      "Epoch 23/50\n",
      "29/29 [==============================] - 153s 5s/step - loss: 0.6717 - accuracy: 0.5987 - val_loss: 0.6708 - val_accuracy: 0.5649\n",
      "Epoch 24/50\n",
      " 4/29 [===>..........................] - ETA: 1:28 - loss: 0.6726 - accuracy: 0.6075"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "train_img= ImageDataGenerator(rescale=1 / 255,\n",
    "    rotation_range=180,\n",
    "    width_shift_range=.2,\n",
    "    height_shift_range=.2,\n",
    "    shear_range=.2,\n",
    "    zoom_range=.2,\n",
    "    horizontal_flip=True,\n",
    "    fill_mode='nearest' )\n",
    "\n",
    "val_img=ImageDataGenerator(rescale=1/255)\n",
    "\n",
    "train_img_gen= train_img.flow_from_directory('D:/cats-v-dogs/training', target_size=(150,150), batch_size=100,  class_mode='binary')\n",
    "validation_img_gen = val_img.flow_from_directory('D:/cats-v-dogs/testing', target_size=(150,150), batch_size=100, class_mode='binary')\n",
    "\n",
    "\n",
    "\n",
    "model= keras.models.Sequential([\n",
    "        keras.layers.Conv2D(32,(3,3),input_shape=(150,150,3), activation= 'relu' ),\n",
    "        keras.layers.MaxPool2D(2,2),\n",
    "        \n",
    "        keras.layers.Conv2D(64,(3,3), activation= 'relu'),\n",
    "        keras.layers.MaxPool2D(2,2),\n",
    "    \n",
    "        keras.layers.Conv2D(64,(3,3), activation= 'relu'),\n",
    "        keras.layers.MaxPool2D(2,2),\n",
    "    \n",
    "        keras.layers.Conv2D(128,(3,3), activation= 'relu'),\n",
    "        keras.layers.MaxPool2D(2,2),\n",
    "    \n",
    "        keras.layers.Flatten(),\n",
    "        keras.layers.Dense(units=512, activation='relu'),\n",
    "        keras.layers.Dense(units=64, activation='relu'),\n",
    "        keras.layers.Dense(units=1, activation= 'sigmoid')\n",
    "])\n",
    "\n",
    "model.summary()\n",
    "\n",
    "from tensorflow.keras.optimizers import RMSprop\n",
    "\n",
    "model.compile(RMSprop(lr=0.00001), loss='binary_crossentropy', metrics=['accuracy'])\n",
    "\n",
    "history= model.fit(train_img_gen, epochs=50, verbose=1,validation_data=validation_img_gen)\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50d5b341",
   "metadata": {},
   "outputs": [],
   "source": [
    "# PLOT LOSS AND ACCURACY\n",
    "%matplotlib inline\n",
    "\n",
    "import matplotlib.image  as mpimg\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "#-----------------------------------------------------------\n",
    "# Retrieve a list of list results on training and test data\n",
    "# sets for each training epoch\n",
    "#-----------------------------------------------------------\n",
    "acc=history.history['accuracy']\n",
    "val_acc=history.history['val_accuracy']\n",
    "loss=history.history['loss']\n",
    "val_loss=history.history['val_loss']\n",
    "\n",
    "epochs=range(len(acc)) # Get number of epochs\n",
    "\n",
    "#------------------------------------------------\n",
    "# Plot training and validation accuracy per epoch\n",
    "#------------------------------------------------\n",
    "plt.plot(epochs, acc, 'r', label=\"Training Accuracy\")\n",
    "plt.plot(epochs, val_acc, 'b', label=\"Validation Accuracy\")\n",
    "plt.legend()\n",
    "plt.title('Training and validation accuracy')\n",
    "plt.figure()\n",
    "\n",
    "#------------------------------------------------\n",
    "# Plot training and validation loss per epoch\n",
    "#------------------------------------------------\n",
    "plt.plot(epochs, loss, 'r', \"Training Loss\")\n",
    "plt.plot(epochs, val_loss, 'b', \"Validation Loss\")\n",
    "\n",
    "\n",
    "plt.title('Training and validation loss')\n",
    "\n",
    "# Desired output. Charts with training and validation metrics. No crash :)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10dc297c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from google.colab import files\n",
    "from keras.preprocessing import image\n",
    "\n",
    "uploaded = files.upload()\n",
    "\n",
    "for fn in uploaded.keys():\n",
    " \n",
    "  # predicting images\n",
    "    path = '/content/' + fn\n",
    "    img = image.load_img(path, target_size=(150,150))\n",
    "    x = image.img_to_array(img)\n",
    "    x = np.expand_dims(x, axis=0)\n",
    "\n",
    "    images = np.vstack([x])\n",
    "    classes = model.predict(images, batch_size=10)\n",
    "    print(classes[0])\n",
    "    if classes[0]>0.5:\n",
    "        print(fn + \" is a dog\")\n",
    "    else:\n",
    "        print(fn + \" is a cat\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
