{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"accelerator_type = 'GPU' ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if(accelerator_type == 'TPU'):    \n    !curl https://raw.githubusercontent.com/pytorch/xla/master/contrib/scripts/env-setup.py -o pytorch-xla-env-setup.py\n    !python pytorch-xla-env-setup.py --apt-packages libomp5 libopenblas-dev\n    import torch_xla\n    import torch_xla.core.xla_model as xm\n    device = xm.xla_device(n=4, devkind='TPU')\n    import torch","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport glob\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport matplotlib.image as mpimg\nimport cv2\nimport seaborn as sn\nfrom tqdm import tqdm\nfrom sklearn.preprocessing import LabelEncoder\n\nimport tensorflow as tf\nfrom keras.preprocessing.image import ImageDataGenerator\n\nfrom keras.optimizers import Adam\nfrom keras.callbacks import ModelCheckpoint\n\n!pip install ../input/efnwheelpy/efficientnet_pytorch-0.7.0-py3-none-any.whl\nimport efficientnet_pytorch\nfrom efficientnet_pytorch import EfficientNet\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.utils.data import DataLoader, Dataset\nimport os","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Reading required files"},{"metadata":{"trusted":true},"cell_type":"code","source":"directory = '../input/landmark-recognition-2020/'\ntrain_dir = '../input/landmark-recognition-2020/train/*/*/*/*'\ntest_dir = '../input/landmark-recognition-2020/test/*/*/*/*'\noutput_dir ='../output/kaggle/working/'\nimage_dir_train='../input/landmark-recognition-2020/train/'\nimage_dir_test='../input/landmark-recognition-2020/test/'\nos.listdir(directory)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Reading sample submission file"},{"metadata":{"trusted":true},"cell_type":"code","source":"test = pd.read_csv(os.path.join(directory,'sample_submission.csv'))\ntest['image_']=test.id.str[0]+\"/\"+test.id.str[1]+\"/\"+test.id.str[2]+\"/\"+test.id+\".jpg\"\ntest.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv(os.path.join(directory,'train.csv'))\ntrain[\"image_\"] = train.id.str[0]+\"/\"+train.id.str[1]+\"/\"+train.id.str[2]+\"/\"+train.id+\".jpg\"\ntrain[\"target_\"] = train.landmark_id.astype(str)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class createDataset(Dataset):\n    def __init__(self, transform, image_dir, df, train_type = True):        \n        self.df = df \n        self.image_dir = image_dir    \n        self.transform = transform\n        self.train_type=train_type\n        \n    def __len__(self):\n        return self.df.shape[0] \n    \n    def __getitem__(self,idx):\n        image_id = self.df.iloc[idx].id\n        image_name = f\"{self.image_dir}/{image_id[0]}/{image_id[1]}/{image_id[2]}/{image_id}.jpg\"\n        self.image = Image.open(image_name)              \n        self.image = self.transform(self.image)\n#         self.Y = torch.Tensor([self.df.iloc[idx].landmark_id]).type(torch.LongTensor)        \n        if(self.train_type):\n            return {'image':self.image, \n                    'label':self.df.iloc[idx].landmark_id}\n        else:\n            return {'image':self.image}","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Filtering out lables having samples less than minimum threshold"},{"metadata":{"trusted":true},"cell_type":"code","source":"Threshold_count = 142\n\nvalid_landmark_df = pd.DataFrame(train['landmark_id'].value_counts()).reset_index()\nvalid_landmark_df.columns =  ['landmark_id', 'count_']\nlist_valid_landmarks = list(valid_landmark_df[valid_landmark_df.count_ >= Threshold_count]['landmark_id'].unique())\nnum_classes = len(list_valid_landmarks)\nprint(\"Total classes in training :\", num_classes)\nprint(train.shape)\ntrain= train[train.landmark_id.isin(list_valid_landmarks)]\n\nvalid_img = lambda img: os.path.exists(f'{image_dir_test}/{img[0]}/{img[1]}/{img[2]}/{img}.jpg')\nif test.id.apply(valid_img).sum()==test.shape[0]:\n    print('All Testing Images are valid')\nelse:\n    print('Found invalid test Images')\n    test=test.loc[test.id.apply(exists)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from sklearn.preprocessing import LabelEncoder\nlabel_encoder = LabelEncoder()\nlabel_encoder.fit(train.landmark_id.values)\nprint('found classes', len(label_encoder.classes_))\nassert len(label_encoder.classes_) == num_classes\n\ntrain.landmark_id = label_encoder.transform(train.landmark_id)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Image transformations ands Image Loader"},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_BS = 64\nTEST_BS = 64\nmean = (0.485, 0.456, 0.406)\nstd =  (0.229,0.225,0.224)\nIMG_SIZE = 128\ntransformations = transforms.Compose([transforms.Resize((IMG_SIZE,IMG_SIZE),interpolation=Image.NEAREST),\n                                      transforms.ToTensor(),\n                                      transforms.Normalize(mean,std)\n                                     ]\n                                    )    \ntrain_data = createDataset(transform = transformations , df = train , image_dir = image_dir_train , train_type = True )\ntrain_loader = DataLoader(dataset = train_data, \n                          batch_size = TRAIN_BS,\n  #                      , num_workers =4\n                          shuffle = False)\n\ntest_data = createDataset(transform = transformations , df = test , \n                          image_dir = image_dir_test ,\n                          train_type = False )\ntest_loader = DataLoader(dataset = test_data, \n                         batch_size = TEST_BS\n#                          , num_workers =4\n                        )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Define competetion's metric : Global Average Precision \nImported global_average_precision method from https://evaluations.readthedocs.io/en/latest/kaggle_2020/global_average_precision.html\n\nGlobal Average Precision Score\nN predictions (label/confidence pairs) sorted in descending order by their confidence scores, then the Global Average Precision is computed as:\n\nGAP=1/M ∑i=1to N  P(i)*rel(i)\n\nN is the total number of predictions returned by the system, across all queries\n\nM is the total number of queries with at least one sample from the training set visible in it (note that some queries may not depict samples)\n\nP(i) is the precision at rank i. (example: consider rank 3 - we have already made 3 predictions, and 2 of them are correct. Then P(3) will be 2/3)\n\nrel(i) denotes the relevance of prediciton i: it’s 1 if the i-th prediction is correct, and 0 otherwise"},{"metadata":{},"cell_type":"markdown","source":"## Model Definition"},{"metadata":{"trusted":true},"cell_type":"code","source":"class EfficientNet(nn.Module):\n    def __init__(self, num_classes):\n        super(EfficientNet, self).__init__()\n        self.base = efficientnet_pytorch.EfficientNet.from_name(f'efficientnet-b0')\n        self.base.load_state_dict(torch.load('../input/modelfnb0/efficientnet-b0-355c32eb.pth'))\n        self.avg_pool = nn.AvgPool2d(3, stride=2)\n        self.dropout = nn.Dropout(p=0.2)\n#         self.batchnorm = nn.BatchNorm2d(100, affine=False)\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.dropout(x)\n#         x = self.batchnorm(x)\n        x = self.classifier(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = EfficientNet(num_classes=num_classes)\nif(accelerator_type == 'TPU'): \n    model = model.to(device)\nelse:\n    model = model.cuda()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-3, betas=(0.9,0.999), eps=1e-3, weight_decay=1e-4)\nlr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=len(train_loader), eta_min=1e-6)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## GAP example"},{"metadata":{"trusted":true},"cell_type":"code","source":"!cp ../input/gappython/global_average_precision.py ./\nimport global_average_precision\ny_true = {\n        'id_001': 123,\n        'id_002': None,\n        'id_003': 999,\n        'id_004': 123,\n        'id_005': 999,\n        'id_006': 888,\n        'id_007': 666,\n        'id_008': 666,\n        'id_009': None,\n        'id_010': 666,\n    }\ny_pred = {\n        'id_001': (123, 0.90),\n        'id_002': (123, 0.10),\n        'id_003': (999, 0.90),\n        'id_005': (999, 0.40),\n        'id_007': (555, 0.60),\n        'id_008': (666, 0.70),\n        'id_010': (666, 0.99),\n    }\n\ndef GAP( y_true,y_pred):\n    return global_average_precision.global_average_precision_score(y_true, y_pred)\n\nGAP(y_true, y_pred)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Run"},{"metadata":{"trusted":true},"cell_type":"code","source":"n_epochs = 1\nloss_list = []\nactivation = nn.Softmax(dim=1)\nloss_list=[]\ngap_score_list=[]\nmodel.train()\nfor epochs in range(n_epochs):    \n    for i, data_x_y in enumerate(tqdm(train_loader)):        \n        x= data_x_y['image']\n        y=data_x_y['label']  \n        \n        optimizer.zero_grad()\n        \n        if(accelerator_type == 'TPU'): \n            yhat =  model(x.to(device))\n            loss = criterion(yhat, y.to(device))   \n            \n        else:\n            yhat =  model(x.cuda())\n            loss = criterion(yhat, y.cuda())\n\n        conf_scores, pred_labels = torch.max(yhat.detach(), dim=1)\n        \n        loss.backward()\n        optimizer.step()\n        lr_scheduler.step()\n            \n        tuple_pred = list(zip(pred_labels.cpu().numpy(),conf_scores.cpu().numpy()))\n        true_labels =y.numpy()\n        y_true = {}\n        y_pred = {}\n\n        for j in range(len(tuple_pred)):\n            y_true[f'{j}'] = true_labels[j]\n            y_pred[f'{j}'] = tuple_pred[j]\n\n        gapscore = GAP(y_true, y_pred)\n        gap_score_list.append(gapscore)\n        loss_list.append(loss.detach())   \n#         if(i==5):\n#             break\n\n        print(f\" {i} LOSS <{loss}> GAP <{gapscore}> \") \n#         print(f\"GAP {gapscore}\") ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.eval()\n\nactivation = nn.Softmax(dim=1)\nall_predicts, all_confs = [], []\n\nwith torch.no_grad():    \n    for i, data in enumerate(tqdm(test_loader)):\n        input_ = data['image']\n\n        yhat = model(input_.cuda())\n        yhat = activation(yhat)\n\n        confs, predicts = torch.topk(yhat, 1)\n        all_confs.append(confs)\n        all_predicts.append(predicts)\n    predicts = torch.cat(all_predicts)\n    confs = torch.cat(all_confs)\n\npredicts_gpu, confs_gpu = predicts, confs\npredicts, confs = predicts_gpu.cpu().numpy(), confs_gpu.cpu().numpy()\nlabels = [label_encoder.inverse_transform(pred) for pred in predicts]\nlabels = [l[0] for l in labels]\nconfidence_score = [score[0] for score in confs]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_predicts[161].size()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(len(test)):\n    test.loc[i, \"landmarks\"] = str(labels[i]) + \" \" + str(confidence_score[i])\n        \ndel test['image_']\ntest.head()   ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test.to_csv(\"submission.csv\", index=False,float_format='%.6f')\ntest.head(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Thank you for going through my first ever solo competition. Please upvote if you liked the approach\n"}],"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":4,"nbformat_minor":4}