{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "b8980bcf-d9c7-a044-8669-c5b835746327"
      },
      "source": [
        "I'm trying to compare the behavior of a kernel running on my laptop and in the kaggle computers.\n",
        "The kernel was written by Jeff Delaney. I run it in a MacBookPro OSX 10.12 python 3.5 keras 1.1.2 with Theano (0.8.2) backend.\n",
        "Running in my laptop I get train_loss to drop from 0.69 to 0.3 in 50 epochs but val_loos grows from 0.7 to 2.5\n",
        "Just looking at the first 10 test images I get ~50% accuracy."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b2da9170-36b9-6561-7944-2af45355b035"
      },
      "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.\n",
        "\n",
        "#select Theano as backend\n",
        "%env KERAS_BACKEND=theano"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "8d4c852c-6f85-e81a-42b8-a39c1c733065"
      },
      "outputs": [],
      "source": [
        "import os, random, cv2\n",
        "#import numpy as np\n",
        "#import pandas as pd\n",
        "from skimage.io import imread\n",
        "from skimage.transform import resize\n",
        "import matplotlib.pyplot as plt\n",
        "from matplotlib import ticker\n",
        "import seaborn as sns\n",
        "%matplotlib inline \n",
        "\n",
        "import keras\n",
        "from keras.models import Sequential\n",
        "from keras.layers import Input, Dropout, Flatten, Convolution2D, MaxPooling2D, Dense, Activation\n",
        "from keras.optimizers import RMSprop, SGD\n",
        "from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping\n",
        "from keras.utils import np_utils\n",
        "from keras import backend as K"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "b4797362-f9a7-25fa-f6eb-c07e862eb3bf"
      },
      "outputs": [],
      "source": [
        "random.seed(2718)\n",
        "K.set_image_dim_ordering('th') \n",
        "print(\"keras version: \", keras.__version__)\n",
        "print(\"keras image dimension ordering: \", keras.backend.image_dim_ordering())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e49893f7-09ea-aa69-13cf-fc2b91c574df"
      },
      "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[:100] + train_cats[:100]\n",
        "random.shuffle(train_images)\n",
        "test_images =  test_images[:25]\n",
        "\n",
        "def read_image(file_path):\n",
        "    #im = imread(file_path)\n",
        "    #im = resize(im, (ROWS, COLS))\n",
        "    #return im\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": "0271ea2c-0eeb-afbd-79d6-ca6b4cad3d26"
      },
      "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": "b5673367-a44f-f5ff-078b-861f7857c9f6"
      },
      "outputs": [],
      "source": [
        "optimizer = RMSprop(lr=1e-4)\n",
        "\n",
        "#epochs = 25\n",
        "#lrate = 4.e-4\n",
        "#decay = lrate/epochs\n",
        "#optimizer = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)\n",
        "\n",
        "\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()\n",
        "#model.summary()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e5006377-eb58-7e9b-2351-bd5b08e378a9"
      },
      "outputs": [],
      "source": [
        "nb_epoch = 10\n",
        "batch_size = 100\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])\n",
        "    \n",
        "\n",
        "    predictions = model.predict(test, verbose=0)\n",
        "    return  predictions, history\n",
        "\n",
        "predictions, history = run_catdog()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "a00fbb62-5091-d7ed-02bc-10406c72e5b0"
      },
      "outputs": [],
      "source": [
        "loss = history.losses\n",
        "val_loss = history.val_losses\n",
        "\n",
        "plt.xlabel('Epochs')\n",
        "plt.ylabel('Loss')\n",
        "plt.title('VGG-16 Loss Trend')\n",
        "plt.plot(loss, 'blue', label='Training Loss')\n",
        "plt.plot(val_loss, 'green', label='Validation Loss')\n",
        "plt.xticks(range(0,nb_epoch)[0::2])\n",
        "plt.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "a640dbfa-1244-1e5d-1bb2-953fda8bee35"
      },
      "source": [
        "If I use cv2 to read the input images, the kernel appears to be doing some learning. Unfortunately the time limit of 1200 s is forcing me to use very few samples."
      ]
    }
  ],
  "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
}