{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# import libraries\nimport torch\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data.sampler import SubsetRandomSampler\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.120738Z","iopub.execute_input":"2023-10-01T07:18:51.121088Z","iopub.status.idle":"2023-10-01T07:18:51.126757Z","shell.execute_reply.started":"2023-10-01T07:18:51.121062Z","shell.execute_reply":"2023-10-01T07:18:51.125517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TrainMNIST(Dataset):\n    \n    def __init__(self, file_path, transform=None):\n        self.data = pd.read_csv(file_path)\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        # load image as ndarray type (Height * Width * Channels)\n        # be carefull for converting dtype to np.uint8 [Unsigned integer (0 to 255)]\n        # in this example, we use ToTensor(), so we define the numpy array like (H, W, C)\n        image = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((28, 28, 1))\n        label = self.data.iloc[index, 0]\n        \n        if self.transform is not None:\n            image = self.transform(image)\n            \n        return image, label","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.131097Z","iopub.execute_input":"2023-10-01T07:18:51.131353Z","iopub.status.idle":"2023-10-01T07:18:51.141072Z","shell.execute_reply.started":"2023-10-01T07:18:51.131331Z","shell.execute_reply":"2023-10-01T07:18:51.139952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestMNIST(Dataset):\n    \n    def __init__(self, file_path, transform=None):\n        self.data = pd.read_csv(file_path)\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, index):\n        # load image as ndarray type (Height * Width * Channels)\n        # be carefull for converting dtype to np.uint8 [Unsigned integer (0 to 255)]\n        # in this example, we use ToTensor(), so we define the numpy array like (H, W, C)\n        image = self.data.iloc[index, 1:].values.astype(np.uint8).reshape((28, 28, 1))\n    \n        \n        if self.transform is not None:\n            image = self.transform(image)\n            \n        return image","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.142621Z","iopub.execute_input":"2023-10-01T07:18:51.143443Z","iopub.status.idle":"2023-10-01T07:18:51.158098Z","shell.execute_reply.started":"2023-10-01T07:18:51.143414Z","shell.execute_reply":"2023-10-01T07:18:51.157160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_loader(dataset, train_batch_size, validation_split=0.2):\n    \"\"\"make dataloader for pytorch training\n\n    Args:\n        dataset ([object]): [the dataset object]\n        train_batch_size ([int]): [training batch size]\n        validation_split (float, optional): [validation ratio]. Defaults to 0.2.\n\n    Returns:\n        [type]: [description]\n    \"\"\"\n    # number of samples in train and test set\n    train_len = int(len(dataset) * (1 - validation_split))\n    test_len = len(dataset) - train_len\n    train_set, test_set = torch.utils.data.random_split(dataset, [train_len, test_len])\n    # create train_loader\n    train_loader = torch.utils.data.DataLoader(\n        train_set, batch_size=train_batch_size, shuffle=True,\n    )\n    # create test_loader\n    test_loader = torch.utils.data.DataLoader(test_set, batch_size=1, shuffle=False,)\n    return train_loader, test_loader","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.239930Z","iopub.execute_input":"2023-10-01T07:18:51.240320Z","iopub.status.idle":"2023-10-01T07:18:51.245882Z","shell.execute_reply.started":"2023-10-01T07:18:51.240300Z","shell.execute_reply":"2023-10-01T07:18:51.245013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mean, std = [0.5], [0.5]\n\ncomposed_train = transforms.Compose([transforms.ToTensor()])\n\n\ncomposed_test = transforms.Compose([transforms.ToTensor()])","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.247678Z","iopub.execute_input":"2023-10-01T07:18:51.248261Z","iopub.status.idle":"2023-10-01T07:18:51.264937Z","shell.execute_reply.started":"2023-10-01T07:18:51.248233Z","shell.execute_reply":"2023-10-01T07:18:51.263895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = TrainMNIST('/kaggle/input/Kannada-MNIST/train.csv', transform=composed_train)\ntest_data = TestMNIST('/kaggle/input/Kannada-MNIST/test.csv', transform=composed_test)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:51.266013Z","iopub.execute_input":"2023-10-01T07:18:51.266383Z","iopub.status.idle":"2023-10-01T07:18:56.259814Z","shell.execute_reply.started":"2023-10-01T07:18:51.266355Z","shell.execute_reply":"2023-10-01T07:18:56.258764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# how many samples per batch to load\nbatch_size = 20\n\n# prepare data loaders\ntrain_loader,val_loader = make_loader(dataset, train_batch_size=batch_size, validation_split=0.2)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.264109Z","iopub.execute_input":"2023-10-01T07:18:56.266223Z","iopub.status.idle":"2023-10-01T07:18:56.277946Z","shell.execute_reply.started":"2023-10-01T07:18:56.266191Z","shell.execute_reply":"2023-10-01T07:18:56.277138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F\n\n# define the NN architecture\nclass Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n        # number of hidden nodes in each layer (512)\n        hidden_1 = 512\n        hidden_2 = 512\n        # linear layer (784 -> hidden_1)\n        self.fc1 = nn.Linear(28 * 28*1, hidden_1)\n        # linear layer (n_hidden -> hidden_2)\n        self.fc2 = nn.Linear(hidden_1, hidden_2)\n        # linear layer (n_hidden -> 10)\n        self.fc3 = nn.Linear(hidden_2, 10)\n\n\n    def forward(self, x):\n        # flatten image input\n        x = x.view(-1, 28 * 28 * 1)\n        # add hidden layer, with relu activation function\n        x = F.relu(self.fc1(x))\n        # add hidden layer, with relu activation function\n        x = F.relu(self.fc2(x))\n        # add output layer\n        x = self.fc3(x)\n        return x\n\n# initialize the NN\ndevice = torch.device(\"cuda\")\n\nmodel = Net().to(device)\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.283135Z","iopub.execute_input":"2023-10-01T07:18:56.285723Z","iopub.status.idle":"2023-10-01T07:18:56.307093Z","shell.execute_reply.started":"2023-10-01T07:18:56.285694Z","shell.execute_reply":"2023-10-01T07:18:56.306003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nfrom torch import nn\nimport torch.nn.functional as F\ncriterion =  nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.0001)\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(\n        optimizer, \"min\", patience=2, factor=0.5\n    )","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.310450Z","iopub.execute_input":"2023-10-01T07:18:56.312635Z","iopub.status.idle":"2023-10-01T07:18:56.319166Z","shell.execute_reply.started":"2023-10-01T07:18:56.312607Z","shell.execute_reply":"2023-10-01T07:18:56.318446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\ndef train_one_epoch(\n    model,\n    train_loader,\n    test_loader,\n    device,\n    optimizer,\n    criterion\n):\n\n    # training-the-model\n    train_loss = 0\n    valid_loss = 0\n    all_labels = []\n    all_preds = []\n    model.train()\n    for data, target in train_loader:\n        # move-tensors-to-GPU\n        data = data.type(torch.FloatTensor).to(device)\n        # target=torch.Tensor(target)\n        target = target.float().to(device)\n        # clear-the-gradients-of-all-optimized-variables\n        optimizer.zero_grad()\n        # forward-pass: compute-predicted-outputs-by-passing-inputs-to-the-model\n        output = model(data)\n        # get the prediction label and target label\n        output = model(data)\n        preds = torch.argmax(output, axis=1).cpu().detach().numpy()\n        labels = target.cpu().numpy()\n        # calculate-the-batch-loss\n        loss = criterion(output.type(torch.FloatTensor), target.type(torch.LongTensor))\n        # backward-pass: compute-gradient-of-the-loss-wrt-model-parameters\n        loss.backward()\n        # perform-a-ingle-optimization-step (parameter-update)\n        optimizer.step()\n        # update-training-loss\n        train_loss += loss.item() * data.size(0)\n        # calculate training metrics\n        all_labels.extend(labels)\n        all_preds.extend(preds)\n    \n    acc = accuracy_score(all_labels, all_preds)\n\n    # validate-the-model\n    model.eval()\n    all_labels = []\n    all_preds = []\n    with torch.no_grad():\n        for data, target in test_loader:\n            data = data.type(torch.FloatTensor).to(device)\n            target = target.to(device)\n            output = model(data)\n            preds = torch.argmax(output, axis=1).tolist()\n            labels = target.tolist()\n            all_labels.extend(labels)\n            all_preds.extend(preds)\n            loss = criterion(output, target)\n\n            # update-average-validation-loss\n            valid_loss += loss.item() * data.size(0)\n\n    val_acc = accuracy_score(all_labels, all_preds)\n    train_loss = train_loss / len(train_loader.sampler)\n    valid_loss = valid_loss / len(test_loader.sampler)\n\n    return (\n        train_loss,\n        valid_loss,\n        acc,\n        val_acc,\n    )","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.323181Z","iopub.execute_input":"2023-10-01T07:18:56.323478Z","iopub.status.idle":"2023-10-01T07:18:56.340063Z","shell.execute_reply.started":"2023-10-01T07:18:56.323450Z","shell.execute_reply":"2023-10-01T07:18:56.339275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.343894Z","iopub.execute_input":"2023-10-01T07:18:56.344667Z","iopub.status.idle":"2023-10-01T07:18:56.356612Z","shell.execute_reply.started":"2023-10-01T07:18:56.344632Z","shell.execute_reply":"2023-10-01T07:18:56.355808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epoch = 20\nbest_val_acc = 0\nimport logging\nimport numpy as np\nprint(\"begin training process\")\nfor i in tqdm(range(0, num_epoch)):\n    loss, val_loss, train_result, val_result = train_one_epoch(\n        model,\n        train_loader,\n        val_loader,\n        device,\n        optimizer,\n        criterion,\n    )\n\n    scheduler.step(val_loss)\n    print(\n        \"Epoch {} / {} \\n Training loss: {} -  training acc: {}\".format(\n            i + 1, num_epoch, loss,train_result\n        )\n    )\n    print(\n        \" \\n Validation loss : {} -  validation acc: {}\".format(val_loss,val_result)\n    )\n    print(\"\\n\")\n    # saving epoch with best validation accuracy\n    if best_val_acc < float(val_result):\n        print(\n            \"Validation accuracy= \"+\n            str(val_result)+\n            \"===> Save best epoch\"\n        )\n        best_val_acc = val_result\n        torch.save(\n            model,\n            \"./\" +  \"best.pt\",\n        )\n    else:\n        print(\n            \"Validation accuracy= \"+ str(val_result)+ \"===> No saving\"\n        )\n        continue","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:18:56.360580Z","iopub.execute_input":"2023-10-01T07:18:56.363267Z","iopub.status.idle":"2023-10-01T07:26:04.563634Z","shell.execute_reply.started":"2023-10-01T07:18:56.363106Z","shell.execute_reply":"2023-10-01T07:26:04.562717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import copy\ntest_model = torch.load(\"/kaggle/working/best.pt\")\ntest_model = test_model.to(device)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:26:04.565017Z","iopub.execute_input":"2023-10-01T07:26:04.565566Z","iopub.status.idle":"2023-10-01T07:26:04.574519Z","shell.execute_reply.started":"2023-10-01T07:26:04.565519Z","shell.execute_reply":"2023-10-01T07:26:04.573688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_loader = torch.utils.data.DataLoader(test_data, batch_size=1, \n    num_workers=0)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:28:15.402116Z","iopub.execute_input":"2023-10-01T07:28:15.402440Z","iopub.status.idle":"2023-10-01T07:28:15.407468Z","shell.execute_reply.started":"2023-10-01T07:28:15.402414Z","shell.execute_reply":"2023-10-01T07:28:15.406548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(model, dataloader):\n    prediction_list = []\n    for i, batch in enumerate(dataloader):\n        data = batch\n        data = data.to(device)\n        outputs = model(data)\n        _, predicted = torch.max(outputs.data, 1) \n        prediction_list.append(predicted.cpu())\n    return prediction_list","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:28:16.032172Z","iopub.execute_input":"2023-10-01T07:28:16.032731Z","iopub.status.idle":"2023-10-01T07:28:16.038212Z","shell.execute_reply.started":"2023-10-01T07:28:16.032699Z","shell.execute_reply":"2023-10-01T07:28:16.037224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = predict(test_model,test_loader)\npredictions_array = [tensor.numpy() for tensor in predictions]\npredictions_ = np.array(predictions_array)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:28:16.460804Z","iopub.execute_input":"2023-10-01T07:28:16.461915Z","iopub.status.idle":"2023-10-01T07:28:19.290182Z","shell.execute_reply.started":"2023-10-01T07:28:16.461879Z","shell.execute_reply":"2023-10-01T07:28:19.289201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = pd.read_csv(\"/kaggle/input/Kannada-MNIST/test.csv\")\nsubmission =  pd.DataFrame({'id': test_data.id})\nsubmission['label'] = predictions_\nsubmission.to_csv(\"submission.csv\", index=None)","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:28:19.292059Z","iopub.execute_input":"2023-10-01T07:28:19.292400Z","iopub.status.idle":"2023-10-01T07:28:19.516728Z","shell.execute_reply.started":"2023-10-01T07:28:19.292371Z","shell.execute_reply":"2023-10-01T07:28:19.515833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-10-01T07:28:19.517787Z","iopub.execute_input":"2023-10-01T07:28:19.518089Z","iopub.status.idle":"2023-10-01T07:28:19.534141Z","shell.execute_reply.started":"2023-10-01T07:28:19.518062Z","shell.execute_reply":"2023-10-01T07:28:19.532805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}