{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Building a Basic CNN: The MNIST Dataset\n\nIn this notebook, we will build a simple CNN-based architecture to classify the 10 digits (0-9) of the MNIST dataset. The objective of this notebook is to build CNNs in Keras.\n\n1. Importing libraries and the dataset\n2. Data preparation: Train-test split, specifying the shape of the input data etc.\n3. Building and understanding the CNN architecture \n4. Fitting and evaluating the model\n"},{"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":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport random\nimport keras\n\nimport matplotlib.pyplot as plt \nimport pandas as pd\n\nfrom datetime import datetime\nnow = datetime.now()\ncurrent_time = now.strftime(\"%H:%M:%S\")\nprint(current_time)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# load the dataset into train and test sets\ndf_train = pd.read_csv('../input/digit-recognizer/train.csv')\ndf_test = pd.read_csv('../input/digit-recognizer/test.csv')\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## we remove the label from train data  in seperate columns and data in seperate test data has no labels \ny_train = df_train.label.to_numpy()\nx_train = df_train.drop('label',axis=1).to_numpy()\nprint(x_train.shape,y_train.shape)\n\nx_test = df_test.to_numpy()\nprint(x_test.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## ## after removing the label we will resize the image into 28*28 size from 784  \n##   from train and test data  in seperate columns and data in seperate \n## normalization i done by dividing by 255 as simple way \n\n\nx_train = x_train.reshape(x_train.shape[0],28,28)\nx_test = x_test.reshape(x_test.shape[0],28,28)\nprint(x_train.shape,x_test.shape)\n\n# convert int to float for all data and normalize using divide by 255.0 : \nx_train = x_train.astype('float32')\nx_test = x_test.astype('float32')\n\n# normalise\nx_train /= 255.0\nx_test /= 255.0\n\nprint(x_train.shape,x_test.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# for input to our CNN network 4D dimesn is required ,t he int shape will be fixed as below \nimg_rows, img_cols = 28, 28\ninput_shape = (img_rows, img_cols, 1)\n\n# number of classes in label\nnum_classes = 10\n\n# reshape x_train  to 3D vectors for CNN conv input \nx_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)\nprint(x_train.shape)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# convert class labels (from digits) to one-hot encoded vectors : ensure to not run it multiple times as to_categorical \n##  will keep on adding dimensions \ny_train = keras.utils.to_categorical(y_train, num_classes)\nprint(y_train.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# model creation we use a 3x3 window over tehimage size of 28x28 as it fits correctly without any window buffer needed  \n\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras import backend as K\n\nmodel = Sequential()\n\n# a keras convolutional layer is called Conv2D\n# help(Conv2D)\n# note that the first layer needs to be told the input shape explicitly\n\n# first conv layer\nmodel.add(Conv2D(128, kernel_size=(3, 3),\n                 activation='relu',\n                 input_shape=input_shape)) # input shape = (img_rows, img_cols, 1)\n\n# second conv layer\nmodel.add(Conv2D(64, kernel_size=(3, 3), \n                 activation='relu'))\n\n\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\n\n# flatten and put a fully connected layer\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu')) # fully connected\nmodel.add(Dense(256, activation='relu')) # fully connected\nmodel.add(Dense(128, activation='relu')) # fully connected\nmodel.add(Dense(64, activation='relu')) # fully connected\n\n# softmax layer\nmodel.add(Dense(num_classes, activation='softmax'))  ## for outpt we use softmax\n\n# model summary\nmodel.summary()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# usual cross entropy loss\n# choose any optimiser such as adam, rmsprop etc , we use adam \n# metric is accuracy\nmodel.compile(loss=keras.losses.categorical_crossentropy,\n              optimizer=keras.optimizers.Adam(),\n              metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit the model we will hold 20% of training data for validation split \nbatch_size = 200  \nepochs = 40\n\ncnn_model =  model.fit(x_train, y_train,\n                       batch_size=batch_size,\n                       epochs=epochs,\n                       verbose=1,\n                       validation_split=0.2\n                      )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":" \ntrain_acc = cnn_model.history['accuracy']\nval_acc = cnn_model.history['val_accuracy']  \ntrain_loss = cnn_model.history['loss'] \nval_loss = cnn_model.history['val_loss'] \n\nepochs = range(epochs)\n\n# subplots \nfig, ax = plt.subplots(1, 2, figsize=(15, 5))\nfig.subplots_adjust(wspace=0.15, hspace=0.025)\nax = ax.ravel() ## plot arrary \n\n\n\nax[0].plot(epochs, cnn_model.history['accuracy'], 'r', label='Training accuracy')\nax[0].plot(epochs, cnn_model.history['val_accuracy'] , 'b', label='Validation accuracy')\nax[0].set_title('Training and validation accuracy')\nax[0].legend()\n\n\nax[1].plot(epochs, cnn_model.history['loss'] , 'r', label='Training Loss')\nax[1].plot(epochs, cnn_model.history['val_loss'] , 'b', label='Validation Loss')\nax[1].set_title('Training and validation loss')\nax[1].legend()\n\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)\nx_test.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## predict the output on test data \ny_pred = np.argmax(model.predict(x_test), axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## lets test 1 image and lable of 0th position \nplt.imshow(x_test[0].reshape(28,28), cmap=plt.get_cmap('gray'), vmin=0, vmax=1)\n# print the predicted label of the above image\ny_pred[0]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"## looks good \n# create csv ataset for redictions and save for submission\nsubmissions = pd.DataFrame()\nsubmissions[\"ImageId\"] = [i for i in range(1, y_pred.shape[0]+1)]\nsubmissions[\"Label\"] = y_pred\n\nsubmissions.to_csv(\"submissions.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}