{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":16017,"databundleVersionId":708189,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 1. Import library","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as transforms\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import DataLoader, Dataset","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-26T06:57:01.198744Z","iopub.execute_input":"2024-06-26T06:57:01.199553Z","iopub.status.idle":"2024-06-26T06:57:06.124647Z","shell.execute_reply.started":"2024-06-26T06:57:01.199518Z","shell.execute_reply":"2024-06-26T06:57:06.123833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:14.039492Z","iopub.execute_input":"2024-06-26T06:57:14.039854Z","iopub.status.idle":"2024-06-26T06:57:14.045952Z","shell.execute_reply.started":"2024-06-26T06:57:14.039826Z","shell.execute_reply":"2024-06-26T06:57:14.045102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Define hyperparameters","metadata":{}},{"cell_type":"code","source":"num_epochs = 60\nbatch_size = 20\nnum_workers = 0\nlearning_rate = 0.01\n\nnum_outputs = 10\n\nhidden_size = 256\ninput_size = 28 * 28","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:16.991694Z","iopub.execute_input":"2024-06-26T06:57:16.992367Z","iopub.status.idle":"2024-06-26T06:57:16.996992Z","shell.execute_reply.started":"2024-06-26T06:57:16.992335Z","shell.execute_reply":"2024-06-26T06:57:16.995947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3 Define custom dataset","metadata":{}},{"cell_type":"code","source":"class KannadaMNIST(Dataset):\n    \n    def __init__(self, path, transforms=None):\n        super().__init__()\n        self.data = pd.read_csv(path)\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        images = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((28, 28, 1))\n        labels = self.data.iloc[index, 0]\n        \n        if self.transforms is not None:\n            images = self.transforms(images)\n#             labels = self.transforms(labels)\n        \n        return images, labels\n    \ntrain_dataset = KannadaMNIST(path='/kaggle/input/Kannada-MNIST/train.csv', transforms=transforms.ToTensor())\n","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:20.452460Z","iopub.execute_input":"2024-06-26T06:57:20.452826Z","iopub.status.idle":"2024-06-26T06:57:24.725824Z","shell.execute_reply.started":"2024-06-26T06:57:20.452783Z","shell.execute_reply":"2024-06-26T06:57:24.724568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_loader = DataLoader(train_dataset, shuffle=True, num_workers=num_workers, batch_size=batch_size)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:24.728034Z","iopub.execute_input":"2024-06-26T06:57:24.728426Z","iopub.status.idle":"2024-06-26T06:57:24.733259Z","shell.execute_reply.started":"2024-06-26T06:57:24.728392Z","shell.execute_reply":"2024-06-26T06:57:24.732344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot some examples\ndata_iter = iter(train_loader)\nimages, labels = next(data_iter)","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:24.734436Z","iopub.execute_input":"2024-06-26T06:57:24.734925Z","iopub.status.idle":"2024-06-26T06:57:24.810288Z","shell.execute_reply.started":"2024-06-26T06:57:24.734901Z","shell.execute_reply":"2024-06-26T06:57:24.809573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20, 4))\nfor idx in np.arange(20):\n    plt.subplot(2, 10, idx+1)\n    # print(np.squeeze(images[idx]),)\n    # np.squeeze removes axes of length one from np.ndarray\n    plt.imshow(np.squeeze(images[idx]), cmap='gray')\n    plt.title(str(labels[idx].item()))\n    plt.xticks([])\n    plt.yticks([])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:24.811823Z","iopub.execute_input":"2024-06-26T06:57:24.812107Z","iopub.status.idle":"2024-06-26T06:57:25.761717Z","shell.execute_reply.started":"2024-06-26T06:57:24.812084Z","shell.execute_reply":"2024-06-26T06:57:25.760840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Create a NeuralNet","metadata":{}},{"cell_type":"code","source":"class NeuralNet(nn.Module):\n    \n    def __init__(self, input_size, hidden_size, output_size):\n        super().__init__()\n        self.L1 = nn.Linear(input_size, hidden_size).to(device)\n        self.L2 = nn.Linear(hidden_size, hidden_size).to(device)\n        self.L3 = nn.Linear(hidden_size, output_size).to(device)\n        \n    def forward(self, data):\n        data = data.view(-1, input_size)\n        out = self.L1(data)\n        out = F.relu(out)\n        out = self.L2(out)\n        out = F.relu(out)\n        out = self.L3(out)\n        \n        return out\n\nmodel = NeuralNet(input_size=input_size, hidden_size=hidden_size, output_size=num_outputs)\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:25.932238Z","iopub.execute_input":"2024-06-26T06:57:25.932561Z","iopub.status.idle":"2024-06-26T06:57:26.075705Z","shell.execute_reply.started":"2024-06-26T06:57:25.932533Z","shell.execute_reply":"2024-06-26T06:57:26.074756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 5. Training Loss and Optimizer","metadata":{}},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:27.429401Z","iopub.execute_input":"2024-06-26T06:57:27.429753Z","iopub.status.idle":"2024-06-26T06:57:27.435124Z","shell.execute_reply.started":"2024-06-26T06:57:27.429725Z","shell.execute_reply":"2024-06-26T06:57:27.434066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:57:28.170823Z","iopub.execute_input":"2024-06-26T06:57:28.171490Z","iopub.status.idle":"2024-06-26T06:57:28.176913Z","shell.execute_reply.started":"2024-06-26T06:57:28.171457Z","shell.execute_reply":"2024-06-26T06:57:28.176014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# initialize tracker for minimum validation loss\ntrain_loss_min = np.Inf # set initial \"min\" to infinity\n\nfor epoch in range(num_epochs):\n    \n    training_loss = 0\n    \n    for data, target in train_loader:\n        \n        data = data.to(device)\n        target = target.to(device)\n        \n        # forward pass\n        y_pred = model(data)\n        \n        # loss\n        loss = criterion(y_pred, target)\n        \n        # loss backward\n        loss.backward()\n        \n        # update weights\n        optimizer.step()\n        # reset grad\n        optimizer.zero_grad()\n        \n        training_loss += loss.item() * data.size(0)\n        \n    avg_training_loss = training_loss / len(train_loader.dataset)\n    \n    print(f'Epoch: {epoch}, Training loss: {avg_training_loss}')\n    \n    if avg_training_loss <= train_loss_min:\n        print(f'Training loss decreases from {train_loss_min:.6f} to {avg_training_loss:.6f}')\n        torch.save(model.state_dict(), 'model.pt')\n        train_loss_min = avg_training_loss","metadata":{"execution":{"iopub.status.busy":"2024-06-26T06:58:23.485434Z","iopub.execute_input":"2024-06-26T06:58:23.486119Z","iopub.status.idle":"2024-06-26T07:13:19.628013Z","shell.execute_reply.started":"2024-06-26T06:58:23.486088Z","shell.execute_reply":"2024-06-26T07:13:19.627051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 6. Load the model and test data","metadata":{}},{"cell_type":"code","source":"model.load_state_dict(torch.load('model.pt'))","metadata":{"execution":{"iopub.status.busy":"2024-06-26T07:14:51.436296Z","iopub.execute_input":"2024-06-26T07:14:51.437012Z","iopub.status.idle":"2024-06-26T07:14:51.446448Z","shell.execute_reply.started":"2024-06-26T07:14:51.436977Z","shell.execute_reply":"2024-06-26T07:14:51.445537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestKannadaMNIST(Dataset):\n    \n    def __init__(self, path, transforms=None):\n        super().__init__()\n        self.data = pd.read_csv(path)\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        images = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((28, 28, 1))\n        \n        if self.transforms is not None:\n            images = self.transforms(images)\n        \n        return images\n    \ntest_dataset = TestKannadaMNIST(path='/kaggle/input/Kannada-MNIST/test.csv', \n                                transforms=transforms.ToTensor())\n\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, num_workers=num_workers)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-26T07:14:52.799020Z","iopub.execute_input":"2024-06-26T07:14:52.799737Z","iopub.status.idle":"2024-06-26T07:14:53.206109Z","shell.execute_reply.started":"2024-06-26T07:14:52.799705Z","shell.execute_reply":"2024-06-26T07:14:53.205277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n\n    data_iter = iter(test_loader)\n    images = next(data_iter).to(device)\n\n    outputs = model(images)\n    _, preds = torch.max(outputs, axis=1)\n    \n    images = images.to('cpu')\n    preds = preds.to('cpu')\n\n    plt.figure(figsize=(20, 10))\n    for i in np.arange(20):\n        plt.subplot(2, 10, i+1)\n        plt.imshow(np.squeeze(images[i].numpy()), cmap='gray')\n        plt.xticks([])\n        plt.yticks([])\n        plt.title(str(preds[i].item()))\n\n# preds","metadata":{"execution":{"iopub.status.busy":"2024-06-26T07:15:46.856262Z","iopub.execute_input":"2024-06-26T07:15:46.856614Z","iopub.status.idle":"2024-06-26T07:15:47.939878Z","shell.execute_reply.started":"2024-06-26T07:15:46.856588Z","shell.execute_reply":"2024-06-26T07:15:47.939002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with torch.no_grad():\n    test_loader = DataLoader(test_dataset, batch_size=batch_size, num_workers=num_workers)\n\n    def predict(model, loader):\n        lst_pred = []\n        for i, images in enumerate(loader):\n            images = images.to(device)\n            outputs = model(images)\n            _, preds = torch.max(outputs, axis=1)\n            lst_pred.append(preds.cpu())\n\n        return lst_pred\n\n    preds = predict(model, test_loader)","metadata":{"execution":{"iopub.status.busy":"2024-06-26T07:16:54.661786Z","iopub.execute_input":"2024-06-26T07:16:54.662187Z","iopub.status.idle":"2024-06-26T07:16:55.552759Z","shell.execute_reply.started":"2024-06-26T07:16:54.662159Z","shell.execute_reply":"2024-06-26T07:16:55.551993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = pd.read_csv('/kaggle/input/Kannada-MNIST/sample_submission.csv')\ndf_results = pd.DataFrame({\n    'id': test_data.index,\n    'label': np.array(preds).reshape(-1)}\n)\ndf_results.to_csv(\"submission.csv\", index=None)","metadata":{"execution":{"iopub.status.busy":"2024-06-26T07:18:10.981420Z","iopub.execute_input":"2024-06-26T07:18:10.982108Z","iopub.status.idle":"2024-06-26T07:18:11.006515Z","shell.execute_reply.started":"2024-06-26T07:18:10.982076Z","shell.execute_reply":"2024-06-26T07:18:11.005835Z"},"trusted":true},"execution_count":null,"outputs":[]}]}