{"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":"Simple baseline utlizing Resnet18 pretrained on ImageNet. The below results are from finetuning only the last layer. This can be set to fine tune all parameters as well. \n\nBelow code assumes the following directory structure: <br>\n<b>dseg_660</b> <br>\n    |--imgs <br>\n    |--labels <br>\n    |--Cocos_Baseline.ipynb <br>\n    \npip/conda install the below packages if it isn't installed already. Namely, you will need pytorch, numpy, pandas, matplotlib, tqdm, sklearn and ml_metrics. ","metadata":{"id":"RTYLuE8vPHB5"}},{"cell_type":"code","source":"#https://drive.google.com/file/d/1-29ZWKDZJVxqs2oojHfqO3ohhCCgP83W/view?usp=sharing \n#mount drive to colab \n#from google.colab import drive\n#drive.mount(\"./drive\")","metadata":{"id":"RW-_2IOOxRK3","outputId":"65744b53-f37a-490f-d0a4-9f2d9bd8436f","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.getcwd()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#download data \nimport zipfile\nwith zipfile.ZipFile(\"../input/hbku2019/imgs.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./\")\nwith zipfile.ZipFile(\"../input/hbku2019/labels.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./\")","metadata":{"id":"RKC-5PBZx50G","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install efficientnet_pytorch\n!pip install ml_metrics","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n#from __future__ import print_function\n#from __future__ import division\n\n# Pytorch DL framework imports\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nfrom torchvision import datasets, models, transforms\nfrom torch.utils.data.dataset import Dataset\nfrom torch.utils.data import WeightedRandomSampler,DataLoader\n\n# Standard python libraries\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport time\nimport os\nimport copy\nfrom PIL import *\n\n# Progress bar\nfrom tqdm.notebook import tqdm\n\n# Function for shuffling the dataset\nfrom sklearn.utils import shuffle\n\n# Imports for calculating metrics\nimport ml_metrics as metrics\n\n# contemporary CNN architecture\nfrom efficientnet_pytorch import EfficientNet\n\nprint(\"PyTorch Version: \",torch.__version__)\nprint(\"Torchvision Version: \",torchvision.__version__)","metadata":{"id":"dbJPezOzPHCD","outputId":"992087aa-7f3e-457c-c22b-1ebbe811e411","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#settings\nbalance=True\ninterrupted=False\n\n# Batch size for training (change depending on how much memory you have)\nbatch_size = 128\n\n# Number of epochs to train for\nnum_epochs = 15\n\n# Number of classes\nnum_classes = 80\n","metadata":{"id":"xUtDw-Tllm1w","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check if gpu is available\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\"); device","metadata":{"id":"CVjQDjRRPHCG","outputId":"5e57eb85-bc81-4aad-f5fd-9ad31cbfca89","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"id":"SfoyjvwVMf-j","outputId":"1f23bb04-3ac0-45a6-84df-5cf1224aecaf","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#paths \nCKP_DIR=\"./training\"\nDATA_DIR= './labels'\nIMG_DIR_TRAIN = './imgs/train/'\nIMG_DIR_TEST = './imgs/test/'\ndata_csv= os.path.join(DATA_DIR,'labels_train.csv')","metadata":{"id":"wzgtLtTrPHCG","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs(CKP_DIR, exist_ok=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data","metadata":{"id":"i-slccyhPHCH"}},{"cell_type":"code","source":"#check categories\ncats = pd.read_csv(os.path.join(DATA_DIR , \"categories.csv\"), header=None)\ncats = list(cats[0]); cats","metadata":{"id":"sWhzQB_QPHCH","outputId":"8e567dff-0996-4fe3-c5d7-2c258ad4cc1f","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#check data\ndata = pd.read_csv(data_csv, header=None)\ndata.head()","metadata":{"id":"Fo8UBF31PHCI","outputId":"c3363eee-725a-4ec3-bb42-fd8a9d1eeafc","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image.open(\"./imgs/train/000000000015.jpg\")","metadata":{"id":"-BBOLBeKOwtl","outputId":"acf3b0b1-fbf1-4845-95b3-bb3dca5368a3","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image.open(\"./imgs/test/000000000003.jpg\")","metadata":{"id":"qeT_V-2JP1g_","outputId":"af626f64-10f6-42af-8eaf-ceb680541b16","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image.open(\"./imgs/train/000000000002.jpg\")","metadata":{"id":"h4RFuTqqPllK","outputId":"06e689f2-212b-495b-8703-6f92e45bc829","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Custom Dataset Object\nWe need to define a custom dataset object to define how raw img files will be loaded into the system for training/testing","metadata":{"id":"4kvs2e42PHCJ"}},{"cell_type":"code","source":"class CustomDatasetFromCSV(Dataset):\n    def __init__(self, df, transformations, folder):\n        \"\"\"\n        Args:\n            csv_path (string): path to csv file\n            transformations: pytorch transforms for transforms and tensor conversion\n            train: flag to determine if train or val set\n        \"\"\"\n        # Transforms\n        self.transforms = transformations\n        # Second column is the photos\n        self.image_arr = np.asarray(df.iloc[:, 0])\n        \n        # Second column is the labels\n        self.label_arr = np.asarray(df.iloc[:, 1:-1])\n\n        # Calculate len\n        self.data_len = len(self.label_arr)\n\n        #Init path to folder with photos\n        self.folder=folder\n\n    def __getitem__(self, index):\n\n        # Get image name from the pandas Series\n        single_image_name = self.image_arr[index]\n        \n        # Open image and convert to RGB (some dataset images are grayscale)\n        img_as_img = Image.open(os.path.join(self.folder, single_image_name)).convert('RGB')\n\n        #Use transforms\n        if self.transforms is not None:\n            img_as_tensor = self.transforms(img_as_img)\n\n        #Get image labels from the pandas DataFrame\n        single_image_label = self.label_arr[index]\n\n        return (img_as_tensor, single_image_label)\n\n    def __len__(self):\n        return self.data_len","metadata":{"id":"OkMAaLmUPHCJ","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load pretrined efficientnet (https://arxiv.org/abs/1905.11946) \nmodel_ft=EfficientNet.from_pretrained(\"efficientnet-b3\", num_classes=num_classes)\n#get defolt input size \ninput_size = EfficientNet.get_image_size('efficientnet-b3')\n# Img model input size\nim_size = input_size","metadata":{"id":"tnVIG_J_OX3L","outputId":"d8786451-6c18-4a0d-d2ac-a844522bcf87","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#add augmentations\ntransform_train = transforms.Compose([transforms.Resize((im_size, im_size)),                           \n                                transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1, hue=0),\n                                transforms.RandomHorizontalFlip(),\n                                transforms.RandomVerticalFlip(),\n                                transforms.RandomAffine(5),\n                                transforms.RandomRotation(180),\n                               transforms.ToTensor(),\n                               #transforms.Lambda(lambda img: img * 2.0 - 1.0)\n                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n                               ])\n# Transformations on inference\ntransform_val = transforms.Compose([transforms.Resize((im_size, im_size)),\n                               transforms.ToTensor(),\n                               #transforms.Lambda(lambda img: img * 2.0 - 1.0)\n                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n                               ])\n\ndf=pd.read_csv(data_csv, header=None)\ndf[\"weight\"]=1\ntrain=df.sample(frac=0.9, random_state=42)\nval=df.drop(train.index)\n\n#calculate weight of classes to improve balance \nif balance==True:\n    weight=train.iloc[:,1:-1].sum()\n    def make_weight(x, weight):\n        return min(weight[x[1:-1]==1])\n    train.weight=train.apply(make_weight, args=(weight,), axis=1)\n    train.weight=sum(weight)/train.weight\n\n\ntrainset = CustomDatasetFromCSV(train, transform_train, IMG_DIR_TRAIN)\nvalset = CustomDatasetFromCSV(val, transform_val, IMG_DIR_TRAIN)\n\n\nif balance==True:\n    class_weights_train=torch.tensor(train.weight.values)\n\n    weighted_sampler_train = WeightedRandomSampler(\n        weights=class_weights_train,\n        num_samples=len(class_weights_train),\n        replacement=True\n    )\n\n    dataloaders_dict = {\"train\":DataLoader(trainset , shuffle=False , batch_size=batch_size, sampler=weighted_sampler_train, num_workers=8),\n                  \"val\": DataLoader(valset , shuffle=False , batch_size=batch_size, num_workers=8)}\nelse:\n    dataloaders_dict = {\"train\":DataLoader(trainset , shuffle=True , batch_size=batch_size, num_workers=8),\n                  \"val\": DataLoader(valset , shuffle=False , batch_size=batch_size, num_workers=8)}","metadata":{"id":"FtUFznGPkRdW","outputId":"39ee6d51-9284-4b80-e48a-672d02060117","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model","metadata":{"id":"g0tkXfKXPHCM"}},{"cell_type":"code","source":"","metadata":{"id":"lmiLqjZzR8lT"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function for calculating MEAN Average Precision(MAP) score\ndef calc_map(preds, labels):\n    preds = np.around(preds.cpu().detach().numpy())\n    labels = labels.cpu().detach().numpy()             \n    pred = []\n    for i in preds:\n        cats = np.nonzero(list(i))[0]\n        pred.append(list(cats))\n    label = []\n    for i in labels:\n        cats = np.nonzero(list(i))[0]\n        label.append(list(cats))\n    return metrics.mapk(label, pred)","metadata":{"id":"3BajKBFOPHCN","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, dataloaders, criterion, optimizer,path_to_ckp, scheduler, num_epochs=25, star_epoch=0):\n    since = time.time()\n\n    val_map_history = []\n\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_mapk = 0.0\n    for epoch in range(star_epoch, num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0\n            running_mapk = 0.0\n            # Iterate over data.\n            for inputs, labels in tqdm(dataloaders[phase]):\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n                labels = labels.float()\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                # forward\n                # track history if only in train\n                with torch.set_grad_enabled(phase == 'train'):\n                    # Get model outputs and calculate loss\n                    outputs = model(inputs)\n                    # For multi-label\n                    outputs = torch.sigmoid(outputs)\n                    loss = criterion(outputs, labels)\n\n                    preds = outputs\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                # statistics\n                running_loss += loss.item() * inputs.size(0)\n                running_mapk += calc_map(preds, labels.data)\n\n            epoch_loss = running_loss / len(dataloaders[phase].dataset)\n\n            epoch_mapk = running_mapk / len(dataloaders[phase])\n\n            #scheduler step\n            if phase=='train':\n                scheduler.step()\n\n            print('{} Loss: {:.4f}  MAP: {:.4f}'.format(phase, epoch_loss,  epoch_mapk))\n\n\n            if phase == 'val' and epoch_mapk > best_mapk:\n                best_mapk = epoch_mapk\n                best_model_wts = copy.deepcopy(model.state_dict())\n                #save checkpoint\n                chp={\n                    \"model\":model.state_dict(),\n                    \"optimizer\":optimizer.state_dict(),\n                    \"epoch\":epoch,\n                    \"scheduler\":scheduler.state_dict()\n                }\n                torch.save(chp,os.path.join(path_to_ckp, \"model_1.pt\"))\n            if phase == 'val':\n                val_map_history.append(epoch_mapk)\n\n        print()\n\n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\n    print('Best val MAP: {:4f}'.format(best_mapk))\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model, val_map_history","metadata":{"id":"J1Sbs3kdPHCN","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#unfreeze percent of layers\ndef unfreeze(model,percent=0.25):\n    l = int(np.ceil(len(model._modules.keys())* percent))\n    l = list(model._modules.keys())[-l:]\n    print(f\"unfreezing these layer {l}\",)\n    for name in l:\n        for params in model._modules[name].parameters():\n            params.requires_grad_(True)","metadata":{"id":"kpA_5st-kG-k","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#freeze all layers\nfor param in model_ft.parameters():\n    param.requires_grad = False\n#unfreeze 60% of layers\nunfreeze(model_ft, 0.6)\n#unfreeze 60% of convolutional bloks\nunfreeze(model_ft._blocks, 0.6)","metadata":{"id":"fmrQnwZZxuBY","outputId":"0f68c6f8-1ec9-4e67-eb29-1ee95487ad2f","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def check_freeze(model):\n    for name ,layer in model._modules.items():\n        s = []\n        for l in layer.parameters():\n            s.append(l.requires_grad)\n        print(name ,all(s))\ncheck_freeze(model_ft)","metadata":{"id":"VigQ3mx5bQG9","outputId":"8aab0bef-8ed2-4526-f67a-40f1fb393b43","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Send the model to GPU\nmodel_ft = model_ft.to(device)","metadata":{"id":"j3bL-S-XPHCR","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://arxiv.org/pdf/2009.14119.pdf\n#I have no idea why it work worse then classic BCELoss at this case\nclass AsymmetricLossOptimized(nn.Module):\n\n    def __init__(self, gamma_neg=4, gamma_pos=1, clip=0.05, eps=1e-8, disable_torch_grad_focal_loss=False):\n        super(AsymmetricLossOptimized, self).__init__()\n\n        self.gamma_neg = gamma_neg\n        self.gamma_pos = gamma_pos\n        self.clip = clip\n        self.disable_torch_grad_focal_loss = disable_torch_grad_focal_loss\n        self.eps = eps\n\n        # prevent memory allocation and gpu uploading every iteration, and encourages inplace operations\n        self.targets = self.anti_targets = self.xs_pos = self.xs_neg = self.asymmetric_w = self.loss = None\n\n    def forward(self, x, y):\n        \"\"\"\"\n        Parameters\n        ----------\n        x: input logits\n        y: targets (multi-label binarized vector)\n        \"\"\"\n\n        self.targets = y\n        self.anti_targets = 1 - y\n\n        # Calculating Probabilities\n        self.xs_pos = torch.sigmoid(x)\n        self.xs_neg = 1.0 - self.xs_pos\n\n        # Asymmetric Clipping\n        if self.clip is not None and self.clip > 0:\n            self.xs_neg.add_(self.clip).clamp_(max=1)\n\n        # Basic CE calculation\n        self.loss = self.targets * torch.log(self.xs_pos.clamp(min=self.eps))\n        self.loss.add_(self.anti_targets * torch.log(self.xs_neg.clamp(min=self.eps)))\n\n        # Asymmetric Focusing\n        if self.gamma_neg > 0 or self.gamma_pos > 0:\n            if self.disable_torch_grad_focal_loss:\n                torch._C.set_grad_enabled(False)\n            self.xs_pos = self.xs_pos * self.targets\n            self.xs_neg = self.xs_neg * self.anti_targets\n            self.asymmetric_w = torch.pow(1 - self.xs_pos - self.xs_neg,\n                                          self.gamma_pos * self.targets + self.gamma_neg * self.anti_targets)\n            if self.disable_torch_grad_focal_loss:\n                torch._C.set_grad_enabled(True)\n            self.loss *= self.asymmetric_w\n\n        return -self.loss.sum()\n","metadata":{"id":"CjHHuVVCPHCS","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer_ft=torch.optim.Adam(model_ft.parameters(),lr=0.0001)\n#criterion=AsymmetricLossOptimized()\ncriterion = torch.nn.BCELoss()\n#Scheduler for linear learning rate reduction\nfrom torch.optim import lr_scheduler\nscheduler = lr_scheduler.StepLR(optimizer_ft, step_size=5, gamma = 0.1)\nepoch=0","metadata":{"id":"opDHY7X9PHCT","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device","metadata":{"id":"JTaZdBz_1-PW","outputId":"b21f85d4-9c6c-488b-acac-2ac2aabcadc6","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load a checkpoint if the training session was interrupted\nif interrupted:\n    ckp=torch.load(CKP_DIR+\"/model_1.pt\")\n    model_ft.load_state_dict(ckp[\"model\"])\n    epoch=ckp[\"epoch\"]\n    optimizer_ft.load_state_dict(ckp[\"optimizer\"])\n    scheduler.load_state_dict(ckp[\"scheduler\"])\n    print(\"checkpoint loaded\")","metadata":{"id":"uZWmKMEOciJu","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#train model\nmodel_ft, hist = train_model(model_ft, dataloaders_dict, criterion, optimizer_ft, CKP_DIR, scheduler, num_epochs=num_epochs, star_epoch=epoch)","metadata":{"id":"huuGmQhN2811","outputId":"71a3c5dc-d48f-41e6-850f-c8da7dd88b81","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epoch","metadata":{"id":"oXzk_rieiWhD","outputId":"ff519f88-fa74-49f7-a8a2-94c099fbdc2e","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Submission\nFollowing code creates a submission file. The submission file should be in the following format: <br>\nimg_id, predictions <br>\nwhere predictions are all the categories in the corresponding image separated by a space. For example <br>\nimg_34, 0 4 <br>\nmeans that image im_34 contains the classes 'person' and 'airplane'.","metadata":{"id":"nEiITlc-PHCU"}},{"cell_type":"code","source":"\nclass CustomTestDataset(Dataset):\n    def __init__(self, path, transformations):\n        \"\"\"\n        Args:\n            csv_path (string): path to csv file\n            transformations: pytorch transforms for transforms and tensor conversion\n        \"\"\"\n        # Transforms\n        self.transforms = transformations\n        # Read the csv file\n        self.paths = sorted(os.listdir(path))\n  \n        self.image_arr = np.asarray(self.paths)\n        \n        self.data_len = len(self.image_arr)\n\n    def __getitem__(self, index):\n        single_image_name = self.image_arr[index]\n        \n        img_as_img = Image.open(os.path.join(IMG_DIR_TEST,single_image_name)).convert('RGB')\n\n        if self.transforms is not None:\n            img_as_tensor = self.transforms(img_as_img)\n\n        return (img_as_tensor, single_image_name)\n\n    def __len__(self):\n        return self.data_len","metadata":{"id":"yKN0tV5yPHCU","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# If augmenting data through transformations, take care\n# not to augment dev and test data\ntransformations=transforms.Compose([transforms.Resize((im_size, im_size)),\n                               transforms.ToTensor(),\n                               transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n                               ])\n\ntest_dataset = CustomTestDataset(\"./imgs/test\", transformations)","metadata":{"id":"ANsePb9ePHCV","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataloaders_dict = torch.utils.data.DataLoader(test_dataset, \n                                                   batch_size=1, \n                                                   shuffle=False, \n                                                   num_workers=4) ","metadata":{"id":"fLuln9rQPHCV","outputId":"0db14bb9-a1d8-4560-f4db-3dd97d0e93a1","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"next(model_ft.parameters()).device","metadata":{"id":"FqTH6lE3hUeF","outputId":"6a8397a4-f540-4085-b053-34b750352d22","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = None\nmodel_ft.eval()\nfor input_img, input_name in tqdm(dataloaders_dict):\n    inputs = input_img.to(device)\n    with torch.set_grad_enabled(False):\n        outputs = model_ft(inputs)\n        outputs = np.around(torch.sigmoid(outputs).cpu().detach().numpy())\n    try:\n        predictions = np.concatenate((predictions,outputs))\n    except:\n        predictions = outputs\n","metadata":{"id":"TKAV-ToMPHCV","outputId":"f4743b94-c294-4d10-d0e2-460ac6458b19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = []\nfor x in predictions:\n    a = np.nonzero(x)[0]\n    b = \" \".join(map(str, a))\n    labels.append(b)","metadata":{"id":"3x1UNuXpPHCW","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame(\n    {'id': test_dataset.paths,\n     'predictions': labels\n    })","metadata":{"id":"c7L4AICHPHCW","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(os.path.join(CKP_DIR,'sample_submission.csv'), index=False)","metadata":{"id":"Elo_xLP8PHCW","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Evaluation","metadata":{"id":"BBhY_udYPHCX"}},{"cell_type":"code","source":"# Load your image and preprocess it \nsample_img = Image.open(\"./imgs/test/000000003808.jpg\").convert('RGB')\n# If augmenting data through transformations, take care\n# not to augment dev and test data\nimg_tensor = transform_val(sample_img)\nimg_tensor = img_tensor.reshape(1, 3, 300, 300)","metadata":{"id":"aA9tpXU_PHCX","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Set model to evaluation mode\nmodel_ft.eval()\nwith torch.no_grad():\n    img_tensor_tensor = img_tensor.to(device)\n    outputs = model_ft(img_tensor_tensor)\n    outputs = torch.sigmoid(outputs)\n    preds = np.around(outputs.cpu().detach().numpy())","metadata":{"id":"ouh11ssgPHCX","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get categories classified as true\ncats_list = [cats[i] for i, x in enumerate(list(preds.squeeze())) if x == 1]","metadata":{"id":"bxC0-6NNPHCX","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(cats_list)","metadata":{"id":"rMOPJiSiPHCY","outputId":"89a875f4-3b5d-48a3-96de-814adaee7add","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_img","metadata":{"id":"3IuusHH4alPR","outputId":"127d06b1-d2ee-4b2e-d5ab-ab9128978696","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"","metadata":{"id":"olN-d0SYNsox"},"execution_count":null,"outputs":[]}]}