{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Dependencies","execution_count":null},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"import sys\nsys.path.insert(0, \"../input/timm-efficientdet-pytorch\")\nsys.path.insert(0, \"../input/omegaconf\")\nsys.path.insert(0, \"../input/weightedboxesfusion\")\nsys.path.insert(0, \"../input/faaltuu/\")\n\nimport ensemble_boxes\nimport torch\nfrom effdet import get_efficientdet_config, EfficientDet, DetBenchEval\nfrom effdet.efficientdet import HeadNet\nfrom sklearn.model_selection import StratifiedKFold\nimport torchvision\nfrom  torchvision.models.utils import load_state_dict_from_url\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nfrom torchvision.models.detection.backbone_utils import BackboneWithFPN\nfrom torchvision.ops import misc as misc_nn_ops\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom matplotlib import pyplot as plt\nfrom collections import OrderedDict\nfrom torch import nn\nimport warnings\nfrom torch.jit.annotations import Tuple, List, Dict, Optional\nfrom timm.models.resnest import resnest101e,resnest269e\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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_path = glob('../input/global-wheat-detection/test/*')\nDATA_ROOT_PATH = '../input/global-wheat-detection/test'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 7419","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_valid_transforms():\n    return A.Compose([\n            A.Resize(height=1024, width=1024, p=1.0),\n            ToTensorV2(p=1.0),\n        ], p=1.0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class 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":{"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_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=2,\n    drop_last=False,\n    collate_fn=collate_fn\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CrossEntropyLabelSmooth(nn.Module):\n    \"\"\"Cross entropy loss with label smoothing regularizer.\n\n    Reference:\n    Szegedy et al. Rethinking the Inception Architecture for Computer Vision. CVPR 2016.\n    Equation: y = (1 - epsilon) * y + epsilon / K.\n\n    Args:\n        num_classes (int): number of classes.\n        epsilon (float): weight.\n    \"\"\"\n    def __init__(self, num_classes, epsilon=0.1, use_gpu=True):\n        super(CrossEntropyLabelSmooth, self).__init__()\n        self.num_classes = num_classes\n        self.epsilon = epsilon\n        self.use_gpu = use_gpu\n        self.logsoftmax = nn.LogSoftmax(dim=1)\n\n    def forward(self, inputs, targets):\n        \"\"\"\n        Args:\n            inputs: prediction matrix (before softmax) with shape (batch_size, num_classes)\n            targets: ground truth labels with shape (num_classes)\n        \"\"\"\n        log_probs = self.logsoftmax(inputs)\n        targets = torch.zeros(log_probs.size()).scatter_(1, targets.unsqueeze(1).data.cpu(), 1)\n        if self.use_gpu: targets = targets.cuda()\n        targets = (1 - self.epsilon) * targets + self.epsilon / self.num_classes\n        loss = (- targets * log_probs).mean(0).sum()\n        return loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fastrcnn_loss(class_logits, box_regression, labels, regression_targets):\n    # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor]\n    \"\"\"\n    Computes the loss for Faster R-CNN.\n    Arguments:\n        class_logits (Tensor)\n        box_regression (Tensor)\n        labels (list[BoxList])\n        regression_targets (Tensor)\n    Returns:\n        classification_loss (Tensor)\n        box_loss (Tensor)\n    \"\"\"\n\n    labels = torch.cat(labels, dim=0)\n    regression_targets = torch.cat(regression_targets, dim=0)\n    labal_smooth_loss = CrossEntropyLabelSmooth(2)\n    classification_loss = labal_smooth_loss(class_logits, labels)\n\n    # get indices that correspond to the regression targets for\n    # the corresponding ground truth labels, to be used with\n    # advanced indexing\n    sampled_pos_inds_subset = torch.nonzero(labels > 0).squeeze(1)\n    labels_pos = labels[sampled_pos_inds_subset]\n    N, num_classes = class_logits.shape\n    box_regression = box_regression.reshape(N, -1, 4)\n\n    box_loss = det_utils.smooth_l1_loss(\n        box_regression[sampled_pos_inds_subset, labels_pos],\n        regression_targets[sampled_pos_inds_subset],\n        beta=1 / 9,\n        size_average=False,\n    )\n    box_loss = box_loss / labels.numel()\n\n    return classification_loss, box_loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fpn_backbone_269(pretrained, norm_layer=misc_nn_ops.FrozenBatchNorm2d, trainable_layers=3):\n    # backbone = resnet.__dict__['resnet18'](pretrained=pretrained,norm_layer=norm_layer)\n    print(f'\\nPretarined is {pretrained}')\n    backbone = resnest269e(pretrained=pretrained)\n    # select layers that wont be frozen\n    assert trainable_layers <= 5 and trainable_layers >= 0\n    layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n    # freeze layers only if pretrained backbone is used\n    for name, parameter in backbone.named_parameters():\n        if all([not name.startswith(layer) for layer in layers_to_train]):\n            parameter.requires_grad_(False)\n    return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}\n    in_channels_stage2 = backbone.inplanes // 8\n    in_channels_list = [\n        in_channels_stage2,\n        in_channels_stage2 * 2,\n        in_channels_stage2 * 4,\n        in_channels_stage2 * 8,\n    ]\n    out_channels = 256\n    return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels)\n\nclass WheatDetector_269(nn.Module):\n    def __init__(self, **kwargs):\n        super(WheatDetector_269, self).__init__()\n        self.backbone = fpn_backbone_269(pretrained=False)\n        self.base = FasterRCNN(self.backbone, num_classes = 2, **kwargs)\n        self.base.roi_heads.fastrcnn_loss = self.fastrcnn_loss\n\n    def fastrcnn_loss(self, class_logits, box_regression, labels, regression_targets):\n        # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor]\n        \"\"\"\n        Computes the loss for Faster R-CNN.\n        Arguments:\n            class_logits (Tensor)\n            box_regression (Tensor)\n            labels (list[BoxList])\n            regression_targets (Tensor)\n        Returns:\n            classification_loss (Tensor)\n            box_loss (Tensor)\n        \"\"\"\n\n        labels = torch.cat(labels, dim=0)\n        regression_targets = torch.cat(regression_targets, dim=0)\n        labal_smooth_loss = CrossEntropyLabelSmooth(2)\n        classification_loss = labal_smooth_loss(class_logits, labels)\n\n        # get indices that correspond to the regression targets for\n        # the corresponding ground truth labels, to be used with\n        # advanced indexing\n        sampled_pos_inds_subset = torch.nonzero(labels > 0).squeeze(1)\n        labels_pos = labels[sampled_pos_inds_subset]\n        N, num_classes = class_logits.shape\n        box_regression = box_regression.reshape(N, -1, 4)\n\n        box_loss = det_utils.smooth_l1_loss(\n            box_regression[sampled_pos_inds_subset, labels_pos],\n            regression_targets[sampled_pos_inds_subset],\n            beta=1 / 9,\n            size_average=False,\n        )\n        box_loss = box_loss / labels.numel()\n\n        return classification_loss, box_loss\n\n    def forward(self, images, targets=None):\n        return self.base(images, targets)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fpn_backbone_101(pretrained, norm_layer=misc_nn_ops.FrozenBatchNorm2d, trainable_layers=3):\n    # backbone = resnet.__dict__['resnet18'](pretrained=pretrained,norm_layer=norm_layer)\n    print(f'\\nPretarined is {pretrained}')\n    backbone = resnest101e(pretrained=pretrained)\n    # select layers that wont be frozen\n    assert trainable_layers <= 5 and trainable_layers >= 0\n    layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n    # freeze layers only if pretrained backbone is used\n    for name, parameter in backbone.named_parameters():\n        if all([not name.startswith(layer) for layer in layers_to_train]):\n            parameter.requires_grad_(False)\n    return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}\n    in_channels_stage2 = backbone.inplanes // 8\n    in_channels_list = [\n        in_channels_stage2,\n        in_channels_stage2 * 2,\n        in_channels_stage2 * 4,\n        in_channels_stage2 * 8,\n    ]\n    out_channels = 256\n    return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels)\n\nclass WheatDetector_101(nn.Module):\n    def __init__(self, **kwargs):\n        super(WheatDetector_101, self).__init__()\n        self.backbone = fpn_backbone_101(pretrained=False)\n        self.base = FasterRCNN(self.backbone, num_classes = 2, **kwargs)\n        self.base.roi_heads.fastrcnn_loss = self.fastrcnn_loss\n\n    def fastrcnn_loss(self, class_logits, box_regression, labels, regression_targets):\n        # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor]\n        \"\"\"\n        Computes the loss for Faster R-CNN.\n        Arguments:\n            class_logits (Tensor)\n            box_regression (Tensor)\n            labels (list[BoxList])\n            regression_targets (Tensor)\n        Returns:\n            classification_loss (Tensor)\n            box_loss (Tensor)\n        \"\"\"\n\n        labels = torch.cat(labels, dim=0)\n        regression_targets = torch.cat(regression_targets, dim=0)\n        labal_smooth_loss = CrossEntropyLabelSmooth(2)\n        classification_loss = labal_smooth_loss(class_logits, labels)\n\n        # get indices that correspond to the regression targets for\n        # the corresponding ground truth labels, to be used with\n        # advanced indexing\n        sampled_pos_inds_subset = torch.nonzero(labels > 0).squeeze(1)\n        labels_pos = labels[sampled_pos_inds_subset]\n        N, num_classes = class_logits.shape\n        box_regression = box_regression.reshape(N, -1, 4)\n\n        box_loss = det_utils.smooth_l1_loss(\n            box_regression[sampled_pos_inds_subset, labels_pos],\n            regression_targets[sampled_pos_inds_subset],\n            beta=1 / 9,\n            size_average=False,\n        )\n        box_loss = box_loss / labels.numel()\n\n        return classification_loss, box_loss\n\n    def forward(self, images, targets=None):\n        return self.base(images, targets)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_net_269(checkpoint_path):\n    model = WheatDetector_269()\n\n    # Load the trained weights\n    checkpoint=torch.load(checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n\n\n    del checkpoint\n    gc.collect()\n\n    model.eval();\n    return model.cuda()\n\ndef load_net_101(checkpoint_path):\n    model = WheatDetector_101()\n\n    # Load the trained weights\n    checkpoint=torch.load(checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n\n\n    del checkpoint\n    gc.collect()\n\n    model.eval();\n    return model.cuda()\n\nmodels = [\n    load_net_101('../input/resnest101/fold0-best-checkpoint.bin'),\n    load_net_101('../input/resnest101/fold1-best-checkpoint.bin'),\n    load_net_101('../input/resnest101/fold2-best-checkpoint.bin'),\n    load_net_101('../input/resnest101/fold3-best-checkpoint.bin'),\n    load_net_101('../input/resnest101/fold4-best-checkpoint.bin'),\n    load_net_269('../input/resnest269/fold0-best-checkpoint.bin'),\n    load_net_269('../input/resnest269/fold1-best-checkpoint.bin'),\n    load_net_269('../input/resnest269/fold2-best-checkpoint.bin'),\n    load_net_269('../input/resnest269/fold3-best-checkpoint.bin'),\n    load_net_269('../input/resnest269/fold4-best-checkpoint.bin')\n]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Custom TTA API\n\nIdea is simple: \n- `augment` make tta for one image\n- `batch_augment` make tta for batch of images\n- `deaugment_boxes` return tta predicted boxes in back to original state of image\n\nAlso we are interested in `Compose` with combinations of tta :)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class BaseWheatTTA:\n    \"\"\" author: @shonenkov \"\"\"\n    image_size = 1024\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[:, [3,1]] \n        res_boxes[:, [1,3]] = boxes[:, [0,2]]\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":{},"cell_type":"markdown","source":"# Demonstration how it works:","execution_count":null},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"def process_det(index, outputs, score_threshold=0.5):\n    boxes = outputs[index]['boxes'].data.cpu().numpy()   \n    scores = outputs[index]['scores'].data.cpu().numpy()\n    boxes = (boxes).clip(min=0, max=1023).astype(int)\n    indexes = np.where(scores>score_threshold)\n    boxes = boxes[indexes]\n    scores = scores[indexes]\n    return boxes, scores","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Combinations of TTA","execution_count":null},{"metadata":{"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":{},"cell_type":"markdown","source":"# WBF over TTA:","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_tta_predictions(images,net, score_threshold=0.1):\n    with torch.no_grad():\n        images = torch.stack(images).float().cuda()\n        predictions = []\n        for tta_transform in tta_transforms:\n            result = []\n            outputs = net(tta_transform.batch_augment(images.clone()))\n\n            for i, image in enumerate(images):\n                boxes = outputs[i]['boxes'].data.cpu().numpy()   \n                scores = outputs[i]['scores'].data.cpu().numpy()\n                indexes = np.where(scores > score_threshold)[0]\n                boxes = boxes[indexes]\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=1024, iou_thr=0.5, 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":{"trusted":true},"cell_type":"code","source":"fold1 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[0])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold1[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n        \nfold2 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[1])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold2[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\n        \nfold3 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[2])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold3[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\nfold4 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[3])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold4[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fold5 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[4])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold5[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\n        \nfold6 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[5])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold6[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\n        \nfold7 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[6])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold7[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n       \nfold8 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[7])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold8[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\nfold9 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[8])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold9[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n\nfold10 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[9])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold10[image_id] = [boxes, scores, labels]\nprint('\\nCompleted')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Inference","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_last_wbf(model1,model2,model3,model4,\n                 model5,model6,model7,model8,model9,model10,\n                 iou_thr=0.5,skip_box_thr=0.43):\n    \n    box1,scores1,labels1 = model1\n    box2,scores2,labels2 = model2\n    box3,scores3,labels3 = model3\n    box4,scores4,labels4 = model4\n    \n    \n    box1 = box1/1023\n    box2 = box2/1023\n    box3 = box3/1023\n    box4 = box4/1023\n     \n    box5,scores5,labels5 = model5\n    box6,scores6,labels6 = model6\n    box7,scores7,labels7 = model7\n    box8,scores8,labels8 = model8\n    box9,scores9,labels9 = model9\n    box10,scores10,labels10 = model10\n    \n    \n    box5 = box5/1023\n    box6 = box6/1023\n    box7 = box7/1023\n    box8 = box8/1023\n    box9 = box9/1023\n    box10 = box10/1023\n    \n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion([box1,box2,box3,box4,box5,box6,box7,box8,box9,box10], \n                                                  [scores1,scores2,scores3,scores4,scores5,scores6,scores7,scores8,scores9,scores10],\n                                                [labels1,labels2,labels3,labels4,labels5,labels6,labels7,labels8,labels9,labels10],\n                                                  weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    return boxes,scores,labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"w = {}\nfor row in range(len(all_path)):\n    image_id = all_path[row].split(\"/\")[-1].split(\".\")[0]\n    boxes,scores,labels = run_last_wbf(fold1[image_id],fold2[image_id],fold3[image_id],fold4[image_id],\n                               fold5[image_id],fold6[image_id],fold7[image_id],fold8[image_id],fold9[image_id],fold10[image_id])\n    boxes = (boxes*1023)\n    indexes = np.where(scores > 0.50)[0]\n    w[image_id] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 7435","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_valid_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":{"trusted":true},"cell_type":"code","source":"class 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":{"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_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=2,\n    drop_last=False,\n    collate_fn=collate_fn\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CrossEntropyLabelSmooth(nn.Module):\n    \"\"\"Cross entropy loss with label smoothing regularizer.\n\n    Reference:\n    Szegedy et al. Rethinking the Inception Architecture for Computer Vision. CVPR 2016.\n    Equation: y = (1 - epsilon) * y + epsilon / K.\n\n    Args:\n        num_classes (int): number of classes.\n        epsilon (float): weight.\n    \"\"\"\n    def __init__(self, num_classes, epsilon=0.1, use_gpu=True):\n        super(CrossEntropyLabelSmooth, self).__init__()\n        self.num_classes = num_classes\n        self.epsilon = epsilon\n        self.use_gpu = use_gpu\n        self.logsoftmax = nn.LogSoftmax(dim=1)\n\n    def forward(self, inputs, targets):\n        \"\"\"\n        Args:\n            inputs: prediction matrix (before softmax) with shape (batch_size, num_classes)\n            targets: ground truth labels with shape (num_classes)\n        \"\"\"\n        log_probs = self.logsoftmax(inputs)\n        targets = torch.zeros(log_probs.size()).scatter_(1, targets.unsqueeze(1).data.cpu(), 1)\n        if self.use_gpu: targets = targets.cuda()\n        targets = (1 - self.epsilon) * targets + self.epsilon / self.num_classes\n        loss = (- targets * log_probs).mean(0).sum()\n        return loss\ndef fastrcnn_loss(class_logits, box_regression, labels, regression_targets):\n    # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor]\n    \"\"\"\n    Computes the loss for Faster R-CNN.\n    Arguments:\n        class_logits (Tensor)\n        box_regression (Tensor)\n        labels (list[BoxList])\n        regression_targets (Tensor)\n    Returns:\n        classification_loss (Tensor)\n        box_loss (Tensor)\n    \"\"\"\n\n    labels = torch.cat(labels, dim=0)\n    regression_targets = torch.cat(regression_targets, dim=0)\n    labal_smooth_loss = CrossEntropyLabelSmooth(2)\n    classification_loss = labal_smooth_loss(class_logits, labels)\n\n    # get indices that correspond to the regression targets for\n    # the corresponding ground truth labels, to be used with\n    # advanced indexing\n    sampled_pos_inds_subset = torch.nonzero(labels > 0).squeeze(1)\n    labels_pos = labels[sampled_pos_inds_subset]\n    N, num_classes = class_logits.shape\n    box_regression = box_regression.reshape(N, -1, 4)\n\n    box_loss = det_utils.smooth_l1_loss(\n        box_regression[sampled_pos_inds_subset, labels_pos],\n        regression_targets[sampled_pos_inds_subset],\n        beta=1 / 9,\n        size_average=False,\n    )\n    box_loss = box_loss / labels.numel()\n\n    return classification_loss, box_loss\ndef fpn_backbone(pretrained, norm_layer=misc_nn_ops.FrozenBatchNorm2d, trainable_layers=3):\n    # backbone = resnet.__dict__['resnet18'](pretrained=pretrained,norm_layer=norm_layer)\n    print(f'\\nPretarined is {pretrained}')\n    backbone = resnest101e(pretrained=pretrained)\n    # select layers that wont be frozen\n    assert trainable_layers <= 5 and trainable_layers >= 0\n    layers_to_train = ['layer4', 'layer3', 'layer2', 'layer1', 'conv1'][:trainable_layers]\n    # freeze layers only if pretrained backbone is used\n    for name, parameter in backbone.named_parameters():\n        if all([not name.startswith(layer) for layer in layers_to_train]):\n            parameter.requires_grad_(False)\n    return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'}\n    in_channels_stage2 = backbone.inplanes // 8\n    in_channels_list = [\n        in_channels_stage2,\n        in_channels_stage2 * 2,\n        in_channels_stage2 * 4,\n        in_channels_stage2 * 8,\n    ]\n    out_channels = 256\n    return BackboneWithFPN(backbone, return_layers, in_channels_list, out_channels)\nclass WheatDetector(nn.Module):\n    def __init__(self, **kwargs):\n        super(WheatDetector, self).__init__()\n        self.backbone = fpn_backbone(pretrained=False)\n        self.base = FasterRCNN(self.backbone, num_classes = 2, **kwargs)\n        self.base.roi_heads.fastrcnn_loss = self.fastrcnn_loss\n\n    def fastrcnn_loss(self, class_logits, box_regression, labels, regression_targets):\n        # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor]\n        \"\"\"\n        Computes the loss for Faster R-CNN.\n        Arguments:\n            class_logits (Tensor)\n            box_regression (Tensor)\n            labels (list[BoxList])\n            regression_targets (Tensor)\n        Returns:\n            classification_loss (Tensor)\n            box_loss (Tensor)\n        \"\"\"\n\n        labels = torch.cat(labels, dim=0)\n        regression_targets = torch.cat(regression_targets, dim=0)\n        labal_smooth_loss = CrossEntropyLabelSmooth(2)\n        classification_loss = labal_smooth_loss(class_logits, labels)\n\n        # get indices that correspond to the regression targets for\n        # the corresponding ground truth labels, to be used with\n        # advanced indexing\n        sampled_pos_inds_subset = torch.nonzero(labels > 0).squeeze(1)\n        labels_pos = labels[sampled_pos_inds_subset]\n        N, num_classes = class_logits.shape\n        box_regression = box_regression.reshape(N, -1, 4)\n\n        box_loss = det_utils.smooth_l1_loss(\n            box_regression[sampled_pos_inds_subset, labels_pos],\n            regression_targets[sampled_pos_inds_subset],\n            beta=1 / 9,\n            size_average=False,\n        )\n        box_loss = box_loss / labels.numel()\n\n        return classification_loss, box_loss\n\n    def forward(self, images, targets=None):\n        return self.base(images, targets)\ndef load_net(checkpoint_path):\n    model = WheatDetector()\n\n    # Load the trained weights\n    checkpoint=torch.load(checkpoint_path)\n    model.load_state_dict(checkpoint['model_state_dict'])\n\n\n    del checkpoint\n    gc.collect()\n\n    model.eval();\n    return model.cuda()\nmodels = [\n    load_net('../input/fold-1-resnest101-512/best-checkpoint.bin'),\n    load_net('../input/fold2resnest101512/best-checkpoint.bin'),\n    load_net('../input/fold3resnest101512/best-checkpoint.bin'),\n    load_net('../input/resnest101fold4/best-checkpoint.bin'),\n    load_net('../input/resnest101fold3/best-checkpoint.bin')\n]","execution_count":null,"outputs":[]},{"metadata":{"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[:, [3,1]] \n        res_boxes[:, [1,3]] = boxes[:, [0,2]]\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)\nfrom 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":{"trusted":true},"cell_type":"code","source":"def make_tta_predictions(images,net, score_threshold=0.1):\n    with torch.no_grad():\n        images = torch.stack(images).float().cuda()\n        predictions = []\n        for tta_transform in tta_transforms:\n            result = []\n            outputs = net(tta_transform.batch_augment(images.clone()))\n\n            for i, image in enumerate(images):\n                boxes = outputs[i]['boxes'].data.cpu().numpy()   \n                scores = outputs[i]['scores'].data.cpu().numpy()\n                indexes = np.where(scores > score_threshold)[0]\n                boxes = boxes[indexes]\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.5, 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*1023\n    return boxes, scores, labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fold0 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[0])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold0[image_id] = [boxes, scores, labels]\n        \nprint('\\nCompleted')\n\n\nfold1 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[1])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold1[image_id] = [boxes, scores, labels]\n        \nprint('\\nCompleted')\n        \nfold2 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[2])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold2[image_id] = [boxes, scores, labels]\n        \nprint('\\nCompleted')\n\n\nfold3 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[3])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold3[image_id] = [boxes, scores, labels]\n        \nprint('\\nCompleted')\n        \nfold4 = {}\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images,models[4])\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i)\n        image_id = image_ids[i]\n        fold4[image_id] = [boxes, scores, labels]\n        \nprint('\\nCompleted')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_last_wbf(model1,model2,model3,model4,model5,\n                 iou_thr=0.5,skip_box_thr=0.43):\n    \n    box1,scores1,labels1 = model1\n    box2,scores2,labels2 = model2\n    box3,scores3,labels3 = model3\n    box4,scores4,labels4 = model4\n    box5,scores5,labels5 = model5\n    \n    \n    box1 = box1/1023\n    box2 = box2/1023\n    box3 = box3/1023\n    box4 = box4/1023\n    box5 = box5/1023\n\n    \n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion([box1,box2,box3,box4,box5], \n                                                  [scores1,scores2,scores3,scores4,scores5],\n                                                [labels1,labels2,labels3,labels4,labels5],\n                                                  weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    return boxes,scores,labels\nx = {}\nfor row in range(len(all_path)):\n    image_id = all_path[row].split(\"/\")[-1].split(\".\")[0]\n    boxes,scores,labels = run_last_wbf(fold1[image_id],fold2[image_id],fold0[image_id],fold3[image_id],fold4[image_id])\n    boxes = (boxes*1023)\n    x[image_id] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{"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()\nmodels = [\n    load_net('../input/efficientdetd51/0.bin'),\n    load_net('../input/efficientdetd51/1.bin'),\n    load_net('../input/efficientdetd51/2.bin'),\n    load_net('../input/efficientdetd51/3.bin'),\n    load_net('../input/efficientdetd51/4.bin'),\n    load_net('../input/efficientdetd51/5.bin'),\n    load_net('../input/efficientdetd51/6.bin'),\n    load_net('../input/efficientdetd51/7.bin'),\n]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_ROOT_PATH = '../input/global-wheat-detection/test/'\nclass TestDatasetRetriever(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]\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    )\ndataset = TestDatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),\n    transforms=get_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=2,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)\n\ndef make_predictions(images, score_threshold=0.35):\n    images = torch.stack(images).cuda().float()\n    predictions = []\n    for net in models:\n        with torch.no_grad():\n            det = net(images, torch.tensor([1]*images.shape[0]).float().cuda())\n            result = []\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                result.append({\n                    'boxes': boxes[indexes],\n                    'scores': scores[indexes],\n                    })\n            predictions.append(result)\n    return predictions","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_wbf(predictions, image_index, image_size=512, iou_thr=0.432, skip_box_thr=0.397, 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]).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":{"trusted":true},"cell_type":"code","source":"y={}\nfor images, image_ids in data_loader:\n    predictions = make_predictions(images)\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i,)\n        boxes = (boxes*2)\n        y[image_ids[i]] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"models = [\n    load_net('../input/efficientdetd52/0.bin'),\n    load_net('../input/efficientdetd52/1.bin'),\n    load_net('../input/efficientdetd52/2.bin'),\n    load_net('../input/efficientdetd52/3.bin'),\n    load_net('../input/efficientdetd52/4.bin'),\n    load_net('../input/kaggleeffnet/plabel_model/last-checkpoint1.bin'),\n    load_net('../input/kaggleeffnet/plabel_model/best-checkpoint-004epoch.bin')\n    ]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"z={}\nfor images, image_ids in data_loader:\n    predictions = make_predictions(images,0.4337)\n    for i, image in enumerate(images):\n        boxes, scores, labels = run_wbf(predictions, image_index=i,iou_thr=0.4637,skip_box_thr=0.12)\n        boxes = (boxes*2)\n        z[image_ids[i]] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_valid_transforms():\n    return A.Compose(\n        [\n            A.Resize(height=1024, width=1024, p=1.0),\n            ToTensorV2(p=1.0),\n        ], \n        p=1.0, \n    )\ndataset = TestDatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),\n    transforms=get_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=2,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)\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=1024, iou_thr=0.432, skip_box_thr=0.397, 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]).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":{"trusted":true},"cell_type":"code","source":"class BaseWheatTTA:\n    \"\"\" author: @shonenkov \"\"\"\n    image_size = 1024\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    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)\n    \nfrom 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":{"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=1024\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\nnet = load_net('../input/effdet1024/best-checkpoint-1024.bin')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"l={}\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        l[image_ids[i]] = [boxes, scores, labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_last_wbf(model1,model2,\n                 iou_thr=0.4,skip_box_thr=0.1):\n    \n    box1,scores1,labels1 = model1\n    box2,scores2,labels2 = model2\n    \n    box1 = box1/1023\n    box2 = box2/1023\n    \n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion([box1,box2], [scores1,scores2],[labels1,labels2],\n                                                                      weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    return boxes,scores,labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_path = glob('../input/global-wheat-detection/test/*')\na = {}\n\nfor row in range(len(all_path)):\n    image_id = all_path[row].split(\"/\")[-1].split(\".\")[0]\n    boxes,scores,labels = run_last_wbf(y[image_id],z[image_id])\n    boxes = (boxes*1023)\n    a[image_id] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_last_wbf(model1,model2,\n                 iou_thr=0.4,skip_box_thr=0.1):\n    \n    box1,scores1,labels1 = model1\n    box2,scores2,labels2 = model2\n    \n    box1 = box1/1023\n    box2 = box2/1023\n    \n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion([box1,box2], [scores1,scores2],[labels1,labels2],\n                                                                      weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    return boxes,scores,labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n\ng = {}\nfor row in range(len(all_path)):\n    image_id = all_path[row].split(\"/\")[-1].split(\".\")[0]\n    boxes,scores,labels = run_last_wbf(x[image_id],a[image_id])\n    boxes = (boxes*1023)\n    g[image_id] = [boxes,scores,labels]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def run_last_wbf(model1,model2,model3,\n                 iou_thr=0.4,skip_box_thr=0.1):\n    \n    box1,scores1,labels1 = model1\n    box2,scores2,labels2 = model2\n    box3,scores3,labels3 = model3\n    \n    box1 = box1/1023\n    box2 = box2/1023\n    box3 = box3/1023\n    \n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion([box1,box2,box3], [scores1,scores2,scores3],[labels1,labels2,labels3],\n                                                                      weights=None,iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    return boxes,scores,labels","execution_count":null,"outputs":[]},{"metadata":{"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)\n\nresults = []\n\nfor row in range(len(all_path)):\n    image_id = all_path[row].split(\"/\")[-1].split(\".\")[0]\n    boxes,scores,labels = run_last_wbf(w[image_id],g[image_id],l[image_id])\n    boxes = (boxes*1023).astype(np.int32).clip(min=0, max=1023)\n    boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n    boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n    result = {'image_id': image_id,'PredictionString': format_prediction_string(boxes, scores)}\n    results.append(result)","execution_count":null,"outputs":[]},{"metadata":{"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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}