{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "67db9700-4c73-7cdb-6040-108c1632c3a6"
      },
      "source": [
        "This code was mostly derived from content posted at Machine Learning Mastery and marginally from code posted by user Koba on Kaggle."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "ab97f41c-1384-b174-0339-05b6f32d14fe"
      },
      "outputs": [],
      "source": [
        "#importing libraries\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "from keras.models import Sequential\n",
        "from keras.layers import Dense\n",
        "from keras.layers import Dropout\n",
        "from keras.layers import Flatten\n",
        "from keras.layers.convolutional import Convolution2D\n",
        "from keras.layers.convolutional import MaxPooling2D\n",
        "from keras.utils import np_utils\n",
        "from keras import backend as K\n",
        "K.set_image_dim_ordering('th')\n",
        "\n",
        "#for repeatability\n",
        "#seed = 7\n",
        "#np.random.seed(seed)\n",
        "\n",
        "# create data sets, skipping the header row with [1:]\n",
        "dataset = pd.read_csv(\"../input/train.csv\")\n",
        "y_train = dataset[[0]].values.ravel()\n",
        "X_train = dataset.iloc[:,1:].values\n",
        "test = pd.read_csv(\"../input/test.csv\").values\n",
        "\n",
        "# reshape to be [samples][pixels][width][height]\n",
        "X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')\n",
        "test = test.reshape(test.shape[0], 1, 28, 28).astype('float32')\n",
        "\n",
        "# normalize inputs from 0-255 to 0-1\n",
        "X_train = X_train / 255\n",
        "test = test / 255\n",
        "\n",
        "# one hot encode outputs\n",
        "y_train = np_utils.to_categorical(y_train)\n",
        "\n",
        "#subsetting loaded data for use as train and test during initial training and tuning\n",
        "randIndexTrain = np.random.randint(X_train.shape[0],size=15000)\n",
        "#randIndexTest = np.random.randint(X_train.shape[0],size=500)\n",
        "\n",
        "#for use during initial model training/ tuning\n",
        "X_train1 = X_train[randIndexTrain,:]\n",
        "y_train1 = y_train[randIndexTrain,:]\n",
        "\n",
        "#X_test1 = X_train[randIndexTest,:]\n",
        "#y_test1 = y_train[randIndexTest,:]\n",
        "\n",
        "#full sized training data load\n",
        "#X_train1 = X_train\n",
        "#y_train1 = y_train\n",
        "\n",
        "\n",
        "#used later to specify the number of neurons in the output layer\n",
        "num_classes = y_train1.shape[1]\n",
        "\n",
        "\n",
        "def baseline_model():\n",
        "\t# create model\n",
        "\tmodel = Sequential()\n",
        "\tmodel.add(Convolution2D(32, 5, 5, border_mode='valid', input_shape=(1, 28, 28), activation='relu'))\n",
        "\tmodel.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\tmodel.add(Dropout(0.2))\n",
        "\tmodel.add(Flatten())\n",
        "\tmodel.add(Dense(128, activation='relu'))\n",
        "\tmodel.add(Dense(num_classes, activation='softmax'))\n",
        "\t# Compile model\n",
        "\tmodel.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
        "\treturn model\n",
        "\n",
        "def larger_model():\n",
        "\t# create model\n",
        "\tmodel = Sequential()\n",
        "\tmodel.add(Convolution2D(30, 5, 5, border_mode='valid', input_shape=(1, 28, 28), activation='relu'))\n",
        "\tmodel.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\tmodel.add(Convolution2D(15, 3, 3, activation='relu'))\n",
        "\tmodel.add(MaxPooling2D(pool_size=(2, 2)))\n",
        "\tmodel.add(Dropout(0.2))\n",
        "\tmodel.add(Flatten())\n",
        "\tmodel.add(Dense(128, activation='relu'))\n",
        "\tmodel.add(Dense(50, activation='relu'))\n",
        "\tmodel.add(Dense(num_classes, activation='softmax'))\n",
        "\t# Compile model\n",
        "\tmodel.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
        "\treturn model\n",
        " \n",
        "\n",
        "# build the model\n",
        "model = larger_model()\n",
        "\n",
        "# Fit the model - initial model training and tuning\n",
        "#model.fit(X_train1, y_train1, validation_data=(X_test1, y_test1), nb_epoch=10, batch_size=200, verbose=0)\n",
        "# Final evaluation of the model\n",
        "#scores = model.evaluate(X_test1, y_test1, verbose=0)\n",
        "#print(head(scores))\n",
        "\n",
        "# save results\n",
        "#np.savetxt('scores_cnn_keras.csv', np.c_[range(1,len(test)+1),scores], delimiter=',', header = 'ImageId,Label', comments = '', fmt='%d')\n",
        "\n",
        "#print(\"Baseline Error: %.2f%%\" % (100-scores[1]*100)) \n",
        "\n",
        "#for Kaggle submission\n",
        "\n",
        "# Fit the model\n",
        "model.fit(X_train1, y_train1, nb_epoch=10, batch_size=200, verbose=0)\n",
        "\n",
        "# Prediction\n",
        "pred = model.predict(test)\n",
        "pred1 = pred.argmax(axis=0)\n",
        "pred2 = np.c_[range(1,len(test)+1),pred1]\n",
        "\n",
        "# save results\n",
        "np.savetxt('submission_cnn_keras.csv', pred2, delimiter=',', header = 'ImageId,Label', comments = '', fmt='%d')"
      ]
    }
  ],
  "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
}