{"cells":[{"metadata":{"_uuid":"8116a075-fac6-4a68-9db6-6e86c2f094a7","_cell_guid":"fcc3cd13-139c-41e9-bb08-0bc03d6677a9","trusted":true},"cell_type":"markdown","source":"# # ** FasterRCNN Pseudo Labeling\nIn this nodebook, I am going to test the pseudo labeling for this dataset. The training data is small, therefore more data usually help. \nI use a published fasterRCNN model and then continue train it for 3 more epochs with pseudo labeling. \nBy using this technique, I improve the LB from 0.6687 to 0.6937\n\n- You can find the [train notebook here](https://www.kaggle.com/pestipeti/pytorch-starter-fasterrcnn-train)\n- [Inference notebook here](https://www.kaggle.com/pestipeti/pytorch-starter-fasterrcnn-inference)\n- The weights are [available here](https://www.kaggle.com/dataset/7d5f1ed9454c848ecb909c109c6fa8e573ea4de299e249c79edc6f47660bf4c5)\n\n\n**I also published 2 notebooks of centernet training and inference\n** [Centernet Training notebook](https://www.kaggle.com/nvnnghia/keras-centernet-training/edit/run/33622446)\n** [Centernet Inference notebook](https://www.kaggle.com/nvnnghia/keras-centernet-inference)\n\nYour upvotes will be my motivation to upgrade those notenote as I make improvements","execution_count":null},{"metadata":{"_uuid":"be25ef9f-923c-458e-9ad4-cf962467af69","_cell_guid":"bdf26506-70fc-4e40-b8ea-f223d23ef185","trusted":true},"cell_type":"code","source":"!pip install --no-deps '../input/resnest/resnest-0.0.5-py3-none-any.whl' >/dev/null","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c63d07c4-25d9-444f-92c1-a87a15d15058","_cell_guid":"da948d41-da6d-4ae7-92f3-1cfad375fb69","trusted":true},"cell_type":"code","source":"import sys\nsys.path.insert(0, \"../input/resnest/pytorch-image-models-master/pytorch-image-models-master\")\nsys.path.append('.')\nsys.path.insert(0, \"./external/wbf\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!cp -r ../input/wheatdetectiontta/* .","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"00700f60-f51e-4b9a-a5d4-5ae6ca05f56a","_cell_guid":"c455c536-749d-48af-8ab8-64c22e726d45","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nimport re\nfrom PIL import Image\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\nimport torch\nimport torchvision\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom matplotlib import pyplot as plt\n\n# import ensemble_boxes\nfrom  torchvision.models.utils import load_state_dict_from_url\nfrom torchvision.models.detection.backbone_utils import resnet_fpn_backbone\nfrom torchvision.models.detection.backbone_utils import BackboneWithFPN\nfrom torchvision.ops import misc as misc_nn_ops\nfrom collections import OrderedDict\nfrom torch import nn\nimport warnings\nfrom torch.jit.annotations import Tuple, List, Dict, Optional\n# from timm.models.resnest import resnest101e\nfrom resnest.torch import resnest101\nfrom glob import glob\nimport gc\n\nimport numba\nimport ast\n# import matplotlib.pyplot as plt\n\nfrom numba import jit\nfrom typing import List, Union, Tuple\n\n\n\nimport time\nimport logging\nimport ensemble_boxes\nimport random\n\nfrom os import mkdir\nfrom torch.utils import data\nfrom config import cfg\nfrom data import make_test_data_loader\nfrom modeling import build_model\nfrom utils.logger import setup_logger\nfrom engine.tester import Tester\nfrom tqdm import tqdm\nfrom itertools import product\nfrom torch.utils.data import Dataset\nfrom albumentations.pytorch.transforms import ToTensorV2\nfrom datetime import datetime\nfrom evaluate.inference import inference\nfrom evaluate.evaluate import evaluate\nfrom tqdm import tqdm\nfrom solver.build import make_optimizer\nfrom solver.lr_scheduler import make_scheduler\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch.utils.data.sampler import SequentialSampler, RandomSampler\nwarnings.filterwarnings(\"ignore\")\n\nimport glob\nfrom pathlib import Path\nfrom ensemble_boxes import *\n\n\nDIR_INPUT = '/kaggle/input/global-wheat-detection'\nDIR_TRAIN = f'{DIR_INPUT}/train'\nDIR_TEST = f'{DIR_INPUT}/test'\n\n# DIR_WEIGHTS = '/kaggle/input/andreshuang'\nDIR_WEIGHTS = '/kaggle/input/resnest-pth'\n\nWEIGHTS_FILE = f'../input/resnest-pth/checkpoint-85.bin'\nbest_score_threshold = 0.54","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import random\nSEED = 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":{"trusted":true},"cell_type":"code","source":"Res_best_score_threshold = 0.1\nEdet_best_score_threshold = 0.1","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ad49d1fd-e06d-4fea-a09f-e35d9b937b4d","_cell_guid":"9e6f7542-244e-4c4f-a62f-51f788026d25","trusted":true},"cell_type":"code","source":"test_df = pd.read_csv(f'{DIR_INPUT}/sample_submission.csv')\n# test_df","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9282d6a5-4b06-4deb-aa09-4acc02fd3310","_cell_guid":"1cbad00d-a255-44bc-8ae5-69c5d90398af","trusted":true},"cell_type":"code","source":"class ResNeSt_WheatTestDataset(Dataset):\n\n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n\n        self.image_ids = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\n        records = self.df[self.df['image_id'] == image_id]\n\n        image = cv2.imread(f'{self.image_dir}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n\n        if self.transforms:\n            sample = {\n                'image': image,\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"576cc7a3-b991-49cd-adb2-d71279734a6b","_cell_guid":"3595b8cd-2b3a-4f1d-912c-6fc1a9beb8f2","trusted":true},"cell_type":"code","source":"# Albumentations\ndef get_train_transform():\n    return A.Compose([\n        A.Flip(0.5),\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})\n\ndef get_valid_transform():\n    return A.Compose([\n        ToTensorV2(p=1.0)\n    ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b1c20a90-69c0-4f7f-b1c6-a799145ca264","_cell_guid":"fa965a08-712d-4afe-a607-dd00cf72476d","trusted":true},"cell_type":"code","source":"# Albumentations\ndef get_test_transform():\n    return A.Compose([\n        # A.Resize(512, 512),\n        ToTensorV2(p=1.0)\n    ])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"91274f3e-481d-4dbf-a142-1bcb03167fe4","_cell_guid":"5b5502f8-c3ee-4275-84cc-b63968fc2cbf","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":{"_uuid":"7afac323-794a-4793-af5f-df4c75f4c39d","_cell_guid":"70a8b36d-3c64-49a3-bfb4-4b347eaf41f2","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":{"_uuid":"e7240833-ee8d-4ad6-9e5e-446a984ca215","_cell_guid":"d08cc99f-9451-4489-bf22-7f4e0cf75dc4","trusted":true},"cell_type":"code","source":"def resnest_fpn_backbone(pretrained, norm_layer=misc_nn_ops.FrozenBatchNorm2d, trainable_layers=3):\n    # resnet_backbone = resnet.__dict__['resnet152'](pretrained=pretrained,norm_layer=norm_layer)\n    backbone = resnest101(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)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9e18c704-4a0c-4b0d-b082-2eabbe19c647","_cell_guid":"96216544-f3be-4b4a-9383-78dd42df6928","trusted":true},"cell_type":"code","source":"class WheatDetector(torch.nn.Module):\n    def __init__(self, trainable_layers=3, **kwargs):\n        super(WheatDetector, self).__init__()\n        backbone = resnest_fpn_backbone(pretrained=False)\n        self.base = FasterRCNN(backbone, num_classes = 2, **kwargs)\n        self.base.roi_heads.fastrcnn_loss = fastrcnn_loss\n\n    def forward(self, images, targets=None):\n        return self.base(images, targets)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d565a67c-2ec9-4dfc-bd58-687c3e9f99ab","_cell_guid":"f33b1f0d-ce15-4ef3-93e8-f651fafeeb67","trusted":true},"cell_type":"code","source":"def load_net(checkpoint_path):\n    model = WheatDetector()\n    checkpoint=torch.load(checkpoint_path)\n    \n    model.load_state_dict(checkpoint[\"model_state_dict\"],strict=False)\n#     model.load_state_dict(checkpoint,strict=False)\n\n    del checkpoint\n    gc.collect()\n\n    model.eval();\n    return model.cuda()\n\nResNeSt_model = load_net(WEIGHTS_FILE)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c226e394-1b5b-41f3-88f4-cd997a7a497d","_cell_guid":"f0fa3cce-b07b-4ac3-be5e-cf24e40f83d0","trusted":true},"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n\n# x = ResNeSt_model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5a6a9639-20dc-41b5-99a2-2ecc767172b9","_cell_guid":"e93f3d2f-a03f-4fc1-98e2-40e7a991b574","trusted":true},"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntest_dataset = ResNeSt_WheatTestDataset(test_df, DIR_TEST, get_test_transform())\n\ntest_data_loader = DataLoader(\n    test_dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"862f0356-521d-4dbd-8c6e-0e58e5f0ae76","_cell_guid":"f0dbb571-4d4a-4e0b-a29c-1a26e83994d4","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\n    return \" \".join(pred_strings)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5aafa682-e78d-48c3-bcb6-f807c637fdc6","_cell_guid":"8e9808fe-972c-4388-882c-e57ff0896f21","trusted":true},"cell_type":"markdown","source":"# # **Detection and make Pseudo labels for test dataset**","execution_count":null},{"metadata":{"_uuid":"944d2b52-e101-4576-82bb-e2f12116dedd","_cell_guid":"288fb0a1-de2e-4fca-ab32-da28212379f7","trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults = []\n\ntestdf_psuedo = []\nfor images, image_ids in test_data_loader:\n\n    images = list(image.to(device) for image in images)\n    outputs = ResNeSt_model(images)\n\n    for i, image in enumerate(images):\n\n        boxes = outputs[i]['boxes'].data.cpu().numpy()\n        scores = outputs[i]['scores'].data.cpu().numpy()\n        \n        boxes = boxes[scores >= detection_threshold].astype(np.int32)\n        scores = scores[scores >= detection_threshold]\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n        \n        for box in boxes:\n            #print(box)\n            result = {\n                'image_id': 'nvnn'+image_id,\n                'width': 1024,\n                'height': 1024,\n                'source': 'nvnn',\n                'x': box[0],\n                'y': box[1],\n                'w': box[2],\n                'h': box[3]\n            }\n            testdf_psuedo.append(result)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4a1575d2-1d19-4c38-85fa-f5862dc15bbd","_cell_guid":"f210489b-c557-4835-b991-cdba135c3229","trusted":true},"cell_type":"code","source":"test_df_pseudo = pd.DataFrame(testdf_psuedo, columns=['image_id', 'width', 'height', 'source', 'x', 'y', 'w', 'h'])\n# test_df_pseudo.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a52f993f-90e8-45e9-9a24-94b0be80fe4a","_cell_guid":"d77bcffe-f5ae-4090-b228-674d481111b1","trusted":true},"cell_type":"markdown","source":"# # **Retrain ResNeSt_model with pseudo labels","execution_count":null},{"metadata":{"_uuid":"7be4e4c8-5473-46a0-89a7-e9483e16dce5","_cell_guid":"a282bddc-982a-4024-a184-b264abd31dfe","trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(f'{DIR_INPUT}/train.csv')\ntrain_df['x'] = -1\ntrain_df['y'] = -1\ntrain_df['w'] = -1\ntrain_df['h'] = -1\n\ndef expand_bbox(x):\n    r = np.array(re.findall(\"([0-9]+[.]?[0-9]*)\", x))\n    if len(r) == 0:\n        r = [-1, -1, -1, -1]\n    return r\n\ntrain_df[['x', 'y', 'w', 'h']] = np.stack(train_df['bbox'].apply(lambda x: expand_bbox(x)))\ntrain_df.drop(columns=['bbox'], inplace=True)\ntrain_df['x'] = train_df['x'].astype(np.float)\ntrain_df['y'] = train_df['y'].astype(np.float)\ntrain_df['w'] = train_df['w'].astype(np.float)\ntrain_df['h'] = train_df['h'].astype(np.float)\n\n# train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"15e0d33c-4808-475e-a350-5120b46ea0c5","_cell_guid":"d0fc7b25-7af1-4839-9a01-c38b64c5388a","trusted":true},"cell_type":"code","source":"image_ids = train_df['image_id'].unique()\nvalid_ids = image_ids[-665:]\ntrain_ids = image_ids #[:-665]\n\nvalid_df = train_df[train_df['image_id'].isin(valid_ids)]\n#train_df = train_df[train_df['image_id'].isin(train_ids)]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f3ce48a3-ad71-437e-9a28-60b8e7bd4847","_cell_guid":"6f014173-8f78-4182-81b9-f4566f4decbe","trusted":true},"cell_type":"code","source":"frames = [train_df, test_df_pseudo]\ntrain_df = test_df_pseudo\n# train_df = pd.concat(frames)\n# train_df.tail()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5888853d-b310-4455-bcb9-8882970a28d1","_cell_guid":"349e3eac-ec00-46d0-81e8-94ba1913b637","trusted":true},"cell_type":"markdown","source":"# # **Wheat dataset for Training**","execution_count":null},{"metadata":{"_uuid":"c803d89e-cfeb-4a2b-ab41-d75c5bf45e11","_cell_guid":"4787c12d-5f10-4823-97ba-96a6368de16e","trusted":true},"cell_type":"code","source":"class ResNeSt_WheatDataset(Dataset):\n\n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n\n        self.image_ids = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\n        records = self.df[self.df['image_id'] == image_id]\n        if 'nvnn' in image_id:\n            image_id = image_id[4:]\n            image = cv2.imread(f'{DIR_TEST}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        else:\n            image = cv2.imread(f'{self.image_dir}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n\n        boxes = records[['x', 'y', 'w', 'h']].values\n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        \n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        area = torch.as_tensor(area, dtype=torch.float32)\n\n        # there is only one class\n        labels = torch.ones((records.shape[0],), dtype=torch.int64)\n        \n        # suppose all instances are not crowd\n        iscrowd = torch.zeros((records.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        # target['masks'] = None\n        target['image_id'] = torch.tensor([index])\n        target['area'] = area\n        target['iscrowd'] = iscrowd\n\n        if self.transforms:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': labels\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n            \n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n\n        return image, target, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"540425a5-1a8a-4dc7-b8ce-22b5badb10f2","_cell_guid":"73167a9b-2cb1-46f7-993a-ea3fcca12463","trusted":true},"cell_type":"code","source":"class Averager:\n    def __init__(self):\n        self.current_total = 0.0\n        self.iterations = 0.0\n\n    def send(self, value):\n        self.current_total += value\n        self.iterations += 1\n\n    @property\n    def value(self):\n        if self.iterations == 0:\n            return 0\n        else:\n            return 1.0 * self.current_total / self.iterations\n\n    def reset(self):\n        self.current_total = 0.0\n        self.iterations = 0.0\n        \n        \ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ntrain_dataset = ResNeSt_WheatDataset(train_df, DIR_TRAIN, get_train_transform())\nvalid_dataset = ResNeSt_WheatDataset(valid_df, DIR_TRAIN, get_valid_transform())\n\n\n# split the dataset in train and test set\nindices = torch.randperm(len(train_dataset)).tolist()\n\ntrain_data_loader = DataLoader(\n    train_dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)\n\nvalid_data_loader = DataLoader(\n    valid_dataset,\n    batch_size=4,\n    shuffle=False,\n    num_workers=4,\n    collate_fn=collate_fn\n)\n\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c13156ff-17ba-4f8d-bd6c-3605bd30dbf7","_cell_guid":"bb4b5be7-db26-45e8-b590-eaa099a72a5a","trusted":true},"cell_type":"markdown","source":"# **Show a sample**","execution_count":null},{"metadata":{"_uuid":"0966f344-8349-455b-a23a-272710d968a0","_cell_guid":"9ac809c7-d22e-4916-b5d6-757b6c3b64cd","trusted":true},"cell_type":"code","source":"# images, targets, image_ids = next(iter(train_data_loader))\n# images = list(image.to(device) for image in images)\n# targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n# boxes = targets[2]['boxes'].cpu().numpy().astype(np.int32)\n# sample = images[2].permute(1,2,0).cpu().numpy()\n\n# fig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\n# for box in boxes:\n#     cv2.rectangle(sample,\n#                   (box[0], box[1]),\n#                   (box[2], box[3]),\n#                   (220, 0, 0), 3)\n    \n# ax.set_axis_off()\n# ax.imshow(sample)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2a70ea25-1531-4f57-add8-fe7bbf513d7f","_cell_guid":"9d6f1da1-f681-4016-936b-92c7257587b8","trusted":true},"cell_type":"markdown","source":"# # ****retrain Faster RCNN****","execution_count":null},{"metadata":{"_uuid":"03602cfc-b625-4ad4-a4d1-d184d5d47902","_cell_guid":"9e856cf6-2d3d-4e85-96e1-9a8fd970a6f4","trusted":true},"cell_type":"code","source":"is_TEST = len(os.listdir('../input/global-wheat-detection/test/')) > 10","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cab8edfe-94ab-490d-bc8e-43d159ac9495","_cell_guid":"1479e5f9-32bd-4f8c-9131-e2154ce846cf","trusted":true},"cell_type":"code","source":"if is_TEST:\n    ResNeSt_model.train()\n    ResNeSt_model.to(device)\n    params = [p for p in ResNeSt_model.parameters() if p.requires_grad]\n    optimizer = torch.optim.SGD(params, lr=0.01, momentum=0.9, weight_decay=0.0001)\n    lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.5)\n    #lr_scheduler = None\n\n    num_epochs = 10\n\n    loss_hist = Averager()\n    itr = 1\n    minloss = 1000\n    for epoch in range(num_epochs):\n        loss_hist.reset()\n\n        for images, targets, image_ids in train_data_loader:\n\n            images = list(image.to(device) for image in images)\n            targets = [{k: v.to(device) for k, v in t.items()} for t in targets]\n\n            loss_dict = ResNeSt_model(images, targets)\n\n            losses = sum(loss for loss in loss_dict.values())\n            loss_value = losses.item()\n\n            loss_hist.send(loss_value)\n\n            optimizer.zero_grad()\n            losses.backward()\n            optimizer.step()\n\n            if itr % 50 == 0:\n                print(f\"Iteration #{itr} loss: {loss_value}\")\n\n            itr += 1\n\n        # update the learning rate\n        if lr_scheduler is not None:\n            lr_scheduler.step()\n\n        print(f\"Epoch #{epoch} loss: {loss_hist.value}\")\n#         if loss_hist.value < minloss:\n#             torch.save(ResNeSt_model.state_dict(),'best_resnestPL40_{}.pth'.format(epoch))\n#         if epoch % 5 == 0:\n#             torch.save(ResNeSt_model.state_dict(), 'resnest_PL40_{}.pth'.format(epoch))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b32140fc-1057-4f5e-a86d-cf8903d5961c","_cell_guid":"73cab589-8338-4990-8aae-1990db36b5d7","trusted":true},"cell_type":"markdown","source":"# # # 1. **waiting**","execution_count":null},{"metadata":{"_uuid":"164f3899-a25d-4801-b4ed-429772df2536","_cell_guid":"0a185a10-8d99-4ee2-a125-4a7c857eaaeb","trusted":true},"cell_type":"code","source":"# torch.save(ResNeSt_model.state_dict(), 'resnest_PL.pth')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"69795696-1b10-493d-88a0-96afa5c87eca","_cell_guid":"bce301a3-e3c7-485b-aa72-0ad03cdc8919","trusted":true},"cell_type":"markdown","source":"# add TTA+OOF+WBF","execution_count":null},{"metadata":{"_uuid":"53db2e6b-b7bb-41a3-86e1-22da8d0c9664","_cell_guid":"ad94c856-094d-4a05-a82f-a68c21ae05c2","trusted":true},"cell_type":"code","source":"class test_wheat(Dataset):\n\n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n\n        self.image_ids = dataframe['image_id'].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\n        records = self.df[self.df['image_id'] == image_id]\n\n        image = cv2.imread(f'{self.image_dir}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n\n        if self.transforms:\n            sample = {\n                'image': image,\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b5e10b08-ad6b-4c54-8ff3-2f2becf01cac","_cell_guid":"685ad49e-b291-43a8-8b95-ccc83c32190f","trusted":true},"cell_type":"code","source":"def get_test_transform():\n    return A.Compose([\n        # A.Resize(512, 512),\n        ToTensorV2(p=1.0)\n    ])\n\ndef collate_batch(batch):\n    return tuple(zip(*batch))\n\ndef build_test_dataset(cfg):\n    test_df = pd.read_csv(f'{cfg.DATASETS.ROOT_DIR}/sample_submission.csv')\n    print(test_df.shape)\n    test_dataset = test_wheat(test_df, f'{cfg.DATASETS.ROOT_DIR}/test', get_test_transform())\n\n    return test_dataset\n\ndef make_test_data_loader(cfg):\n    batch_size = cfg.TEST.IMS_PER_BATCH\n\n    test_dataset = build_test_dataset(cfg)\n\n    num_workers = cfg.DATALOADER.NUM_WORKERS\n\n    test_loader = data.DataLoader(\n        test_dataset,\n        batch_size=batch_size,\n        shuffle=False,\n        num_workers=num_workers,\n        drop_last=False,\n        collate_fn=collate_batch\n    )\n\n    return test_loader\n\ntest_loader = make_test_data_loader(cfg)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"do_edet = False","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"978393eb-6295-48d7-82bb-0863506c2f69","_cell_guid":"1cea4080-760e-4d7c-9b29-2aaf6b55c838","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\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\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\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\n\nclass TTACompose(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n\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\ndef Res_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\n              predictions]\n    boxes, scores, labels = ensemble_boxes.ensemble_boxes_wbf.weighted_boxes_fusion(boxes, scores, labels,\n                                                                                    weights=None, iou_thr=iou_thr,\n                                                                                    skip_box_thr=skip_box_thr)\n    boxes = boxes * (image_size - 1)\n    return boxes, scores, labels\n    \nRes_tta_transforms = []\nfor tta_combination in product([TTAHorizontalFlip(), None],\n                               [TTAVerticalFlip(), None],\n                               [TTARotate90(), None]):\n    Res_tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f70ba6d9-bf47-48fa-ab28-8c2cd52a084b","_cell_guid":"34cf9398-0143-46a4-9b73-88976985e4f7","trusted":true},"cell_type":"code","source":"# # NMS算法\n#     # bboxes维度为[N,4]，scores维度为[N,], 均为tensor\n# def nms(bboxes, scores, threshold=0.5):\n#     x1 = bboxes[:,0]\n#     y1 = bboxes[:,1]\n#     x2 = bboxes[:,2]\n#     y2 = bboxes[:,3]\n#     areas = (x2-x1)*(y2-y1)   # [N,] 每个bbox的面积\n#     _, order = scores.sort(0, descending=True)    # 降序排列\n\n#     keep = []\n#     while order.numel() > 0:       # torch.numel()返回张量元素个数\n#         if order.numel() == 1:     # 保留框只剩一个\n#             i = order.item()\n#             keep.append(i)\n#             break\n#         else:\n#             i = order[0].item()    # 保留scores最大的那个框box[i]\n#             keep.append(i)\n\n#         # 计算box[i]与其余各框的IOU(思路很好)\n#         xx1 = x1[order[1:]].clamp(min=x1[i])   # [N-1,]\n#         yy1 = y1[order[1:]].clamp(min=y1[i])\n#         xx2 = x2[order[1:]].clamp(max=x2[i])\n#         yy2 = y2[order[1:]].clamp(max=y2[i])\n#         inter = (xx2-xx1).clamp(min=0) * (yy2-yy1).clamp(min=0)   # [N-1,]\n\n#         iou = inter / (areas[i]+areas[order[1:]]-inter)  # [N-1,]\n#         idx = (iou <= threshold).nonzero().squeeze() # 注意此时idx为[N-1,] 而order为[N,]\n#         if idx.numel() == 0:\n#             break\n#         order = order[idx+1]  # 修补索引之间的差值\n#     return torch.LongTensor(keep)   # Pytorch的索引值为LongTensor","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"73cf385d-f4d6-4572-a3b3-cbb464ee7005","_cell_guid":"859fbf26-28d8-401a-9562-37603b67117d","trusted":true},"cell_type":"code","source":"def Res_make_tta_predictions(Res_tta_transforms, images, model):\n        with torch.no_grad():\n            images = torch.stack(images).float().cuda()\n            predictions = []\n            enboxes = []\n            enscores = []\n            for tta_transform in Res_tta_transforms:\n                result = []\n                outputs = model(tta_transform.batch_augment(images.clone()))\n#                 outputs = non_max_suppression(outputs, NMS_CONF_THR, NMS_IOU_THR, merge=True, classes=None, agnostic=False)\n                for i, image in enumerate(images):\n#                     output = nms(outputs[i]['boxes'], scores = outputs[i]['scores'], threshold=0.5)\n                    boxes = outputs[i]['boxes'].data.cpu().numpy()\n#                     print(boxes)\n#                     print(boxes.shape)\n#                     print(outputs[i]['boxes'][output])\n                    scores = outputs[i]['scores'].data.cpu().numpy()\n#                     indexes = np.where(scores > score_threshold)[0]\n#                     boxes = boxes[indexes]\n#                     scores = scores[indexes]\n                    boxes = tta_transform.deaugment_boxes(boxes.copy())\n#                     enboxes.append(boxes)\n#                     enscores.append(scores) \n    \n                    result.append({\n                        'boxes': boxes,\n                        'scores': scores,\n                    })\n                predictions.append(result)\n        return predictions","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fb943993-c689-4ebe-8df1-9b5a18fb64a6","_cell_guid":"31c29f03-1695-4199-9924-fadd83bfcaa6","trusted":true},"cell_type":"code","source":"def get_train_transforms(cfg):\n    return A.Compose(\n        [\n#             A.RandomSizedCrop(min_max_height=cfg.INPUT.RSC_MIN_MAX_HEIGHT, height=cfg.INPUT.RSC_HEIGHT,\n#                               width=cfg.INPUT.RSC_WIDTH, p=cfg.INPUT.RSC_PROB),\n#             A.RandomSizedCrop(min_max_height=cfg.INPUT.RSC_MIN_MAX_HEIGHT, p=cfg.INPUT.RSC_PROB),\n            A.OneOf([\n                A.HueSaturationValue(hue_shift_limit=cfg.INPUT.HSV_H, sat_shift_limit=cfg.INPUT.HSV_S,\n                                     val_shift_limit=cfg.INPUT.HSV_V, p=cfg.INPUT.HSV_PROB),\n                A.RandomBrightnessContrast(brightness_limit=cfg.INPUT.BC_B,\n                                           contrast_limit=cfg.INPUT.BC_C, p=cfg.INPUT.BC_PROB),\n            ],p=cfg.INPUT.COLOR_PROB),\n            A.ToGray(p=cfg.INPUT.TOFGRAY_PROB),\n            A.HorizontalFlip(p=cfg.INPUT.HFLIP_PROB),\n            A.VerticalFlip(p=cfg.INPUT.VFLIP_PROB),\n            # A.Resize(height=512, width=512, p=1),\n            A.Cutout(num_holes=cfg.INPUT.COTOUT_NUM_HOLES, max_h_size=cfg.INPUT.COTOUT_MAX_H_SIZE,\n                     max_w_size=cfg.INPUT.COTOUT_MAX_W_SIZE, fill_value=cfg.INPUT.COTOUT_FILL_VALUE, p=cfg.INPUT.COTOUT_PROB),\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(cfg):\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    )","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"40676dce-9088-4a2e-8ce8-a634ec6c0a15","_cell_guid":"7458660a-6cd4-4e65-a38e-6b3d80190535","trusted":true},"cell_type":"code","source":"def build_transforms(cfg, is_train=True):\n    if is_train:\n        transform = get_train_transforms(cfg)\n    else:\n        transform = get_valid_transforms(cfg)\n\n    return transform","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"edb3d23c-d0eb-457d-bfa6-0d57770ee0f1","_cell_guid":"3b04d2be-c7ae-4570-8acf-9cc7db43f090","trusted":true},"cell_type":"code","source":"def split_dataset(cfg):\n    fold_train_df = pd.read_csv(f'{cfg.DATASETS.ROOT_DIR}/train.csv')\n    \n    skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\n    df_folds = fold_train_df[['image_id']].copy()\n    df_folds.loc[:, 'bbox_count'] = 1\n    df_folds = df_folds.groupby('image_id').count()\n    df_folds.loc[:, 'source'] = fold_train_df[['image_id', 'source']].groupby('image_id').min()['source']\n    df_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    )\n    df_folds.loc[:, 'fold'] = 0\n\n    for 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\n\n    train_ids = df_folds[df_folds['fold'] != cfg.DATASETS.VALID_FOLD].index.values\n    valid_ids = df_folds[df_folds['fold'] == cfg.DATASETS.VALID_FOLD].index.values\n    if cfg.DEBUG:\n        train_ids = train_ids[:40]\n        valid_ids = valid_ids[:10]\n\n    return train_ids, valid_ids\ntrain_ids, valid_ids = split_dataset(cfg)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"14de2ce3-ca29-4a29-916e-d7164d0e9e9c","_cell_guid":"143e0cca-6f82-4c1b-8a0b-2943aca235fc","trusted":true},"cell_type":"code","source":"def expand_bbox(x):\n    r = np.array(re.findall(\"([0-9]+[.]?[0-9]*)\", x))\n    if len(r) == 0:\n        r = [-1, -1, -1, -1]\n    return r","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"84b174e2-ec1a-4de4-8a84-bea57d819e27","_cell_guid":"06d8762f-9ac1-4803-a0ac-0dffcc728f8c","trusted":true},"cell_type":"code","source":"marking = pd.read_csv(f'{cfg.DATASETS.ROOT_DIR}/train.csv')\nmarking['x'] = -1\nmarking['y'] = -1\nmarking['w'] = -1\nmarking['h'] = -1\n\n#     bboxs = np.stack(marking['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\n#     for i, column in enumerate(['x', 'y', 'w', 'h']):\n#         marking[column] = bboxs[:, i]\n\nmarking[['x', 'y', 'w', 'h']] = np.stack(marking['bbox'].apply(lambda x: expand_bbox(x)))\nmarking.drop(columns=['bbox'], inplace=True)\nmarking['x'] = marking['x'].astype(np.float)\nmarking['y'] = marking['y'].astype(np.float)\nmarking['w'] = marking['w'].astype(np.float)\nmarking['h'] = marking['h'].astype(np.float)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"12f61fde-f758-4536-ae4f-6af2d84a737a","_cell_guid":"f62cce1a-a5a6-4988-85b0-8a6fe25cca5f","trusted":true},"cell_type":"code","source":"marking['area'] = marking['w'] * marking['h']\nmarking = marking[marking['area'] < 154200.0]\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]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66a132ca-2ca8-4127-8dea-200eecb821b5","_cell_guid":"a2fd8983-94ff-45f8-839a-13b8fe56840c","trusted":true},"cell_type":"code","source":"class ResNeSt_val_WheatDataset(Dataset):\n\n#     def __init__(self, dataframe, image_dir, transforms=None):\n    def __init__(self, root, marking, image_ids, transforms=None):\n        super().__init__()\n\n        self.image_dir = root\n        self.image_ids = image_ids\n        self.marking = marking\n        \n#         self.image_ids = dataframe['image_id'].unique()\n#         self.df = dataframe\n#         self.image_dir = image_dir\n        self.transforms = transforms\n\n    def __getitem__(self, index: int):\n\n        image_id = self.image_ids[index]\n#         records = self.df[self.df['image_id'] == image_id]\n        records = self.marking[self.marking['image_id'] == image_id]\n        if 'cjc' in image_id:\n            image_id = image_id[3:]\n            image = test_images[image_id]\n        else:\n            image = cv2.imread(f'{self.image_dir}/train/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        image /= 255.0\n\n        boxes = records[['x', 'y', 'w', 'h']].values\n        boxes[:, 2] = boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = boxes[:, 1] + boxes[:, 3]\n        \n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        area = torch.as_tensor(area, dtype=torch.float32)\n\n        # there is only one class\n        labels = torch.ones((records.shape[0],), dtype=torch.int64)\n        \n        # suppose all instances are not crowd\n        iscrowd = torch.zeros((records.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        # target['masks'] = None\n        target['image_id'] = torch.tensor([index])\n        target['area'] = area\n        target['iscrowd'] = iscrowd\n\n        if self.transforms:\n            sample = {\n                'image': image,\n                'bboxes': target['boxes'],\n                'labels': labels\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n            \n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n\n        return image, target, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e25ef752-1a9c-41d0-a72b-98038eada16b","_cell_guid":"11b386bb-0a68-491d-8038-df0025420c35","trusted":true},"cell_type":"code","source":"def build_dataset(cfg):\n#     train_ids, valid_ids = split_dataset(cfg)\n#     train_dataset = ResNeSt_val_WheatDataset(\n#         root = cfg.DATASETS.ROOT_DIR,\n#         image_ids=train_ids,\n#         marking=marking,\n#         transforms=build_transforms(cfg, is_train=True),\n# #         test=False,\n#     )\n\n    validation_dataset = ResNeSt_val_WheatDataset(\n        root=cfg.DATASETS.ROOT_DIR,\n        image_ids=valid_ids,\n        marking=marking,\n        transforms=build_transforms(cfg, is_train=False),\n#         test=True,\n    )\n\n    return validation_dataset","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"1fbfc5ec-fed5-4fd2-9d83-0625ff382319","_cell_guid":"4ed94264-b273-47ba-b3bf-a2d010d3a3e9","trusted":true},"cell_type":"code","source":"def make_data_loader(cfg, is_train=True):\n    if is_train:\n        batch_size = cfg.SOLVER.IMS_PER_BATCH\n    else:\n        batch_size = cfg.TEST.IMS_PER_BATCH\n\n#     train_dataset, validation_dataset = build_dataset(cfg)\n    validation_dataset = build_dataset(cfg)\n    num_workers = cfg.DATALOADER.NUM_WORKERS\n#     train_loader = data.DataLoader(\n#         train_dataset,\n#         batch_size=batch_size,\n#         sampler=RandomSampler(train_dataset),\n#         pin_memory=False,\n#         drop_last=True,\n#         num_workers=num_workers,\n#         collate_fn=collate_batch,\n#     )\n    val_loader = data.DataLoader(\n        validation_dataset,\n        batch_size=batch_size,\n        num_workers=num_workers,\n        shuffle=False,\n        sampler=SequentialSampler(validation_dataset),\n        pin_memory=False,\n        collate_fn=collate_batch,\n    )\n\n    return val_loader\n\nval_loader = make_data_loader(cfg, is_train=True)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"bbc7d1b1-5cf0-4c9a-ab0f-81877b9db3bf","_cell_guid":"33860913-efd8-413e-997f-420785b597a8","trusted":true},"cell_type":"code","source":"# validate\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\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":"379919fa-96ca-4a57-afb6-8de80bea1e09","_cell_guid":"5c53a39a-8d4c-4560-a0de-1308b9c4d9a7","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 = Res_make_tta_predictions(Res_tta_transforms, images, model)\n\n#             predictions_real = pred(images, model)\n#             predictions.append(predictions_real)\n\n            for i, image in enumerate(images):\n                boxes, scores, labels = Res_run_wbf(predictions, image_index=i)\n                boxes = boxes.round().astype(np.int32).clip(min=0, max=1023) \n\n                all_prediction = {\n                    'pred_enboxes': boxes,\n                    'pred_enscores': scores,\n                    'gt_boxes': targets[i]['boxes'].cpu().numpy().astype(int),\n                    'image_id': image_ids[i],\n                }\n\n                all_predictions.append(all_prediction)\n            valid_loader.set_description(f'Validate Step {step}/{len(val_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":"08668820-d27f-4b83-9782-b5eb89b31f90","_cell_guid":"0c222d13-8613-44ef-a6f1-a14d22dee5a6","trusted":true},"cell_type":"code","source":"if is_TEST:\n    all_predictions = validation(ResNeSt_model)\n    # print(all_predictions)\n\n    # best_iou_thr = 0.5\n    # best_skip_box_thr = 0.43\n\n    Res_best_final_score, Res_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 > Res_best_final_score:\n            Res_best_final_score = final_score\n            Res_best_score_threshold = score_threshold\n    print('-'*30)\n    print(f'[Res_Best Score Threshold]: {Res_best_score_threshold}')\n    print(f'[Res_OOF Score]: {Res_best_final_score:.4f}')\n    print('-'*30)\n    # print(all_predictions)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# EffientDet(PL+TTA+WBF+OOF)","execution_count":null},{"metadata":{"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":{"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\n\nsys.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":{"trusted":true},"cell_type":"code","source":"effdet_weights = \"../input/effdetretrains/retrain.bin\"","execution_count":null,"outputs":[]},{"metadata":{"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":{"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":{"trusted":true},"cell_type":"code","source":"marking['area'] = marking['w'] * marking['h']\n# print(len(marking))\nmarking = marking[marking['area'] < 154200.0]\n# print(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]\n# print(len(marking))","execution_count":null,"outputs":[]},{"metadata":{"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    )\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":{"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":{"trusted":true},"cell_type":"code","source":"class TrainGlobalConfig:\n    num_workers = 2\n    batch_size = 4 \n    n_epochs = 10 # 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":{"trusted":true},"cell_type":"code","source":"# !mkdir test\n# !cp -r ../input/global-wheat-detection/test/* test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# img = cv2.imread(\"test/aac893a91.jpg\")\n# img = cv2.resize(img, (600, 600))\n# cv2.imwrite('test/atcc93b91.jpg', img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_ROOT_PATH = '../input/global-wheat-detection/test'\n\nclass test_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.resize(image, (512, 512))\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 = test_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":{"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":{"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":{"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":{"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":{"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            \n            results_plabel.append(result_p)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results_df = pd.DataFrame(results_plabel, columns=['image_id', 'width','height','source','x','y','w','h'])\n# results_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results_df['image_id'] = results_df['image_id'].apply(lambda x: DATA_ROOT_PATH+'/'+ x +'.jpg')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# !cp -r ../input/global-wheat-detection/train/* test","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_ROOT_PATH = '../input/global-wheat-detection/train'\n# marking['image_id'] = marking['image_id'].apply(lambda x: TRAIN_ROOT_PATH+'/'+ x+'.jpg')\ntrain_data_plabel = results_df # pd.concat([results_df, marking], axis=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# test_ids_ = os.listdir(\"../input/global-wheat-detection/test\")\n# test_idss = []\n# for test_id in test_ids_:  \n#     ids = test_id[:-4]\n#     test_idss.append(ids)\n# #print(test_idss)\n# test_images = {}\n# test_ids = []\n# for 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)\n# #print(len(test_images))\n# test_ids = pd.DataFrame(test_ids,columns=['image_id'])\n# #print(test_ids)\n# # print(test_images[test_ids[1]])\n# test_ids['image_id'] = test_ids['image_id'].apply(lambda x: DATA_ROOT_PATH+'/'+ x+'.jpg')","execution_count":null,"outputs":[]},{"metadata":{"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":{"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":{"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        \n        return result_image, result_boxes","execution_count":null,"outputs":[]},{"metadata":{"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=True,\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":{"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)\n","execution_count":null,"outputs":[]},{"metadata":{"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":{"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":{"trusted":true},"cell_type":"code","source":"if is_TEST:\n    run_training()\nelse:\n    pass","execution_count":null,"outputs":[]},{"metadata":{"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":{"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":{"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    Edet_best_final_score, Edet_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 > Edet_best_final_score:\n            Edet_best_final_score = final_score\n            Edet_best_score_threshold = score_threshold\n    print('-'*30)\n    print(f'[Edet_Best Score Threshold]: {Edet_best_score_threshold}')\n    print(f'[Edet_OOF Score]: {Edet_best_final_score:.4f}')\n    print('-'*30)\n    # print(all_predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Res_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)\n\ndef Edet_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":{"trusted":true},"cell_type":"code","source":"def do_transforms(is_Edet):\n    if is_Edet:\n        transform = Edet_get_test_transforms()\n    else:\n        transform = Res_get_test_transforms()\n\n    return transform","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class TestDatasetRetriever(Dataset):\n\n    def __init__(self, image_ids, path, transforms=None):\n        super().__init__()\n        self.image_ids = image_ids\n        self.transforms = transforms\n        self.path = path\n\n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        image = cv2.imread(f'{self.path}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\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":"def to_tensor(images):\n    tmp = []\n    for img in images:\n        img = img.astype(np.float32)\n        img /= 255.0\n        img = torch.tensor(img, dtype=torch.float32)\n        tmp.append(img.permute(2,0,1))\n    return torch.stack(tmp)\n\n\n\ndef Res_make_tta_predictions_2(Res_tta_transforms, images, model):\n    \n    with torch.no_grad():\n        #images = torch.stack(images).float().cuda()\n        predictions = []\n        enboxes = []\n        enscores = []\n        for tta_transform in Res_tta_transforms:\n            result = []\n            outputs = model(tta_transform.batch_augment(images.clone()))\n#                 outputs = non_max_suppression(outputs, NMS_CONF_THR, NMS_IOU_THR, merge=True, classes=None, agnostic=False)\n            for i, image in enumerate(images):\n#                     output = nms(outputs[i]['boxes'], scores = outputs[i]['scores'], threshold=0.5)\n                boxes = outputs[i]['boxes'].data.cpu().numpy()\n#                     print(boxes)\n#                     print(boxes.shape)\n#                     print(outputs[i]['boxes'][output])\n                scores = outputs[i]['scores'].data.cpu().numpy()\n#                     indexes = np.where(scores > score_threshold)[0]\n#                     boxes = boxes[indexes]\n#                     scores = scores[indexes]\n                boxes = tta_transform.deaugment_boxes(boxes.copy())\n#                     enboxes.append(boxes)\n#                     enscores.append(scores) \n\n                result.append({\n                    'boxes': boxes,\n                    'scores': scores,\n                })\n            predictions.append(result)\n    return predictions\n    \n    \n# use TTA\ndef make_tta_predictions_2(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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TEST_ROOT_PATH = '../input/global-wheat-detection/test'\n\ntest_dataset = TestDatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{TEST_ROOT_PATH}/*.jpg')]),\n    path=TEST_ROOT_PATH\n)\n\ntest_data_loader = DataLoader(\n    test_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":{"trusted":true},"cell_type":"code","source":"ResNeSt_model.eval()\nnet.eval()\ntorch.cuda.empty_cache()\n# test_load = tqdm(test_loader, total=len(test_loader), desc=\"Testing\")\nresults = []\n# best_score_threshold = 0.54\nfor images, image_ids in test_data_loader:\n\n    image = images[0]\n    \n    height, width, _ = image.shape\n    \n    image_res = cv2.resize(image, (1024, 1024))\n    \n    image = cv2.resize(image, (512, 512))\n    \n    image = to_tensor([image]).cuda()\n    image_res = to_tensor([image_res]).cuda()\n    \n    Res_predictions = Res_make_tta_predictions_2(Res_tta_transforms, image_res, ResNeSt_model)\n    Res_boxes, Res_scores, Res_labels = Res_run_wbf(Res_predictions, image_index=0)\n#     Res_boxes = Res_boxes.round().astype(np.int32).clip(min=0, max=1023)\n\n    Res_boxes = Res_boxes[Res_scores >= Res_best_score_threshold].astype(np.int32)\n    Res_scores = Res_scores[Res_scores >= Res_best_score_threshold]\n    \n    \n    Edet_predictions = make_tta_predictions_2(image)\n    Edet_boxes, Edet_scores, Edet_labels = run_wbf(Edet_predictions, image_index=0)\n#     Edet_boxes = (Edet_boxes*2).astype(np.int32).clip(min=0, max=1023)\n    Edet_boxes = Edet_boxes*2\n    \n    Edet_boxes = Edet_boxes[Edet_scores >= Edet_best_score_threshold].astype(np.int32)\n    Edet_scores = Edet_scores[Edet_scores >= Edet_best_score_threshold]\n    \n    \n    #fuse\n    boxes = [Res_boxes / 1023, Edet_boxes / 1023]\n    scores = [Res_scores, Edet_scores]\n    labels = [Res_labels, Edet_labels]\n    \n    boxes, scores, labels = weighted_boxes_fusion(boxes, scores, labels, \n                                                    weights=None, iou_thr=0.44, skip_box_thr=0.43)\n    \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\n    result = {\n        'image_id': image_ids[0],\n        'PredictionString': format_prediction_string(boxes, scores)\n    }\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":"!rm -rf utils\n!rm -rf experiments\n!rm -rf data\n!rm -rf tools\n!rm -rf layers\n!rm -rf solver\n!rm -rf config\n!rm -rf evaluate\n!rm -rf tests\n!rm -rf engine\n!rm -rf modeling\n!rm -rf configs\n!rm -rf LICENSE\n!rm -rf README.md\n!rm -rf external\n!rm -rf plabel_model","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}