{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#loading dataset\npath = '../input/Kannada-MNIST'\ndf = pd.read_csv(path+'/train.csv')\ndf_test = pd.read_csv(path+'/test.csv')\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#converting dataframe to 28x28 numpy array like an image\n\nx_train = df.iloc[:,1:].values.reshape(df.shape[0],28,28)\nx_test = df_test.iloc[:,1:].values.reshape(df_test.shape[0],28,28)\n\ny_train = df.iloc[:,0].values\nid_test = df_test.iloc[:,0].values\n\n#Creating a stratified split to validate the model\nx_train,x_val, y_train,y_val = train_test_split(x_train,y_train,stratify=y_train,test_size=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#distribution of categories\nsns.countplot(y_train)","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"#printing a sample train image with label\nsample_num = 3\nplt.imshow(x_train[sample_num],cmap='gray')\nprint('label: '+str(y_train[sample_num]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#normalizing the input data for better convergence\nx_train = x_train/255\nx_val = x_val/255\nx_test = x_test/255","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Tensorflow Conv2D accepts input in the shape of [m,h,w,c] = [samples size, height, width, channels]\n#Thus we need to add the channel size as 1 for grayscale image\n\nx_train = x_train.reshape(x_train.shape[0], 28, 28, 1)\nx_val = x_val.reshape(x_val.shape[0], 28, 28, 1)\nx_test = x_test.reshape(x_test.shape[0],28,28,1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### CNN model"},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"# making a CNN network using tf.keras\n\nmodel = tf.keras.models.Sequential([\n    \n    #args for conv2 are self explanatory\n    tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), strides=(1,1),padding='same',activation='relu', input_shape=(28, 28,1)),\n    tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), strides=(2,2),padding='same',activation='relu'),\n    tf.keras.layers.Dropout(0.2),\n    # 2nd layer\n    tf.keras.layers.Conv2D(128,kernel_size=(3,3), strides=(1,1),padding='same', activation='relu'),\n    tf.keras.layers.Conv2D(128,kernel_size=(3,3), strides=(2,2),padding='same', activation='relu'),\n    tf.keras.layers.Dropout(0.2),\n    # 3rd layer\n    tf.keras.layers.Conv2D(256,kernel_size=(3,3), strides=(1,1),padding='same', activation='relu'),\n    # Flatten the results to feed into a DNN\n    tf.keras.layers.Flatten(),\n    #FC hidden layer 1\n    tf.keras.layers.Dense(512, activation='relu'),\n    tf.keras.layers.Dropout(0.2),\n    #FC hidden layer 2\n    tf.keras.layers.Dense(128, activation='relu'),    \n    #since we have 10 classes we use 10 neurons with softmax for classification\n    tf.keras.layers.Dense(10, activation='softmax')\n\n])\n\n#using adam (RMSProp+momentum) for fast convergence\nmodel.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(x_train,y_train,validation_data=(x_val,y_val),epochs=10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.plot(history.history['accuracy'],label='train')\nplt.plot(history.history['val_accuracy'],label='validation')\nplt.ylabel('Accuracy')\nplt.xlabel('Epochs')\nplt.legend()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#finding the accuracy on validation set\nval_loss,val_acc = model.evaluate(x_val,y_val)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predictions = model.predict(x_val)\n\n#printing some of the predicitons for analysis\nf,ax = plt.subplots(7,7,figsize=(15,15))\n\ny_pred = np.argmax(predictions,axis=1)\n\nfor i in range(49):\n    \n    ax[int(i/7),int(i%7)].imshow(x_test[i,:,:,0],cmap='gray')\n    ax[int(i/7),int(i%7)].set_title('Prediction:'+str(y_pred[i]))\n    ax[int(i/7),int(i%7)].axis('off')\n    \nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import seaborn as sns\nfrom sklearn.metrics import confusion_matrix\nplt.figure(figsize=(15,10))\n#Here 0 to 28 labels are mapped to their original categories\nax = sns.heatmap(confusion_matrix(y_val,y_pred),annot=True,cmap='GnBu');\nax.set_xlabel('Predicted values');\nax.set_ylabel('True values');\nax.set_title('Confusion matrix');","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"1. We need to further train on number 7, 1\n2. Getting data or augmentation could help"},{"metadata":{"trusted":true},"cell_type":"code","source":"y_test_pred = np.argmax(model.predict(x_test),axis=1)\n\nresult = pd.DataFrame([id_test,y_test_pred],index=['id','label']).T\nresult = result.set_index('id')\nresult.to_csv('submission.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Saving the model weights to load later\n\nmodel.save_weights(\"kannada_MNIST_model.h5\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"py36","language":"python","name":"py36"},"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.9"}},"nbformat":4,"nbformat_minor":1}