{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","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":31089,"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)\nimport torch, torchvision, torchinfo\nimport torch.nn as nn\nimport torch.optim as optim\nimport datasets as huggingface_datasets\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-12-20T12:54:00.575913Z","iopub.execute_input":"2025-12-20T12:54:00.576733Z","iopub.status.idle":"2025-12-20T12:54:05.090253Z","shell.execute_reply.started":"2025-12-20T12:54:00.576699Z","shell.execute_reply":"2025-12-20T12:54:05.089342Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"training_dataframe = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\n#training_data = huggingface_datasets.load_dataset(\"mnist\",split=\"train\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:05.091510Z","iopub.execute_input":"2025-12-20T12:54:05.091874Z","iopub.status.idle":"2025-12-20T12:54:07.580423Z","shell.execute_reply.started":"2025-12-20T12:54:05.091852Z","shell.execute_reply":"2025-12-20T12:54:07.579542Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Digit_Data_Loader(torch.utils.data.Dataset):\n\n    def __init__(self,dataset):\n        self.training_dataframe = dataset\n        self.data_transformations = torchvision.transforms.Compose([\n            torchvision.transforms.ToTensor()\n        ])\n\n    def __getitem__(self,index):\n        row = self.training_dataframe.iloc[index]   # get the row at this index\n        label = row['label']                        # labels column\n        image = row.drop('label').values.astype(np.uint8).reshape(28,28)  # rest of row is pixel values\n        image_tensor = self.data_transformations(image)\n        return image_tensor, label\n\n\n\n    def __len__(self):\n        return len(self.training_dataframe)\n\n\ncustom_dataset = Digit_Data_Loader(training_dataframe)\ncutom_dataloader = torch.utils.data.DataLoader(custom_dataset,batch_size = 32, shuffle= True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:07.581706Z","iopub.execute_input":"2025-12-20T12:54:07.582157Z","iopub.status.idle":"2025-12-20T12:54:07.589743Z","shell.execute_reply.started":"2025-12-20T12:54:07.582121Z","shell.execute_reply":"2025-12-20T12:54:07.588192Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dataset        = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ncustom_test_dataset = Digit_Data_Loader(test_dataset)\ntest_dataloader     = torch.utils.data.DataLoader(custom_test_dataset, batch_size = 32, shuffle= True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:07.592308Z","iopub.execute_input":"2025-12-20T12:54:07.592621Z","iopub.status.idle":"2025-12-20T12:54:09.848932Z","shell.execute_reply.started":"2025-12-20T12:54:07.592599Z","shell.execute_reply":"2025-12-20T12:54:09.848014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_random_parameters = torch.nn.Sequential(\n    \n    torch.nn.Flatten(start_dim=1),         # Dim:BCHW -> (0:B , 1:C, 2:H, 3:W)\n\n    torch.nn.Linear(in_features = 28*28*1  , out_features   = 40   ), torch.nn.ReLU(),                 # LAYER 1: 1st Hidden Layer\n    torch.nn.Linear(in_features = 40       , out_features = 30     ), torch.nn.ReLU(),                 # LAYER 2: 2nd Hidden Layer\n\n    torch.nn.Linear(in_features = 30       , out_features = 10   ),                                  # OUTPUT LAYER\n)\n\nmodel = model_random_parameters\n\ntorchinfo.summary(model, input_size= (1,1*28*28), verbose=2);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:09.849860Z","iopub.execute_input":"2025-12-20T12:54:09.850159Z","iopub.status.idle":"2025-12-20T12:54:09.888662Z","shell.execute_reply.started":"2025-12-20T12:54:09.850132Z","shell.execute_reply":"2025-12-20T12:54:09.887694Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define loss function (CrossEntropy is good for classification)\nloss_function = nn.CrossEntropyLoss()\n\n# Define optimizer (SGD is simple; Adam is often better)\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\n# Number of times to go through the full dataset\nepochs = 5  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:09.889647Z","iopub.execute_input":"2025-12-20T12:54:09.889982Z","iopub.status.idle":"2025-12-20T12:54:09.896320Z","shell.execute_reply.started":"2025-12-20T12:54:09.889955Z","shell.execute_reply":"2025-12-20T12:54:09.895131Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training loop\nfor epoch in range(epochs):\n    print(f\"Epoch {epoch+1}/{epochs}\")\n\n    # Keep track of total loss for monitoring\n    total_loss = 0  \n\n    for images, labels in cutom_dataloader:\n        # Flatten images if they are not already in correct shape\n        # images shape should be [batch_size, 1, 28, 28]\n        images = images.view(-1, 1, 28, 28).float()\n\n        # 1. Forward pass: get predictions from the model\n        outputs = model(images)\n\n        # 2. Compute the loss\n        loss = loss_function(outputs, labels)\n\n        # 3. Backward pass: reset gradients, calculate new gradients\n        optimizer.zero_grad()\n        loss.backward()\n\n        # 4. Update weights\n        optimizer.step()\n\n        # Add current loss to total\n        total_loss += loss.item()\n\n    # Print average loss for this epoch\n    print(f\"Average Loss: {total_loss/len(cutom_dataloader):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:54:09.897345Z","iopub.execute_input":"2025-12-20T12:54:09.897645Z","iopub.status.idle":"2025-12-20T12:56:07.000496Z","shell.execute_reply.started":"2025-12-20T12:54:09.897617Z","shell.execute_reply":"2025-12-20T12:56:06.999392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def evaluate_model(model, dataloader):\n    model.eval()  # set to evaluation mode\n    correct = 0\n    total = 0\n\n    with torch.no_grad():  # no gradient tracking\n        for images, labels in dataloader:\n            images = images.view(-1, 1, 28, 28).float()\n\n            outputs = model(images)                 # predictions (logits)\n            _, predicted = torch.max(outputs, 1)    # index of highest score\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n\n    accuracy = 100 * correct / total\n    return accuracy","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:56:07.001561Z","iopub.execute_input":"2025-12-20T12:56:07.001930Z","iopub.status.idle":"2025-12-20T12:56:07.008015Z","shell.execute_reply.started":"2025-12-20T12:56:07.001900Z","shell.execute_reply":"2025-12-20T12:56:07.007187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy = evaluate_model(model,test_dataloader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:56:07.009275Z","iopub.execute_input":"2025-12-20T12:56:07.009537Z","iopub.status.idle":"2025-12-20T12:56:28.175224Z","shell.execute_reply.started":"2025-12-20T12:56:07.009508Z","shell.execute_reply":"2025-12-20T12:56:28.174455Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(accuracy)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:56:28.177328Z","iopub.execute_input":"2025-12-20T12:56:28.177908Z","iopub.status.idle":"2025-12-20T12:56:28.182439Z","shell.execute_reply.started":"2025-12-20T12:56:28.177879Z","shell.execute_reply":"2025-12-20T12:56:28.181607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport torch, torchvision\n\n# Load test.csv\ndf = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\n\n# Convert to tensor: (num_samples, 1, 28, 28) and normalize to [0,1]\ntensors = torch.tensor(df.to_numpy(), dtype=torch.float32).reshape(-1, 1, 28, 28) / 255.0\n\n# Switch model to eval mode\nmodel.eval()\n\n# Disable gradient tracking\nwith torch.no_grad():\n    y_prediction_logits = model(tensors)\n    y_labels_predicted = torch.argmax(y_prediction_logits, dim=1)\n\n# Build submission DataFrame\nsubmission = pd.DataFrame({\n    'ImageId': torch.arange(1, len(y_labels_predicted) + 1).cpu().numpy(),\n    'Label': y_labels_predicted.cpu().numpy()\n})\n\n# Save to CSV\nsubmission.to_csv('submission.csv', index=False)\nprint(\"✅ submission.csv created successfully!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:56:28.183328Z","iopub.execute_input":"2025-12-20T12:56:28.183645Z","iopub.status.idle":"2025-12-20T12:56:29.891484Z","shell.execute_reply.started":"2025-12-20T12:56:28.183616Z","shell.execute_reply":"2025-12-20T12:56:29.890536Z"}},"outputs":[],"execution_count":null}]}