{"cells":[{"metadata":{"_uuid":"5858ad6f-70c5-43f8-a7f7-e3ee248cf3d8","_cell_guid":"7411df24-bcf7-42a6-bb13-69c3434e1e91","trusted":true},"cell_type":"markdown","source":"It is a combined famework of efficientdet, which has TTA, PL, etc. It is a combination of works from notebooks of this competition. The final score is about 0.7340. I hope you can get some help from this notebook.","execution_count":null},{"metadata":{"_uuid":"a2429e32-c6a0-490e-847e-fc5cb1d933f1","_cell_guid":"78945832-cffb-4780-b986-104a6fc9bd72","trusted":true},"cell_type":"code","source":"!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n!pip install --no-deps '../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5146ed49-8d33-46b8-b695-0c4f540f7324","_cell_guid":"e1542f60-ba1a-45a7-a12d-a38c4dcf90f0","trusted":true},"cell_type":"code","source":"import sys\nsys.path.insert(0, \"../input/omegaconf\")\nsys.path.insert(0, \"../input/weightedboxesfusion\")\n\nimport ensemble_boxes \nimport torch\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom torch.utils.data import Dataset,DataLoader\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\nimport cv2\nimport gc\nfrom tqdm import tqdm\nfrom matplotlib import pyplot as plt\nimport os\nfrom datetime import datetime\nimport time\nimport random\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch.utils.data.sampler import SequentialSampler, RandomSampler","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c603a7b6-9477-4b97-933c-fa83dd90a273","_cell_guid":"b0cc0b85-8603-4c7b-a5d5-a0e947cf4347","trusted":true},"cell_type":"code","source":"sys.path.insert(0, \"../input/timm-efficientdet-pytorch\")\nfrom effdet import get_efficientdet_config, EfficientDet, DetBenchEval\nfrom effdet.efficientdet import HeadNet","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fd2cc5e3-16e1-42cb-be3b-e85522abf0fa","_cell_guid":"0a77ba71-590a-4041-b7d0-079c877a522b","trusted":true},"cell_type":"code","source":"best_score_threshold = 0.54","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9bb23b3d-00c1-48e8-ba1f-a50cc9b0fd94","_cell_guid":"ab751c2f-ba02-4b82-aa40-949ec49af815","trusted":true},"cell_type":"code","source":"SEED = 42\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n\nseed_everything(SEED)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cbb26d47-fe4e-47bf-b8b9-540f495e2ac2","_cell_guid":"c11fd3d0-38ac-4a7c-90dd-18a5d5e625fd","trusted":true},"cell_type":"code","source":"effdet_weights = \"../input/effdetretrains/retrain.bin\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c4d0f66e-b1eb-48fd-a9bf-839cd33e8cac","_cell_guid":"103bf135-dfdb-451d-89bf-de55d59bc975","trusted":true},"cell_type":"code","source":"marking = pd.read_csv('../input/global-wheat-detection/train.csv')\n\nbboxs = np.stack(marking['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\nfor i, column in enumerate(['x', 'y', 'w', 'h']):\n    marking[column] = bboxs[:,i]\nmarking.drop(columns=['bbox'], inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b42c52fb-9508-41a7-acf1-07ca953c316e","_cell_guid":"a7d733c0-80b1-4897-9f0e-ef6459a915a1","trusted":true},"cell_type":"code","source":"marking['area'] = marking['w'] * marking['h']\nprint(len(marking))\nmarking = marking[marking['area'] < 154200.0]\nprint(len(marking))\nerror_bbox = [100648.0, 145360.0, 149744.0, 119790.0, 106743.0]\nmarking = marking[~marking['area'].isin(error_bbox)]\nmarking = marking[marking['w'] >= 10.0]\nmarking = marking[marking['h'] >= 10.0]\nprint(len(marking))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"33da38f6-5aad-4548-8e65-3d1a9f9f291b","_cell_guid":"c246c4ce-0db8-4468-9312-9b7d8cd7dd5f","trusted":true},"cell_type":"code","source":"def get_train_transforms():\n    return A.Compose(\n        [\n            A.RandomSizedCrop(min_max_height=(800, 800), height=1024, width=1024, p=0.5),\n            A.OneOf([\n                A.HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit= 0.1, \n                                     val_shift_limit=0.1, p=0.9),\n                A.RandomBrightnessContrast(brightness_limit=0.1, \n                                           contrast_limit=0.1, p=0.9),\n            ],p=0.9),\n            A.ToGray(p=0.01),\n            A.HorizontalFlip(p=0.5),\n            A.VerticalFlip(p=0.5),\n            A.Resize(height=512, width=512, p=1),\n            A.Cutout(num_holes=10, max_h_size=64, max_w_size=64, fill_value=0, p=0.5),\n            ToTensorV2(p=1.0),\n        ], \n        p=1.0, \n        bbox_params=A.BboxParams(\n            format='pascal_voc',\n            min_area=0, \n            min_visibility=0,\n            label_fields=['labels']\n        )\n    )\n\ndef get_valid_transforms():\n    return A.Compose(\n        [\n            A.Resize(height=512, width=512, p=1.0),\n            ToTensorV2(p=1.0),\n        ], \n        p=1.0, \n        bbox_params=A.BboxParams(\n            format='pascal_voc',\n            min_area=0, \n            min_visibility=0,\n            label_fields=['labels']\n        )\n    )\ndef get_test_transforms():\n    return A.Compose([\n            A.Resize(height=512, width=512, p=1.0),\n            ToTensorV2(p=1.0),\n        ], p=1.0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8ffafe38-7085-4d6e-88ae-ee97cbb9fe4f","_cell_guid":"0a2b4f0c-4123-4346-96e4-b3783d37654d","trusted":true},"cell_type":"code","source":"import warnings\n\nwarnings.filterwarnings(\"ignore\")\n\nclass Fitter:\n    \n    def __init__(self, model, device, config):\n        self.config = config\n        self.epoch = 0\n\n        self.base_dir = f'./{config.folder}'\n        if not os.path.exists(self.base_dir):\n            os.makedirs(self.base_dir)\n        \n        self.log_path = f'{self.base_dir}/log.txt'\n        self.best_summary_loss = 10**5\n\n        self.model = model\n        self.device = device\n\n        param_optimizer = list(self.model.named_parameters())\n        no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']\n        optimizer_grouped_parameters = [\n            {'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 'weight_decay': 0.001},\n            {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}\n        ] \n\n        self.optimizer = torch.optim.Adam(self.model.parameters(), lr=config.lr)\n        self.scheduler = config.SchedulerClass(self.optimizer, **config.scheduler_params)\n        self.log(f'Fitter prepared. Device is {self.device}')\n\n    def fit(self, train_loader, validation_loader):\n        for e in range(self.config.n_epochs):\n            if self.config.verbose:\n                lr = self.optimizer.param_groups[0]['lr']\n                timestamp = datetime.utcnow().isoformat()\n                self.log(f'\\n{timestamp}\\nLR: {lr}')\n\n            t = time.time()\n            summary_loss = self.train_one_epoch(train_loader)\n\n            self.log(f'[RESULT]: Train. Epoch: {self.epoch}, summary_loss: {summary_loss.avg:.5f}, time: {(time.time() - t):.5f}')\n            self.save(f'{self.base_dir}/last-checkpoint1.bin')\n\n            t = time.time()\n            summary_loss = self.validation(validation_loader)\n\n            self.log(f'[RESULT]: Val. Epoch: {self.epoch}, summary_loss: {summary_loss.avg:.5f}, time: {(time.time() - t):.5f}')\n            if summary_loss.avg < self.best_summary_loss:\n                self.best_summary_loss = summary_loss.avg\n                self.model.eval()\n                self.save(f'{self.base_dir}/best-checkpoint-{str(self.epoch).zfill(3)}epoch.bin')\n                for path in sorted(glob(f'{self.base_dir}/best-checkpoint-*epoch.bin'))[:-3]:\n                    os.remove(path)\n\n            if self.config.validation_scheduler:\n                self.scheduler.step(metrics=summary_loss.avg)\n\n            self.epoch += 1\n\n    def validation(self, val_loader):\n        self.model.eval()\n        summary_loss = AverageMeter()\n        t = time.time()\n        for step, (images, targets, image_ids) in enumerate(val_loader):\n            if self.config.verbose:\n                if step % self.config.verbose_step == 0:\n                    print(\n                        f'Val Step {step}/{len(val_loader)}, ' + \\\n                        f'summary_loss: {summary_loss.avg:.5f}, ' + \\\n                        f'time: {(time.time() - t):.5f}', end='\\r'\n                    )\n            with torch.no_grad():\n                images = torch.stack(images)\n                batch_size = images.shape[0]\n                images = images.to(self.device).float()\n                boxes = [target['boxes'].to(self.device).float() for target in targets]\n                labels = [target['labels'].to(self.device).float() for target in targets]\n\n                loss, _, _ = self.model(images, boxes, labels)\n                summary_loss.update(loss.detach().item(), batch_size)\n\n        return summary_loss\n\n    def train_one_epoch(self, train_loader):\n        self.model.train()\n        summary_loss = AverageMeter()\n        t = time.time()\n        for step, (images, targets, image_ids) in enumerate(train_loader):\n            if self.config.verbose:\n                if step % self.config.verbose_step == 0:\n                    print(\n                        f'Train Step {step}/{len(train_loader)}, ' + \\\n                        f'summary_loss: {summary_loss.avg:.5f}, ' + \\\n                        f'time: {(time.time() - t):.5f}', end='\\r'\n                    )\n            \n            images = torch.stack(images)\n            images = images.to(self.device).float()\n            batch_size = images.shape[0]\n            boxes = [target['boxes'].to(self.device).float() for target in targets]\n            labels = [target['labels'].to(self.device).float() for target in targets]\n                \n            accumulation_steps = 3\n            loss, _, _ = self.model(images, boxes, labels)\n            loss = loss/accumulation_steps\n            loss.backward()\n            summary_loss.update(loss.detach().item(), batch_size)\n            \n            if ((step + 1)%accumulation_steps) == 0:\n                self.optimizer.step()\n                self.optimizer.zero_grad()\n            \n            if self.config.step_scheduler:\n                self.scheduler.step()\n\n        return summary_loss\n    \n    def save(self, path):\n        self.model.eval()\n        torch.save({\n            'model_state_dict': self.model.model.state_dict(),\n            'optimizer_state_dict': self.optimizer.state_dict(),\n            'scheduler_state_dict': self.scheduler.state_dict(),\n            'best_summary_loss': self.best_summary_loss,\n            'epoch': self.epoch,\n        }, path)\n\n    def load(self, path):\n        checkpoint = torch.load(path)\n        self.model.model.load_state_dict(checkpoint['model_state_dict'])\n        self.optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n        self.scheduler.load_state_dict(checkpoint['scheduler_state_dict'])\n        self.best_summary_loss = checkpoint['best_summary_loss']\n        self.epoch = checkpoint['epoch'] + 1\n        \n    def log(self, message):\n        if self.config.verbose:\n            print(message)\n        with open(self.log_path, 'a+') as logger:\n            logger.write(f'{message}\\n')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"72927545-910c-49a0-89a8-86381ea1b45b","_cell_guid":"b858e0d1-4b35-4239-bca6-9ee52e752177","trusted":true},"cell_type":"code","source":"class TrainGlobalConfig:\n    num_workers = 2\n    batch_size = 4 \n    n_epochs = 1 # n_epochs = 40\n    lr = 0.0001\n\n    folder = 'plabel_model'\n\n    # -------------------\n    verbose = True\n    verbose_step = 1\n    # -------------------\n\n    # --------------------\n    step_scheduler = False  # do scheduler.step after optimizer.step\n    validation_scheduler = True  # do scheduler.step after validation stage loss\n\n    SchedulerClass = torch.optim.lr_scheduler.ReduceLROnPlateau\n    scheduler_params = dict(\n        mode='min',\n        factor=0.5,\n        patience=1,\n        verbose=False, \n        threshold=0.0001,\n        threshold_mode='abs',\n        cooldown=0, \n        min_lr=1e-8,\n        eps=1e-08\n    )","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d857f151-bfcd-45e0-80dc-834214fd8e8d","_cell_guid":"945b79ad-5ee7-4855-805b-3407bb3b3e91","trusted":true},"cell_type":"code","source":"DATA_ROOT_PATH = '../input/global-wheat-detection/test'\n\nclass DatasetRetriever(Dataset):\n\n    def __init__(self, image_ids, transforms=None):\n        super().__init__()\n        self.image_ids = image_ids\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        image = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        if self.transforms:\n            sample = {'image': image}\n            sample = self.transforms(**sample)\n            image = sample['image']\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d3520585-6b33-420c-aff0-9a15d9a19e99","_cell_guid":"b6794797-173e-419b-8293-34ac5c2ff9fb","trusted":true},"cell_type":"code","source":"dataset = DatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),\n    transforms=get_test_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=1,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9e337a6f-ba0d-4187-ae29-dd8091d34d05","_cell_guid":"75bb71bb-55a4-4dd2-b3cc-059596828cf3","trusted":true},"cell_type":"code","source":"def load_net(checkpoint_path):\n    config = get_efficientdet_config('tf_efficientdet_d5')\n    net = EfficientDet(config, pretrained_backbone=False)\n\n    config.num_classes = 1\n    config.image_size=512\n    net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))\n\n    checkpoint = torch.load(checkpoint_path)\n    net.load_state_dict(checkpoint['model_state_dict'])\n\n    del checkpoint\n    gc.collect()\n\n    net = DetBenchEval(net, config)\n    net.eval();\n    return net.cuda()\n\n# your place of the model\nnet = load_net(effdet_weights)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"20c738cf-d95c-473b-a403-35e7174a5181","_cell_guid":"ade58112-69e5-4e30-8505-085efbaea4ad","trusted":true},"cell_type":"code","source":"class BaseWheatTTA:\n    \"\"\" author: @shonenkov \"\"\"\n    image_size = 512\n\n    def augment(self, image):\n        raise NotImplementedError\n    \n    def batch_augment(self, images):\n        raise NotImplementedError\n    \n    def deaugment_boxes(self, boxes):\n        raise NotImplementedError\n\nclass TTAHorizontalFlip(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n\n    def augment(self, image):\n        return image.flip(1)\n    \n    def batch_augment(self, images):\n        return images.flip(2)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [1,3]] = self.image_size - boxes[:, [3,1]]\n        return boxes\n\nclass TTAVerticalFlip(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    \n    def augment(self, image):\n        return image.flip(2)\n    \n    def batch_augment(self, images):\n        return images.flip(3)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [0,2]] = self.image_size - boxes[:, [2,0]]\n        return boxes\n    \nclass TTARotate90(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    \n    def augment(self, image):\n        return torch.rot90(image, 1, (1, 2))\n\n    def batch_augment(self, images):\n        return torch.rot90(images, 1, (2, 3))\n    \n    def deaugment_boxes(self, boxes):\n        res_boxes = boxes.copy()\n        res_boxes[:, [0,2]] = self.image_size - boxes[:, [1,3]]\n        res_boxes[:, [1,3]] = boxes[:, [2,0]]\n        return res_boxes\n\nclass TTACompose(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    def __init__(self, transforms):\n        self.transforms = transforms\n        \n    def augment(self, image):\n        for transform in self.transforms:\n            image = transform.augment(image)\n        return image\n    \n    def batch_augment(self, images):\n        for transform in self.transforms:\n            images = transform.batch_augment(images)\n        return images\n    \n    def prepare_boxes(self, boxes):\n        result_boxes = boxes.copy()\n        result_boxes[:,0] = np.min(boxes[:, [0,2]], axis=1)\n        result_boxes[:,2] = np.max(boxes[:, [0,2]], axis=1)\n        result_boxes[:,1] = np.min(boxes[:, [1,3]], axis=1)\n        result_boxes[:,3] = np.max(boxes[:, [1,3]], axis=1)\n        return result_boxes\n    \n    def deaugment_boxes(self, boxes):\n        for transform in self.transforms[::-1]:\n            boxes = transform.deaugment_boxes(boxes)\n        return self.prepare_boxes(boxes)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a22e6445-1d29-4eea-bcdf-9f66381baf50","_cell_guid":"3b4721c1-0f50-43e1-85e8-20dff7baba60","trusted":true},"cell_type":"code","source":"from itertools import product\n\ntta_transforms = []\nfor tta_combination in product([TTAHorizontalFlip(), None], \n                               [TTAVerticalFlip(), None],\n                               [TTARotate90(), None]):\n    tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ea622cd0-b7a5-4fc1-86ea-7a1bca48bf7f","_cell_guid":"bfb2087a-9b80-4d0d-a9e5-f07bbcb55e79","trusted":true},"cell_type":"code","source":"# use TTA\ndef make_tta_predictions(images, score_threshold=0.25):\n    with torch.no_grad():\n        images = torch.stack(images).float().cuda()\n        predictions = []\n        for tta_transform in tta_transforms:\n            result = []\n            det = net(tta_transform.batch_augment(images.clone()), torch.tensor([1]*images.shape[0]).float().cuda())\n\n            for i in range(images.shape[0]):\n                boxes = det[i].detach().cpu().numpy()[:,:4]    \n                scores = det[i].detach().cpu().numpy()[:,4]\n                indexes = np.where(scores > score_threshold)[0]\n                boxes = boxes[indexes]\n                boxes[:, 2] = boxes[:, 2] + boxes[:, 0]\n                boxes[:, 3] = boxes[:, 3] + boxes[:, 1]\n                boxes = tta_transform.deaugment_boxes(boxes.copy())\n                result.append({\n                    'boxes': boxes,\n                    'scores': scores[indexes],\n                })\n            predictions.append(result)\n    return predictions\n\ndef run_wbf(predictions, image_index, image_size=512, iou_thr=0.44, skip_box_thr=0.43, weights=None):\n    boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist() for prediction in predictions]\n    scores = [prediction[image_index]['scores'].tolist() for prediction in predictions]\n    labels = [np.ones(prediction[image_index]['scores'].shape[0]).astype(int).tolist() for prediction in predictions]\n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    boxes = boxes*(image_size-1)\n    return boxes, scores, labels","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"48aeb872-f18e-4d31-9ace-722fe9748e83","_cell_guid":"44ac7d15-41bd-4c9e-8a43-14915ea3a1fe","trusted":true},"cell_type":"code","source":"def format_prediction_string(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(\"{0:.4f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n    return \" \".join(pred_strings)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"00ab4d1c-0cb6-44cf-8ee4-e4bb7e259eb2","_cell_guid":"da5e5425-1e02-4d8f-a54a-f41516914ef5","trusted":true},"cell_type":"code","source":"results_plabel = []\n\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images)\n    for i, image in enumerate(images):\n        image_id = image_ids[i]\n        image_ = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        h,w,_ = np.shape(image_)\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        boxes = (boxes*2).astype(np.int32).clip(min=0, max=1023)\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        \n        # make plabel\n        for box in boxes:\n            result_p = {\n                'image_id': image_id,\n                'width':w,\n                'height':h,\n                'source':'usask_1',\n                'x':box[0],\n                'y':box[1],\n                'w':box[2],\n                'h':box[3],\n            }\n            results_plabel.append(result_p)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(predictions)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8fbcc232-8529-4099-8f5f-4f3ab284eb22","_cell_guid":"612f6bea-f96c-42cb-96ab-004bfe0aac4f","trusted":true},"cell_type":"code","source":"results_df = pd.DataFrame(results_plabel, columns=['image_id', 'width','height','source','x','y','w','h'])\nresults_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"06402820-e8dd-41c5-a26c-afc69a0ffaa0","_cell_guid":"0ac44c5a-93c9-4507-808c-d51c82019ec6","trusted":true},"cell_type":"code","source":"marking.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0056bcaf-0b1e-4c45-93ac-06f56eeae582","_cell_guid":"2376ebc5-91f4-418d-a31b-13ddb18d7031","trusted":true},"cell_type":"code","source":"results_df['image_id'] = results_df['image_id'].apply(lambda x: DATA_ROOT_PATH+'/'+ x+'.jpg')\nresults_df['image_id']","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8319a8ab-c9af-453b-b5ef-7c6105d7d77d","_cell_guid":"5b494c80-2a7e-4725-a949-88c7cbe6aba7","trusted":true},"cell_type":"code","source":"TRAIN_ROOT_PATH = '../input/global-wheat-detection/train'\nmarking['image_id'] = marking['image_id'].apply(lambda x: TRAIN_ROOT_PATH+'/'+ x+'.jpg')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"332d90c3-9eca-4272-8891-37ca7efb503a","_cell_guid":"0834c4fc-2696-4bac-b995-4013ccc22a81","trusted":true},"cell_type":"code","source":"train_data_plabel = pd.concat([results_df,marking], axis=0)\n# train_data_plabel = results_df\ntrain_data_plabel","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ce37ddb9-7996-4178-9aa5-8f6b8aacba80","_cell_guid":"5dfd54be-6641-49f8-854c-4cc73cf024b9","trusted":true},"cell_type":"code","source":"test_ids_ = os.listdir(\"../input/global-wheat-detection/test\")\ntest_idss = []\nfor test_id in test_ids_:  \n    ids = test_id[:-4]\n    test_idss.append(ids)\nprint(test_idss)\ntest_images = {}\ntest_ids = []\nfor t_id in test_idss:\n    test_image = cv2.imread(f'../input/global-wheat-detection/test/{t_id}.jpg', cv2.IMREAD_COLOR)\n#     if t_id == '51b3e36ab' or t_id == 'aac893a91':\n#         test_image = cv2.resize(test_image,(512,512))\n\n#     if test_image.shape[0] == 1024 and test_image.shape[1] == 1024:\n    test_images[t_id] = test_image\n    test_ids.append(t_id)\nprint(len(test_images))\ntest_ids = pd.DataFrame(test_ids,columns=['image_id'])\nprint(test_ids)\n# print(test_images[test_ids[1]])\ntest_ids['image_id'] = test_ids['image_id'].apply(lambda x: DATA_ROOT_PATH+'/'+ x+'.jpg')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b32daf91-56f5-4f82-aa0c-78bb9643da48","_cell_guid":"ab40db46-1ca5-432e-b919-967f6c8f466c","trusted":true},"cell_type":"code","source":"# cross validation\nskf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\ndf_folds = train_data_plabel[['image_id']].copy()\ndf_folds.loc[:, 'bbox_count'] = 1\ndf_folds = df_folds.groupby('image_id').count()\ndf_folds.loc[:, 'source'] = marking[['image_id', 'source']].groupby('image_id').min()['source']\ndf_folds.loc[:, 'stratify_group'] = np.char.add(\n    df_folds['source'].values.astype(str),\n    df_folds['bbox_count'].apply(lambda x: f'_{x // 15}').values.astype(str)\n)\ndf_folds.loc[:, 'fold'] = 0\n\nfor fold_number, (train_index, val_index) in enumerate(skf.split(X=df_folds.index, y=df_folds['stratify_group'])):\n    df_folds.loc[df_folds.iloc[val_index].index, 'fold'] = fold_number","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6a4962c9-0f7f-4917-97a3-5877d0e5e1db","_cell_guid":"d4f7e385-6dec-40ca-88fb-f5683a47e20a","trusted":true},"cell_type":"code","source":"fold_number = 0\ntrain_ids = df_folds[df_folds['fold'] != fold_number].index.values\n# train_ids = test_ids['image_id']\nvalid_ids = df_folds[df_folds['fold'] == fold_number].index.values\n# train_ids","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"81becc99-820a-4702-bd07-638c7d8e156b","_cell_guid":"225ad3ea-59b1-4d9b-aff7-a5e442d3bd41","trusted":true},"cell_type":"code","source":"# TRAIN_ROOT_PATH = '../input/global-wheat-detection/train'\n\nclass DatasetRetriever(Dataset):\n\n    def __init__(self, marking, image_ids, transforms=None, test=False):\n        super().__init__()\n\n        self.image_ids = image_ids\n        self.marking = marking\n        self.transforms = transforms\n        self.test = test\n\n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        \n        if self.test or random.random() > 0.5:\n            image, boxes = self.load_image_and_boxes(index)\n        else:\n            image, boxes = self.load_cutmix_image_and_boxes(index)\n\n        # there is only one class\n        labels = torch.ones((boxes.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([index])\n\n        if self.transforms:\n            for i in range(10):\n                sample = self.transforms(**{\n                    'image': image,\n                    'bboxes': target['boxes'],\n                    'labels': labels\n                })\n                if len(sample['bboxes']) > 0:\n                    image = sample['image']\n                    target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n                    target['boxes'][:,[0,1,2,3]] = target['boxes'][:,[1,0,3,2]]  #yxyx: be warning\n                    break\n\n        return image, target, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]\n\n    def load_image_and_boxes(self, index):\n        image_id = self.image_ids[index]\n        image = cv2.imread(image_id, cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n        records = self.marking[self.marking['image_id'] == image_id]\n        boxes = records[['x', 'y', 'w', 'h']].values\n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        return image, boxes\n\n    def load_cutmix_image_and_boxes(self, index, imsize=1024):\n        \"\"\" \n        This implementation of cutmix author:  https://www.kaggle.com/nvnnghia \n        Refactoring and adaptation: https://www.kaggle.com/shonenkov\n        \"\"\"\n        w, h = imsize, imsize\n        s = imsize // 2\n    \n        xc, yc = [int(random.uniform(imsize * 0.25, imsize * 0.75)) for _ in range(2)]  # center x, y\n        indexes = [index] + [random.randint(0, self.image_ids.shape[0] - 1) for _ in range(3)]\n\n        result_image = np.full((imsize, imsize, 3), 1, dtype=np.float32)\n        result_boxes = []\n\n        for i, index in enumerate(indexes):\n            image, boxes = self.load_image_and_boxes(index)\n            if i == 0:\n                x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc  # xmin, ymin, xmax, ymax (large image)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h  # xmin, ymin, xmax, ymax (small image)\n            elif i == 1:  # top right\n                x1a, y1a, x2a, y2a = xc, max(yc - h, 0), min(xc + w, s * 2), yc\n                x1b, y1b, x2b, y2b = 0, h - (y2a - y1a), min(w, x2a - x1a), h\n            elif i == 2:  # bottom left\n                x1a, y1a, x2a, y2a = max(xc - w, 0), yc, xc, min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), 0, max(xc, w), min(y2a - y1a, h)\n            elif i == 3:  # bottom right\n                x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h)\n            result_image[y1a:y2a, x1a:x2a] = image[y1b:y2b, x1b:x2b]\n            padw = x1a - x1b\n            padh = y1a - y1b\n\n            boxes[:, 0] += padw\n            boxes[:, 1] += padh\n            boxes[:, 2] += padw\n            boxes[:, 3] += padh\n\n            result_boxes.append(boxes)\n\n        result_boxes = np.concatenate(result_boxes, 0)\n        np.clip(result_boxes[:, 0:], 0, 2 * s, out=result_boxes[:, 0:])\n        result_boxes = result_boxes.astype(np.int32)\n        result_boxes = result_boxes[np.where((result_boxes[:,2]-result_boxes[:,0])*(result_boxes[:,3]-result_boxes[:,1]) > 0)]\n        return result_image, result_boxes","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a094e76b-e99a-48ff-ac86-8214a038604c","_cell_guid":"7afc7e99-5193-43e3-b05a-ffbe89bf5068","trusted":true},"cell_type":"code","source":"train_dataset = DatasetRetriever(\n    image_ids=train_ids,\n    marking=train_data_plabel,\n    transforms=get_train_transforms(),\n    test=False,\n)\n\nvalidation_dataset = DatasetRetriever(\n    image_ids=valid_ids,\n    marking=train_data_plabel,\n    transforms=get_valid_transforms(),\n    test=True,\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0e9e32a1-30de-4ebe-8d3e-51e91eaefda8","_cell_guid":"171f5040-6f9e-406b-93eb-3ea7db25553e","trusted":true},"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_loader = torch.utils.data.DataLoader(\n    train_dataset,\n    batch_size=TrainGlobalConfig.batch_size,\n    sampler=RandomSampler(train_dataset),\n    pin_memory=False,\n    drop_last=True,\n    num_workers=TrainGlobalConfig.num_workers,\n    collate_fn=collate_fn,\n)\nval_loader = torch.utils.data.DataLoader(\n    validation_dataset, \n    batch_size=TrainGlobalConfig.batch_size,\n    num_workers=TrainGlobalConfig.num_workers,\n    shuffle=False,\n    sampler=SequentialSampler(validation_dataset),\n    pin_memory=False,\n    collate_fn=collate_fn,\n)\n\n\ndef run_training():\n    device = torch.device('cuda:0')\n    net.to(device)\n    \n    fitter = Fitter(model=net, device=device, config=TrainGlobalConfig)\n    fitter.fit(train_loader, val_loader)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3f0618d6-4d36-456d-a746-59b61eca7cec","_cell_guid":"0254a2f5-3323-4cee-8491-32dc92ec08a3","trusted":true},"cell_type":"code","source":"from effdet import get_efficientdet_config, EfficientDet, DetBenchTrain\nfrom effdet.efficientdet import HeadNet\n\ndef get_net():\n    \n    config = get_efficientdet_config('tf_efficientdet_d5')\n    net = EfficientDet(config, pretrained_backbone=False)\n    \n    config.num_classes = 1\n    config.image_size = 512\n    net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))\n    checkpoint = torch.load(effdet_weights)\n    net.load_state_dict(checkpoint['model_state_dict'])\n   \n    return DetBenchTrain(net, config)\n\nnet = get_net()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d22dc907-7737-4ade-969e-849074ada210","_cell_guid":"f3309286-4b63-4552-a3f3-1f0bc7542d0a","trusted":true},"cell_type":"code","source":"class AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"06b91c70-2ada-49e6-a2e4-30fba50d2fec","_cell_guid":"8bfc7d5f-f392-4ef0-b6ab-c788e0aab4ee","trusted":true},"cell_type":"code","source":"is_TEST = len(os.listdir('../input/global-wheat-detection/test/'))>1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a3fbf09f-8d5b-4585-a17c-1383c6e97474","_cell_guid":"7a32e6ed-0eba-417b-aaaa-0daf08695c8a","trusted":true},"cell_type":"code","source":"if is_TEST:\n    run_training()\nelse:\n    pass","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"77406ba9-df9f-4223-9e67-bad3b84bbff2","_cell_guid":"615c909d-7f15-4dcf-9a32-383277ec3c82","trusted":true},"cell_type":"code","source":"weights = f'plabel_model/last-checkpoint1.bin' \nif not os.path.exists(weights):\n    weights = effdet_weights\n\nnet = load_net(weights)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2b86ae19-c67b-44aa-8bee-c4e6bce05873","_cell_guid":"cb67a8dd-b54e-45e4-a983-e5aeb734bda3","trusted":true},"cell_type":"markdown","source":"# OOF","execution_count":null},{"metadata":{"_uuid":"a1d4247f-3a82-464b-abcc-1cb8d06acdc5","_cell_guid":"a2f54b00-0cb3-4167-bb4d-c80565528a1d","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport numba\nimport re\nimport cv2\nimport ast\nimport matplotlib.pyplot as plt\n\nfrom numba import jit\nfrom typing import List, Union, Tuple\n\n\n@jit(nopython=True)\ndef calculate_iou(gt, pr, form='pascal_voc') -> float:\n    \"\"\"Calculates the Intersection over Union.\n\n    Args:\n        gt: (np.ndarray[Union[int, float]]) coordinates of the ground-truth box\n        pr: (np.ndarray[Union[int, float]]) coordinates of the prdected box\n        form: (str) gt/pred coordinates format\n            - pascal_voc: [xmin, ymin, xmax, ymax]\n            - coco: [xmin, ymin, w, h]\n    Returns:\n        (float) Intersection over union (0.0 <= iou <= 1.0)\n    \"\"\"\n    if form == 'coco':\n        gt = gt.copy()\n        pr = pr.copy()\n\n        gt[2] = gt[0] + gt[2]\n        gt[3] = gt[1] + gt[3]\n        pr[2] = pr[0] + pr[2]\n        pr[3] = pr[1] + pr[3]\n\n    # Calculate overlap area\n    dx = min(gt[2], pr[2]) - max(gt[0], pr[0]) + 1\n    \n    if dx < 0:\n        return 0.0\n    \n    dy = min(gt[3], pr[3]) - max(gt[1], pr[1]) + 1\n\n    if dy < 0:\n        return 0.0\n\n    overlap_area = dx * dy\n\n    # Calculate union area\n    union_area = (\n            (gt[2] - gt[0] + 1) * (gt[3] - gt[1] + 1) +\n            (pr[2] - pr[0] + 1) * (pr[3] - pr[1] + 1) -\n            overlap_area\n    )\n\n    return overlap_area / union_area\n\n\n@jit(nopython=True)\ndef find_best_match(gts, pred, pred_idx, threshold = 0.5, form = 'pascal_voc', ious=None) -> int:\n    \"\"\"Returns the index of the 'best match' between the\n    ground-truth boxes and the prediction. The 'best match'\n    is the highest IoU. (0.0 IoUs are ignored).\n\n    Args:\n        gts: (List[List[Union[int, float]]]) Coordinates of the available ground-truth boxes\n        pred: (List[Union[int, float]]) Coordinates of the predicted box\n        pred_idx: (int) Index of the current predicted box\n        threshold: (float) Threshold\n        form: (str) Format of the coordinates\n        ious: (np.ndarray) len(gts) x len(preds) matrix for storing calculated ious.\n\n    Return:\n        (int) Index of the best match GT box (-1 if no match above threshold)\n    \"\"\"\n    best_match_iou = -np.inf\n    best_match_idx = -1\n\n    for gt_idx in range(len(gts)):\n        \n        if gts[gt_idx][0] < 0:\n            # Already matched GT-box\n            continue\n        \n        iou = -1 if ious is None else ious[gt_idx][pred_idx]\n\n        if iou < 0:\n            iou = calculate_iou(gts[gt_idx], pred, form=form)\n            \n            if ious is not None:\n                ious[gt_idx][pred_idx] = iou\n\n        if iou < threshold:\n            continue\n\n        if iou > best_match_iou:\n            best_match_iou = iou\n            best_match_idx = gt_idx\n\n    return best_match_idx\n\n@jit(nopython=True)\ndef calculate_precision(gts, preds, threshold = 0.5, form = 'coco', ious=None) -> float:\n    \"\"\"Calculates precision for GT - prediction pairs at one threshold.\n\n    Args:\n        gts: (List[List[Union[int, float]]]) Coordinates of the available ground-truth boxes\n        preds: (List[List[Union[int, float]]]) Coordinates of the predicted boxes,\n               sorted by confidence value (descending)\n        threshold: (float) Threshold\n        form: (str) Format of the coordinates\n        ious: (np.ndarray) len(gts) x len(preds) matrix for storing calculated ious.\n\n    Return:\n        (float) Precision\n    \"\"\"\n    n = len(preds)\n    tp = 0\n    fp = 0\n    \n    # for pred_idx, pred in enumerate(preds_sorted):\n    for pred_idx in range(n):\n\n        best_match_gt_idx = find_best_match(gts, preds[pred_idx], pred_idx,\n                                            threshold=threshold, form=form, ious=ious)\n\n        if best_match_gt_idx >= 0:\n            # True positive: The predicted box matches a gt box with an IoU above the threshold.\n            tp += 1\n            # Remove the matched GT box\n            gts[best_match_gt_idx] = -1\n\n        else:\n            # No match\n            # False positive: indicates a predicted box had no associated gt box.\n            fp += 1\n\n    # False negative: indicates a gt box had no associated predicted box.\n    fn = (gts.sum(axis=1) > 0).sum()\n\n    return tp / (tp + fp + fn)\n\n\n@jit(nopython=True)\ndef calculate_image_precision(gts, preds, thresholds = (0.5, ), form = 'coco') -> float:\n    \"\"\"Calculates image precision.\n\n    Args:\n        gts: (List[List[Union[int, float]]]) Coordinates of the available ground-truth boxes\n        preds: (List[List[Union[int, float]]]) Coordinates of the predicted boxes,\n               sorted by confidence value (descending)\n        thresholds: (float) Different thresholds\n        form: (str) Format of the coordinates\n\n    Return:\n        (float) Precision\n    \"\"\"\n    n_threshold = len(thresholds)\n    image_precision = 0.0\n    \n    ious = np.ones((len(gts), len(preds))) * -1\n    # ious = None\n\n    for threshold in thresholds:\n        precision_at_threshold = calculate_precision(gts.copy(), preds, threshold=threshold,\n                                                     form=form, ious=ious)\n        image_precision += precision_at_threshold / n_threshold\n\n    return image_precision\n\n    \n# Numba typed list!\niou_thresholds = numba.typed.List()\n\nfor x in [0.5, 0.55, 0.6, 0.65, 0.7, 0.75]:\n    iou_thresholds.append(x)\n    \n# def validate():\n#     source = 'convertor/fold0/images/val2017'\n    \n#     weights = 'weights/best.pt'\n#     if not os.path.exists(weights):\n#         weights = WEIGHTS\n    \n#     device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n#     # Load model\n#     model = torch.load(weights, map_location=device)['model'].float()  # load to FP32\n#     model.to(device).eval()\n    \n#     dataset = LoadImages(source, img_size=1024)\n\n#     results = []\n    \n#     for path, img, img0, vid_cap in dataset:\n            \n#         image_id = os.path.basename(path).split('.')[0]\n#         img = img.transpose(1,2,0) # [H, W, 3]\n        \n#         enboxes = []\n#         enscores = []\n        \n#         # only rot, no flip\n#         if is_ROT:    \n#             for i in range(4):\n#                 img1 = TTAImage(img, i)\n#                 boxes, scores = detect1Image(img1, img0, model, device, aug=False)\n#                 for _ in range(3-i):\n#                     boxes = rotBoxes90(boxes, *img.shape[:2])            \n#                 enboxes.append(boxes)\n#                 enscores.append(scores) \n        \n#         # flip\n#         boxes, scores = detect1Image(img, img0, model, device, aug=is_AUG)\n#         enboxes.append(boxes)\n#         enscores.append(scores) \n            \n#         #boxes, scores, labels = run_wbf(enboxes, enscores, image_size=1024, iou_thr=WBF_IOU_THR, skip_box_thr=WBF_CONF_THR)    \n#         #boxes = boxes.astype(np.int32).clip(min=0, max=1024)\n#         #boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n#         #boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        \n#         #boxes = boxes[scores >= 0.05].astype(np.int32)\n#         #scores = scores[scores >= float(0.05)]\n        \n#         records = marking[marking['image_id'] == image_id]\n#         gtboxes = records[['x', 'y', 'w', 'h']].values\n#         gtboxes = gtboxes.astype(np.int32).clip(min=0, max=1024)\n#         gtboxes[:, 2] = gtboxes[:, 0] + gtboxes[:, 2]\n#         gtboxes[:, 3] = gtboxes[:, 1] + gtboxes[:, 3]\n        \n            \n#         result = {\n#             'image_id': image_id,\n#             'pred_enboxes': enboxes, # xyhw\n#             'pred_enscores': enscores,\n#             'gt_boxes': gtboxes, # xyhw\n#         }\n\n#         results.append(result)\n        \n#     return results\n\n# def calculate_final_score(all_predictions,predictions, iou_thr, skip_box_thr, score_threshold):\n#     final_scores = []\n#     for i in range(len(all_predictions)):\n#         gt_boxes = all_predictions[i]['gt_boxes'].copy()\n#         enboxes = all_predictions[i]['pred_enboxes'].copy()\n#         enscores = all_predictions[i]['pred_enscores'].copy()\n#         image_id = all_predictions[i]['image_id']\n# #         print(enboxes)\n# #         print(enscores)\n# #         pred_boxes, scores, labels = run_wbf(predictions,image_index)    \n# #         pred_boxes = pred_boxes.astype(np.int32).clip(min=0, max=1024)\n\n#         indexes = np.where(scores>score_threshold)\n#         pred_boxes = pred_boxes[indexes]\n#         scores = scores[indexes]\n\n#         image_precision = calculate_image_precision(gt_boxes, pred_boxes,thresholds=iou_thresholds,form='pascal_voc')\n#         final_scores.append(image_precision)\n\n#     return np.mean(final_scores)\n\ndef calculate_final_score(all_predictions, score_threshold):\n    final_scores = []\n    final_missed_boxes_nums = []\n    # Numba typed list!\n    iou_thresholds = numba.typed.List()\n\n    for x in [0.5, 0.55, 0.6, 0.65, 0.7, 0.75]:\n        iou_thresholds.append(x)\n\n    for i in range(len(all_predictions)):\n        gt_boxes = all_predictions[i]['gt_boxes'].copy()\n        pred_boxes = all_predictions[i]['pred_enboxes'].copy()\n        scores = all_predictions[i]['pred_enscores'].copy()\n        image_id = all_predictions[i]['image_id']\n\n        indexes = np.where(scores > score_threshold)\n        pred_boxes = pred_boxes[indexes]\n        scores = scores[indexes]\n\n        image_precision = calculate_image_precision(gt_boxes, pred_boxes, thresholds=iou_thresholds, form='pascal_voc')\n        final_scores.append(image_precision)\n\n    return np.mean(final_scores)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"43e0eac6-9ca8-4c09-9bff-3952b55906d4","_cell_guid":"e3737e8d-1ec9-4fb4-b199-a19cadc5a853","trusted":true},"cell_type":"code","source":"def validation(model):\n    model.eval()\n    t = time.time()\n    all_predictions = []\n    torch.cuda.empty_cache()\n    valid_loader = tqdm(val_loader, total=len(val_loader), desc=\"Validating\")\n    with torch.no_grad():\n#             for step, (images, targets, image_ids) in enumerate(valid_loader):\n#                 images = list(image.cuda() for image in images)\n#                 outputs = model(images)\n# #                 inference(all_predictions, images, outputs, targets, image_ids)\n#                 for i, image in enumerate(images):\n#                     boxes = outputs[i]['boxes'].data.cpu().numpy().astype(np.int32)\n#                     scores = outputs[i]['scores'].data.cpu().numpy()\n#                     # boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n#                     # boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        results = []\n        for step, (images, targets, image_ids) in enumerate(valid_loader):\n#             images = list(image.cuda() for image in images)\n            predictions = make_tta_predictions(images)\n\n            for i, image in enumerate(images):\n                boxes, scores, labels = run_wbf(predictions, image_index=i)\n#                 boxes = boxes.round().astype(np.int32).clip(min=0, max=1023) \n                boxes = (boxes*2).astype(np.int32).clip(min=0, max=1023)\n    \n    \n                records = train_data_plabel[train_data_plabel['image_id'] == image_ids[i]]\n                gtboxes = records[['x', 'y', 'w', 'h']].values\n                gtboxes = gtboxes.astype(np.int32).clip(min=0, max=1023)\n                gtboxes[:, 2] = gtboxes[:, 0] + gtboxes[:, 2]\n                gtboxes[:, 3] = gtboxes[:, 1] + gtboxes[:, 3]\n                \n                \n                all_prediction = {\n                    'pred_enboxes': boxes,\n                    'pred_enscores': scores,\n                    'gt_boxes': gtboxes,\n                    'image_id': image_ids[i],\n                }\n\n                all_predictions.append(all_prediction)\n            valid_loader.set_description(f'Validate Step {step}/{len(valid_loader)}, ' + \\\n                                         f'time: {(time.time() - t):.5f}')\n#         best_score_threshold, best_final_score = evaluate(self.all_predictions)\n\n    return all_predictions","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"33a36b4d-8aba-4afa-932a-2cb650bf320f","_cell_guid":"7a4c33c2-22b3-4f6a-b2a7-109219fc73db","trusted":true},"cell_type":"code","source":"if is_TEST:\n    all_predictions = validation(net)\n#     print(all_predictions)\n\n    # best_iou_thr = 0.5\n    # best_skip_box_thr = 0.43\n\n    best_final_score, best_score_threshold = 0, 0\n    for score_threshold in tqdm(np.arange(0, 1, 0.01), total=np.arange(0, 1, 0.01).shape[0], desc=\"OOF\"):\n        final_score = calculate_final_score(all_predictions, score_threshold)\n        if final_score > best_final_score:\n            best_final_score = final_score\n            best_score_threshold = score_threshold\n    print('-'*30)\n    print(f'[Best Score Threshold]: {best_score_threshold}')\n    print(f'[OOF Score]: {best_final_score:.4f}')\n    print('-'*30)\n    # print(all_predictions)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"7a7303db-bbf2-40ec-bad9-dab9eceb397b","_cell_guid":"3882cd0b-f746-4607-8474-6131dda7cfc9","trusted":true},"cell_type":"code","source":"results = []\n\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images)\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        boxes = (boxes*2).astype(np.int32).clip(min=0, max=1023)\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n\n        boxes = boxes[scores >= best_score_threshold].astype(np.int32)\n        scores = scores[scores >= best_score_threshold]\n        \n        result = {\n            'image_id': image_id,\n            'PredictionString': format_prediction_string(boxes, scores)\n        }\n        results.append(result)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d0672caf-10d8-47e4-99b8-c0488e2a74b7","_cell_guid":"e1bd011b-e366-4ed9-ab2c-5576921df931","trusted":true},"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.to_csv('submission.csv', index=False)\ntest_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"50bdd6f3-0ed9-40e2-8372-aa5b28e4aeeb","_cell_guid":"667322f4-081c-4abe-b86e-f754bbdbdc4d","trusted":true},"cell_type":"code","source":"# ## show some pictures\n# import matplotlib.pyplot as plt\n\n# for j, (images, image_ids) in enumerate(data_loader):\n    \n\n#     predictions = make_tta_predictions(images)\n\n#     i = 0\n#     sample = images[i].permute(1,2,0).cpu().numpy()\n\n#     boxes, scores, labels = run_wbf(predictions, image_index=i)\n#     boxes = boxes.astype(np.int32).clip(min=0, max=511)\n\n#     fig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\n#     for box in boxes:\n#         cv2.rectangle(sample, (box[0], box[1]), (box[2], box[3]), (1, 0, 0), 1)\n\n#     ax.set_axis_off()\n#     ax.imshow(sample)","execution_count":null,"outputs":[]}],"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}