{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":30839,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:42.131472Z","iopub.execute_input":"2025-01-15T02:27:42.131825Z","iopub.status.idle":"2025-01-15T02:27:42.141024Z","shell.execute_reply.started":"2025-01-15T02:27:42.131798Z","shell.execute_reply":"2025-01-15T02:27:42.139715Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# *Necessary imports*","metadata":{}},{"cell_type":"code","source":"# have np and pd already\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, confusion_matrix\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D, BatchNormalization\nfrom tensorflow.keras import Input\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T03:14:00.383310Z","iopub.execute_input":"2025-01-15T03:14:00.383754Z","iopub.status.idle":"2025-01-15T03:14:00.395797Z","shell.execute_reply.started":"2025-01-15T03:14:00.383721Z","shell.execute_reply":"2025-01-15T03:14:00.394443Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Loading + Exploring data**","metadata":{}},{"cell_type":"code","source":"train_path = '/kaggle/input/digit-recognizer/train.csv'\ntest_path = '/kaggle/input/digit-recognizer/test.csv'\n\ntrain_data = pd.read_csv(train_path)\ntest_data = pd.read_csv(test_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:42.244478Z","iopub.execute_input":"2025-01-15T02:27:42.244879Z","iopub.status.idle":"2025-01-15T02:27:46.190764Z","shell.execute_reply.started":"2025-01-15T02:27:42.244851Z","shell.execute_reply":"2025-01-15T02:27:46.189546Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":">*Call head() method to view training data*","metadata":{}},{"cell_type":"code","source":"train_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:46.192685Z","iopub.execute_input":"2025-01-15T02:27:46.193071Z","iopub.status.idle":"2025-01-15T02:27:46.210232Z","shell.execute_reply.started":"2025-01-15T02:27:46.193027Z","shell.execute_reply":"2025-01-15T02:27:46.208762Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"> *From this we can determine that there are 785 columns (1 for label and 784 for pixels)*\n> *train_data includes label, while test_data only contains pixel values*\n\n> Next, we'll create a method to visualize the data a bit better.","metadata":{}},{"cell_type":"code","source":"def plot_digit(index):\n    digit = train_data.iloc[index, 1:].values.reshape(28, 28)\n    plt.imshow(digit, cmap='gray')\n    plt.title(f\"Label: {train_data.iloc[index, 0]}\")\n    plt.show()\n\nfor i in range(5):\n    plot_digit(i)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:46.211909Z","iopub.execute_input":"2025-01-15T02:27:46.212335Z","iopub.status.idle":"2025-01-15T02:27:47.162897Z","shell.execute_reply.started":"2025-01-15T02:27:46.212295Z","shell.execute_reply":"2025-01-15T02:27:47.161613Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Preprocessing**","metadata":{}},{"cell_type":"markdown","source":">*Split the data into features and labels*","metadata":{}},{"cell_type":"code","source":"X = train_data.drop('label', axis=1).values\ny = train_data['label'].values","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:47.164262Z","iopub.execute_input":"2025-01-15T02:27:47.164692Z","iopub.status.idle":"2025-01-15T02:27:47.430763Z","shell.execute_reply.started":"2025-01-15T02:27:47.164659Z","shell.execute_reply":"2025-01-15T02:27:47.429499Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":">*Normalize the pixel values*","metadata":{}},{"cell_type":"code","source":"X = X / 255.0\ntest_data = test_data / 255.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:27:47.431979Z","iopub.execute_input":"2025-01-15T02:27:47.432405Z","iopub.status.idle":"2025-01-15T02:27:47.623832Z","shell.execute_reply.started":"2025-01-15T02:27:47.432366Z","shell.execute_reply":"2025-01-15T02:27:47.622688Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"> Reshape the data for the CNN into a 28x28x1 format","metadata":{}},{"cell_type":"code","source":"X = X.reshape(-1, 28, 28, 1)\n\n# Convert DataFrame to NumPy array and reshape\nif isinstance(test_data, pd.DataFrame):\n    test_data = test_data.to_numpy().reshape(-1, 28, 28, 1)\nelse:\n    test_data = test_data.reshape(-1, 28, 28, 1)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T03:04:05.359203Z","iopub.execute_input":"2025-01-15T03:04:05.359760Z","iopub.status.idle":"2025-01-15T03:04:05.369190Z","shell.execute_reply.started":"2025-01-15T03:04:05.359724Z","shell.execute_reply":"2025-01-15T03:04:05.366206Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"> Train-Test Split","metadata":{}},{"cell_type":"code","source":"X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:30:07.069360Z","iopub.execute_input":"2025-01-15T02:30:07.069869Z","iopub.status.idle":"2025-01-15T02:30:07.533560Z","shell.execute_reply.started":"2025-01-15T02:30:07.069833Z","shell.execute_reply":"2025-01-15T02:30:07.532364Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **CNN Creation**","metadata":{}},{"cell_type":"code","source":"model = Sequential([\n    Input(shape=(28, 28, 1)),\n    Conv2D(32, (3, 3), activation='relu'),\n    BatchNormalization(),\n    Conv2D(32, (3, 3), activation='relu'),\n    MaxPooling2D((2, 2)),\n    Dropout(0.25),\n\n    Conv2D(64, (3, 3), activation='relu'),\n    BatchNormalization(),\n    Conv2D(64, (3, 3), activation='relu'),\n    MaxPooling2D((2, 2)),\n    Dropout(0.25),\n\n    Flatten(),\n    Dense(256, activation='relu'),\n    Dropout(0.5),\n    Dense(10, activation='softmax')\n])\n\nmodel.compile(optimizer='adam',\n              loss='sparse_categorical_crossentropy',\n              metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T03:14:32.350904Z","iopub.execute_input":"2025-01-15T03:14:32.351318Z","iopub.status.idle":"2025-01-15T03:14:32.488463Z","shell.execute_reply.started":"2025-01-15T03:14:32.351285Z","shell.execute_reply":"2025-01-15T03:14:32.487337Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# *Training the model and tracking its progress*","metadata":{}},{"cell_type":"code","source":"lr_scheduler = ReduceLROnPlateau(\n    monitor='val_loss', \n    factor=0.5, \n    patience=3, \n    min_lr=1e-6\n)\n\nhistory = model.fit(\n    X_train, y_train,\n    validation_data=(X_val, y_val),\n    epochs=50,\n    batch_size=32,\n    callbacks=[lr_scheduler]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T03:27:14.816167Z","iopub.execute_input":"2025-01-15T03:27:14.816526Z","iopub.status.idle":"2025-01-15T03:27:21.521506Z","shell.execute_reply.started":"2025-01-15T03:27:14.816497Z","shell.execute_reply":"2025-01-15T03:27:21.519779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:38:26.152553Z","iopub.execute_input":"2025-01-15T02:38:26.152976Z","iopub.status.idle":"2025-01-15T02:38:26.346680Z","shell.execute_reply.started":"2025-01-15T02:38:26.152943Z","shell.execute_reply":"2025-01-15T02:38:26.345514Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Evaluate and Predict**","metadata":{}},{"cell_type":"code","source":"val_loss, val_acc = model.evaluate(X_val, y_val)\nprint(f\"Validation Accuracy: {val_acc:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:39:33.894708Z","iopub.execute_input":"2025-01-15T02:39:33.895147Z","iopub.status.idle":"2025-01-15T02:39:35.213636Z","shell.execute_reply.started":"2025-01-15T02:39:33.895119Z","shell.execute_reply":"2025-01-15T02:39:35.212451Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predictions = model.predict(test_data)\npredicted_labels = np.argmax(predictions, axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:39:39.315736Z","iopub.execute_input":"2025-01-15T02:39:39.316141Z","iopub.status.idle":"2025-01-15T02:39:43.958112Z","shell.execute_reply.started":"2025-01-15T02:39:39.316110Z","shell.execute_reply":"2025-01-15T02:39:43.956425Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Submission**","metadata":{}},{"cell_type":"code","source":"submission = pd.DataFrame({'ImageId': range(1, len(predicted_labels) + 1), 'Label': predicted_labels})\nsubmission.to_csv('submission.csv', index=False)\nprint('Successfully saved submission')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-15T02:40:52.888898Z","iopub.execute_input":"2025-01-15T02:40:52.889325Z","iopub.status.idle":"2025-01-15T02:40:52.919282Z","shell.execute_reply.started":"2025-01-15T02:40:52.889298Z","shell.execute_reply":"2025-01-15T02:40:52.918293Z"}},"outputs":[],"execution_count":null}]}