{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Reading the dataset for training. "},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')\ntrain.head(10)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Reshaping the columns of the dataframe to form the images. "},{"metadata":{"trusted":true},"cell_type":"code","source":"Y_train = train[\"label\"]\nX_train = train.drop([\"label\"],axis=1)\nX_train = X_train.values.astype('float32')\nX_train = X_train.reshape(X_train.shape[0],28,28,1)\nprint(\"Size of dataset: \",X_train.shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Visualizing and verifying one of the images in the dataset."},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.imshow(X_train[100], cmap=plt.get_cmap('gray'))\nplt.title(Y_train[100]);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I have used three methods for data augmentation:\n1. Image Binarization\n2. Image Rotation\n3. Image translation"},{"metadata":{"trusted":true},"cell_type":"code","source":"#Converting the images to black and white\nimport cv2\n\nX_train_bw = np.zeros((len(X_train),28,28))\nfor i in range(len(X_train)):\n    (thresh, X_train_bw[i,:,:]) = cv2.threshold(X_train[i], 127, 255, cv2.THRESH_BINARY)\n\nX_train_bw = X_train_bw.reshape(len(X_train_bw),28,28,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.subplot(1,2,1)\nplt.title('Original Image')\nplt.imshow(X_train[100], cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,2,2)\nplt.title('Binarized Image')\nplt.imshow(X_train_bw[100], cmap=plt.get_cmap('gray'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Rotating the images clockwise and anticlockwise by 20 degrees. \n\npos_matrix = cv2.getRotationMatrix2D((14, 14), 20, 1.0)\nneg_matrix = cv2.getRotationMatrix2D((14, 14), -20, 1.0)\n\nX_train_rot_pos = np.zeros((len(X_train),28,28))\nfor i in range(len(X_train)):\n    X_train_rot_pos[i,:,:] = cv2.warpAffine(X_train[i], pos_matrix, (28, 28))\nX_train_rot_pos = X_train_rot_pos.reshape(len(X_train_rot_pos),28,28,1)\n\nX_train_rot_neg = np.zeros((len(X_train),28,28))\nfor i in range(len(X_train)):\n    X_train_rot_neg[i,:,:] = cv2.warpAffine(X_train[i], neg_matrix, (28, 28))\nX_train_rot_neg = X_train_rot_neg.reshape(len(X_train_rot_neg),28,28,1)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Verifying\nplt.subplot(1,3,1)\nplt.title('Original Image')\nplt.imshow(X_train[100],cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,3,2)\nplt.title('Anti-Clockwise Rotation')\nplt.imshow(X_train_rot_pos[100], cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,3,3)\nplt.title('Clockwise Rotation')\nplt.imshow(X_train_rot_neg[100], cmap=plt.get_cmap('gray'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Translation of images by 5 units in all four directions.\n\npos_trans_x = np.float32([[1, 0, 5], [0, 1, 0]]) \nneg_trans_x = np.float32([[1, 0, -5], [0, 1, 0]]) \npos_trans_y = np.float32([[1, 0, 0], [0, 1, 5]]) \nneg_trans_y = np.float32([[1, 0, 0], [0, 1, -5]]) \n\nX_train_pos_x = np.zeros((len(X_train),28,28))\nX_train_pos_y = np.zeros((len(X_train),28,28))\nX_train_neg_x = np.zeros((len(X_train),28,28))\nX_train_neg_y = np.zeros((len(X_train),28,28))\nfor i in range(len(X_train)):\n    X_train_pos_x[i,:,:] = cv2.warpAffine(X_train[i], pos_trans_x, (28, 28))\n    X_train_pos_y[i,:,:] = cv2.warpAffine(X_train[i], pos_trans_y, (28, 28))\n    X_train_neg_x[i,:,:] = cv2.warpAffine(X_train[i], neg_trans_x, (28, 28))\n    X_train_neg_y[i,:,:] = cv2.warpAffine(X_train[i], neg_trans_y, (28, 28))\n    \nX_train_pos_x = X_train_pos_x.reshape(len(X_train_pos_x),28,28,1)\nX_train_pos_y = X_train_pos_y.reshape(len(X_train_pos_y),28,28,1)\nX_train_neg_x = X_train_neg_x.reshape(len(X_train_neg_x),28,28,1)\nX_train_neg_y = X_train_neg_y.reshape(len(X_train_neg_y),28,28,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Verifying\nplt.subplot(1,5,1)\nplt.imshow(X_train[100],cmap=plt.get_cmap('gray'))\nplt.title('Original Image')\n\nplt.subplot(1,5,2)\nplt.title('+ve x')\nplt.imshow(X_train_pos_x[100], cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,5,3)\nplt.title('-ve x')\nplt.imshow(X_train_neg_x[100], cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,5,4)\nplt.title('+ve y')\nplt.imshow(X_train_pos_y[100], cmap=plt.get_cmap('gray'))\n\nplt.subplot(1,5,5)\nplt.title('-ve y')\nplt.imshow(X_train_neg_y[100], cmap=plt.get_cmap('gray'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Adding all the generated data\n\nX_train = np.concatenate((X_train,X_train_bw,X_train_rot_pos,X_train_rot_neg,\n                          X_train_pos_x,X_train_neg_x,X_train_pos_y,X_train_neg_y),axis=0)\nY_train = pd.concat([Y_train,Y_train,Y_train,Y_train,Y_train,Y_train,Y_train,Y_train],axis=0)\nY_train = Y_train.values\nprint(\"Number of images: \",len(X_train))\nprint(\"Number of labels: \",len(Y_train))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Normalizing the dataset\n\nmax_px = X_train.max()\nmin_px = X_train.min()\nprint(\"Maximum pixel value: \",max_px)\nprint(\"Minimum pixel value: \",min_px)\n\nX_train = (X_train - min_px)/(max_px - min_px)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#One-Hot encoding the labels\n\nfrom keras.utils import to_categorical\n\nY_train_encoded = to_categorical(Y_train)\nprint(\"Shape of labels: \",Y_train_encoded.shape)\n#Verifying\nprint(Y_train[10])\nprint(Y_train_encoded[10])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Here I have used NAdam as the optimizer and kullback_leibler_divergence as the loss function. \nThe CNN model is as follows:\nConv2D*2 --> MaxPooling2D --> Dropout --> Conv2D*2 --> MaxPooling2D --> Flatten --> Dense --> Dropout --> Dense (output)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#CNN classifier\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D,Input\n\ninput_shape = (28,28,1)\nmodel = Sequential()\nmodel.add(Input(shape=input_shape))\nmodel.add(Conv2D(64, kernel_size=(3,3), activation=\"relu\"))\nmodel.add(Conv2D(64, kernel_size=(3,3), activation=\"relu\"))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\nmodel.add(Conv2D(128, kernel_size=(3,3), activation=\"relu\"))\nmodel.add(Conv2D(128, kernel_size=(3,3), activation=\"relu\"))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Flatten())\nmodel.add(Dense(256, activation=\"relu\"))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(10,activation=\"softmax\"))\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Training the model..."},{"metadata":{"trusted":true},"cell_type":"code","source":"model.compile(optimizer='Nadam', loss='kullback_leibler_divergence', metrics=['accuracy'])\nmodel.fit(X_train,Y_train_encoded, batch_size=128, epochs=10,validation_split=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Analyzing the wrong predictions in the train dataset\n\nY_train_predict = model.predict(X_train)\npredicted_train_label = []\nfor y in Y_train_predict:\n    predicted_train_label.append(np.argmax(y))\n    \nwrong_prediction = []\nfor l in range(len(predicted_train_label)):\n    if(predicted_train_label[l] != Y_train[l]):\n        wrong_prediction.append(l)\nprint(len(wrong_prediction))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Reading the test dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.read_csv('/kaggle/input/digit-recognizer/test.csv')\ntest.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_test = test.values.astype('float32')\nX_test = X_test.reshape(X_test.shape[0],28,28,1)\nplt.imshow(X_test[100], cmap=plt.get_cmap('gray'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Normalizing the test dataset\n\nmax_px = X_test.max()\nmin_px = X_test.min()\nprint(\"Maximum pixel value: \",max_px)\nprint(\"Minimum pixel value: \",min_px)\n\nX_test = (X_test - min_px)/(max_px - min_px)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Predicting the test labels using the trained model\n\nY_predict = model.predict(X_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Finding the predicted label using the predicted probabilities\n\npredicted_label = []\nfor y in Y_predict:\n    predicted_label.append(np.argmax(y))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Writing the result in the output file\n\nsubmission_df = pd.DataFrame({'ImageId' : list(range(1,test.shape[0]+1)),'Label' : predicted_label})\nsubmission = submission_df.to_csv('submission.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}