{"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":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Global Wheat Detection - Faster RCNN</h2>","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom tqdm.notebook import tqdm\nimport torch\nimport torchvision\nimport torchvision.transforms as T\nfrom collections import defaultdict, deque\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nimport ast\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\n\nimport cv2\nimport os,sys,matplotlib,re\nfrom PIL import Image\nfrom skimage import exposure\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport matplotlib.pyplot as plt\nimport matplotlib.image as immg\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":false,"execution":{"iopub.status.busy":"2021-06-24T07:55:26.965326Z","iopub.execute_input":"2021-06-24T07:55:26.965663Z","iopub.status.idle":"2021-06-24T07:55:26.973653Z","shell.execute_reply.started":"2021-06-24T07:55:26.965633Z","shell.execute_reply":"2021-06-24T07:55:26.972576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:05:39.878972Z","iopub.execute_input":"2021-06-24T08:05:39.879290Z","iopub.status.idle":"2021-06-24T08:05:39.883775Z","shell.execute_reply.started":"2021-06-24T08:05:39.879261Z","shell.execute_reply":"2021-06-24T08:05:39.882825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = '../input/gwd-512-image-resized/'\ntrain_df = pd.read_csv('../input/global-wheat-detection/train.csv')\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:09:20.479453Z","iopub.execute_input":"2021-06-24T08:09:20.479831Z","iopub.status.idle":"2021-06-24T08:09:20.631129Z","shell.execute_reply.started":"2021-06-24T08:09:20.479801Z","shell.execute_reply":"2021-06-24T08:09:20.630060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['x_min'] = -1\ntrain_df['y_min'] = -1\ntrain_df['w'] = -1\ntrain_df['h'] = -1\n\ntrain_df[['x_min', 'y_min', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: ast.literal_eval(x)))\ntrain_df.drop(columns=['bbox'], inplace=True)\ntrain_df['x_min'] = train_df['x_min'].astype(np.float)\ntrain_df['y_min'] = train_df['y_min'].astype(np.float)\ntrain_df['w'] = train_df['w'].astype(np.float)\ntrain_df['h'] = train_df['h'].astype(np.float)\ntrain_df['x_max'] = train_df['x_min']+train_df['w']\ntrain_df['y_max'] = train_df['y_min']+train_df['h']","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:09:20.978594Z","iopub.execute_input":"2021-06-24T08:09:20.978911Z","iopub.status.idle":"2021-06-24T08:09:23.581783Z","shell.execute_reply.started":"2021-06-24T08:09:20.978883Z","shell.execute_reply":"2021-06-24T08:09:23.580829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:09:23.583361Z","iopub.execute_input":"2021-06-24T08:09:23.583732Z","iopub.status.idle":"2021-06-24T08:09:23.597497Z","shell.execute_reply.started":"2021-06-24T08:09:23.583695Z","shell.execute_reply":"2021-06-24T08:09:23.596601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = train_df.copy()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:10:07.278843Z","iopub.execute_input":"2021-06-24T08:10:07.279167Z","iopub.status.idle":"2021-06-24T08:10:07.287551Z","shell.execute_reply.started":"2021-06-24T08:10:07.279136Z","shell.execute_reply":"2021-06-24T08:10:07.286495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['x_min'] = df['x_min']*512/1024\ndf['x_max'] = np.ceil(df['x_max']*512/1024)\ndf['y_min'] = df['y_min']*512/1024\ndf['y_max'] = np.ceil(df['y_max']*512/1024)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:10:09.098353Z","iopub.execute_input":"2021-06-24T08:10:09.098693Z","iopub.status.idle":"2021-06-24T08:10:09.113801Z","shell.execute_reply.started":"2021-06-24T08:10:09.098664Z","shell.execute_reply":"2021-06-24T08:10:09.112791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.describe()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:10:42.739344Z","iopub.execute_input":"2021-06-24T08:10:42.739680Z","iopub.status.idle":"2021-06-24T08:10:42.808198Z","shell.execute_reply.started":"2021-06-24T08:10:42.739650Z","shell.execute_reply":"2021-06-24T08:10:42.807188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:red; border:1px dotted red\">Dataset</h2>","metadata":{}},{"cell_type":"code","source":"df = df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:10:56.939120Z","iopub.execute_input":"2021-06-24T08:10:56.939444Z","iopub.status.idle":"2021-06-24T08:10:56.949773Z","shell.execute_reply.started":"2021-06-24T08:10:56.939413Z","shell.execute_reply":"2021-06-24T08:10:56.948873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_grp = df.groupby(['image_id'])\nb_fea = ['x_min', 'y_min', 'x_max', 'y_max']","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:11:00.598593Z","iopub.execute_input":"2021-06-24T08:11:00.598902Z","iopub.status.idle":"2021-06-24T08:11:00.603149Z","shell.execute_reply.started":"2021-06-24T08:11:00.598875Z","shell.execute_reply":"2021-06-24T08:11:00.602326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:11:00.928129Z","iopub.execute_input":"2021-06-24T08:11:00.928445Z","iopub.status.idle":"2021-06-24T08:11:00.931990Z","shell.execute_reply.started":"2021-06-24T08:11:00.928416Z","shell.execute_reply":"2021-06-24T08:11:00.931119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"name = df.image_id.unique()[9]\nloc = path+name+'.jpg'\naaa = df_grp.get_group(name)\nbbx = aaa.loc[:,b_fea]\nimg = immg.imread(loc)\nfig,ax = plt.subplots(figsize=(18,10))\nax.imshow(img,cmap='binary')\nfor i in range(len(bbx)):\n    box = bbx.iloc[i].values\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=1,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='white', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:11:53.999156Z","iopub.execute_input":"2021-06-24T08:11:53.999484Z","iopub.status.idle":"2021-06-24T08:11:55.030418Z","shell.execute_reply.started":"2021-06-24T08:11:53.999453Z","shell.execute_reply":"2021-06-24T08:11:55.029410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset","metadata":{}},{"cell_type":"code","source":"class WheatDataset(object):\n    def __init__(self, df, IMG_DIR, transforms=None):\n        # select only those classes that have boxes\n        \n        self.df = df\n        self.img_dir = IMG_DIR\n        self.image_ids = self.df['image_id'].unique().tolist()\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    \n    def __getitem__(self, idx):\n        image_id = self.image_ids[idx]\n        records = self.df[self.df['image_id'] == image_id]\n        image = cv2.imread(self.img_dir+image_id+\".jpg\",cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        \n        boxes = records[['x_min', 'y_min', 'x_max', 'y_max']].to_numpy()\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        labels = torch.ones((records.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([idx])\n        target['area'] = torch.as_tensor(area, dtype=torch.float32)\n        target['iscrowd'] = torch.zeros((records.shape[0],), dtype=torch.int64)\n    \n        if self.transforms:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': labels\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n            \n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n\n        return torch.tensor(image), target, image_id","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2021-06-24T08:13:51.556444Z","iopub.execute_input":"2021-06-24T08:13:51.556786Z","iopub.status.idle":"2021-06-24T08:13:51.570286Z","shell.execute_reply.started":"2021-06-24T08:13:51.556755Z","shell.execute_reply":"2021-06-24T08:13:51.569625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Transforms","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = (512,512)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:19:48.973365Z","iopub.execute_input":"2021-06-24T08:19:48.973726Z","iopub.status.idle":"2021-06-24T08:19:48.977826Z","shell.execute_reply.started":"2021-06-24T08:19:48.973695Z","shell.execute_reply":"2021-06-24T08:19:48.976929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\ndef get_train_transform():\n    return A.Compose([\n        A.Flip(0.5),\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})\n\ndef get_valid_transform():\n    return A.Compose([\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:20:40.164339Z","iopub.execute_input":"2021-06-24T08:20:40.164677Z","iopub.status.idle":"2021-06-24T08:20:40.169879Z","shell.execute_reply.started":"2021-06-24T08:20:40.164644Z","shell.execute_reply":"2021-06-24T08:20:40.169012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_dir = \"../input/gwd-512-image-resized/\"","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:20:59.504143Z","iopub.execute_input":"2021-06-24T08:20:59.504465Z","iopub.status.idle":"2021-06-24T08:20:59.508560Z","shell.execute_reply.started":"2021-06-24T08:20:59.504435Z","shell.execute_reply":"2021-06-24T08:20:59.507633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"WDS = WheatDataset(df, img_dir ,get_train_transform())","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:21:26.194066Z","iopub.execute_input":"2021-06-24T08:21:26.194376Z","iopub.status.idle":"2021-06-24T08:21:26.208831Z","shell.execute_reply.started":"2021-06-24T08:21:26.194346Z","shell.execute_reply":"2021-06-24T08:21:26.207895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Checking a Dataset Sample","metadata":{}},{"cell_type":"code","source":"import random\nimg, tar,_ = WDS[random.randint(0,1000)]\nbbox = tar['boxes'].numpy()\nfig,ax = plt.subplots(figsize=(18,10))\nax.imshow(img.permute(1,2,0).cpu().numpy())\nfor i in range(len(bbox)):\n    box = bbox[i]\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='red', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:21:42.044099Z","iopub.execute_input":"2021-06-24T08:21:42.044422Z","iopub.status.idle":"2021-06-24T08:21:42.757143Z","shell.execute_reply.started":"2021-06-24T08:21:42.044390Z","shell.execute_reply":"2021-06-24T08:21:42.756352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_ids = df['image_id'].unique()\nvalid_ids = image_ids[-665:]\ntrain_ids = image_ids[:-665]\nvalid_df = df[df['image_id'].isin(valid_ids)]\ntrain_df = df[df['image_id'].isin(train_ids)]\ntrain_df.shape,valid_df.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:22:39.904153Z","iopub.execute_input":"2021-06-24T08:22:39.904480Z","iopub.status.idle":"2021-06-24T08:22:39.949876Z","shell.execute_reply.started":"2021-06-24T08:22:39.904448Z","shell.execute_reply":"2021-06-24T08:22:39.948999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## DataLoader","metadata":{}},{"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = WheatDataset(train_df,img_dir , get_train_transform())\nvalid_dataset = WheatDataset(valid_df,img_dir, get_valid_transform())\n\n\n# split the dataset in train and test set\nindices = torch.randperm(len(train_dataset)).tolist()\n\ntrain_data_loader = DataLoader(\n    train_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)\n\nvalid_data_loader = DataLoader(\n    valid_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:25:01.964467Z","iopub.execute_input":"2021-06-24T08:25:01.964825Z","iopub.status.idle":"2021-06-24T08:25:01.984562Z","shell.execute_reply.started":"2021-06-24T08:25:01.964795Z","shell.execute_reply":"2021-06-24T08:25:01.983756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Training</h2>","metadata":{}},{"cell_type":"code","source":"num_classes = 2  # 1 class (wheat) + background\n# load a model; pre-trained on COCO\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)\n# get number of input features for the classifier\nin_features = model.roi_heads.box_predictor.cls_score.in_features\n\n# replace the pre-trained head with a new one\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:43.144172Z","iopub.execute_input":"2021-06-24T08:49:43.144488Z","iopub.status.idle":"2021-06-24T08:49:43.845462Z","shell.execute_reply.started":"2021-06-24T08:49:43.144457Z","shell.execute_reply":"2021-06-24T08:49:43.844674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.to(device)\nparams = [p for p in model.parameters() if p.requires_grad]\noptimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)\nlr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)\n#lr_scheduler = None","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:44.202739Z","iopub.execute_input":"2021-06-24T08:49:44.203045Z","iopub.status.idle":"2021-06-24T08:49:44.265107Z","shell.execute_reply.started":"2021-06-24T08:49:44.203015Z","shell.execute_reply":"2021-06-24T08:49:44.264309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Averager","metadata":{}},{"cell_type":"code","source":"class Averager:\n    def __init__(self):\n        self.current_total = 0.0\n        self.iterations = 0.0\n\n    def send(self, value):\n        self.current_total += value\n        self.iterations += 1\n\n    @property\n    def value(self):\n        if self.iterations == 0:\n            return 0\n        else:\n            return 1.0 * self.current_total / self.iterations\n\n    def reset(self):\n        self.current_total = 0.0\n        self.iterations = 0.0","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:46.153374Z","iopub.execute_input":"2021-06-24T08:49:46.153720Z","iopub.status.idle":"2021-06-24T08:49:46.159698Z","shell.execute_reply.started":"2021-06-24T08:49:46.153686Z","shell.execute_reply":"2021-06-24T08:49:46.158789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Below apply_nms function\n\n**Performs non-maximum suppression (NMS) on the boxes according to their intersection-over-union (IoU).**\n\n**NMS iteratively removes lower scoring boxes which have an IoU greater than iou_threshold with another (higher scoring) box.**\n\n**If multiple boxes have the exact same score and satisfy the IoU criterion with respect to a reference box, the selected box is not guaranteed to be the same between CPU and GPU. This is similar to the behavior of argsort in PyTorch when repeated values are present.**\n\nSource : https://pytorch.org/vision/stable/ops.html","metadata":{}},{"cell_type":"code","source":"# the function takes the original prediction and the iou threshold.\ndef apply_nms(orig_prediction, iou_thresh=0.2):\n    \n    # torchvision returns the indices of the bboxes to keep\n    keep = torchvision.ops.nms(orig_prediction['boxes'], orig_prediction['scores'], iou_thresh)\n    \n    final_prediction = orig_prediction\n    final_prediction['boxes'] = final_prediction['boxes'][keep]\n    final_prediction['scores'] = final_prediction['scores'][keep]\n    final_prediction['labels'] = final_prediction['labels'][keep]\n    \n    return final_prediction","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:47.738759Z","iopub.execute_input":"2021-06-24T08:49:47.739089Z","iopub.status.idle":"2021-06-24T08:49:47.746022Z","shell.execute_reply.started":"2021-06-24T08:49:47.739059Z","shell.execute_reply":"2021-06-24T08:49:47.745134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training","metadata":{}},{"cell_type":"code","source":"num_epochs = 10","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:49.182907Z","iopub.execute_input":"2021-06-24T08:49:49.183223Z","iopub.status.idle":"2021-06-24T08:49:49.187166Z","shell.execute_reply.started":"2021-06-24T08:49:49.183192Z","shell.execute_reply":"2021-06-24T08:49:49.186215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_hist = Averager()\nbest_epoch = 0\nmin_loss = sys.maxsize\nfor epoch in range(num_epochs):\n    loss_hist.reset()\n    tk = tqdm(train_data_loader)\n    model.train();\n    for images, targets, image_ids in tk:\n        \n        images = list(image.to(device) for image in images)\n        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n        loss_dict = model(images, targets)\n\n        losses = sum(loss for loss in loss_dict.values())\n        loss_value = losses.item()\n\n        loss_hist.send(loss_value)\n\n        optimizer.zero_grad()\n        losses.backward()\n        optimizer.step()\n        \n        tk.set_postfix(train_loss=loss_value)\n    tk.close()\n    \n    # update the learning rate\n    if lr_scheduler is not None:\n        lr_scheduler.step()\n\n    print(f\"Epoch #{epoch} loss: {loss_hist.value}\") \n    \n    if loss_hist.value<min_loss:\n        print(\"Better model found at epoch {0} with {1:0.5f} loss value\".format(epoch,loss_hist.value))\n        torch.save(model.state_dict(), f\"model_state_epoch_{epoch}.pth\")\n        min_loss = loss_hist.value\n        best_epoch = epoch\n    #validation \n    model.eval();\n    with torch.no_grad():\n        tk = tqdm(valid_data_loader)\n        for images, targets, image_ids in tk:\n        \n            images = list(image.to(device) for image in images)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n            val_output = model(images)\n            val_output = [{k: v.to('cpu') for k, v in t.items()} for t in val_output]\n            IOU = []\n            for j in range(len(val_output)):\n                val_out = apply_nms(val_output[j])\n                a,b = val_out['boxes'].cpu().detach(), targets[j]['boxes'].cpu().detach()\n                chk = torchvision.ops.box_iou(a,b)\n                res = np.nanmean(chk.sum(axis=1)/(chk>0).sum(axis=1))\n                IOU.append(res)\n            tk.set_postfix(IoU=np.mean(IOU))\n        tk.close()\n        \nmodel.load_state_dict(torch.load(f\"./model_state_epoch_{best_epoch}.pth\"));","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:49:50.105472Z","iopub.execute_input":"2021-06-24T08:49:50.105819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load(f\"./model_state_epoch_{best_epoch}.pth\"));","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:46:05.670215Z","iopub.execute_input":"2021-06-24T08:46:05.670552Z","iopub.status.idle":"2021-06-24T08:46:05.814697Z","shell.execute_reply.started":"2021-06-24T08:46:05.670502Z","shell.execute_reply":"2021-06-24T08:46:05.813871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Analyze</h2>","metadata":{}},{"cell_type":"markdown","source":"## Validation And Prediction","metadata":{}},{"cell_type":"code","source":"img,target,_ = valid_dataset[50]\n# put the model in evaluation mode\nmodel.eval()\nwith torch.no_grad():\n    prediction = model([img.to(device)])[0]\n    \nprint('predicted #boxes: ', len(prediction['boxes']))\nprint('real #boxes: ', len(target['boxes']))","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:46:39.243335Z","iopub.execute_input":"2021-06-24T08:46:39.243674Z","iopub.status.idle":"2021-06-24T08:46:39.332993Z","shell.execute_reply.started":"2021-06-24T08:46:39.243643Z","shell.execute_reply":"2021-06-24T08:46:39.332111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Ground Truths","metadata":{}},{"cell_type":"code","source":"bbox = target['boxes'].numpy()\nfig,ax = plt.subplots(1,figsize=(18,10))\nax.imshow(img.permute(1,2,0).cpu().numpy())\nfor i in range(len(bbox)):\n    box = bbox[i]\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], \"wheat\", verticalalignment='top', color='red', fontsize=13, weight='bold')\n    ax.add_patch(rect)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:46:54.240662Z","iopub.execute_input":"2021-06-24T08:46:54.240984Z","iopub.status.idle":"2021-06-24T08:46:54.905743Z","shell.execute_reply.started":"2021-06-24T08:46:54.240954Z","shell.execute_reply":"2021-06-24T08:46:54.904964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_valid(img,prediction,nms=True,detect_thresh=0.5):\n    fig,ax = plt.subplots(figsize=(18,10))\n    val_img = img.permute(1,2,0).cpu().numpy()\n    ax.imshow(val_img)\n    nms_prediction = apply_nms(prediction, iou_thresh=0.2) if nms else prediction\n    val_scores = nms_prediction['scores'].cpu().detach().numpy()\n    bbox = nms_prediction['boxes'].cpu().detach().numpy()\n    for i in range(len(bbox)):\n        if val_scores[i]>=detect_thresh:\n            box = bbox[i]\n            x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n            rect = matplotlib.patches.Rectangle((x,y),w,h,linewidth=2 ,edgecolor='r',facecolor='none',)\n            ax.text(*box[:2], \"wheat {0:.3f}\".format(val_scores[i]), verticalalignment='top', color='white', fontsize=12, weight='bold')\n            ax.add_patch(rect)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:46:59.988758Z","iopub.execute_input":"2021-06-24T08:46:59.989076Z","iopub.status.idle":"2021-06-24T08:46:59.998171Z","shell.execute_reply.started":"2021-06-24T08:46:59.989046Z","shell.execute_reply":"2021-06-24T08:46:59.996634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predictions on valid set","metadata":{}},{"cell_type":"code","source":"plot_valid(img,prediction)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:47:02.633355Z","iopub.execute_input":"2021-06-24T08:47:02.633703Z","iopub.status.idle":"2021-06-24T08:47:03.271283Z","shell.execute_reply.started":"2021-06-24T08:47:02.633670Z","shell.execute_reply":"2021-06-24T08:47:03.270337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 align=center style=\"color:blue; border:1px dotted blue\">Predictions on Test Dataset</h2>","metadata":{}},{"cell_type":"code","source":"submission = pd.read_csv('../input/global-wheat-detection/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:00.649452Z","iopub.execute_input":"2021-06-24T08:48:00.649806Z","iopub.status.idle":"2021-06-24T08:48:00.663643Z","shell.execute_reply.started":"2021-06-24T08:48:00.649776Z","shell.execute_reply":"2021-06-24T08:48:00.662855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(object):\n    def __init__(self, df, IMG_DIR, transforms=None):\n        # select only those classes that have boxes\n        \n        self.df = df\n        self.img_dir = IMG_DIR\n        self.transforms = transforms\n        self.image_ids = self.df['image_id'].tolist()\n        \n    def __len__(self):\n        return len(self.image_ids)\n    \n    def __getitem__(self, idx):\n        \n        image_id = self.image_ids[idx]\n        image = cv2.imread(self.img_dir+image_id+\".jpg\",cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        #image /= 255.0\n        \n        if self.transforms:\n            sample = {\n                'image': image,\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n\n        return image, image_id","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:03.908486Z","iopub.execute_input":"2021-06-24T08:48:03.908974Z","iopub.status.idle":"2021-06-24T08:48:03.916767Z","shell.execute_reply.started":"2021-06-24T08:48:03.908938Z","shell.execute_reply":"2021-06-24T08:48:03.915320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_test_transform(IMG_SIZE=(512,512)):\n    return A.Compose([\n         A.Normalize(mean=(0, 0, 0), std=(1, 1, 1), max_pixel_value=255.0, p=1.0),\n        A.Resize(*IMG_SIZE),\n        ToTensorV2(p=1.0)\n    ])","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:09.308339Z","iopub.execute_input":"2021-06-24T08:48:09.308724Z","iopub.status.idle":"2021-06-24T08:48:09.315826Z","shell.execute_reply.started":"2021-06-24T08:48:09.308678Z","shell.execute_reply":"2021-06-24T08:48:09.314575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img_dir = '../input/global-wheat-detection/test/'","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:14.323568Z","iopub.execute_input":"2021-06-24T08:48:14.323882Z","iopub.status.idle":"2021-06-24T08:48:14.328430Z","shell.execute_reply.started":"2021-06-24T08:48:14.323852Z","shell.execute_reply":"2021-06-24T08:48:14.327463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = (512,512)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:16.848211Z","iopub.execute_input":"2021-06-24T08:48:16.848543Z","iopub.status.idle":"2021-06-24T08:48:16.852746Z","shell.execute_reply.started":"2021-06-24T08:48:16.848496Z","shell.execute_reply":"2021-06-24T08:48:16.851874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(submission, test_img_dir ,get_test_transform(IMG_SIZE))","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:19.128336Z","iopub.execute_input":"2021-06-24T08:48:19.128678Z","iopub.status.idle":"2021-06-24T08:48:19.132985Z","shell.execute_reply.started":"2021-06-24T08:48:19.128645Z","shell.execute_reply":"2021-06-24T08:48:19.132133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for j in range(submission.shape[0]):\n    img,_ = test_dataset[j]\n    # put the model in evaluation mode\n    model.eval()\n    with torch.no_grad():\n        prediction = model([img.to(device)])[0]\n    plot_valid(img,prediction)","metadata":{"execution":{"iopub.status.busy":"2021-06-24T08:48:26.609233Z","iopub.execute_input":"2021-06-24T08:48:26.609574Z","iopub.status.idle":"2021-06-24T08:48:32.528403Z","shell.execute_reply.started":"2021-06-24T08:48:26.609521Z","shell.execute_reply":"2021-06-24T08:48:32.527641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}