{"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":false,"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-08-29T10:22:56.450546Z","iopub.execute_input":"2025-08-29T10:22:56.450829Z","iopub.status.idle":"2025-08-29T10:22:58.807951Z","shell.execute_reply.started":"2025-08-29T10:22:56.450781Z","shell.execute_reply":"2025-08-29T10:22:58.807005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install datasets torch lightning gradio torchinfo","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:22:58.809933Z","iopub.execute_input":"2025-08-29T10:22:58.810357Z","iopub.status.idle":"2025-08-29T10:26:21.323405Z","shell.execute_reply.started":"2025-08-29T10:22:58.810335Z","shell.execute_reply":"2025-08-29T10:26:21.322504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset, DataLoader\nimport pandas as pd\n\nclass CustomDataset(Dataset):\n    def __init__(self):\n        self.training_dataframe = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\n        # Fix dataframe variable name and normalize images\n        self.images = self.training_dataframe.iloc[:, 1:].values.reshape(-1, 28, 28) / 255.0\n        self.labels = self.training_dataframe.iloc[:, 0].values\n\n    def __getitem__(self, index):\n        image = self.images[index]\n        label = self.labels[index]\n        # Convert image to torch tensor, add channel dimension (1, 28, 28)\n        image = torch.tensor(image, dtype=torch.float32).unsqueeze(0)\n        label = torch.tensor(label, dtype=torch.long)\n        return image, label\n        \n    def __len__(self):\n        return len(self.labels)\n\ncustom_dataset = CustomDataset()\ncustom_dataloader = DataLoader(custom_dataset, batch_size=64, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:27:55.798918Z","iopub.execute_input":"2025-08-29T10:27:55.799221Z","iopub.status.idle":"2025-08-29T10:27:58.15907Z","shell.execute_reply.started":"2025-08-29T10:27:55.799191Z","shell.execute_reply":"2025-08-29T10:27:58.158289Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:28:04.234995Z","iopub.execute_input":"2025-08-29T10:28:04.235295Z","iopub.status.idle":"2025-08-29T10:28:04.239377Z","shell.execute_reply.started":"2025-08-29T10:28:04.235273Z","shell.execute_reply":"2025-08-29T10:28:04.238584Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\"\"\"validation_dataset        = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\ncustom_validation_dataset = CustomDataset(validation_dataset)\nvalidation_dataloader     = torch.utils.data.DataLoader(custom_validation_dataset, batch_size = 32, shuffle= True)\"\"\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:28:18.301526Z","iopub.execute_input":"2025-08-29T10:28:18.30216Z","iopub.status.idle":"2025-08-29T10:28:19.772552Z","shell.execute_reply.started":"2025-08-29T10:28:18.30213Z","shell.execute_reply":"2025-08-29T10:28:19.771455Z"}},"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-08-29T10:29:00.526468Z","iopub.execute_input":"2025-08-29T10:29:00.526844Z","iopub.status.idle":"2025-08-29T10:29:00.562777Z","shell.execute_reply.started":"2025-08-29T10:29:00.526787Z","shell.execute_reply":"2025-08-29T10:29:00.561854Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"import torch.optim as optim","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:29:10.838499Z","iopub.execute_input":"2025-08-29T10:29:10.83885Z","iopub.status.idle":"2025-08-29T10:29:10.843775Z","shell.execute_reply.started":"2025-08-29T10:29:10.83878Z","shell.execute_reply":"2025-08-29T10:29:10.84259Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss()                   # good for classification\noptimizer = optim.Adam(model.parameters(), lr=0.001) # Adam usually works well","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:29:13.294162Z","iopub.execute_input":"2025-08-29T10:29:13.294951Z","iopub.status.idle":"2025-08-29T10:29:16.542579Z","shell.execute_reply.started":"2025-08-29T10:29:13.294921Z","shell.execute_reply":"2025-08-29T10:29:16.541944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 50\n\nfor epoch in range(epochs):\n    model.train()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n    \n    for images, labels in custom_dataloader:\n        images, labels = images.to(device), labels.to(device)\n        \n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        running_loss += loss.item()\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n    \n    acc = 100 * correct / total\n    print(f\"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(custom_dataloader):.4f}, Accuracy: {acc:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:29:21.582557Z","iopub.execute_input":"2025-08-29T10:29:21.583036Z","iopub.status.idle":"2025-08-29T10:31:32.549725Z","shell.execute_reply.started":"2025-08-29T10:29:21.583011Z","shell.execute_reply":"2025-08-29T10:31:32.548819Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\ncorrect = 0\ntotal = 0\nwith torch.no_grad():\n    for images, labels in custom_dataloader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\nprint(f\"Final Training Accuracy: {100 * correct / total:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:31:37.223893Z","iopub.execute_input":"2025-08-29T10:31:37.224199Z","iopub.status.idle":"2025-08-29T10:31:38.948339Z","shell.execute_reply.started":"2025-08-29T10:31:37.22418Z","shell.execute_reply":"2025-08-29T10:31:38.947157Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_test = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\n\ntest_tensors = torch.tensor(df_test.to_numpy(), dtype=torch.float32).reshape(-1,1*28*28) / 255.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:31:45.024246Z","iopub.execute_input":"2025-08-29T10:31:45.024542Z","iopub.status.idle":"2025-08-29T10:31:46.502323Z","shell.execute_reply.started":"2025-08-29T10:31:45.024523Z","shell.execute_reply":"2025-08-29T10:31:46.50152Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\ntest_tensors = test_tensors.to(device)\nmodel.eval","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:31:49.559322Z","iopub.execute_input":"2025-08-29T10:31:49.559947Z","iopub.status.idle":"2025-08-29T10:31:49.568309Z","shell.execute_reply.started":"2025-08-29T10:31:49.559916Z","shell.execute_reply":"2025-08-29T10:31:49.567301Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with torch.no_grad():\n    outputs = model(test_tensors)\n    predicted_labels = torch.argmax(outputs, dim=1) \nsubmission = pd.DataFrame({\n    'ImageId': torch.arange(1, len(predicted_labels)+1).cpu().numpy(), \n    'Label': predicted_labels.cpu().numpy()                              \n})\n\nsubmission.to_csv('submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-29T10:31:54.863395Z","iopub.execute_input":"2025-08-29T10:31:54.864053Z","iopub.status.idle":"2025-08-29T10:31:54.921121Z","shell.execute_reply.started":"2025-08-29T10:31:54.864027Z","shell.execute_reply":"2025-08-29T10:31:54.920253Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}