{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This implementation gives us a ~98% accuracy on the MNIS dataset.\n\nIt uses the LeNet Convolutional Neural Network as presented [here](https://pyimagesearch.com/2016/08/01/lenet-convolutional-neural-network-in-python/).","metadata":{}},{"cell_type":"markdown","source":"### Import packages","metadata":{}},{"cell_type":"code","source":"# import the necessary packages\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D\nfrom tensorflow.keras.layers import MaxPooling2D\nfrom tensorflow.keras.layers import Activation\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras import backend as K\n\nfrom tensorflow.keras.optimizers import SGD\nfrom tensorflow.keras.datasets import mnist\nfrom sklearn.preprocessing import LabelBinarizer\nfrom sklearn.metrics import classification_report\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-19T00:02:09.543870Z","iopub.execute_input":"2022-07-19T00:02:09.544333Z","iopub.status.idle":"2022-07-19T00:02:18.170634Z","shell.execute_reply.started":"2022-07-19T00:02:09.544308Z","shell.execute_reply":"2022-07-19T00:02:18.169949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Create model class","metadata":{}},{"cell_type":"code","source":"class LeNet:\n  @staticmethod\n  def build(width, height, depth, classes):\n    # initialize the model\n    model = Sequential()\n    input_shape = (height, width, depth)\n\n    # first set of CONV => RELU => POOL layers\n    model.add(Conv2D(20, (5, 5), padding=\"same\", input_shape=input_shape))\n    model.add(Activation(\"relu\"))\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))\n\n    # second set of CONV => RELU => POOL layers\n    model.add(Conv2D(50, (5, 5), padding=\"same\"))\n    model.add(Activation(\"relu\"))\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))\n\n    # first (and only) set of FC => RELU layers\n    model.add(Flatten())\n    model.add(Dense(500))\n    model.add(Activation(\"relu\"))\n\n    # softmax classifier\n    model.add(Dense(classes))\n    model.add(Activation(\"softmax\"))\n\n    # return the constructed network architecture\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:18.172655Z","iopub.execute_input":"2022-07-19T00:02:18.173423Z","iopub.status.idle":"2022-07-19T00:02:18.181618Z","shell.execute_reply.started":"2022-07-19T00:02:18.173389Z","shell.execute_reply":"2022-07-19T00:02:18.180995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data preprocessing","metadata":{}},{"cell_type":"code","source":"# Import training and test datasets\ntrain_data = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ntest_data = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\n\n# Get labels\nlabels = train_data['label']\ntrain_data = train_data.drop(columns=['label'])\n\n# Convert to Numpy arrays\ntrain_data = train_data.to_numpy()\ntest_data = test_data.to_numpy()","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:18.182625Z","iopub.execute_input":"2022-07-19T00:02:18.183008Z","iopub.status.idle":"2022-07-19T00:02:23.594857Z","shell.execute_reply.started":"2022-07-19T00:02:18.182975Z","shell.execute_reply":"2022-07-19T00:02:23.593797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Design matrix that has shape: num_samples x rows x columns x depth\ntrain_data = train_data.reshape((train_data.shape[0], 28, 28, 1))\ntest_data = test_data.reshape((test_data.shape[0], 28, 28, 1))","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:23.596432Z","iopub.execute_input":"2022-07-19T00:02:23.596813Z","iopub.status.idle":"2022-07-19T00:02:23.603101Z","shell.execute_reply.started":"2022-07-19T00:02:23.596785Z","shell.execute_reply":"2022-07-19T00:02:23.601284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Scale data to the range of [0, 1]\ntrain_data = train_data.astype(\"float32\") / 255.0\ntest_data = test_data.astype(\"float32\") / 255.0","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:23.605468Z","iopub.execute_input":"2022-07-19T00:02:23.605785Z","iopub.status.idle":"2022-07-19T00:02:23.714851Z","shell.execute_reply.started":"2022-07-19T00:02:23.605754Z","shell.execute_reply":"2022-07-19T00:02:23.713731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the labels from integers to vectors\nle = LabelBinarizer()\ntrain_labels = le.fit_transform(labels)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:23.715959Z","iopub.execute_input":"2022-07-19T00:02:23.716242Z","iopub.status.idle":"2022-07-19T00:02:23.728898Z","shell.execute_reply.started":"2022-07-19T00:02:23.716215Z","shell.execute_reply":"2022-07-19T00:02:23.727765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training the network","metadata":{}},{"cell_type":"code","source":"# Initialise the optimizer and model\nopt = SGD(lr=0.01)\nmodel = LeNet.build(width=28, height=28, depth=1, classes=10)\nmodel.compile(loss=\"categorical_crossentropy\", optimizer=opt, metrics=[\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:23.729955Z","iopub.execute_input":"2022-07-19T00:02:23.730188Z","iopub.status.idle":"2022-07-19T00:02:23.883135Z","shell.execute_reply.started":"2022-07-19T00:02:23.730166Z","shell.execute_reply":"2022-07-19T00:02:23.882372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the network\nH = model.fit(train_data, train_labels, batch_size=128, epochs=20, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:02:23.884532Z","iopub.execute_input":"2022-07-19T00:02:23.885082Z","iopub.status.idle":"2022-07-19T00:09:09.879710Z","shell.execute_reply.started":"2022-07-19T00:02:23.885043Z","shell.execute_reply":"2022-07-19T00:09:09.879121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# evaluate the network\npredictions = model.predict(train_data, batch_size=128)\nprint(classification_report(train_labels.argmax(axis=1), predictions.argmax(axis=1), target_names=[str(x) for x in le.classes_]))\n\n# plot the training loss and accuracy\nplt.style.use(\"ggplot\")\nplt.figure()\nplt.plot(np.arange(0, 20), H.history[\"loss\"], label=\"train_loss\")\n#plt.plot(np.arange(0, 20), H.history[\"val_loss\"], label=\"val_loss\")\nplt.plot(np.arange(0, 20), H.history[\"accuracy\"], label=\"train_acc\")\n#plt.plot(np.arange(0, 20), H.history[\"val_accuracy\"], label=\"val_acc\")\nplt.title(\"Training Loss and Accuracy\")\nplt.xlabel(\"Epoch #\")\nplt.ylabel(\"Loss/Accuracy\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:09:09.881123Z","iopub.execute_input":"2022-07-19T00:09:09.881450Z","iopub.status.idle":"2022-07-19T00:09:17.410782Z","shell.execute_reply.started":"2022-07-19T00:09:09.881419Z","shell.execute_reply":"2022-07-19T00:09:17.409853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get predictions for training network\npredictions = model.predict(test_data, batch_size=128)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:09:17.412874Z","iopub.execute_input":"2022-07-19T00:09:17.413132Z","iopub.status.idle":"2022-07-19T00:09:22.077969Z","shell.execute_reply.started":"2022-07-19T00:09:17.413099Z","shell.execute_reply":"2022-07-19T00:09:22.077316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Export CSV file","metadata":{}},{"cell_type":"code","source":"# Convert to DataFrame\ndf = pd.DataFrame(predictions.argmax(axis=1), columns=['Label'])\ndf.index += 1\ndf.index.name = 'ImageId'\n\n# Export DataFrame\ndf.to_csv('submission.csv', index=True)","metadata":{"execution":{"iopub.status.busy":"2022-07-19T00:09:22.078860Z","iopub.execute_input":"2022-07-19T00:09:22.079169Z","iopub.status.idle":"2022-07-19T00:09:22.118167Z","shell.execute_reply.started":"2022-07-19T00:09:22.079138Z","shell.execute_reply":"2022-07-19T00:09:22.117234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}