{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":31090,"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)\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset, random_split\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-08-21T09:07:26.281536Z","iopub.execute_input":"2025-08-21T09:07:26.281796Z","iopub.status.idle":"2025-08-21T09:07:31.909809Z","shell.execute_reply.started":"2025-08-21T09:07:26.281777Z","shell.execute_reply":"2025-08-21T09:07:31.909078Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:36.096147Z","iopub.execute_input":"2025-08-21T09:07:36.096546Z","iopub.status.idle":"2025-08-21T09:07:38.692200Z","shell.execute_reply.started":"2025-08-21T09:07:36.096525Z","shell.execute_reply":"2025-08-21T09:07:38.691365Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:41.673442Z","iopub.execute_input":"2025-08-21T09:07:41.673710Z","iopub.status.idle":"2025-08-21T09:07:41.699454Z","shell.execute_reply.started":"2025-08-21T09:07:41.673691Z","shell.execute_reply":"2025-08-21T09:07:41.698904Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:44.656045Z","iopub.execute_input":"2025-08-21T09:07:44.656286Z","iopub.status.idle":"2025-08-21T09:07:46.182575Z","shell.execute_reply.started":"2025-08-21T09:07:44.656269Z","shell.execute_reply":"2025-08-21T09:07:46.182006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:48.177709Z","iopub.execute_input":"2025-08-21T09:07:48.178204Z","iopub.status.idle":"2025-08-21T09:07:48.189450Z","shell.execute_reply.started":"2025-08-21T09:07:48.178180Z","shell.execute_reply":"2025-08-21T09:07:48.188909Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(train.iloc[0,1:].values.reshape(28,28), cmap='gray')\nplt.title(f\"Label: {train.iloc[0,0]}\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:51.012646Z","iopub.execute_input":"2025-08-21T09:07:51.013148Z","iopub.status.idle":"2025-08-21T09:07:51.260200Z","shell.execute_reply.started":"2025-08-21T09:07:51.013123Z","shell.execute_reply":"2025-08-21T09:07:51.259454Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train.iloc[:, 1:].values.reshape(-1, 1, 28, 28) / 255.0  # Normalize and reshape\ny = train.iloc[:, 0].values","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:54.693668Z","iopub.execute_input":"2025-08-21T09:07:54.694349Z","iopub.status.idle":"2025-08-21T09:07:54.810597Z","shell.execute_reply.started":"2025-08-21T09:07:54.694314Z","shell.execute_reply":"2025-08-21T09:07:54.809829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_test = test.values.reshape(-1, 1, 28, 28) / 255.0  # Test data (no labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:07:57.816669Z","iopub.execute_input":"2025-08-21T09:07:57.817274Z","iopub.status.idle":"2025-08-21T09:07:57.891307Z","shell.execute_reply.started":"2025-08-21T09:07:57.817250Z","shell.execute_reply":"2025-08-21T09:07:57.890653Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = torch.tensor(X, dtype=torch.float32)\ny = torch.tensor(y, dtype=torch.long)\nX_test = torch.tensor(X_test, dtype=torch.float32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:00.081540Z","iopub.execute_input":"2025-08-21T09:08:00.082237Z","iopub.status.idle":"2025-08-21T09:08:00.239482Z","shell.execute_reply.started":"2025-08-21T09:08:00.082213Z","shell.execute_reply":"2025-08-21T09:08:00.238744Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DigitDataset(Dataset):\n    def __init__(self, X, y=None):\n        self.X = X\n        self.y = y\n    \n    def __len__(self):\n        return len(self.X)\n    \n    def __getitem__(self, idx):\n        if self.y is not None:\n            return self.X[idx], self.y[idx]\n        else:\n            return self.X[idx]\n\ndataset = DigitDataset(X, y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:02.567490Z","iopub.execute_input":"2025-08-21T09:08:02.567781Z","iopub.status.idle":"2025-08-21T09:08:02.572746Z","shell.execute_reply.started":"2025-08-21T09:08:02.567761Z","shell.execute_reply":"2025-08-21T09:08:02.572129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Split train/val\ntrain_size = int(0.8 * len(dataset))\nval_size = len(dataset) - train_size\ntrain_dataset, val_dataset = random_split(dataset, [train_size, val_size])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:05.486581Z","iopub.execute_input":"2025-08-21T09:08:05.487130Z","iopub.status.idle":"2025-08-21T09:08:05.506835Z","shell.execute_reply.started":"2025-08-21T09:08:05.487106Z","shell.execute_reply":"2025-08-21T09:08:05.506300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)\ntest_loader = DataLoader(DigitDataset(X_test), batch_size=64, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:09.739428Z","iopub.execute_input":"2025-08-21T09:08:09.740124Z","iopub.status.idle":"2025-08-21T09:08:09.743967Z","shell.execute_reply.started":"2025-08-21T09:08:09.740098Z","shell.execute_reply":"2025-08-21T09:08:09.743369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n        self.conv_layers = nn.Sequential(\n            nn.Conv2d(1, 32, kernel_size=3, padding=1),  \n            nn.ReLU(),\n            nn.MaxPool2d(2, 2),   # 14x14\n\n            nn.Conv2d(32, 64, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2, 2)    # 7x7\n        )\n        self.fc_layers = nn.Sequential(\n            nn.Flatten(),\n            nn.Linear(64*7*7, 128),\n            nn.ReLU(),\n            nn.Dropout(0.3),\n            nn.Linear(128, 10)   # 10 classes (digits 0–9)\n        )\n    \n    def forward(self, x):\n        x = self.conv_layers(x)\n        x = self.fc_layers(x)\n        return x\n\nmodel = CNN()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:12.360436Z","iopub.execute_input":"2025-08-21T09:08:12.361179Z","iopub.status.idle":"2025-08-21T09:08:12.380127Z","shell.execute_reply.started":"2025-08-21T09:08:12.361153Z","shell.execute_reply":"2025-08-21T09:08:12.379482Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:08:15.872623Z","iopub.execute_input":"2025-08-21T09:08:15.873357Z","iopub.status.idle":"2025-08-21T09:08:18.640762Z","shell.execute_reply.started":"2025-08-21T09:08:15.873331Z","shell.execute_reply":"2025-08-21T09:08:18.640003Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 5\nfor epoch in range(epochs):\n    model.train()\n    train_loss, correct, total = 0, 0, 0\n    \n    for images, labels in train_loader:\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        \n        train_loss += loss.item()\n        _, predicted = outputs.max(1)\n        total += labels.size(0)\n        correct += predicted.eq(labels).sum().item()\n    \n    val_loss, val_correct, val_total = 0, 0, 0\n    model.eval()\n    with torch.no_grad():\n        for images, labels in val_loader:\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            val_loss += loss.item()\n            _, predicted = outputs.max(1)\n            val_total += labels.size(0)\n            val_correct += predicted.eq(labels).sum().item()\n    \n    print(f\"Epoch {epoch+1}/{epochs} | \"\n          f\"Train Loss: {train_loss/len(train_loader):.4f}, \"\n          f\"Train Acc: {100*correct/total:.2f}% | \"\n          f\"Val Loss: {val_loss/len(val_loader):.4f}, \"\n          f\"Val Acc: {100*val_correct/val_total:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:23:05.916515Z","iopub.execute_input":"2025-08-21T09:23:05.917201Z","iopub.status.idle":"2025-08-21T09:24:18.390310Z","shell.execute_reply.started":"2025-08-21T09:23:05.917175Z","shell.execute_reply":"2025-08-21T09:24:18.389558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\npredictions = []\nwith torch.no_grad():\n    for images in test_loader:\n        outputs = model(images)\n        _, predicted = outputs.max(1)\n        predictions.extend(predicted.cpu().numpy())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:24:26.167294Z","iopub.execute_input":"2025-08-21T09:24:26.168006Z","iopub.status.idle":"2025-08-21T09:24:30.570678Z","shell.execute_reply.started":"2025-08-21T09:24:26.167979Z","shell.execute_reply":"2025-08-21T09:24:30.570009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"ImageId\": np.arange(1, len(predictions)+1),\n    \"Label\": predictions\n})\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"Submission file saved as submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-21T09:24:33.872489Z","iopub.execute_input":"2025-08-21T09:24:33.872787Z","iopub.status.idle":"2025-08-21T09:24:33.948801Z","shell.execute_reply.started":"2025-08-21T09:24:33.872765Z","shell.execute_reply":"2025-08-21T09:24:33.948227Z"}},"outputs":[],"execution_count":null}]}