{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "3441299d-7a3c-a067-cd39-ef05c82569d2"
      },
      "outputs": [],
      "source": [
        "from __future__ import print_function\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "np.random.seed(1337)  # for reproducibility\n",
        "%matplotlib inline\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "from sklearn.model_selection import train_test_split\n",
        "from keras.models import Sequential\n",
        "from keras.layers import Dense, Dropout, Activation, Flatten\n",
        "from keras.layers import Convolution2D, MaxPooling2D\n",
        "from keras.utils import np_utils\n",
        "from keras import backend as K"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "fbe0f166-842f-d2af-9997-c2cb293dc7f1"
      },
      "outputs": [],
      "source": [
        "# getting the datasets\n",
        "train = pd.read_csv(\"../input/train.csv\")\n",
        "test = pd.read_csv(\"../input/test.csv\")\n",
        "print(train.shape)\n",
        "print(test.shape)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "ec005123-85c5-dfa5-99a4-a27a40b099c3"
      },
      "outputs": [],
      "source": [
        "# plot some digits\n",
        "for i in range(9):\n",
        "    plt.subplot(3,3,i+1)\n",
        "    data =train.ix[i, 'pixel0':'pixel783'].reshape(28,28)\n",
        "    plt.imshow(data, cmap='gray')\n",
        "    plt.axis('off')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "e7eb2102-d104-bd18-2de2-18cab1d5031c"
      },
      "outputs": [],
      "source": [
        "# separate predictors and labels, transform to ndarrays\n",
        "y = train[[0]].values.ravel() # labels/target\n",
        "X = train.iloc[:,1:].values   # Predictors(pixels that form the image)\n",
        "test = test.values"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "dadd7c31-f050-a643-938c-7dfbc8004aae"
      },
      "outputs": [],
      "source": [
        "batch_size = 128\n",
        "nb_classes = 10\n",
        "nb_epoch = 12\n",
        "\n",
        "# input image dimensions: 28x28 = 784 pixels (exactly what we have in training dataset)\n",
        "img_rows, img_cols = 28, 28\n",
        "# number of convolutional filters to use\n",
        "nb_filters = 32\n",
        "# size of pooling area for max pooling\n",
        "pool_size = (2, 2)\n",
        "# convolution kernel size\n",
        "kernel_size = (3, 3)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "baa82608-4108-3346-646a-bbb9cef70f20"
      },
      "outputs": [],
      "source": [
        "# Split our data into train and test, this way will be able to evaluate the perfomance of the model\n",
        "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)\n",
        "\n",
        "if K.set_image_dim_ordering == 'th':\n",
        "    X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)\n",
        "    X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)\n",
        "    test = test.reshape(test.shape[0], 1, img_rows, img_cols)\n",
        "    input_shape = (1, img_rows, img_cols)\n",
        "else:\n",
        "    X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)\n",
        "    X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)\n",
        "    test = test.reshape(test.shape[0], img_rows, img_cols, 1)\n",
        "    input_shape = (img_rows, img_cols, 1)\n",
        "\n",
        "# convert to array, specify data type, and reshape\n",
        "X_train = X_train.astype('float32')\n",
        "X_test = X_test.astype('float32')\n",
        "test = test.astype('float32')\n",
        "\n",
        "# Normalize data to have zero mean and unit variance. \n",
        "X_train /= 255\n",
        "X_test /= 255\n",
        "test /= 255\n",
        "\n",
        "print('X_train shape:', X_train.shape)\n",
        "print(X_train.shape[0], 'train samples')\n",
        "print(X_test.shape[0], 'test samples')\n",
        "\n",
        "# convert class vectors to binary class matrices\n",
        "y_train = np_utils.to_categorical(y_train, nb_classes)\n",
        "y_test = np_utils.to_categorical(y_test, nb_classes)\n",
        "print(\"One hot encoding: {}\".format(y_train[0, :]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "aeea550b-a381-f8db-3cae-9205d935b463"
      },
      "source": [
        "**CNN Model definition**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "cb500ee4-09f1-9b51-f2a6-d2f4f8b83e64"
      },
      "outputs": [],
      "source": [
        "# The Sequential model is a linear stack of layers\n",
        "model = Sequential()\n",
        "\n",
        "# in the first layer, you must specify the expected input data shape\n",
        "# input: 28x28 images with 1 channel -> (1, 28, 28) tensors.\n",
        "# this applies 32 (nb_filters) convolution filters of size 3x3 each.\n",
        "model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],\n",
        "                        border_mode='valid',\n",
        "                        input_shape=input_shape))\n",
        "model.add(Activation('relu'))\n",
        "model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))\n",
        "model.add(Activation('relu'))\n",
        "model.add(MaxPooling2D(pool_size=pool_size))\n",
        "model.add(Dropout(0.25))\n",
        "\n",
        "model.add(Flatten())\n",
        "\n",
        "# Dense(128) is a fully-connected layer with 128 hidden units.\n",
        "model.add(Dense(128))\n",
        "model.add(Activation('relu'))\n",
        "model.add(Dropout(0.5))\n",
        "model.add(Dense(nb_classes))\n",
        "model.add(Activation('softmax'))\n",
        "\n",
        "\n",
        "# a loss function. This is the objective that the model will try to minimize.\n",
        "# It can be the string identifier of an existing loss function (such as categorical_crossentropy or mse),\n",
        "# or it can be an objective function\n",
        "model.compile(loss='categorical_crossentropy',\n",
        "              optimizer='adadelta',\n",
        "              metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "3e9a5553-f909-6729-bd0c-ad3f79cbb0d7"
      },
      "outputs": [],
      "source": [
        "# train the model, iterating on the data in batches\n",
        "# of 128 samples(batch_size declared above)\n",
        "model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,\n",
        "          verbose=1, validation_data=(X_test, y_test))\n",
        "score = model.evaluate(X_test, y_test, verbose=0)\n",
        "print('Test score:', score[0])\n",
        "print('Test accuracy:', score[1])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "5fba7d40-047c-92b5-9ce1-b8cf641687dd"
      },
      "outputs": [],
      "source": [
        "# Make new predictions with the model on the kaggle test dataset\n",
        "predictions = model.predict_classes(test, batch_size=batch_size)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "fd1cb1ef-4ee1-af83-0f0d-11e49d240806"
      },
      "outputs": [],
      "source": [
        "submission = pd.DataFrame({\n",
        "        \"ImageId\": np.arange(1,len(test)+1),\n",
        "        \"Label\": predictions\n",
        "    })\n",
        "submission.to_csv('submission_cnn.csv', index=False)"
      ]
    }
  ],
  "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
}