{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**MNIST Digit Classifier using CNN and Keras**\n\nThis script performs handwritten digit recognition on the MNIST dataset using a convolutional neural network (CNN) built with Keras. The pipeline begins by importing necessary libraries such as TensorFlow, Keras, and data handling tools like NumPy and Pandas. Two sets of training data are used: one from the Kaggle competition dataset (train.csv and test.csv) and another from the built-in Keras MNIST dataset. Both datasets are preprocessed by reshaping the images to 28x28x1 format and normalizing pixel values to the 0–1 range. The labels are one-hot encoded for categorical classification.\n\nNext, the script merges the Kaggle and Keras training sets to form a larger, more diverse dataset. A convolutional neural network is defined with three convolutional layers, each followed by batch normalization, dropout (to reduce overfitting), and max pooling. The network ends with a fully connected dense layer and a softmax layer that outputs class probabilities.\n\nThe model is first trained for 30 epochs on the merged 102,000-image dataset using a batch size of 2048. Its accuracy is evaluated on the original Keras test set of 10,000 images. After verifying good performance, the model is retrained on the combined training and test datasets (112,000 total samples) to maximize learning from all available data. Finally, predictions are made on the test dataset, and the results are formatted into a submission CSV file.","metadata":{}},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Import libraries**\n\nThis section sets up the necessary environment and tools for building a neural network. It imports libraries for numerical operations, data handling, and visualization. Warnings are suppressed to keep the output clean. TensorFlow is configured to run on the CPU by disabling GPU usage, and all non-critical log messages are hidden. Lastly, it imports essential modules from TensorFlow and Keras, including model-building tools, neural network layers, utilities for label encoding, and the built-in MNIST dataset.","metadata":{}},{"cell_type":"code","source":"# Import libraries\n\nimport os\nfrom operator import itemgetter    \nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings('ignore')\n\nos.environ['CUDA_VISIBLE_DEVICES'] = '-1' # Force CPU execution to avoid CUDA errors\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # Suppress TensorFlow CUDA warnings\n\nimport tensorflow as tf\nfrom keras import models, layers\nfrom keras.utils import to_categorical\nfrom keras.datasets import mnist","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-08T10:02:18.845736Z","iopub.execute_input":"2025-05-08T10:02:18.846042Z","iopub.status.idle":"2025-05-08T10:02:18.851844Z","shell.execute_reply.started":"2025-05-08T10:02:18.846017Z","shell.execute_reply":"2025-05-08T10:02:18.850686Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Load data**\n\nThis section loads the digit recognition dataset provided by Kaggle. It reads the training and test CSV files into Pandas DataFrames. From the training data, it separates the target labels (train_labelsKaggle) from the image pixel values (train_imagesKaggle). The test data (test_imagesKaggle) is copied as-is for future predictions.","metadata":{}},{"cell_type":"code","source":"# Load data\ntrainRaw = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')\ntestRaw = pd.read_csv('/kaggle/input/digit-recognizer/test.csv')\ntrain_labelsKaggle = trainRaw['label']\ntrain_imagesKaggle = trainRaw.drop(['label'], axis=1)\ntest_imagesKaggle = testRaw.copy()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T08:03:30.128592Z","iopub.execute_input":"2025-05-08T08:03:30.129721Z","iopub.status.idle":"2025-05-08T08:03:34.357895Z","shell.execute_reply.started":"2025-05-08T08:03:30.129692Z","shell.execute_reply":"2025-05-08T08:03:34.356727Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Reshape to 28x28 and normalize**\n\nThis section reshapes the Kaggle image data from flat 1D arrays to 28x28 pixel grayscale images with a single channel. It then normalizes the pixel values to the [0, 1] range by dividing by 255, which helps improve model training. Finally, it one-hot encodes the training labels to prepare them for categorical classification.","metadata":{}},{"cell_type":"code","source":"# Reshape to 28x28 and normalize\ntrain_imagesKaggle = train_imagesKaggle.values.reshape(-1, 28, 28, 1).astype('float32') / 255\ntest_imagesKaggle = test_imagesKaggle.values.reshape(-1, 28, 28, 1).astype('float32') / 255\ntrain_labelsKaggle = to_categorical(train_labelsKaggle)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T08:03:34.358661Z","iopub.execute_input":"2025-05-08T08:03:34.358944Z","iopub.status.idle":"2025-05-08T08:03:34.566567Z","shell.execute_reply.started":"2025-05-08T08:03:34.358918Z","shell.execute_reply":"2025-05-08T08:03:34.565345Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Load Keras MNIST data**\n\nThis section loads the original MNIST dataset provided by Keras, containing handwritten digit images and their labels. It reshapes both training and test images to 28x28 pixel format with a single channel, normalizes pixel values to the [0, 1] range, and applies one-hot encoding to the digit labels for use in classification.","metadata":{}},{"cell_type":"code","source":"# Load Keras MNIST data\n(train_imagesKeras, train_labelsKeras), (test_imagesKeras, test_labelsKeras) = mnist.load_data()\ntrain_imagesKeras = train_imagesKeras.reshape(-1, 28, 28, 1).astype('float32') / 255\ntest_imagesKeras = test_imagesKeras.reshape(-1, 28, 28, 1).astype('float32') / 255\ntrain_labelsKeras = to_categorical(train_labelsKeras)\ntest_labelsKeras = to_categorical(test_labelsKeras)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T08:03:34.568788Z","iopub.execute_input":"2025-05-08T08:03:34.569120Z","iopub.status.idle":"2025-05-08T08:03:36.087679Z","shell.execute_reply.started":"2025-05-08T08:03:34.569089Z","shell.execute_reply":"2025-05-08T08:03:36.085032Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Merge Kaggle + Keras train datasets**\n\nThis section merges the training data from the Keras MNIST dataset and the Kaggle dataset into a single training set by concatenating both the images and their corresponding one-hot encoded labels along the sample axis.","metadata":{}},{"cell_type":"code","source":"# Merge Kaggle + Keras train datasets\ntrain_images = np.concatenate((train_imagesKeras, train_imagesKaggle), axis=0)\ntrain_labels = np.concatenate((train_labelsKeras, train_labelsKaggle), axis=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T08:03:36.088772Z","iopub.execute_input":"2025-05-08T08:03:36.089157Z","iopub.status.idle":"2025-05-08T08:03:36.348777Z","shell.execute_reply.started":"2025-05-08T08:03:36.089100Z","shell.execute_reply":"2025-05-08T08:03:36.346730Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**CNN Model with BatchNormalization and reduced Dropout**\n\nThis section defines a Convolutional Neural Network (CNN) model using Keras' Sequential API. The model consists of three convolutional layers with ReLU activation, each followed by BatchNormalization and Dropout to improve training stability and reduce overfitting. MaxPooling layers reduce spatial dimensions after the first two convolutional layers. The final output is flattened and passed through a dense layer with 128 neurons before reaching the softmax output layer, which classifies the digits into one of 10 categories. The model is compiled using the Adam optimizer and categorical cross-entropy loss, with accuracy as the evaluation metric.","metadata":{}},{"cell_type":"code","source":"# CNN Model with BatchNormalization and reduced Dropout\n\ndef build_model():\n    model = models.Sequential()\n    model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))\n    model.add(layers.BatchNormalization())\n    model.add(layers.Dropout(0.3))\n    model.add(layers.MaxPooling2D((2, 2)))\n    model.add(layers.Conv2D(64, (3, 3), activation='relu'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.Dropout(0.3))\n    model.add(layers.MaxPooling2D((2, 2)))\n    model.add(layers.Conv2D(64, (3, 3), activation='relu'))\n    model.add(layers.BatchNormalization())\n    model.add(layers.Dropout(0.3))\n    model.add(layers.Flatten())\n    model.add(layers.Dense(128, activation='relu'))\n    model.add(layers.Dense(10, activation='softmax'))\n    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T08:03:36.351293Z","iopub.execute_input":"2025-05-08T08:03:36.351602Z","iopub.status.idle":"2025-05-08T08:03:36.364271Z","shell.execute_reply.started":"2025-05-08T08:03:36.351580Z","shell.execute_reply":"2025-05-08T08:03:36.363129Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Train model**\n\nThis section initializes the CNN model by calling the build_model() function and then trains it on the combined Kaggle and Keras MNIST training dataset. The model is trained for 30 epochs with a large batch size of 2048 to speed up training, and the verbose=1 argument ensures that training progress is printed during execution.","metadata":{}},{"cell_type":"code","source":"# Train model\nmodel = build_model()\nmodel.fit(train_images, train_labels, epochs=30, batch_size=2048, verbose=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T10:02:28.158861Z","iopub.execute_input":"2025-05-08T10:02:28.159173Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Evaluate on Keras test set**\n\nThis section evaluates the trained CNN model on the 10,000-image test set provided by Keras, which was not used during training. It prints the test accuracy as a four-decimal float, allowing you to assess the model’s generalization performance.","metadata":{}},{"cell_type":"code","source":"# Evaluate on Keras test set\ntest_loss, test_acc = model.evaluate(test_imagesKeras, test_labelsKeras, verbose=0)\nprint(f\"Test Accuracy on Keras test set: {test_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T09:00:23.767041Z","iopub.execute_input":"2025-05-08T09:00:23.767346Z","iopub.status.idle":"2025-05-08T09:00:26.337782Z","shell.execute_reply.started":"2025-05-08T09:00:23.767323Z","shell.execute_reply":"2025-05-08T09:00:26.336546Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Final model with all data**\n\nThis section retrains the model from scratch using the full dataset, including both the Kaggle and Keras training sets as well as the Keras test set. By combining all available labeled data (112,000 images in total), the model can potentially achieve better generalization on unseen digits. The new model is trained for 30 epochs with a batch size of 2048.","metadata":{}},{"cell_type":"code","source":"# Final model with all data\ntrain_imagesFin = np.concatenate((train_images, test_imagesKeras), axis=0)\ntrain_labelsFin = np.concatenate((train_labels, test_labelsKeras), axis=0)\nmodel = build_model()\nmodel.fit(train_imagesFin, train_labelsFin, epochs=30, batch_size=2048, verbose=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T09:00:26.338742Z","iopub.execute_input":"2025-05-08T09:00:26.339034Z","iopub.status.idle":"2025-05-08T10:00:12.112547Z","shell.execute_reply.started":"2025-05-08T09:00:26.339013Z","shell.execute_reply":"2025-05-08T10:00:12.111342Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Predict on test data**\n\nThis section generates predictions for the test dataset by passing it through the trained model. The output probabilities from the softmax layer are converted into final digit labels by selecting the index (digit) with the highest probability for each image.","metadata":{}},{"cell_type":"code","source":"# Predict on test data\ny_pred = np.argmax(model.predict(test_imagesKaggle), axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T10:00:12.115356Z","iopub.execute_input":"2025-05-08T10:00:12.115676Z","iopub.status.idle":"2025-05-08T10:00:19.482808Z","shell.execute_reply.started":"2025-05-08T10:00:12.115651Z","shell.execute_reply":"2025-05-08T10:00:19.481592Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<font color = \"DeepSkyBlue\">**Save submission**\n\nThis section prepares the final submission file for Kaggle. It loads the sample submission file, replaces the Label column with the model’s predictions, saves it as submission.csv, and displays the first few rows to verify the output format.","metadata":{}},{"cell_type":"code","source":"# Save submission\nsample_submission = pd.read_csv('/kaggle/input/digit-recognizer/sample_submission.csv')\nsample_submission['Label'] = y_pred\nsample_submission.to_csv('submission.csv', index=False)\nprint(sample_submission.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-08T10:01:10.178304Z","iopub.execute_input":"2025-05-08T10:01:10.178622Z","iopub.status.idle":"2025-05-08T10:01:10.254878Z","shell.execute_reply.started":"2025-05-08T10:01:10.178596Z","shell.execute_reply":"2025-05-08T10:01:10.253952Z"}},"outputs":[],"execution_count":null}]}