{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Handwritten Digit Recognizer using Stratified K-Fold Convolutional Neural Network"},{"metadata":{},"cell_type":"markdown","source":"#### Introduction\n\n###### This kernel uses Stratified K-Fold to train a simple Covolutional Neural Netwrok for the Digit Reconizer dataset."},{"metadata":{},"cell_type":"markdown","source":"### Importing important libraries"},{"metadata":{"trusted":true},"cell_type":"code","source":"import math\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport os\nprint(os.listdir(\"../input\"))\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\nimport tensorflow as tf","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Reading Datasets"},{"metadata":{},"cell_type":"markdown","source":"##### Reading the Train Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv('../input/train.csv')\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Reading the Test Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.read_csv(\"../input/test.csv\")\ntest.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test.describe()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Exploratory Data Analsysis"},{"metadata":{},"cell_type":"markdown","source":"#### Checking for NULL values (if any)."},{"metadata":{"trusted":true},"cell_type":"code","source":"train.melt(id_vars=\"label\")['value'].isnull().sum()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test.melt()['value'].isnull().sum()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Count of each labels"},{"metadata":{"trusted":true},"cell_type":"code","source":"train['label'].value_counts().sort_index()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Plots for number of training data for each number."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Plot\nplt.figure(figsize=(8, 4))\nsns.set_style(\"whitegrid\")\nsns.countplot(x=\"label\", data=train)\nplt.xlabel(\"Label\")\nplt.ylabel(\"Count\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Dividing the training dataset into X and y"},{"metadata":{"trusted":true},"cell_type":"code","source":"y = train['label']\nX = train.drop(['label'], axis = 1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Normalize the pixel data, i.e. converting values from 0 - 254 to 0 - 1 "},{"metadata":{"trusted":true},"cell_type":"code","source":"X = X / 255\ntest = test / 255","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Converting labels to numpy array"},{"metadata":{"trusted":true},"cell_type":"code","source":"y = np.array(y)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Reshaping image to 28px X 28px dimension"},{"metadata":{"trusted":true},"cell_type":"code","source":"X = X.values.reshape(-1,28,28,1)\ntest = test.values.reshape(-1,28,28,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(X[0][:,:,0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Modelling CNN"},{"metadata":{},"cell_type":"markdown","source":"#### Importing Stratified K-Fold"},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Tensorflow Model"},{"metadata":{},"cell_type":"markdown","source":"> ##### Conv2D --> MaxPool2D --> Conv2D --> MaxPool2D --> Conv2D --> MaxPool2D --> Conv2D --> MaxPool2D --> Flatten --> Dense Softmax"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Tensorflow Keras CNN Model\nmodel = tf.keras.models.Sequential()\n\nmodel.add(tf.keras.layers.Conv2D(32, (3,3), padding = \"same\", activation = \"relu\", input_shape = X.shape[1:]))\nmodel.add(tf.keras.layers.MaxPool2D(2,2))\n\nmodel.add(tf.keras.layers.Conv2D(64, (3,3), padding = \"same\", activation = \"relu\"))\nmodel.add(tf.keras.layers.MaxPool2D(2,2))\n\nmodel.add(tf.keras.layers.Conv2D(128, (3,3), padding = \"same\", activation = \"relu\"))\nmodel.add(tf.keras.layers.MaxPool2D(2,2))\n\nmodel.add(tf.keras.layers.Conv2D(256, (3,3), padding = \"same\", activation = \"relu\"))\nmodel.add(tf.keras.layers.MaxPool2D(2,2))\n\nmodel.add(tf.keras.layers.Flatten())\n\nmodel.add(tf.keras.layers.Dense(10, activation='softmax'))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Optimizer and loss function\n\n##### Adam is used as optiomizer with loss function of 'Sparse Categorical Crossentropy'."},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='adam', \n              loss='sparse_categorical_crossentropy', \n              metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Training with Stratified K-Fold\n\n##### The model is trained using 12 splits."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Stratified K-Fold\nk_fold = StratifiedKFold(n_splits=12, random_state=12, shuffle=True)\n\nfor k_train_index, k_test_index in k_fold.split(X, y):\n    model.fit(X[k_train_index,:], y[k_train_index], epochs=5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Evalutaing the training dataset for the accuracy."},{"metadata":{"trusted":true},"cell_type":"code","source":"val_loss, val_acc = model.evaluate(X, y)\nval_acc","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### Saving the model"},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save(\"dr_cnn_model.h5\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Predicting the submission dataframe"},{"metadata":{},"cell_type":"markdown","source":"###### Finding the predection for the test dataset."},{"metadata":{"trusted":true},"cell_type":"code","source":"test_pred = model.predict(test)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Building the submission dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.DataFrame()\nsubmission['ImageId'] = range(1, (len(test)+1))\nsubmission['Label'] = np.argmax(test_pred, axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### Saving the submission dataset as submission.csv"},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.to_csv(\"submission.csv\", index=False)","execution_count":null,"outputs":[]}],"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.6.6"}},"nbformat":4,"nbformat_minor":1}