{"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":"# Dependencies\nimport PIL\nimport numpy as np\nimport pandas as pd\nimport random\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torchvision.transforms.functional import to_pil_image\nimport math\nimport shutil\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport os\nimport zipfile\nfrom copy import deepcopy\n\n# progress bar\nfrom tqdm import tqdm\nfrom tqdm.notebook import tqdm as tqdm_nb\n\nfrom sklearn.model_selection import KFold, StratifiedKFold\nfrom sklearn import preprocessing\nfrom sklearn.metrics import confusion_matrix\n\nimport pandas as pd","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-27T07:25:00.122544Z","iopub.execute_input":"2022-03-27T07:25:00.122995Z","iopub.status.idle":"2022-03-27T07:25:02.912299Z","shell.execute_reply.started":"2022-03-27T07:25:00.122882Z","shell.execute_reply":"2022-03-27T07:25:02.911572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv('../input/Kannada-MNIST/train.csv')\nprint(len(train_df))\ntrain_df","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:02.913875Z","iopub.execute_input":"2022-03-27T07:25:02.914737Z","iopub.status.idle":"2022-03-27T07:25:08.038049Z","shell.execute_reply.started":"2022-03-27T07:25:02.914698Z","shell.execute_reply":"2022-03-27T07:25:08.035887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.countplot(x='label', data=train_df)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:08.039527Z","iopub.execute_input":"2022-03-27T07:25:08.039895Z","iopub.status.idle":"2022-03-27T07:25:08.414833Z","shell.execute_reply.started":"2022-03-27T07:25:08.039847Z","shell.execute_reply":"2022-03-27T07:25:08.414146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Display image from csv\n\nColormap: https://matplotlib.org/stable/gallery/color/colormap_reference.html\n\nJust see images. any of transforming be not yet.","metadata":{}},{"cell_type":"code","source":"def array_to_image_tensor(array):\n    return np.array(array).reshape(28, 28, 1).astype(np.int32)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:08.416491Z","iopub.execute_input":"2022-03-27T07:25:08.417168Z","iopub.status.idle":"2022-03-27T07:25:08.421542Z","shell.execute_reply.started":"2022-03-27T07:25:08.417131Z","shell.execute_reply":"2022-03-27T07:25:08.420413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(3, 10, figsize=(10, 4))\nfig.suptitle('Labels / Images')\nax = ax.ravel()\nfor i in range(30):\n    raw = np.array(train_df.iloc[i])\n    label, img = raw[0], array_to_image_tensor(raw[1:])\n    ax[i].imshow(img, cmap='gist_gray')\n    ax[i].axis(\"off\")\n    ax[i].set_title(str(label))\nplt.subplots_adjust(hspace=0.2)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:08.422938Z","iopub.execute_input":"2022-03-27T07:25:08.423186Z","iopub.status.idle":"2022-03-27T07:25:09.563266Z","shell.execute_reply.started":"2022-03-27T07:25:08.423155Z","shell.execute_reply":"2022-03-27T07:25:09.562254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mean = torch.tensor([0.485, 0.456, 0.406], dtype=torch.float32)\nstd = torch.tensor([0.229, 0.224, 0.225], dtype=torch.float32)\nnormalize = transforms.Normalize(mean.tolist(), std.tolist())\nunnormalize = transforms.Normalize((-mean / std).tolist(), (1.0 / std).tolist())","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:09.564598Z","iopub.execute_input":"2022-03-27T07:25:09.564874Z","iopub.status.idle":"2022-03-27T07:25:09.608635Z","shell.execute_reply.started":"2022-03-27T07:25:09.564839Z","shell.execute_reply":"2022-03-27T07:25:09.607588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Put into Dataset and see it","metadata":{}},{"cell_type":"markdown","source":"Make custom Dataset for load binary pixels from dataframe, and convert it to RGB pixels with size (3, 28, 28)\n\nBecause of memory, we can not have all pixels after load from dataframe. So, just do transform only when get item","metadata":{}},{"cell_type":"code","source":"class DigitDataset(torch.utils.data.Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.transform = transform\n        self.targets = np.array(df['label']).reshape(-1, 1)\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        image = np.array(self.df.iloc[idx][1:]).reshape(28, 28) # (28, 28)\n        image = image.astype(np.float32)\n        label = self.df.iloc[idx]['label']\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n    \n    def gettargets(self):\n        return self.targets","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:09.61049Z","iopub.execute_input":"2022-03-27T07:25:09.611124Z","iopub.status.idle":"2022-03-27T07:25:09.620796Z","shell.execute_reply.started":"2022-03-27T07:25:09.611073Z","shell.execute_reply":"2022-03-27T07:25:09.620076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In dataset, the size of image is `(28, 28)`. so we needs to transform it to resize to `(224, 224)` for VGG and also RGB channels.\n\n`bin_to_rgb(t)` makes binary image to RGB image with `(3, 28, 28)`. now it can be PIL Image.","metadata":{}},{"cell_type":"code","source":"def bin_to_rgb(t):\n    h, w = t.shape\n    img = np.array([np.array(t).reshape(1, h, w)] * 3).reshape(3, h, w).astype(np.float32)\n    return torch.tensor(img)\n\ntrain_set = DigitDataset(train_df, transform=transforms.Compose([\n    bin_to_rgb,\n    normalize,\n]))\ntrain_loader = torch.utils.data.DataLoader(train_set, batch_size=64)\n\nimages, labels = next(iter(train_loader))\nto_pil_image(images[0]).resize((240, 240), PIL.Image.NEAREST)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:09.622531Z","iopub.execute_input":"2022-03-27T07:25:09.623037Z","iopub.status.idle":"2022-03-27T07:25:09.72225Z","shell.execute_reply.started":"2022-03-27T07:25:09.622991Z","shell.execute_reply":"2022-03-27T07:25:09.721385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rows = 4\ncols = 8\nimages, labels = next(iter(train_loader))\n\nfig, ax = plt.subplots(rows, cols, figsize=(12, 6))\nfig.suptitle('from dataset')\nax = ax.ravel()\nfor i in range(rows * cols):\n    image = images[i]\n    label = labels[i].numpy().item()\n    ax[i].imshow(np.asarray(to_pil_image(image)))\n    ax[i].axis(\"off\")\n    ax[i].set_title(label)\nplt.subplots_adjust(hspace=0.5)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:09.723991Z","iopub.execute_input":"2022-03-27T07:25:09.72463Z","iopub.status.idle":"2022-03-27T07:25:11.070041Z","shell.execute_reply.started":"2022-03-27T07:25:09.724583Z","shell.execute_reply":"2022-03-27T07:25:11.05897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# CPU/GPU\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint('device:', device)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:11.073053Z","iopub.execute_input":"2022-03-27T07:25:11.07375Z","iopub.status.idle":"2022-03-27T07:25:11.080514Z","shell.execute_reply.started":"2022-03-27T07:25:11.073701Z","shell.execute_reply":"2022-03-27T07:25:11.079564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class MyConvNet(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.layer = nn.Sequential(\n            nn.Conv2d(3, 64, kernel_size=(3, 3), padding=1),\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.Conv2d(64, 128, 3, padding=1),  # (128, 28, 28)\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.MaxPool2d(2, stride=2),         # (128, 14, 14)\n            \n            nn.Conv2d(128, 256, 3, padding=1), # (128, 14, 14)\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            nn.Conv2d(256, 256, 3, padding=1), # (256, 14, 14)\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            nn.MaxPool2d(2, 2),                # (256, 7, 7)\n            \n            nn.Conv2d(256, 512, 3),            # (512, 5, 5)\n            nn.BatchNorm2d(512),\n            nn.ReLU(),\n            nn.Conv2d(512, 512, 3),            # (512, 3, 3)\n            nn.BatchNorm2d(512),\n            nn.ReLU(),\n            nn.MaxPool2d(2, stride=1),         # (512, 2, 2)\n        )\n        self.classifier = nn.Sequential(\n            nn.Linear(512 * 2 * 2, 128),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(128, 10),\n        )\n\n    def forward(self, x):\n        x = self.layer(x)\n        x = x.view(x.size(0), -1)\n        x = self.classifier(x)\n        return x\n\n\nmodel = MyConvNet().to(device)\n\nprint(\"Params to learn:\")\nparams_to_update = []\nfor name, param in model.named_parameters():\n    if param.requires_grad == True:\n        params_to_update.append(param)\n        print(\"\\t\",name)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(params_to_update, lr=0.00002)\n\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:31:14.590953Z","iopub.execute_input":"2022-03-27T07:31:14.59129Z","iopub.status.idle":"2022-03-27T07:31:14.65698Z","shell.execute_reply.started":"2022-03-27T07:31:14.591252Z","shell.execute_reply":"2022-03-27T07:31:14.655766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from datetime import datetime, timedelta\nstart_time = datetime.now()\nprint('start at:', start_time)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:25:20.146234Z","iopub.execute_input":"2022-03-27T07:25:20.146514Z","iopub.status.idle":"2022-03-27T07:25:20.152538Z","shell.execute_reply.started":"2022-03-27T07:25:20.146485Z","shell.execute_reply":"2022-03-27T07:25:20.151412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHES = 50\nfold_count = 3\nbatch_size = 64\n\nkfold = StratifiedKFold(n_splits=fold_count, shuffle=True)\n\nprint(f'Epoches = {EPOCHES}, Fold = {fold_count}, batch size = {batch_size}')\n\ntrain_losses = []\nvalid_losses = []\ntrain_accs = []\nvalid_accs = []\n\nbest = {\n    'epoch': 0,\n    'train_loss': 1e9,\n    'valid_loss': 1e9,\n    'state': {},\n    'cm': confusion_matrix([], [], labels=range(10)),\n}\n\ndef train_valid_diff(epoch):\n    if epoch < 0: return math.inf\n    return abs(train_losses[epoch] - valid_losses[epoch])\n\nmodel.to(device)\n\n# Run apoch\nepoch = 0\nearly_stop = None\nwhile epoch < EPOCHES:\n    # K-Fold cross validation\n    splited_folds = kfold.split(train_set, train_set.targets)\n    for fold, (train_idx, valid_idx) in enumerate(splited_folds):\n        pbar = tqdm_nb(total=len(train_idx)+len(valid_idx)/2, desc=f'{epoch+1}/{EPOCHES} epoch')\n        # Split dataset and loader\n        train_subsampler = torch.utils.data.SubsetRandomSampler(train_idx)\n        valid_subsampler = torch.utils.data.SubsetRandomSampler(valid_idx)\n        # Use as train/valid set from train data set by k-fold\n        train_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, sampler=train_subsampler)\n        valid_loader = torch.utils.data.DataLoader(train_set, batch_size=batch_size, sampler=valid_subsampler)\n\n        running_loss = 0.0\n        running_acc = []\n\n        # Train\n        model.train()\n        for inputs, labels in train_loader:\n            inputs, labels = inputs.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n\n            outputs = model.forward(inputs)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            pred = torch.argmax(outputs.data, dim=1).to(device)\n\n            running_loss += loss.item()\n            running_acc.append(torch.sum(pred == labels).to('cpu') / len(labels))\n\n            pbar.update(len(labels))\n\n        # train loss (average)\n        train_loss = running_loss / len(train_loader)\n        train_acc = np.array(running_acc).mean()\n        train_losses.append(train_loss)\n        train_accs.append(train_acc)\n\n        model_state = deepcopy(model.state_dict())\n\n        # valid loss (just for check)\n        model.eval()\n        with torch.no_grad():\n            valid_loss_sum = 0\n            valid_acc = []\n            valid_cm = confusion_matrix([], [], labels=range(10))\n            v_cnt = len(valid_loader) * 0.5 # partial valid set\n            for i, (images, labels) in enumerate(valid_loader):\n                if i >= v_cnt: break\n                images, labels = images.to(device), labels.to(device)\n                outputs = model(images).to(device)\n                pred = torch.argmax(outputs.data, dim=1)\n                pred = pred.to(device)\n                last_valid_result = (images, labels, pred)\n                valid_loss_sum += criterion(outputs, labels).item()\n                valid_acc.append(torch.sum(pred == labels).to('cpu') / len(labels))\n                cm = confusion_matrix(labels.to('cpu'), pred.to('cpu'), labels=range(10))\n                valid_cm = np.add(valid_cm, cm)\n                pbar.update(len(labels))\n            valid_loss = valid_loss_sum / v_cnt\n            valid_acc_avg = np.array(valid_acc).mean()\n            valid_losses.append(valid_loss)\n            valid_accs.append(valid_acc_avg)\n\n        print('[%d] fold=%d, train loss: %.6f (%.3f %%), valid loss: %.6f (%.3f %%)' % \\\n              (epoch + 1, fold, train_loss, train_acc * 100, valid_loss, valid_acc_avg * 100))\n\n        # get best\n        if valid_loss < best['valid_loss']:\n            best = {\n                'epoch': epoch,\n                'train_loss': train_loss,\n                'valid_loss': valid_loss,\n                'state': model_state,\n                'cm': valid_cm,\n            }\n\n        pbar.close()\n\n        epoch += 1\n        if epoch >= EPOCHES: break\n        if epoch < 3: continue\n\n        tl = np.array(train_losses[-3:]).mean()\n        vl = np.array(valid_losses[-3:]).mean()\n        minl, maxl = min(vl, tl), max(vl, tl)\n\n        # Early stop conditions\n        if minl > 0.5 and 2 * minl < maxl and 2 * train_valid_diff(epoch-1) < train_valid_diff(epoch):\n            early_stop = 'Train and valid have distance by overfitting'\n            break\n        if np.array([tl, vl]).mean() < 0.0005:\n            early_stop = 'Trained well enough'\n            break\n        if start_time + timedelta(hours=2) < datetime.now():\n            early_stop = 'Too much time'\n            break\n    if early_stop != None:\n        print('Early Stop -', early_stop)\n        break","metadata":{"execution":{"iopub.status.busy":"2022-03-27T07:31:19.136307Z","iopub.execute_input":"2022-03-27T07:31:19.136648Z","iopub.status.idle":"2022-03-27T07:31:32.245965Z","shell.execute_reply.started":"2022-03-27T07:31:19.136616Z","shell.execute_reply":"2022-03-27T07:31:32.244681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save model\nSAVE_BEST_PATH = './best_parameters.pth'\ntorch.save(best['state'], SAVE_BEST_PATH)\nbest_ = deepcopy(best)\nbest_.pop('state')\nbest_.pop('cm')\nprint(best_)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:33.399752Z","iopub.execute_input":"2022-03-27T05:03:33.400481Z","iopub.status.idle":"2022-03-27T05:03:33.420088Z","shell.execute_reply.started":"2022-03-27T05:03:33.40044Z","shell.execute_reply":"2022-03-27T05:03:33.419213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Draw chart\nplt.plot(train_losses, label=\"train loss\")\nplt.plot(valid_losses, label=\"valid loss\")\nplt.title(\"Loss\")\nplt.xlabel(\"epoch\")\nplt.axvline(best['epoch'], color='red', linestyle=':')\nplt.axhline(0, color='gray', linestyle=':')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:33.779056Z","iopub.execute_input":"2022-03-27T05:03:33.779584Z","iopub.status.idle":"2022-03-27T05:03:34.023262Z","shell.execute_reply.started":"2022-03-27T05:03:33.779541Z","shell.execute_reply":"2022-03-27T05:03:34.022323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Draw chart\nplt.plot(train_accs, label=\"train acc\")\nplt.plot(valid_accs, label=\"valid acc\")\nplt.title(\"Accuracy\")\nplt.xlabel(\"epoch\")\nplt.axvline(best['epoch'], color='red', linestyle=':')\nplt.axhline(1.0, color='gray', linestyle=':')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:34.061987Z","iopub.execute_input":"2022-03-27T05:03:34.062285Z","iopub.status.idle":"2022-03-27T05:03:34.293408Z","shell.execute_reply.started":"2022-03-27T05:03:34.062253Z","shell.execute_reply":"2022-03-27T05:03:34.291852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20, 6))\n\nplt.subplot(1, 2, 1)\nplt.plot(train_losses, label=\"train loss\")\nplt.title(\"Train Loss\")\nplt.xlabel(\"epoch\")\nplt.axvline(best['epoch'], color='red', linestyle=':')\nplt.axhline(0, color='gray', linestyle=':')\nplt.legend()\n\nplt.subplot(1, 2, 2)\nplt.plot(valid_losses, label=\"valid loss\")\nplt.title(\"Valid Loss\")\nplt.xlabel(\"epoch\")\nplt.axvline(best['epoch'], color='red', linestyle=':')\nplt.axhline(0, color='gray', linestyle=':')\nplt.legend()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:34.295436Z","iopub.execute_input":"2022-03-27T05:03:34.295755Z","iopub.status.idle":"2022-03-27T05:03:34.696541Z","shell.execute_reply.started":"2022-03-27T05:03:34.295715Z","shell.execute_reply":"2022-03-27T05:03:34.695648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, labels, preds = last_valid_result\nplt.figure(figsize=(15, 10))\nfor index in range(5 * 5):\n    plt.subplot(5, 5, index + 1)\n    # image = unnormalize(images[index])\n    image = images[index]\n    image = np.asarray(to_pil_image(image.to('cpu')))\n    label = labels[index].to('cpu').numpy().item()\n    guess = preds[index].to('cpu').numpy().item()\n    plt.title('{} [L:{}]'.format(guess, label))\n    plt.imshow(image)\n    plt.axis(\"off\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:34.698487Z","iopub.execute_input":"2022-03-27T05:03:34.699003Z","iopub.status.idle":"2022-03-27T05:03:35.558602Z","shell.execute_reply.started":"2022-03-27T05:03:34.698956Z","shell.execute_reply":"2022-03-27T05:03:35.557928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.heatmap(best['cm'], annot=True, cmap='Greens')","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:35.559765Z","iopub.execute_input":"2022-03-27T05:03:35.560166Z","iopub.status.idle":"2022-03-27T05:03:36.223549Z","shell.execute_reply.started":"2022-03-27T05:03:35.560134Z","shell.execute_reply":"2022-03-27T05:03:36.222476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Now, prepare to submit\n\nAccording document of competition, submission file format is:\n```\nImageId,Label\n1,0\n2,0\n3,0\n...\n```\n\nso, predict result by trained model and write it down.","metadata":{}},{"cell_type":"code","source":"class SubmitDataset(torch.utils.data.Dataset):\n    def __init__(self, df, transform=None):\n        self.df = df\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        image = np.array(self.df.iloc[idx][1:]).reshape(28, 28) # (28, 28)\n        if self.transform:\n            image = self.transform(image)\n        return image, idx","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:36.226347Z","iopub.execute_input":"2022-03-27T05:03:36.226682Z","iopub.status.idle":"2022-03-27T05:03:36.233247Z","shell.execute_reply.started":"2022-03-27T05:03:36.226639Z","shell.execute_reply":"2022-03-27T05:03:36.232369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.read_csv('../input/Kannada-MNIST/test.csv')\ntest_set = SubmitDataset(test_df, transform=transforms.Compose([\n    bin_to_rgb,\n    normalize,\n]))\ntest_loader = torch.utils.data.DataLoader(test_set, batch_size=64)\ntest_df","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:36.234468Z","iopub.execute_input":"2022-03-27T05:03:36.234676Z","iopub.status.idle":"2022-03-27T05:03:36.537558Z","shell.execute_reply.started":"2022-03-27T05:03:36.234651Z","shell.execute_reply":"2022-03-27T05:03:36.536787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rows = 4\ncols = 8\nimages, indices = next(iter(test_loader))\n\nfig, ax = plt.subplots(rows, cols, figsize=(12, 6))\nfig.suptitle('test set')\nax = ax.ravel()\nfor i in range(rows * cols):\n    image = images[i]\n    index = indices[i]\n    ax[i].imshow(np.asarray(to_pil_image(image)))\n    ax[i].set_title(f'id={index}')\n    ax[i].axis(\"off\")\nplt.subplots_adjust(hspace=0.5)","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:36.538937Z","iopub.execute_input":"2022-03-27T05:03:36.539178Z","iopub.status.idle":"2022-03-27T05:03:37.902602Z","shell.execute_reply.started":"2022-03-27T05:03:36.539148Z","shell.execute_reply":"2022-03-27T05:03:37.901959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load model which getting the best during train according by accuracy.","metadata":{}},{"cell_type":"code","source":"best_model = MyConvNet().to(device)\nbest_model.load_state_dict(torch.load(SAVE_BEST_PATH))","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:37.90393Z","iopub.execute_input":"2022-03-27T05:03:37.904178Z","iopub.status.idle":"2022-03-27T05:03:37.920852Z","shell.execute_reply.started":"2022-03-27T05:03:37.904149Z","shell.execute_reply":"2022-03-27T05:03:37.92019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df = pd.DataFrame(columns=['id', 'label'])\n\nbest_model.eval()\nwith torch.no_grad():\n    for images, indices in tqdm_nb(test_loader):\n        images, indices = images.to(device), indices.to(device)\n        outputs = best_model(images).to(device)\n        pred = torch.argmax(outputs.data, dim=1)\n        last_test_result = (images, pred.to(device))\n        \n        indices = indices.to('cpu').numpy()\n        pred = pred.to('cpu').numpy()\n        pred_df = pd.DataFrame({'id': indices, 'label': pred})\n        result_df = result_df.append(pred_df)\n\nresult_df.to_csv('submission.csv', index=False)\n\nresult_df","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:37.923072Z","iopub.execute_input":"2022-03-27T05:03:37.923536Z","iopub.status.idle":"2022-03-27T05:03:40.697072Z","shell.execute_reply.started":"2022-03-27T05:03:37.923494Z","shell.execute_reply":"2022-03-27T05:03:40.695881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, preds = last_test_result\n\nrows = 2\ncols = len(images) // rows\nfig, ax = plt.subplots(rows, cols, figsize=(cols * 2, rows * 2))\nax = ax.ravel()\nfor i in range(len(images)):\n    # image = unnormalize(images[i])\n    image = images[i]\n    image = np.asarray(to_pil_image(image.to('cpu')))\n    guess = preds[i].to('cpu').numpy().item()\n    ax[i].imshow(image)\n    ax[i].axis(\"off\")\n    ax[i].set_title(guess)\nplt.subplots_adjust(hspace=0.2)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-27T05:03:40.698768Z","iopub.execute_input":"2022-03-27T05:03:40.69938Z","iopub.status.idle":"2022-03-27T05:03:41.029921Z","shell.execute_reply.started":"2022-03-27T05:03:40.69933Z","shell.execute_reply":"2022-03-27T05:03:41.029073Z"},"trusted":true},"execution_count":null,"outputs":[]}]}