{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Importing Library"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nfrom keras.models import Sequential\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.layers.convolutional import Conv2D\nfrom keras.layers.convolutional import MaxPooling2D\nfrom keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D\nfrom keras.layers.core import Activation\nfrom keras.layers.core import Flatten\nfrom keras.layers.core import Dropout\nfrom keras.layers.core import Dense\nfrom keras.utils import np_utils\nimport tensorflow as tf\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ReduceLROnPlateau\nfrom sklearn.model_selection import train_test_split\nfrom keras.utils.np_utils import to_categorical\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Reading Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train.head(10)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Splitting the Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train = train.drop(\"label\",axis=True)\nY_train = train[\"label\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train = X_train / 255.0\ntest = test / 255.0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Reshape image in 3 dimensions (height = 28px, width = 28px , canal = 1)\nX_train = X_train.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":"#Encoding the output class label (One-Hot Encoding)\nY_train = to_categorical(Y_train, num_classes = 10)\nY_train[2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train, X_val, Y_train, Y_val = train_test_split(X_train, Y_train, test_size = 0.1, random_state=2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## EDA and Data Visualisation "},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"trainX shape:\", X_train.shape, \"\\ntrainY shape:\", Y_train.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train[\"label\"].hist(bins=10)\nclasses = [0,1,2,3,4,5,6,7,8,9]\nax=sns.countplot(x=\"label\", data=train)\nax.set_xticklabels(classes)\nplt.xlabel(\"Numbers\")\nplt.title(\"Frequency of digits(0-9) in the data \\n\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(10,5))\nfor i in range(10):\n    \n    plt.subplot(2,5,i+1)\n    plt.imshow(np.array(train.iloc[:,1:][train[\"label\"]==i].iloc[0,:]).reshape(28,28))\n    plt.xticks([])\n    plt.yticks([])\n    \nplt.suptitle(\"Visualising Numbers 0-9\")    \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Augmentation\n\n* In order to avoid overfitting problem, we need to expand artificially our handwritten digit dataset. This will help us in increasing the number of data in our dataset. \n* This will change the training data with small transformations to reproduce the variations occuring when someone is writing a digit."},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen = ImageDataGenerator(\n        featurewise_center=False,             # set input mean to 0 over the dataset\n        samplewise_center=False,              # set each sample mean to 0\n        featurewise_std_normalization=False,  # divide inputs by std of the dataset\n        samplewise_std_normalization=False,   # divide each input by its std\n        zca_whitening=False,                  # apply ZCA whitening\n        rotation_range=10,                    # randomly rotate images in the range (degrees, 0 to 180)\n        zoom_range = 0.1,                     # Randomly zoom image \n        width_shift_range=0.1,                # randomly shift images horizontally (fraction of total width)\n        height_shift_range=0.1,               # randomly shift images vertically (fraction of total height)\n        horizontal_flip=False,                # randomly flip images\n        vertical_flip=False)                  # randomly flip images\n\n\ndatagen.fit(X_train)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"For the data augmentation, I choosed to :\n\n* Randomly rotate some training images by 10 degrees\n* Randomly Zoom by 10% some training images\n* Randomly shift images horizontally by 10% of the width\n* Randomly shift images vertically by 10% of the height\n* I did not apply a vertical_flip nor horizontal_flip since it could have lead to misclassify symetrical numbers such as 6 and 9.\n\nOnce our model is ready, we fit the training dataset ."},{"metadata":{},"cell_type":"markdown","source":"## Model Building"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Sequential()\n\nmodel.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', activation ='relu', input_shape = (28,28,1)))\nmodel.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', activation ='relu'))\nmodel.add(MaxPool2D(pool_size=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(256, activation = \"relu\"))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(10, activation = \"softmax\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(loss='categorical_crossentropy',\n             optimizer='rmsprop',\n             metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Callback"},{"metadata":{"trusted":true},"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', \n                                            patience=3, \n                                            verbose=1, \n                                            factor=0.5, \n                                            min_lr=0.00001)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(datagen.flow(X_train,Y_train, batch_size=86),\n                              epochs = 30, validation_data = (X_val,Y_val),\n                              verbose = 2, steps_per_epoch=X_train.shape[0] // 86\n                              , callbacks=[learning_rate_reduction])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Predictions"},{"metadata":{"trusted":true},"cell_type":"code","source":"predictions = model.predict(test, verbose=0)\npredictions[0:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred=[]\nfor i in list(range(0,len(predictions))):\n    pred.append(np.argmax(predictions[i]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submissions=pd.DataFrame({\"ImageId\": list(range(1,len(predictions)+1)),\n                         \"Label\": pred})\nsubmissions.to_csv(\"DR.csv\", index=False, header=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Post Training Visualisation"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Plot the loss and accuracy curves for training and validation \nplt.figure(figsize=(10,10))\nfig, ax = plt.subplots(2,1)\nax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\nax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\nlegend = ax[0].legend(loc='best', shadow=True)\n\nax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\nax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\nlegend = ax[1].legend(loc='best', shadow=True)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}