{"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 numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torchvision\nfrom torchvision import transforms\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import TensorDataset\nfrom torch.utils.data import Dataset\nfrom sklearn.metrics import accuracy_score\nfrom tqdm.auto import tqdm","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"/kaggle/input/Kannada-MNIST/train.csv\")\ntest_df = pd.read_csv(\"/kaggle/input/Kannada-MNIST/Dig-MNIST.csv\")\nsubmission_set = pd.read_csv(\"/kaggle/input/Kannada-MNIST/test.csv\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image = train_df.drop(columns=[\"label\"])\ntrain_label = train_df[\"label\"]\n\ntest_image = test_df.drop(columns=[\"label\"])\ntest_label = test_df[\"label\"]\n\nprediction_image = submission_set.drop(columns=[\"id\"])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_image, val_image, train_label, val_label = train_test_split(train_image, train_label, test_size=0.3)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image.reset_index(drop=True, inplace=True)\ntrain_label.reset_index(drop=True, inplace=True)\n\nval_image.reset_index(drop=True, inplace=True)\nval_label.reset_index(drop=True, inplace=True)\n\ntest_image.reset_index(drop=True, inplace=True)\ntest_label.reset_index(drop=True, inplace=True)\n\nprediction_image.reset_index(drop=True, inplace=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMAGE_SIZE = 28\n\nclass KannadaDataset(Dataset):\n    def __init__(self, images, labels, transforms = None) -> None:\n        self.X = images\n        self.y = labels\n        self.transforms = transforms\n    \n    def __len__(self):\n        return (len(self.X))\n    \n    def __getitem__(self, i):\n        data = self.X.iloc[i,:]\n        data = np.array(data).astype(np.uint8).reshape(IMAGE_SIZE, IMAGE_SIZE, 1)\n        if self.transforms:\n            data = self.transforms(data)  \n        if self.y is not None:\n            return (data, self.y[i])\n        else:\n            return data","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transforms = transforms.Compose(([\n    transforms.ToPILImage(),\n    transforms.ToTensor(),\n]))\n\nval_transforms = transforms.Compose(([\n    transforms.ToPILImage(),\n    transforms.ToTensor(),\n]))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 32\n\ntrain_dataset = KannadaDataset(train_image, train_label, train_transforms)\n\nval_dataset = KannadaDataset(val_image, val_label, val_transforms)\n\ntest_dataset = KannadaDataset(test_image, test_label, val_transforms)\n\nsubmission_dataset = KannadaDataset(prediction_image, None, val_transforms)\n\ntrain_dataloader = DataLoader(train_dataset,\n                              batch_size = BATCH_SIZE,\n                              shuffle = True)\nval_dataloader = DataLoader(val_dataset,\n                            batch_size = BATCH_SIZE,\n                            shuffle = False)\ntest_dataloader = DataLoader(test_dataset,\n                             batch_size = BATCH_SIZE,\n                             shuffle = False)\nprediction_dataloader = DataLoader(submission_dataset,\n                                   batch_size = BATCH_SIZE,\n                                   shuffle = False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, labels = next(iter(train_dataloader))\nimages, labels = images[:8], labels[:8]\nplt.imshow(torchvision.utils.make_grid(images)[0,:,:], cmap=\"gray\")\nprint(labels)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class KannadaCNN(nn.Module):\n    def __init__(self, ouputs) -> None:\n        super().__init__()\n        self.layer1 = nn.Sequential(\n            nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU()            \n        )\n        self.layer2 = nn.Sequential(\n            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2)\n        )\n        self.layer3 = nn.Sequential(\n            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(128),\n            nn.ReLU()\n        )\n        self.layer4 = nn.Sequential(\n            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2)\n        )\n        self.fc1 = nn.Sequential(\n            nn.Flatten(),\n            nn.Dropout(0.5),\n            nn.Linear(128*7*7, 4096),\n            nn.ReLU()\n        )\n        self.fc2 = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU()\n        )\n        self.fc3 = nn.Sequential(\n            nn.Linear(4096, ouputs)\n        )\n    \n    def forward(self, x):\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n        x = self.fc1(x)\n        x = self.fc2(x)\n        x = self.fc3(x)\n        return x","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EarlyStopping:\n    def __init__(self, patience=7, verbose=False, delta=0):\n        self.patience = patience\n        self.verbose = verbose\n        self.counter = 0\n        self.best_score = None\n        self.early_stop = False\n        self.val_loss_min = np.Inf\n        self.delta = delta\n\n    def __call__(self, val_loss, model):\n\n        score = -val_loss\n\n        if self.best_score is None:\n            self.best_score = score\n        elif score < self.best_score + self.delta:\n            self.counter += 1\n            print(f'EarlyStopping counter: {self.counter} out of {self.patience}')\n            if self.counter >= self.patience:\n                self.early_stop = True\n        else:\n            self.best_score = score\n            self.counter = 0","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def trainModel(model: torch.nn.Module, \n               dataloader: torch.utils.data.DataLoader, \n               optimizer: torch.optim.Optimizer, \n               loss_fn = torch.nn.Module, \n               device: torch.device = device):\n    model.train()\n    train_loss, train_acc = 0, 0\n    for X, y in dataloader:\n        X, y = X.to(device), y.to(device)\n        y_pred = model(X)\n        loss = loss_fn(y_pred, y)\n        train_loss += loss\n        train_acc += accuracy_score(y.cpu(), y_pred.cpu().argmax(dim=1))\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        train_loss /= len(dataloader)\n    train_acc /= len(dataloader)\n    print(f\"Train loss: {train_loss:.4f} | Train accuracy: {train_acc:.4f}\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def valMmodel(model: torch.nn.Module,\n              dataloader: torch.utils.data.DataLoader,\n              loss_fn: torch.nn.Module,\n              device: torch.device = device):\n    val_loss, val_acc = 0, 0\n    model.eval()\n    with torch.inference_mode():\n        for X, y in dataloader:\n            X, y = X.to(device), y.to(device)\n            y_pred = model(X)\n            val_loss += loss_fn(y_pred, y)\n            val_acc += accuracy_score(y.cpu(), y_pred.cpu().argmax(dim=1))\n        val_loss /= len(dataloader)\n        val_acc /= len(dataloader)\n        print(f\"Val loss: {val_loss:.4f} | Val accuracy: {val_acc:.4f}\")\n        return val_loss","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evalModel(model: torch.nn.Module, \n               dataloader: torch.utils.data.DataLoader, \n               loss_fn: torch.nn.Module,\n               device: torch.device = device):\n    loss, acc = 0, 0\n    model.eval()\n    with torch.inference_mode():\n        for X, y in dataloader:\n            X, y = X.to(device), y.to(device)\n            y_pred = model(X)\n            loss += loss_fn(y_pred, y)\n            acc += accuracy_score(y.cpu(), y_pred.cpu().argmax(dim=1)) \n        loss /= len(dataloader)\n        acc /= len(dataloader)       \n    return {\"model_name\": model.__class__.__name__, \n            \"model_loss\": loss.item(),\n            \"model_acc\": acc}","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = KannadaCNN(len(classes)).to(device)\nprint(model)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.01)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.manual_seed(0)\nEPOCHS = 50\nearly_stopping = EarlyStopping(patience=5, verbose=False, delta=0.001)\nfor epoch in tqdm(range(EPOCHS)):\n    trainModel(model, train_dataloader, optimizer, loss_fn, device)\n    val_loss = valMmodel(model, val_dataloader, loss_fn, device)\n    early_stopping(val_loss, model)\n    if early_stopping.early_stop:\n        break","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_results = evalModel(model, test_dataloader, loss_fn, device)\nprint(model_results)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"/kaggle/input/Kannada-MNIST/sample_submission.csv\")\nsubmission.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = torch.LongTensor().to(device)\nmodel.eval()\nwith torch.inference_mode():\n    for X in prediction_dataloader:\n        X= X.to(device)\n        y_pred = model(X)\n        preds = torch.cat((preds, y_pred.argmax(dim=1)), dim=0)\nsubmission[\"label\"] = preds.cpu().numpy()\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{},"execution_count":null,"outputs":[]}]}