{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":30822,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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-05T20:59:58.584354Z","iopub.execute_input":"2025-01-05T20:59:58.584679Z","iopub.status.idle":"2025-01-05T20:59:58.591869Z","shell.execute_reply.started":"2025-01-05T20:59:58.584654Z","shell.execute_reply":"2025-01-05T20:59:58.591127Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport torch\n\ndata_path_train = \"/kaggle/input/digit-recognizer/train.csv\"\ntrain_data = pd.read_csv(data_path_train)\ntrain_data.head(10)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:59:58.593004Z","iopub.execute_input":"2025-01-05T20:59:58.593222Z","iopub.status.idle":"2025-01-05T21:00:00.284695Z","shell.execute_reply.started":"2025-01-05T20:59:58.593204Z","shell.execute_reply":"2025-01-05T21:00:00.283807Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_path_test = \"/kaggle/input/digit-recognizer/test.csv\"\ntest_data = pd.read_csv(data_path_test)\ntest_data.head(10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:00.286175Z","iopub.execute_input":"2025-01-05T21:00:00.286426Z","iopub.status.idle":"2025-01-05T21:00:01.350448Z","shell.execute_reply.started":"2025-01-05T21:00:00.286406Z","shell.execute_reply":"2025-01-05T21:00:01.349576Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.351980Z","iopub.execute_input":"2025-01-05T21:00:01.352308Z","iopub.status.idle":"2025-01-05T21:00:01.357029Z","shell.execute_reply.started":"2025-01-05T21:00:01.352279Z","shell.execute_reply":"2025-01-05T21:00:01.356231Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.357958Z","iopub.execute_input":"2025-01-05T21:00:01.358199Z","iopub.status.idle":"2025-01-05T21:00:01.371847Z","shell.execute_reply.started":"2025-01-05T21:00:01.358181Z","shell.execute_reply":"2025-01-05T21:00:01.371188Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\n# Ensure correct number of columns\nX_train = train_data.iloc[:, 1:].values  # All rows, columns from 1 to 784 (features)\ny_train = train_data.iloc[:, 0].values  # All rows, column 0 (labels)\n\nX_test = test_data.iloc[:, :784].values  # Ensure only the first 784 columns\ny_test = test_data.iloc[:, 0].values  # Labels (if available)\n\n# Convert to PyTorch tensors and reshape\nX_train_tensor = torch.tensor(X_train, dtype=torch.float32).view(-1, 1, 28, 28)\ny_train_tensor = torch.tensor(y_train, dtype=torch.long)\n\nX_test_tensor = torch.tensor(X_test, dtype=torch.float32).view(-1, 1, 28, 28)\ny_test_tensor = torch.tensor(y_test, dtype=torch.long)\n\n# Normalize pixel values\nX_train_tensor /= 255.0\nX_test_tensor /= 255.0\n\n# Create TensorDataset\ntrain_data = torch.utils.data.TensorDataset(X_train_tensor, y_train_tensor)\ntest_data = torch.utils.data.TensorDataset(X_test_tensor, y_test_tensor)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.372640Z","iopub.execute_input":"2025-01-05T21:00:01.372906Z","iopub.status.idle":"2025-01-05T21:00:01.507330Z","shell.execute_reply.started":"2025-01-05T21:00:01.372875Z","shell.execute_reply":"2025-01-05T21:00:01.506275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\nloaders = {\n    'train': DataLoader(\n        train_data,\n        batch_size=100,\n        shuffle=True,\n        num_workers=0,\n    ),\n\n    'test':DataLoader(\n        test_data,\n        batch_size=100,\n        shuffle=False,\n        num_workers=0,\n            \n        \n    )\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.508244Z","iopub.execute_input":"2025-01-05T21:00:01.508486Z","iopub.status.idle":"2025-01-05T21:00:01.513232Z","shell.execute_reply.started":"2025-01-05T21:00:01.508466Z","shell.execute_reply":"2025-01-05T21:00:01.512271Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loaders","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.515928Z","iopub.execute_input":"2025-01-05T21:00:01.516151Z","iopub.status.idle":"2025-01-05T21:00:01.532104Z","shell.execute_reply.started":"2025-01-05T21:00:01.516131Z","shell.execute_reply":"2025-01-05T21:00:01.531289Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.533546Z","iopub.execute_input":"2025-01-05T21:00:01.533884Z","iopub.status.idle":"2025-01-05T21:00:01.546241Z","shell.execute_reply.started":"2025-01-05T21:00:01.533852Z","shell.execute_reply":"2025-01-05T21:00:01.545524Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"(a) Input: raw pixel values are provided as input. \n(b) Convolutional layer: Input layers translates the results of neuron layer. There is a need to specify the filter to be used. Each filter can only be a 5*5 window that will slide over input data and get pixels with maximum intensities. \n(c) Rectified linear unit [ReLU] layer: provided activation function on the data taken as an image. In the case of backpropagation, ReLU function is used which prevents the values of pixels form changing. \n(d) Pooling layer: Performs a down-sampling operation in volume along the dimensions (width, height). \n(e) Fully connected layer: score class is focused, and a maximum score of the input digits is found\n\nFound in a paper named : Handwritten digit classification using Convolutional Neural Networks","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F\n\nclass CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n#         # First convolutional layer: \n#         # Takes input with 1 channel (grayscale image) and outputs 10 feature maps, \n#         # using a 5x5 kernel to process the input\n        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)  # Input: 1x28x28, Output: 10x24x24 using formula (input_size - 2* (kernel) / padding )+ 1\n#         # Second convolutional layer: \n#         # Takes 10 feature maps from the previous layer and outputs 20 feature maps\n        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)  # Input: 10x24x24, Output: 20x20x20\n\n        \n#         # Dropout layer: Randomly zeroes some of the features during training \n#         # to prevent overfitting and improve generalization\n        self.conv2_drop = nn.Dropout2d()\n        \n#         # Fully connected layer 1: \n#         # Flattens the output from the convolutional layers to 320 features, \n#         # then reduces it to 50 features\n#         # the reason to 320 is : \n        self.fc1 = nn.Linear(20 * 4 * 4, 50) \n#         # Fully connected layer 2:\n#         # Reduces the 50 features down to 10 (for classification into 10 classes)\n        self.fc2 = nn.Linear(50, 10)  # Output layer with 10 units for 10 classes (digits 0-9)\n#   \n\n    \n    def forward(self, x):\n        x = F.relu(self.conv1(x))  # Output: 10x24x24\n        x = F.max_pool2d(x, 2)     # Max pooling: 10x12x12\n        x = F.relu(self.conv2(x))  # Output: 20x8x8\n        x = F.max_pool2d(x, 2)     # Max pooling: 20x4x4\n        x = self.conv2_drop(x)     # Apply dropout\n        x = x.view(x.size(0), -1)  # Flatten the tensor for fully connected layers\n        x = F.relu(self.fc1(x))    # Fully connected layer\n        x = self.fc2(x)            # Output layer (no softmax because it's handled by CrossEntropyLoss)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.546977Z","iopub.execute_input":"2025-01-05T21:00:01.547175Z","iopub.status.idle":"2025-01-05T21:00:01.562619Z","shell.execute_reply.started":"2025-01-05T21:00:01.547159Z","shell.execute_reply":"2025-01-05T21:00:01.561831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch \ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = CNN().to(device)\noptimizer = optim.Adam(model.parameters(), lr=0.005)\nloss_fn= nn.CrossEntropyLoss()\n\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.563365Z","iopub.execute_input":"2025-01-05T21:00:01.563589Z","iopub.status.idle":"2025-01-05T21:00:01.579730Z","shell.execute_reply.started":"2025-01-05T21:00:01.563571Z","shell.execute_reply":"2025-01-05T21:00:01.579046Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train(epoch):\n    model.train()\n    for batch_idx, (data, target) in enumerate(loaders['train']):\n        # Reshape input\n        data = data.view(-1, 1, 28, 28)  # Reshape to (batch_size, 1, 28, 28)\n        data, target = data.to(device), target.to(device)\n        \n        optimizer.zero_grad()\n        output = model(data)\n        loss = loss_fn(output, target)\n        loss.backward()  # Backpropagation\n        optimizer.step()  # Update parameters\n        \n        if batch_idx % 20 == 0:\n            print(f\"Train Epoch: {epoch} [{batch_idx * len(data)}/{len(loaders['train'].dataset)} \"\n                  f\"({100. * batch_idx / len(loaders['train']):.0f}%)]\\tLoss: {loss.item():.6f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.580523Z","iopub.execute_input":"2025-01-05T21:00:01.580731Z","iopub.status.idle":"2025-01-05T21:00:01.594634Z","shell.execute_reply.started":"2025-01-05T21:00:01.580706Z","shell.execute_reply":"2025-01-05T21:00:01.593839Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ndef test():\n    model.eval()\n    test_loss = 0\n    correct = 0\n    with torch.no_grad():\n        for data, target in loaders['test']:\n            data, target = data.to(device), target.to(device)\n            output = model(data)\n            test_loss += loss_fn(output, target).item()\n            pred = output.argmax(dim=1, keepdim=True)\n            correct += pred.eq(target.view_as(pred)).sum().item()\n\n    test_loss /= len(loaders['test'].dataset)\n    accuracy = 100. * correct / len(loaders['test'].dataset)\n    print(f\"\\nTest set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(loaders['test'].dataset)} \"\n          f\"({accuracy:.0f}%)\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.595350Z","iopub.execute_input":"2025-01-05T21:00:01.595548Z","iopub.status.idle":"2025-01-05T21:00:01.608538Z","shell.execute_reply.started":"2025-01-05T21:00:01.595513Z","shell.execute_reply":"2025-01-05T21:00:01.607805Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for epoch in range(1, 11):\n    train(epoch)\n    test()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:01.609447Z","iopub.execute_input":"2025-01-05T21:00:01.609726Z","iopub.status.idle":"2025-01-05T21:00:24.402612Z","shell.execute_reply.started":"2025-01-05T21:00:01.609699Z","shell.execute_reply":"2025-01-05T21:00:24.401722Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def generate_submission(model, test_loader, output_file=\"submission.csv\"):\n    \"\"\"\n    Generate predictions for the test set and save them in a CSV file for Kaggle submission.\n    Parameters:\n        model (torch.nn.Module): Trained PyTorch model.\n        test_loader (DataLoader): DataLoader for the test dataset.\n        output_file (str): Name of the output CSV file.\n    \"\"\"\n    model.eval()  # Set the model to evaluation mode\n    predictions = []\n    \n    with torch.no_grad():\n        for data, _ in test_loader:  # DataLoader returns (data, _), but labels are not needed\n            data = data.to(device)\n            output = model(data)\n            preds = output.argmax(dim=1, keepdim=False)  # Get the predicted class\n            predictions.extend(preds.cpu().numpy())  # Move predictions to CPU and store them\n\n    # Create the submission DataFrame\n    submission = pd.DataFrame({\n        \"ImageId\": range(1, len(predictions) + 1),  # Image IDs start at 1\n        \"Label\": predictions  # Predicted labels\n    })\n\n    submission.to_csv(output_file, index=False)  # Save submission file\n    print(f\"Submission file saved as {output_file}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:24.403542Z","iopub.execute_input":"2025-01-05T21:00:24.403866Z","iopub.status.idle":"2025-01-05T21:00:24.409204Z","shell.execute_reply.started":"2025-01-05T21:00:24.403834Z","shell.execute_reply":"2025-01-05T21:00:24.408393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"generate_submission(model, loaders['test'], \"submission.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:00:24.409911Z","iopub.execute_input":"2025-01-05T21:00:24.410095Z","iopub.status.idle":"2025-01-05T21:00:24.975400Z","shell.execute_reply.started":"2025-01-05T21:00:24.410079Z","shell.execute_reply":"2025-01-05T21:00:24.974703Z"}},"outputs":[],"execution_count":null}]}