{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e6cf43a1-39d8-ce30-82c0-39ba98f90d4b"
      },
      "outputs": [],
      "source": [
        "# This Python 3 environment comes with many helpful analytics libraries installed\n",
        "# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n",
        "# For example, here's several helpful packages to load in \n",
        "\n",
        "import numpy as np # linear algebra\n",
        "import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n",
        "\n",
        "# Input data files are available in the \"../input/\" directory.\n",
        "# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n",
        "\n",
        "from subprocess import check_output\n",
        "print(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))\n",
        "\n",
        "# Any results you write to the current directory are saved as output."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "73b85258-8ad3-286a-9f91-a1f63d2a5569"
      },
      "outputs": [],
      "source": [
        "import os, cv2, random\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "from matplotlib import ticker\n",
        "import seaborn as sns\n",
        "%matplotlib inline \n",
        "\n",
        "from keras.models import Sequential\n",
        "from keras.layers import Input, Dropout, Flatten, Convolution2D, MaxPooling2D, Dense, Activation\n",
        "from keras.optimizers import RMSprop\n",
        "from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping\n",
        "from keras.utils import np_utils"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "3bffb1d3-3446-46a8-cd42-f490e9efbe18"
      },
      "outputs": [],
      "source": [
        "TRAIN_DIR = '../input/train/'\n",
        "TEST_DIR = '../input/test/'\n",
        "\n",
        "ROWS = 64\n",
        "COLS = 64\n",
        "CHANNELS = 3\n",
        "\n",
        "train_images = [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR)] # use this for full dataset\n",
        "train_dogs =   [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'dog' in i]\n",
        "train_cats =   [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'cat' in i]\n",
        "\n",
        "test_images =  [TEST_DIR+i for i in os.listdir(TEST_DIR)]\n",
        "\n",
        "\n",
        "# slice datasets for memory efficiency on Kaggle Kernels, delete if using full dataset\n",
        "train_images = train_dogs[:1000] + train_cats[:1000]\n",
        "random.shuffle(train_images)\n",
        "test_images =  test_images[:25]\n",
        "\n",
        "def read_image(file_path):\n",
        "    img = cv2.imread(file_path, cv2.IMREAD_COLOR) #cv2.IMREAD_GRAYSCALE\n",
        "    return cv2.resize(img, (ROWS, COLS), interpolation=cv2.INTER_CUBIC)\n",
        "\n",
        "\n",
        "def prep_data(images):\n",
        "    count = len(images)\n",
        "    data = np.ndarray((count, CHANNELS, ROWS, COLS), dtype=np.uint8)\n",
        "\n",
        "    for i, image_file in enumerate(images):\n",
        "        image = read_image(image_file)\n",
        "        data[i] = image.T\n",
        "        if i%250 == 0: print('Processed {} of {}'.format(i, count))\n",
        "    \n",
        "    return data\n",
        "\n",
        "train = prep_data(train_images)\n",
        "test = prep_data(test_images)\n",
        "\n",
        "print(\"Train shape: {}\".format(train.shape))\n",
        "print(\"Test shape: {}\".format(test.shape))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "803b01e1-d313-e32b-06d5-01f452f692f8"
      },
      "outputs": [],
      "source": [
        "print(len(train[0][0][0]))\n",
        "print(train[0][0][0])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "8fc1dbd7-0c82-2882-ebae-a9c1b0f6ebe4"
      },
      "outputs": [],
      "source": [
        "labels = []\n",
        "for i in train_images:\n",
        "    if 'dog' in i:\n",
        "        labels.append(1)\n",
        "    else:\n",
        "        labels.append(0)\n",
        "\n",
        "sns.countplot(labels)\n",
        "sns.plt.title('Cats and Dogs')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a38f5665-6f88-a71f-ee36-8a946d8efb75"
      },
      "outputs": [],
      "source": [
        "firstImage = train_images[0]\n",
        "scaled = read_image(firstImage)\n",
        "print(scaled[0][0])\n",
        "#plt.imshow(scaled)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e9cd30db-e4e5-9ef7-bb61-8d32d73b6324"
      },
      "outputs": [],
      "source": [
        "def show_cats_and_dogs(idx):\n",
        "    cat = read_image(train_cats[idx])\n",
        "    dog = read_image(train_dogs[idx])\n",
        "    pair = np.concatenate((cat, dog), axis=1)\n",
        "    plt.figure(figsize=(10,5))\n",
        "    plt.imshow(pair)\n",
        "    plt.show()\n",
        "    \n",
        "for idx in range(0,5):\n",
        "    show_cats_and_dogs(idx)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "96db8648-e22b-b58b-8229-edebc629d578"
      },
      "outputs": [],
      "source": [
        "dog_avg = np.array([dog[0].T for i, dog in enumerate(train) if labels[i]==1]).mean(axis=0)\n",
        "plt.imshow(dog_avg)\n",
        "plt.title('Your Average Dog')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "0afecaab-2c9e-2b7a-ccc8-dee15e5f11e5"
      },
      "outputs": [],
      "source": [
        "cat_avg = np.array([cat[0].T for i, cat in enumerate(train) if labels[i]==0]).mean(axis=0)\n",
        "plt.imshow(cat_avg)\n",
        "plt.title('Your Average Cat')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "dea467c0-f049-106b-2cd7-2566d352b45f"
      },
      "outputs": [],
      "source": [
        "optimizer = RMSprop(lr=1e-4)\n",
        "objective = 'binary_crossentropy'\n",
        "\n",
        "\n",
        "def catdog():\n",
        "    \n",
        "    model = Sequential()\n",
        "\n",
        "    model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=(3, ROWS, COLS), activation='relu'))\n",
        "    model.add(Convolution2D(32, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\n",
        "    model.add(Convolution2D(64, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(Convolution2D(64, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "    \n",
        "    model.add(Convolution2D(128, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(Convolution2D(128, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "    \n",
        "    model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\n",
        "#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "#     model.add(Convolution2D(256, 3, 3, border_mode='same', activation='relu'))\n",
        "#     model.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\n",
        "    model.add(Flatten())\n",
        "    model.add(Dense(256, activation='relu'))\n",
        "    model.add(Dropout(0.5))\n",
        "    \n",
        "    model.add(Dense(256, activation='relu'))\n",
        "    model.add(Dropout(0.5))\n",
        "\n",
        "    model.add(Dense(1))\n",
        "    model.add(Activation('sigmoid'))\n",
        "\n",
        "    model.compile(loss=objective, optimizer=optimizer, metrics=['accuracy'])\n",
        "    return model\n",
        "\n",
        "\n",
        "model = catdog()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a550976f-7c0e-dace-7b5c-58583c716015"
      },
      "outputs": [],
      "source": [
        "nb_epoch = 10\n",
        "batch_size = 16\n",
        "\n",
        "## Callback for loss logging per epoch\n",
        "class LossHistory(Callback):\n",
        "    def on_train_begin(self, logs={}):\n",
        "        self.losses = []\n",
        "        self.val_losses = []\n",
        "        \n",
        "    def on_epoch_end(self, batch, logs={}):\n",
        "        self.losses.append(logs.get('loss'))\n",
        "        self.val_losses.append(logs.get('val_loss'))\n",
        "\n",
        "early_stopping = EarlyStopping(monitor='val_loss', patience=3, verbose=1, mode='auto')        \n",
        "        \n",
        "def run_catdog():\n",
        "    \n",
        "    history = LossHistory()\n",
        "    model.fit(train, labels, batch_size=batch_size, nb_epoch=nb_epoch,\n",
        "              validation_split=0.25, verbose=0, shuffle=True, callbacks=[history, early_stopping])\n",
        "    \n",
        "\n",
        "    predictions = model.predict(test, verbose=0)\n",
        "    return predictions, history\n",
        "\n",
        "predictions, history = run_catdog()"
      ]
    }
  ],
  "metadata": {
    "_change_revision": 0,
    "_is_fork": false,
    "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.5.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}