{"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":"markdown","source":"# Introduction\nThis notebook uses my trained model generated from https://www.kaggle.com/hdsk38/pytorch-starter-train-efficientnet to predict the hidden test dataset. Please go to the notebook to see the details of trained model. Many codes are forked from https://www.kaggle.com/rhtsingh/pytorch-training-inference-efficientnet-baseline. Thank you [\n@rhtsingh](https://www.kaggle.com/rhtsingh)!\n\nI hope this notebook will help more kagglers to join this competition. Cheers! :)","metadata":{}},{"cell_type":"code","source":"!pip install ../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master/ > /dev/null # no output\n!pip install torch_optimizer --no-index --find-links=file:///kaggle/input/torch-optimizer/torch_optimizer","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:56:23.397830Z","iopub.execute_input":"2021-08-18T14:56:23.398365Z","iopub.status.idle":"2021-08-18T14:56:58.734123Z","shell.execute_reply.started":"2021-08-18T14:56:23.398253Z","shell.execute_reply":"2021-08-18T14:56:58.733119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport gc\ngc.enable()\nimport sys\nimport math\nimport json\nimport time\nimport random\nfrom glob import glob\nfrom datetime import datetime\n\nimport cv2\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport multiprocessing\nfrom sklearn.preprocessing import LabelEncoder\n\nimport torch\nimport torchvision\nfrom torch import Tensor\nfrom torchvision import transforms\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.autograd import Variable\nfrom torch.nn.parameter import Parameter\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom tqdm import tqdm\n\nimport efficientnet_pytorch\n\nimport torch_optimizer as optim\nimport albumentations as A\n\nimport sklearn\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:56:58.737631Z","iopub.execute_input":"2021-08-18T14:56:58.737902Z","iopub.status.idle":"2021-08-18T14:57:01.925765Z","shell.execute_reply.started":"2021-08-18T14:56:58.737873Z","shell.execute_reply":"2021-08-18T14:57:01.924898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IN_KERNEL = os.environ.get('KAGGLE_WORKING_DIR') is not None\nBATCH_SIZE = 64\nNUM_WORKERS = multiprocessing.cpu_count()\nNUM_TOP_PREDICTS = 1","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.927589Z","iopub.execute_input":"2021-08-18T14:57:01.927920Z","iopub.status.idle":"2021-08-18T14:57:01.933127Z","shell.execute_reply.started":"2021-08-18T14:57:01.927884Z","shell.execute_reply":"2021-08-18T14:57:01.931748Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dir = '../input/landmark-recognition-2021/test/'","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.934981Z","iopub.execute_input":"2021-08-18T14:57:01.935463Z","iopub.status.idle":"2021-08-18T14:57:01.943390Z","shell.execute_reply.started":"2021-08-18T14:57:01.935428Z","shell.execute_reply":"2021-08-18T14:57:01.942580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageDataset(torch.utils.data.Dataset):\n    def __init__(self, dataframe: pd.DataFrame, image_dir:str, mode: str):\n        self.df = dataframe\n        self.mode = mode\n        self.image_dir = image_dir\n        \n        transforms_list = []\n        if self.mode == 'train':\n            # Increase image size from (64,64) to higher resolution,\n            # Make sure to change in RandomResizedCrop as well.\n            transforms_list = [\n                transforms.Resize((64,64)),\n                transforms.RandomHorizontalFlip(),\n                transforms.RandomChoice([\n                    transforms.RandomResizedCrop(64),\n                    transforms.ColorJitter(0.2, 0.2, 0.2, 0.2),\n                    transforms.RandomAffine(degrees=15, translate=(0.2, 0.2),\n                                            scale=(0.8, 1.2), shear=15,\n                                            resample=Image.BILINEAR)\n                ]),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                      std=[0.229, 0.224, 0.225]),\n            ]\n        else:\n            transforms_list.extend([\n                # Keep this resize same as train\n                transforms.Resize((64,64)),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                      std=[0.229, 0.224, 0.225]),\n            ])\n        self.transforms = transforms.Compose(transforms_list)\n\n    def __getitem__(self, index: int):\n        image_id = self.df.iloc[index].id\n        image_path = f\"{self.image_dir}/{image_id[0]}/{image_id[1]}/{image_id[2]}/{image_id}.jpg\"\n        image = Image.open(image_path)\n        image = self.transforms(image)\n\n        if self.mode == 'test':\n            return {'image':image}\n        else:\n            return {'image':image, \n                    'target':self.df.iloc[index].landmark_id}\n\n    def __len__(self) -> int:\n        return self.df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.944439Z","iopub.execute_input":"2021-08-18T14:57:01.944678Z","iopub.status.idle":"2021-08-18T14:57:01.959477Z","shell.execute_reply.started":"2021-08-18T14:57:01.944656Z","shell.execute_reply":"2021-08-18T14:57:01.958571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EfficientNetEncoderHead(nn.Module):\n    def __init__(self, depth, num_classes):\n        super(EfficientNetEncoderHead, self).__init__()\n        self.depth = depth\n        self.base = efficientnet_pytorch.EfficientNet.from_name(f'efficientnet-b{self.depth}')#tropicbird\n        pretrained_file = glob(f'../input/efficientnet-pytorch/efficientnet-b{self.depth}*')[0]\n        checkpoint = torch.load(pretrained_file)\n        self.base.load_state_dict(checkpoint)\n        \n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.output_filter = self.base._fc.in_features\n        self.classifier = nn.Linear(self.output_filter, num_classes)\n    def forward(self, x):\n        x = self.base.extract_features(x)\n        x = self.avg_pool(x).squeeze(-1).squeeze(-1)\n        x = self.classifier(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.960701Z","iopub.execute_input":"2021-08-18T14:57:01.961117Z","iopub.status.idle":"2021-08-18T14:57:01.972413Z","shell.execute_reply.started":"2021-08-18T14:57:01.961079Z","shell.execute_reply":"2021-08-18T14:57:01.971665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def inference(data_loader, model):\n    model.eval()\n\n    activation = nn.Softmax(dim=1)\n    all_predicts, all_confs, all_targets = [], [], []\n\n    with torch.no_grad():\n        for i, data in enumerate(tqdm(data_loader, disable=IN_KERNEL)):\n            if data_loader.dataset.mode != 'test':\n                input_, target = data['image'], data['target']\n            else:\n                input_, target = data['image'], None\n\n            output = model(input_.cuda())\n            output = activation(output)\n\n            confs, predicts = torch.topk(output, NUM_TOP_PREDICTS)\n            all_confs.append(confs)\n            all_predicts.append(predicts)\n\n            if target is not None:\n                all_targets.append(target)\n\n    predicts = torch.cat(all_predicts)\n    confs = torch.cat(all_confs)\n    targets = torch.cat(all_targets) if len(all_targets) else None\n\n    return predicts, confs, targets","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.973824Z","iopub.execute_input":"2021-08-18T14:57:01.974257Z","iopub.status.idle":"2021-08-18T14:57:01.987167Z","shell.execute_reply.started":"2021-08-18T14:57:01.974224Z","shell.execute_reply":"2021-08-18T14:57:01.986366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def generate_submission(test_loader, model, label_encoder):\n    predicts_gpu, confs_gpu, _ = inference(test_loader, model)\n    predicts, confs = predicts_gpu.cpu().numpy(), confs_gpu.cpu().numpy()\n\n    #The modified labels are inversed to the original labels\n    labels = [label_encoder.inverse_transform(pred) for pred in predicts]\n    print('labels')\n    print(np.array(labels))\n    print('confs')\n    print(np.array(confs))\n\n    sub = test_loader.dataset.df\n\n    def concat(label: np.ndarray, conf: np.ndarray):\n        return ' '.join([f'{str(L)} {str(np.round(c,4))}' for L, c in zip(label, conf)])\n    sub['landmarks'] = [concat(label, conf) for label, conf in zip(labels, confs)]\n\n    sub = sub.set_index('id')\n    sub.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:01.989101Z","iopub.execute_input":"2021-08-18T14:57:01.990688Z","iopub.status.idle":"2021-08-18T14:57:02.002244Z","shell.execute_reply.started":"2021-08-18T14:57:01.990664Z","shell.execute_reply":"2021-08-18T14:57:02.001446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_filenames=[]\nfor dirname, _, filenames in os.walk('../input/landmark-recognition-2021/test'):\n    for filename in filenames:\n        test_filenames.append(filename.split(\".\")[0])\ntest=pd.DataFrame({\"id\":test_filenames,\"landmarks\":\"\"})","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:02.003274Z","iopub.execute_input":"2021-08-18T14:57:02.004396Z","iopub.status.idle":"2021-08-18T14:57:09.951025Z","shell.execute_reply.started":"2021-08-18T14:57:02.004367Z","shell.execute_reply":"2021-08-18T14:57:09.950159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = ImageDataset(test, test_dir, mode='test')\ntest_loader = DataLoader(test_dataset, \n                         batch_size=BATCH_SIZE,\n                         shuffle=False, num_workers=NUM_WORKERS)","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:09.952301Z","iopub.execute_input":"2021-08-18T14:57:09.952650Z","iopub.status.idle":"2021-08-18T14:57:09.958064Z","shell.execute_reply.started":"2021-08-18T14:57:09.952615Z","shell.execute_reply":"2021-08-18T14:57:09.956845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load label encoder","metadata":{}},{"cell_type":"code","source":"label_encoder = LabelEncoder()\nlabel_encoder.classes_ = np.load('../input/pytorch-starter-train-efficientnet/classes.npy')","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:09.959378Z","iopub.execute_input":"2021-08-18T14:57:09.959936Z","iopub.status.idle":"2021-08-18T14:57:09.983585Z","shell.execute_reply.started":"2021-08-18T14:57:09.959896Z","shell.execute_reply":"2021-08-18T14:57:09.982832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load model weights","metadata":{}},{"cell_type":"code","source":"model = EfficientNetEncoderHead(depth=0, num_classes=len(label_encoder.classes_))\nmodel.cuda()\nmodel.load_state_dict(torch.load(\"../input/pytorch-starter-train-efficientnet/new_weight_efficientnet.pth\"))","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:09.984702Z","iopub.execute_input":"2021-08-18T14:57:09.985202Z","iopub.status.idle":"2021-08-18T14:57:18.713324Z","shell.execute_reply.started":"2021-08-18T14:57:09.985164Z","shell.execute_reply":"2021-08-18T14:57:18.712471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make prediction","metadata":{}},{"cell_type":"code","source":"generate_submission(test_loader, model, label_encoder)\npd.read_csv(\"./submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2021-08-18T14:57:18.714614Z","iopub.execute_input":"2021-08-18T14:57:18.714943Z","iopub.status.idle":"2021-08-18T14:58:51.731671Z","shell.execute_reply.started":"2021-08-18T14:57:18.714909Z","shell.execute_reply":"2021-08-18T14:58:51.730628Z"},"trusted":true},"execution_count":null,"outputs":[]}]}