{"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":"# 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","execution":{"iopub.status.busy":"2022-10-08T20:36:43.999676Z","iopub.execute_input":"2022-10-08T20:36:44.000802Z","iopub.status.idle":"2022-10-08T20:36:44.033190Z","shell.execute_reply.started":"2022-10-08T20:36:44.000674Z","shell.execute_reply":"2022-10-08T20:36:44.031663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\nimport numpy as np\nimport torch\n\nclass CustomerDataset(Dataset):\n    def __init__(self, path, transform=None, mode=None):\n        xy = np.loadtxt(path, delimiter=',', dtype=np.float32, skiprows=1)\n        self.n_samples = xy.shape[0]\n        \n        self.x_data = torch.from_numpy(xy[:, 1:]).view(-1, 28, 28) # size [n_samples, 28, 28]\n        self.y_data = torch.from_numpy(xy[:, [0]]) # size [n_samples, 1]\n        self.y_data = self.y_data.type(torch.LongTensor)\n        \n        # rescale the images\n        self.x_data *= 1/255\n        \n        # shift the training data images\n        if mode == 'train':\n            shift_px = 1\n            up_images = torch.cat((self.x_data[:, shift_px:], torch.zeros((self.n_samples, shift_px, 28))), 1)\n\n            down_images = torch.cat((torch.zeros((self.n_samples, shift_px, 28)), self.x_data[:, :-shift_px]), 1)\n\n            left_images = torch.cat((self.x_data[:,:,shift_px:], torch.zeros((self.n_samples, 28, shift_px))), 2)\n\n            right_images = torch.cat((torch.zeros((self.n_samples, 28, shift_px)), self.x_data[:,:,:-shift_px]), 2)\n\n            self.x_data = torch.cat((self.x_data, up_images, down_images, left_images, right_images), 0)\n            self.y_data = torch.cat((self.y_data, self.y_data, self.y_data, self.y_data, self.y_data), 0)\n            \n            self.n_samples = self.x_data.shape[0]\n        \n        # size [n_samples, channel, 28, 28]\n        self.x_data = self.x_data.view(-1, 1, 28, 28) \n    \n    # get one sample from dataset\n    def __getitem__(self, index):\n        return self.x_data[index], self.y_data[index]\n\n    # call len(dataset) to return the size\n    def __len__(self):\n        return self.n_samples","metadata":{"execution":{"iopub.status.busy":"2022-10-08T20:40:59.514839Z","iopub.execute_input":"2022-10-08T20:40:59.515193Z","iopub.status.idle":"2022-10-08T20:40:59.527486Z","shell.execute_reply.started":"2022-10-08T20:40:59.515165Z","shell.execute_reply":"2022-10-08T20:40:59.525851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nclass ConvNetFinal(nn.Module):\n    def __init__(self):\n        super(ConvNetFinal, self).__init__()\n        self.conv1 = nn.Conv2d(1, 64, 3)\n        self.conv2 = nn.Conv2d(64, 64, 3)\n        self.conv3 = nn.Conv2d(64, 128, 3)\n        self.conv4 = nn.Conv2d(128, 128, 3)\n        self.pool = nn.MaxPool2d(2, 2)\n        self.fc1 = nn.Linear(128*4*4, 256) \n        self.fc2 = nn.Linear(256, 10)\n        self.bn1 = nn.BatchNorm2d(64, momentum=0.5)\n        self.bn2 = nn.BatchNorm2d(64, momentum=0.3)\n        self.bn3 = nn.BatchNorm2d(128, momentum=0.2)\n        self.bn4 = nn.BatchNorm2d(128, momentum=0.1)\n        self.relu = nn.LeakyReLU()\n\n    def forward(self, x):\n        # -> n, 1, 28, 28\n        x = self.bn1(self.relu(self.conv1(x)))             # -> n, 64, 26, 26\n        x = self.pool(self.bn2(self.relu(self.conv2(x))))  # -> n, 64, 12, 12\n        x = self.bn3(self.relu(self.conv3(x)))             # -> n, 128, 10, 10\n        x = self.pool(self.bn4(self.relu(self.conv4(x))))  # -> n, 128, 4, 4\n        x = x.view(-1, 128*4*4)                         # -> n, 128*4*4\n        x = self.relu(self.fc1(x))                         # -> n, 256\n        x = self.fc2(x)                                 # -> n, 10\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-10-09T14:51:21.927681Z","iopub.execute_input":"2022-10-09T14:51:21.928053Z","iopub.status.idle":"2022-10-09T14:51:21.941307Z","shell.execute_reply.started":"2022-10-09T14:51:21.928015Z","shell.execute_reply":"2022-10-09T14:51:21.940170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset, DataLoader, random_split\nimport torch.nn as nn\nimport pandas as pd\nfrom copy import deepcopy\n\n# GPU Device configuration\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# Hyper-parameters\nnum_classes = 10\nnum_epochs = 45\nbatch_size = 1000\nlearning_rate = 0.001\n\nmode = 'train'\nmodel_class = 'final'\n\ntrain_path = \"/kaggle/input/Kannada-MNIST/train.csv\"\n\ntest_path = \"/kaggle/input/Kannada-MNIST/test.csv\"\ndig_path = \"/kaggle/input/Kannada-MNIST/Dig-MNIST.csv\"\n\n# if model_class == 'simple':\n#     model = models.ConvNetSimple().to(device)\n# elif model_class == 'nn':\n#     model = models.NeuralNet().to(device)\n# elif model_class == 'paper':\n#     model = models.ConvNetPaper().to(device)\n# else:\n#     model = ConvNetFinal().to(device)\nmodel = ConvNetFinal().to(device)\n\nif mode == 'train':\n    # Load dataset\n    dataset = CustomerDataset(train_path, mode='train')\n#     sample_size = dataset.__len__()\n\n    # Split dataset\n#     validate_dataset, train_dataset = random_split(dataset, [int(sample_size*0.1), sample_size-int(sample_size*0.1)])\n\n    train_loader = DataLoader(dataset=dataset,\n                            batch_size=batch_size,\n                            shuffle=True)\n    \n#     validate_loader = DataLoader(dataset=validate_dataset,\n#                         batch_size=batch_size,\n#                         shuffle=True)\n\n    # Loss and optimizer\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)  \n\n    # Train the model\n    n_total_steps = len(train_loader)\n    last_accuracy = 0\n    tolerance = 0\n    train_accuracies = []\n    vali_accuracies = []\n    for epoch in range(num_epochs):\n        for i, (images, labels) in enumerate(train_loader):  \n            images = images.to(device)\n            labels = labels.view(-1).to(device)\n            \n            # Forward pass\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            \n            # Backward and optimize\n            optimizer.zero_grad()\n            loss.backward()\n            optimizer.step()\n\n            if (i+1) % 100 == 0:\n                print (f'Epoch: {epoch+1}/{num_epochs}, Step: {i+1}/{n_total_steps}, Loss: {loss.item():.4f}')\n        \n        # Calculate accurancy on validation dataset\n#         n_correct = 0\n#         n_samples = 0\n#         with torch.no_grad():\n#             for images, labels in validate_loader:\n#                 images = images.to(device)\n#                 labels = labels.view(-1).to(device)\n#                 outputs = model(images)\n\n#                 _, predicted = torch.max(outputs.data, 1)\n#                 n_samples += labels.size(0)\n#                 n_correct += (predicted == labels).sum().item()\n\n#         acc = 100.0 * n_correct / n_samples\n        \n#         print(acc)\n\n#         # early stop\n#         if -1 < tolerance < 6 :\n#             if abs(acc - last_accuracy) > 0.01:\n#                 tolerance = 0\n#             else:\n#                 tolerance += 1\n                \n#         if tolerance >= 6:\n#             print(\"save best model\")\n#             best_model_state = deepcopy(model.state_dict())\n#             torch.save(best_model_state, \"best_model.pt\")\n#             tolerance = -1\n        \n#         last_accuracy = acc\n\n    # Save model\n    torch.save(model.state_dict(), \"latest_model.pt\")\nelse:\n    model.load_state_dict(torch.load(\"best_model.pt\"))\n    model.eval()\n\n# =============================Generate Submission.csv================================\n# model = ConvNetFinal().to(device)\n\n# model.load_state_dict(torch.load(\"best_model.pt\"))\n# model.eval()\n\n# print(\"loaded best model\")\n\ntest_dataset = CustomerDataset(test_path)\n\ntest_loader = DataLoader(dataset=test_dataset,\n                        batch_size=batch_size,\n                        shuffle=False)\n\ndf = pd.DataFrame(columns = ['id', 'label'])\n\nwith torch.no_grad():\n    n_correct = 0\n    n_samples = 0\n    for images, ids in test_loader:\n        images = images.to(device)\n        ids = ids.view(-1)\n        outputs = model(images)\n        # max returns (value ,index)\n        _, predicted = torch.max(outputs.data, 1)\n        \n        new_df = pd.DataFrame({'id': ids.numpy(), 'label': predicted.cpu().numpy()})\n        df = pd.concat((df, new_df))\n\ndf.to_csv('submission.csv', index=False)\n\n# ==============================Test DIG-MNIST.csv=================================\n\ndig_dataset = CustomerDataset(dig_path)\n\ndig_loader = DataLoader(dataset=dig_dataset,\n                        batch_size=batch_size,\n                        shuffle=False)\n\nwith torch.no_grad():\n    n_correct = 0\n    n_samples = 0\n    for images, labels in dig_loader:\n        images = images.to(device)\n        labels = labels.view(-1).to(device)\n        outputs = model(images)\n\n        _, predicted = torch.max(outputs.data, 1)\n        n_samples += labels.size(0)\n        n_correct += (predicted == labels).sum().item()\n\n    acc = 100.0 * n_correct / n_samples\n    print(f'Accuracy on the Dig-MNIST images: {acc} %')","metadata":{"execution":{"iopub.status.busy":"2022-10-08T21:59:05.363286Z","iopub.execute_input":"2022-10-08T21:59:05.363965Z","iopub.status.idle":"2022-10-08T22:02:43.236663Z","shell.execute_reply.started":"2022-10-08T21:59:05.363929Z","shell.execute_reply":"2022-10-08T22:02:43.235363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}