{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":52279,"databundleVersionId":5822112,"sourceType":"competition"},{"sourceId":6021726,"sourceType":"datasetVersion","datasetId":3446188},{"sourceId":8023843,"sourceType":"datasetVersion","datasetId":4728466}],"dockerImageVersionId":30512,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport random\nimport torch\nimport os","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:03:40.691688Z","iopub.execute_input":"2024-04-06T06:03:40.691988Z","iopub.status.idle":"2024-04-06T06:03:44.298751Z","shell.execute_reply.started":"2024-04-06T06:03:40.691961Z","shell.execute_reply":"2024-04-06T06:03:44.297606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everythig(seed):\n    np.random.seed(seed)\n    random.seed(seed)\n    os.environ[\"GLOBALSEED\"] = str(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:03:48.268360Z","iopub.execute_input":"2024-04-06T06:03:48.269478Z","iopub.status.idle":"2024-04-06T06:03:48.275107Z","shell.execute_reply.started":"2024-04-06T06:03:48.269444Z","shell.execute_reply":"2024-04-06T06:03:48.274137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed_everythig(42)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:03:48.856088Z","iopub.execute_input":"2024-04-06T06:03:48.856789Z","iopub.status.idle":"2024-04-06T06:03:48.889483Z","shell.execute_reply.started":"2024-04-06T06:03:48.856756Z","shell.execute_reply":"2024-04-06T06:03:48.888759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from itertools import chain\nimport json\nimport os\nimport shutil\nfrom tqdm.notebook import tqdm\nfrom colorama import Fore\nimport yaml","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:03:50.019109Z","iopub.execute_input":"2024-04-06T06:03:50.019467Z","iopub.status.idle":"2024-04-06T06:03:50.108509Z","shell.execute_reply.started":"2024-04-06T06:03:50.019438Z","shell.execute_reply":"2024-04-06T06:03:50.107575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class COCODataset:\n    def __init__(self, images_dirpath: str, annotations_filepath: str, length: int = 1633):\n        self.train_size = None\n        self.val_size = None\n        self.length = length\n        self.classes = None\n        self.labels_counter = None\n        self.normalize = None\n\n        self.images_dirpath = images_dirpath\n        self.annotations_filepath = annotations_filepath\n        self.dataset_dirpath = os.path.join(os.getcwd(), \"dataset\")\n        self.train_dirpath =  os.path.join(self.dataset_dirpath, \"train\")\n        self.val_dirpath =  os.path.join(self.dataset_dirpath, \"val\")\n        self.config_path = os.path.join(self.dataset_dirpath, \"coco.yaml\")\n\n        self.samples = self.parse_jsonl(annotations_filepath)\n        self.classes_dict = {\n            \"background\": 0,\n            \"blood_vessel\": 1,\n            \"glomerulus\": 2,\n            \"unsure\": 3,\n        }\n\n    def __prepare_dirs(self) -> None:\n        if not os.path.exists(self.dataset_dirpath):\n            os.makedirs(os.path.join(self.train_dirpath, \"images\"), exist_ok=True)\n            os.makedirs(os.path.join(self.train_dirpath, \"labels\"), exist_ok=True)\n            os.makedirs(os.path.join(self.val_dirpath, \"images\"), exist_ok=True)\n            os.makedirs(os.path.join(self.val_dirpath, \"labels\"), exist_ok=True)\n        else:\n            raise RuntimeError(\"Dataset already exists!\")\n\n    def __define_splitratio(self) -> None:\n        self.train_size = round(self.length * self.train_size)\n        self.val_size = self.length - self.train_size\n        assert self.train_size + self.val_size == self.length\n\n    def parse_jsonl(self, path: str) -> list[dict, ...]:\n        with open(path, 'r') as json_file:\n            jsonl_samples = [\n                json.loads(line)\n                for line in tqdm(\n                    json_file, desc=\"Processing polygons\", total=self.length\n                )\n            ]\n        return jsonl_samples\n\n    def __define_paths(self, i: int) -> dict:\n        data_path = self.val_dirpath\n        if i < self.train_size:\n            data_path = self.train_dirpath\n        return {\n            \"images\": os.path.join(data_path, \"images\"),\n            \"labels\": os.path.join(data_path, \"labels\")\n        }\n\n    @staticmethod\n    def __get_label_path(paths_dict: dict, identifier: str) -> str:\n        return os.path.join(\n            paths_dict[\"labels\"],\n            f\"{identifier}.txt\"\n        )\n\n    @staticmethod\n    def __get_image_path(paths_dict: dict, identifier: str) -> str:\n        return os.path.join(\n            paths_dict[\"images\"],\n            f\"{identifier}.tif\"\n        )\n\n    def __copy_image(self, dst_path: str, identifier: str) -> str:\n        shutil.copyfile(\n            os.path.join(self.images_dirpath, f\"{identifier}.tif\"),\n            dst_path\n        )\n\n    def __copy_label(self, annotations: list, dst_path: str) -> None:\n        with open(dst_path, \"w\") as file:\n            for annotation in annotations:\n                coordinates = annotation[\"coordinates\"][0]\n                label = self.classes_dict[annotation[\"type\"]]\n                if label in self.classes:\n                    if coordinates:\n                        if self.normalize:\n                            coordinates = np.array(coordinates) / 512.0\n                        coordinates = \" \".join(map(str, chain(*coordinates)))\n                        file.write(f\"{label} {coordinates}\\n\")\n                        self.labels_counter += 1\n\n    def __splitfolders(self):\n        for i, line in tqdm(\n                enumerate(self.samples),\n                desc=\"Dataset creation\", total=self.length\n        ):\n            self.labels_counter = 0\n            identifier = line[\"id\"]\n            annotations = line[\"annotations\"]\n            paths_dict = self.__define_paths(i)\n\n            dst_image_path = self.__get_image_path(paths_dict, identifier)\n            dst_label_path = self.__get_label_path(paths_dict, identifier)\n\n            self.__copy_image(dst_image_path, identifier)\n            self.__copy_label(annotations, dst_label_path)\n\n            if self.labels_counter == 0:\n                os.remove(dst_image_path)\n                os.remove(dst_label_path)\n\n    def __count_dataset(self) -> dict:\n        train_images = len(os.listdir(os.path.join(self.train_dirpath, \"images\")))\n        train_labels = len(os.listdir(os.path.join(self.train_dirpath, \"labels\")))\n        val_images = len(os.listdir(os.path.join(self.val_dirpath, \"images\")))\n        val_labels = len(os.listdir(os.path.join(self.val_dirpath, \"labels\")))\n        return {\n            \"train_images\": train_images,\n            \"train_labels\": train_labels,\n            \"val_images\": val_images,\n            \"val_labels\": val_labels\n        }\n\n    @staticmethod\n    def __check_sanity(count_dict: dict) -> None:\n        assert count_dict[\"train_images\"] == count_dict[\"train_labels\"]\n        assert count_dict[\"val_images\"] == count_dict[\"val_labels\"]\n\n    def __finalizing(self, count_dict: dict) -> None:\n        assert os.path.exists(self.dataset_dirpath)\n\n        example_structure = [\n            \"dataset\",\n            \"train\", \"labels\", \"images\",\n            \"val\", \"labels\", \"images\"\n        ]\n\n        dir_bone = (\n            dirname.split(\"/\")[-1]\n            for dirname, _, filenames in os.walk(self.dataset_dirpath)\n            if dirname.split(\"/\")[-1] in example_structure\n        )\n\n        try:\n            print(\"\\n~ HuBMAP Dataset Structure ~\\n\")\n            print(\n            f\"\"\"\n          ├── {next(dir_bone)}\n          │   │\n          │   ├── {next(dir_bone)}\n          │   │   └── {next(dir_bone)}\n          │   │   └── {next(dir_bone)}\n          │   │\n          │   ├── {next(dir_bone)}\n          │   │   └── {next(dir_bone)}\n          │   │   └── {next(dir_bone)}\n            \"\"\"\n            )\n        except StopIteration as e:\n            print(e)\n        else:\n            print(Fore.GREEN + \"-> Success\")\n            print(Fore.GREEN + f\"Train dataset: {count_dict['train_images']}\\nVal dataset: {count_dict['val_images']}\")\n\n    def get_config(self) ->dict:\n        names = [\"background\", \"blood_vessel\", \"glomerulus\", \"unsure\"]\n        return {\n            \"train\": str(self.train_dirpath),\n            \"val\": str(self.val_dirpath),\n            \"names\": [names[i] for i in self.classes]\n        }\n\n    @staticmethod\n    def display_config(config: dict) -> None:\n        print(Fore.BLACK + \"\\n~ HuBMAP Config Structure ~\\n\")\n        print(\n        f\"\"\"\n      │   │\n      │   ├── train\n      │   │   └── {config['train']}/images\n      │   │\n      │   │\n      │   ├── val\n      │   │   └── {config['val']}/images\n      │   │\n      │   │\n      │   ├── names\n      │   │   └── {' '.join(config['names'])}\n        \"\"\"\n        )\n        print(Fore.GREEN + \"-> Success\")\n        print(Fore.GREEN + f\"Number of classes: {len(config['names'])}\"\n                           f\"\\nClasses: {' '.join(config['names'])}\"\n              )\n\n    def write_config(self, config: dict) -> None:\n        with open(self.config_path, mode=\"w\") as f:\n            yaml.safe_dump(stream=f, data=config)\n\n    def __call__(self, train_size: float,\n                 classes: list[int, ...],\n                 make_config: bool = True,\n                 normalize: bool = True\n                ) -> None:\n\n        self.train_size = train_size\n        self.classes = classes\n        self.normalize = normalize\n\n        self.__define_splitratio()\n        self.__prepare_dirs()\n        self.__splitfolders()\n        count_dict = self.__count_dataset()\n        self.__check_sanity(count_dict)\n        self.__finalizing(count_dict)\n\n        if make_config:\n            config = self.get_config()\n            self.write_config(config)\n            self.display_config(config)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:03:51.946133Z","iopub.execute_input":"2024-04-06T06:03:51.946489Z","iopub.status.idle":"2024-04-06T06:03:51.982408Z","shell.execute_reply.started":"2024-04-06T06:03:51.946460Z","shell.execute_reply":"2024-04-06T06:03:51.981380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"coco = COCODataset(\n    annotations_filepath=\"/kaggle/input/hubmap-hacking-the-human-vasculature/polygons.jsonl\",\n    images_dirpath=\"/kaggle/input/hubmap-hacking-the-human-vasculature/train\",\n) ","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:01.015978Z","iopub.execute_input":"2024-04-06T05:07:01.016283Z","iopub.status.idle":"2024-04-06T05:07:05.491746Z","shell.execute_reply.started":"2024-04-06T05:07:01.016257Z","shell.execute_reply":"2024-04-06T05:07:05.490879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"coco(train_size=0.80, classes=[1, 2, 3], normalize=False)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:05.492861Z","iopub.execute_input":"2024-04-06T05:07:05.493139Z","iopub.status.idle":"2024-04-06T05:07:36.585090Z","shell.execute_reply.started":"2024-04-06T05:07:05.493115Z","shell.execute_reply":"2024-04-06T05:07:36.584279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection.mask_rcnn import MaskRCNNPredictor","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:36.586144Z","iopub.execute_input":"2024-04-06T05:07:36.586410Z","iopub.status.idle":"2024-04-06T05:07:36.805203Z","shell.execute_reply.started":"2024-04-06T05:07:36.586386Z","shell.execute_reply":"2024-04-06T05:07:36.804433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(num_classes: int):\n    # load an instance segmentation model pre-trained on COCO\n    model = torchvision.models.detection.maskrcnn_resnet50_fpn(weights=\"DEFAULT\")\n\n    # get number of input features for the classifier\n    in_features = model.roi_heads.box_predictor.cls_score.in_features\n    # replace the pre-trained head with a new one\n    model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n\n    # now get the number of input features for the mask classifier\n    in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels\n    hidden_layer = 256\n    # and replace the mask predictor with a new one\n    model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask,\n                                                       hidden_layer,\n                                                       num_classes)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:36.806445Z","iopub.execute_input":"2024-04-06T05:07:36.807240Z","iopub.status.idle":"2024-04-06T05:07:36.812783Z","shell.execute_reply.started":"2024-04-06T05:07:36.807213Z","shell.execute_reply":"2024-04-06T05:07:36.811943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = get_model(4)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:36.816694Z","iopub.execute_input":"2024-04-06T05:07:36.817055Z","iopub.status.idle":"2024-04-06T05:07:38.404291Z","shell.execute_reply.started":"2024-04-06T05:07:36.817020Z","shell.execute_reply":"2024-04-06T05:07:38.403496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffd37a; font-family:verdana; color: #543800; border: 2px #543800 solid\">\n    <b>What about transforming our data?</b>\n<br>Firstly, we absolutely need to bring the pictures to a single size and also normalize them. It would also not be bad to augment our data. But here's the problem. After all, we are now working not with an image and its single mask as in semantic segmentation, but with individual instances, their masks and boxes. In this case, we can ignore color transformations, but all spatial transformations change both box and mask coordinates. In this case, we must take this into account. A wonderful library from the community comes to the rescue - albumentations. It will allow you to quickly and easily take into account all the transformations. Otherwise, we had to read it ourselves.<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"![](https://www.researchgate.net/publication/319413978/figure/fig2/AS:533727585333249@1504261980375/Data-augmentation-using-semantic-preserving-transformation-for-SBIR.png)","metadata":{}},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:38.405349Z","iopub.execute_input":"2024-04-06T05:07:38.405627Z","iopub.status.idle":"2024-04-06T05:07:39.800612Z","shell.execute_reply.started":"2024-04-06T05:07:38.405592Z","shell.execute_reply":"2024-04-06T05:07:39.799849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffd37a; font-family:verdana; color: #543800; border: 2px #543800 solid\">\n    <b>Transforms for training</b>\n</div>","metadata":{}},{"cell_type":"code","source":"train_transforms = [\n    A.Resize(512, 512, p=1), \n    A.HorizontalFlip(p=0.5),\n    A.VerticalFlip(p=0.5),\n    A.RandomBrightnessContrast(p=0.45),\n    A.HueSaturationValue(p=0.35),\n    \n    A.OneOf([\n        A.MotionBlur(),\n        A.Blur(blur_limit=3),\n        A.MedianBlur(blur_limit=3),\n        A.GaussNoise()\n        ], p=0.10\n    ),\n                         \n    A.Normalize(),\n    ToTensorV2()\n]","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.801798Z","iopub.execute_input":"2024-04-06T05:07:39.802071Z","iopub.status.idle":"2024-04-06T05:07:39.808733Z","shell.execute_reply.started":"2024-04-06T05:07:39.802047Z","shell.execute_reply":"2024-04-06T05:07:39.807845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffd37a; font-family:verdana; color: #543800; border: 2px #543800 solid\">\n    <b>And for validation</b>\n</div>","metadata":{}},{"cell_type":"code","source":"val_transforms = [\n    A.Resize(512, 512, p=1), \n    A.Normalize(),\n    ToTensorV2()\n]","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.810221Z","iopub.execute_input":"2024-04-06T05:07:39.810477Z","iopub.status.idle":"2024-04-06T05:07:39.820047Z","shell.execute_reply.started":"2024-04-06T05:07:39.810455Z","shell.execute_reply":"2024-04-06T05:07:39.819306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #859cd6; font-family:verdana; color: #001342; border: 2px #001342 solid\">\n    <b>It's time to take care of our dataset</b>\n    <br>It should act as an interface for getting images and a dictionary with target data. What I'm talking about?<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #859cd6; font-family:verdana; color: #001342; border: 2px #001342 solid\">\n<ul class=\"simple\">\n<li><p>image: a PIL Image of size <code class=\"docutils literal notranslate\"><span class=\"pre\">(H,</span> <span class=\"pre\">W)</span></code></p></li>\n<li><p>target: a dict containing the following fields</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">boxes</span> <span class=\"pre\">(FloatTensor[N,</span> <span class=\"pre\">4])</span></code>: the coordinates of the <code class=\"docutils literal notranslate\"><span class=\"pre\">N</span></code>\nbounding boxes in <code class=\"docutils literal notranslate\"><span class=\"pre\">[x0,</span> <span class=\"pre\">y0,</span> <span class=\"pre\">x1,</span> <span class=\"pre\">y1]</span></code> format, ranging from <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>\nto <code class=\"docutils literal notranslate\"><span class=\"pre\">W</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code> to <code class=\"docutils literal notranslate\"><span class=\"pre\">H</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">labels</span> <span class=\"pre\">(Int64Tensor[N])</span></code>: the label for each bounding box. <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code> represents always the background class.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">image_id</span> <span class=\"pre\">(Int64Tensor[1])</span></code>: an image identifier. It should be\nunique between all the images in the dataset, and is used during\nevaluation</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">area</span> <span class=\"pre\">(Tensor[N])</span></code>: The area of the bounding box. This is used\nduring evaluation with the COCO metric, to separate the metric\nscores between small, medium and large boxes.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">iscrowd</span> <span class=\"pre\">(UInt8Tensor[N])</span></code>: instances with iscrowd=True will be\nignored during evaluation.</p></li>\n<li><p>(optionally) <code class=\"docutils literal notranslate\"><span class=\"pre\">masks</span> <span class=\"pre\">(UInt8Tensor[N,</span> <span class=\"pre\">H,</span> <span class=\"pre\">W])</span></code>: The segmentation\nmasks for each one of the objects</p></li>\n<li><p>(optionally) <code class=\"docutils literal notranslate\"><span class=\"pre\">keypoints</span> <span class=\"pre\">(FloatTensor[N,</span> <span class=\"pre\">K,</span> <span class=\"pre\">3])</span></code>: For each one of\nthe N objects, it contains the K keypoints in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">[x,</span> <span class=\"pre\">y,</span> <span class=\"pre\">visibility]</span></code> format, defining the object. visibility=0\nmeans that the keypoint is not visible. Note that for data\naugmentation, the notion of flipping a keypoint is dependent on\nthe data representation, and you should probably adapt\n<code class=\"docutils literal notranslate\"><span class=\"pre\">references/detection/transforms.py</span></code> for your new keypoint\nrepresentation</p></li>\n</ul>\n</li>\n</ul>\n</div>","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import Dataset\nimport albumentations as A\nimport torchvision.transforms as T\nimport cv2\nimport os\nimport yaml\nfrom typing import Literal, Any, Union,Tuple\nfrom tqdm import tqdm\nimport json","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.821034Z","iopub.execute_input":"2024-04-06T05:07:39.821291Z","iopub.status.idle":"2024-04-06T05:07:39.829887Z","shell.execute_reply.started":"2024-04-06T05:07:39.821268Z","shell.execute_reply":"2024-04-06T05:07:39.829101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HuBMAPDataset(Dataset):\n    def __init__(self,\n                 stage: Literal[\"train\", \"val\"],\n                 config_path: str,\n                 transforms: Union[A.Compose, T.Compose] = None,\n                 *args, **kwargs\n                 ):\n        self.config = self.load_config(config_path)\n        self.images_dirpath = None\n        self.labels_dirpath = None\n        self.__define_paths(stage)\n\n        self.names = self.config[\"names\"]\n        self.num_classes = len(self.names)\n        self.samples = os.listdir(self.labels_dirpath)\n\n        if transforms:\n            self.bbox_params = {\n                \"format\": \"pascal_voc\",\n                \"min_area\": 0,\n                \"min_visibility\": 0,\n                \"label_fields\": [\"category_id\"]\n            }\n            self.transforms = A.Compose(transforms, bbox_params=self.bbox_params)\n\n    @staticmethod\n    def load_config(path: str) -> dict:\n        with open(path, mode=\"r\") as f:\n            data = yaml.load(stream=f, Loader=yaml.SafeLoader)\n        return data\n\n    def __len__(self) -> int:\n        return len(self.samples)\n\n    def __getitem__(self, idx: int) -> Tuple[torch.Tensor, dict]:\n        filename = self.samples[idx].split(\".\")[0]\n        paths = self._get_paths(filename)\n        image = cv2.imread(paths[\"image\"], cv2.COLOR_BGR2RGB)\n        if image is None:\n            print(f\"Error loading image: {paths['image']}\")\n            return None, None\n\n        target = self._get_target(paths[\"label\"])\n        if target is None:\n            print(f\"No target found for image: {paths['image']}\")\n            return None, None\n\n        target[\"image_id\"] = torch.tensor([idx])\n        \n        if self.transforms:\n            image, target = self.transform(image, target)\n        else:\n            target = self.format_target(target)\n\n        return image, target\n\n    def format_target(self, target: dict) -> dict:\n        return {\n            \"boxes\": torch.as_tensor(target[\"boxes\"], dtype=torch.float32),\n            \"masks\": torch.as_tensor(target[\"masks\"], dtype=torch.uint8),\n            \"labels\": torch.as_tensor(target[\"labels\"], dtype=torch.int64),\n            \"image_id\": target[\"image_id\"],\n            \"area\": self.__get_area(target[\"boxes\"]),\n            \"iscrowd\": torch.zeros((len(target[\"labels\"]),), dtype=torch.int64)\n        }\n\n    def transform(self, image: np.ndarray, target: dict) -> Tuple[torch.Tensor, dict]:\n        transformed = self.transforms(\n            image=image, masks=target[\"masks\"],\n            bboxes=target[\"boxes\"],\n            category_id=target[\"labels\"]\n        )\n\n        image = transformed[\"image\"]\n        target[\"masks\"] = torch.as_tensor(\n            np.array(list(map(np.array, transformed[\"masks\"])), dtype=np.uint8)\n        )\n\n        target[\"labels\"] = torch.tensor(transformed[\"category_id\"])\n        target[\"boxes\"] = torch.as_tensor(transformed[\"bboxes\"], dtype=torch.float32)\n        target[\"area\"] = self.__get_area(target[\"boxes\"])\n        return image, target\n\n    def __define_paths(self, stage: Literal[\"train\", \"val\"]) -> None:\n        data_dirpath = self.config[stage]\n        self.images_dirpath = os.path.join(data_dirpath, \"images\")\n        self.labels_dirpath = os.path.join(data_dirpath, \"labels\")\n\n    def _get_paths(self, filename: str) -> dict:\n        image_path = os.path.join(self.images_dirpath, f\"{filename}.tif\")\n        label_path = os.path.join(self.labels_dirpath, f\"{filename}.txt\")\n        return {\n            \"image\": image_path,\n            \"label\": label_path\n        }\n\n    def _get_target_sample(self) -> dict:\n        return {\n            \"boxes\": [],\n            \"masks\": [],\n            \"area\": [],\n            \"labels\": [],\n            \"iscrowd\": None,\n            \"image_id\": None\n        }\n\n    def _get_target(self, annotations_path: str) -> dict:\n        target = self._get_target_sample()\n\n        with open(annotations_path, \"r\") as file:\n            for line in file:\n                label = int(line[0])\n                coordinates = np.array(list(map(int, line[1:].split()))).reshape(1, -1, 2)\n                mask = self.__get_mask(label, coordinates)\n                # Resize mask to a fixed size if needed\n                mask = cv2.resize(mask, (512, 512))\n                box = self.__get_box(mask)\n                target[\"masks\"].append(mask)\n                target[\"boxes\"].append(box)\n                target[\"labels\"].append(label)\n\n        num_objs = len(target[\"labels\"])\n        target[\"iscrowd\"] = torch.zeros((num_objs,), dtype=torch.int64)\n        return target\n\n\n    @staticmethod\n    def __get_mask(label: int, coordinates: np.ndarray) -> np.ndarray:\n        mask = np.zeros((512, 512), dtype=np.uint8)\n        return cv2.fillPoly(\n            mask, pts=coordinates,\n            color=(label, label, label)\n        )\n\n    @staticmethod\n    def __get_box(mask: np.ndarray) -> list[np.ndarray, ...]:\n        pos = np.nonzero(mask)\n        xmin = np.min(pos[1])\n        xmax = np.max(pos[1])\n        ymin = np.min(pos[0])\n        ymax = np.max(pos[0])\n        return [xmin, ymin, xmax, ymax]\n\n    @staticmethod\n    def __get_area(boxes: list[list, ...]) -> torch.Tensor:\n         return (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.831198Z","iopub.execute_input":"2024-04-06T05:07:39.831427Z","iopub.status.idle":"2024-04-06T05:07:39.858650Z","shell.execute_reply.started":"2024-04-06T05:07:39.831407Z","shell.execute_reply":"2024-04-06T05:07:39.857862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #859cd6; font-family:verdana; color: #001342; border: 2px #001342 solid\">\n    <b>Dataset for training</b>\n</div>","metadata":{}},{"cell_type":"code","source":"train_dataset = HuBMAPDataset(\n    stage=\"train\",\n    config_path=coco.config_path,\n    transforms=train_transforms\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.859617Z","iopub.execute_input":"2024-04-06T05:07:39.859878Z","iopub.status.idle":"2024-04-06T05:07:39.872431Z","shell.execute_reply.started":"2024-04-06T05:07:39.859855Z","shell.execute_reply":"2024-04-06T05:07:39.871627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #859cd6; font-family:verdana; color: #001342; border: 2px #001342 solid\">\n    <b>Dataset for validation</b>\n</div>","metadata":{}},{"cell_type":"code","source":"val_dataset = HuBMAPDataset(\n    stage=\"val\",\n    config_path=coco.config_path,\n    transforms=val_transforms\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.873478Z","iopub.execute_input":"2024-04-06T05:07:39.873817Z","iopub.status.idle":"2024-04-06T05:07:39.880922Z","shell.execute_reply.started":"2024-04-06T05:07:39.873786Z","shell.execute_reply":"2024-04-06T05:07:39.880175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filename = val_dataset.samples[0].split(\".\")[0]\nfilename","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.881880Z","iopub.execute_input":"2024-04-06T05:07:39.882138Z","iopub.status.idle":"2024-04-06T05:07:39.891288Z","shell.execute_reply.started":"2024-04-06T05:07:39.882116Z","shell.execute_reply":"2024-04-06T05:07:39.890558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks_zero=val_dataset._get_target(val_dataset._get_paths(filename)['label'])['masks']","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.892382Z","iopub.execute_input":"2024-04-06T05:07:39.892695Z","iopub.status.idle":"2024-04-06T05:07:39.921939Z","shell.execute_reply.started":"2024-04-06T05:07:39.892672Z","shell.execute_reply":"2024-04-06T05:07:39.921102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks_zero","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.922991Z","iopub.execute_input":"2024-04-06T05:07:39.923239Z","iopub.status.idle":"2024-04-06T05:07:39.931790Z","shell.execute_reply.started":"2024-04-06T05:07:39.923217Z","shell.execute_reply":"2024-04-06T05:07:39.930919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Plot all masks overlayed on each other\ncombined_mask = np.zeros_like(masks_zero[0])\n\nfor mask in masks_zero:\n    combined_mask += mask\n\nplt.imshow(combined_mask, cmap='gray')\nplt.title('Combined Masks')\nplt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:39.933083Z","iopub.execute_input":"2024-04-06T05:07:39.933386Z","iopub.status.idle":"2024-04-06T05:07:40.143426Z","shell.execute_reply.started":"2024-04-06T05:07:39.933361Z","shell.execute_reply":"2024-04-06T05:07:40.142515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_val=[]\nY_val=[]\nfor i in range (len(val_dataset)) :\n    n = val_dataset.__getitem__(i)\n    X_val.append(n[0])\n    Y_val.append(n[1])\n    \nlen(X_val),len(Y_val)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:40.144509Z","iopub.execute_input":"2024-04-06T05:07:40.144786Z","iopub.status.idle":"2024-04-06T05:07:49.659184Z","shell.execute_reply.started":"2024-04-06T05:07:40.144762Z","shell.execute_reply":"2024-04-06T05:07:49.658290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Y_val[0]","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:49.660558Z","iopub.execute_input":"2024-04-06T05:07:49.661174Z","iopub.status.idle":"2024-04-06T05:07:49.695359Z","shell.execute_reply.started":"2024-04-06T05:07:49.661137Z","shell.execute_reply":"2024-04-06T05:07:49.694461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataloaders\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #b7ebea; font-family:verdana; color: #233d3d; border: 2px #233d3d solid\">\n    <b>And how to manipulate the unloading of data?</b>\n    <br>Imagine that for training the neural network there are mastaba data, which should remain less in the RAM for a short while and stay in the video memory for a longer time. This is quite costly in terms of storage. But what to do? Make a lazy iterator. At least before, the output was like this, as soon as the loader issued the batch, it immediately appeared in memory, and disappeared from the iterator, and at the same time, the iterator itself contained only information about the object, and not the object itself. However, now we do not need to worry about such low-level things and we are engaged in the Dataloader sports class. You, in turn, now know why it is needed.<br>\n</div>","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import DataLoader","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:49.696565Z","iopub.execute_input":"2024-04-06T05:07:49.696911Z","iopub.status.idle":"2024-04-06T05:07:50.103802Z","shell.execute_reply.started":"2024-04-06T05:07:49.696880Z","shell.execute_reply":"2024-04-06T05:07:50.102810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #b7ebea; font-family:verdana; color: #233d3d; border: 2px #233d3d solid\">\n    <b>Dataloader for training</b>\n</div>","metadata":{}},{"cell_type":"code","source":"train_dataloader = DataLoader(\n    dataset=train_dataset,\n    batch_size=8, \n    shuffle=True,\n    pin_memory=True,\n    num_workers=4,\n    collate_fn=lambda x: tuple(zip(*x))\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:02:44.895317Z","iopub.execute_input":"2024-04-06T06:02:44.896260Z","iopub.status.idle":"2024-04-06T06:02:44.901326Z","shell.execute_reply.started":"2024-04-06T06:02:44.896224Z","shell.execute_reply":"2024-04-06T06:02:44.900288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #b7ebea; font-family:verdana; color: #233d3d; border: 2px #233d3d solid\">\n    <b>And for validation</b>\n</div>","metadata":{}},{"cell_type":"code","source":"val_dataloader = DataLoader(\n    dataset=val_dataset,\n    batch_size=8, \n    shuffle=False,\n    pin_memory=True,\n    num_workers=4,\n    collate_fn=lambda x: tuple(zip(*x))\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:02:49.557890Z","iopub.execute_input":"2024-04-06T06:02:49.558754Z","iopub.status.idle":"2024-04-06T06:02:49.563397Z","shell.execute_reply.started":"2024-04-06T06:02:49.558720Z","shell.execute_reply":"2024-04-06T06:02:49.562510Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Logging\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #eec4ff; font-family:verdana; color: #511b66; border: 2px #511b66 solid\">\n    <b>And now a little about the control of experiments</b>\n    <br>Experiment control tools are a very important part of your pipeline. With the help of them, you can track learning and compare results with previous ones to solve your problem. It is very convenient and allows you not to get confused.<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"# Weights and biases\n  \n <p align='center'> \n <a href=\"https://pypi.python.org/pypi/wandb\"><img src=\"https://img.shields.io/pypi/v/wandb\" /></a> \n <a href=\"https://anaconda.org/conda-forge/wandb\"><img src=\"https://img.shields.io/conda/vn/conda-forge/wandb\" /></a> \n <a href=\"https://circleci.com/gh/wandb/wandb\"><img src=\"https://img.shields.io/circleci/build/github/wandb/wandb/main\" /></a> \n <a href=\"https://codecov.io/gh/wandb/wandb\"><img src=\"https://img.shields.io/codecov/c/gh/wandb/wandb\" /></a> \n </p> \n <p align='center'> \n <a href=\"https://colab.research.google.com/github/wandb/examples/blob/master/colabs/intro/Intro_to_Weights_%26_Biases.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" /></a> \n </p> \n  \n Use W&B to build better models faster. Track and visualize all the pieces of your machine learning pipeline, from datasets to production machine learning models. Get started with W&B today, [sign up for a free account!](https://wandb.com?utm_source=github&utm_medium=code&utm_campaign=wandb&utm_content=readme) \n  \n 🎓 W&B is free for students, educators, and academic researchers. For more information, visit [https://wandb.ai/site/research](https://wandb.ai/site/research?utm_source=github&utm_medium=code&utm_campaign=wandb&utm_content=readme). \n  \n Want to use Weights & Biases for seamless collaboration between your ML or Data Science team? Looking for Production-grade MLOps at scale? Sign up to one of [our plans](https://wandb.ai/site/pricing) or [contact the Sales Team](https://wandb.ai/site/contact).\n","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #eec4ff; font-family:verdana; color: #511b66; border: 2px #511b66 solid\">\n    <b>Please follow the <a href=https://wandb.ai/site>link</a>. Sign up and then paste your API key into the box that pops up below. Do not disclose your key to anyone. Here it is required so that you can track the training</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"![](https://i.ibb.co/q1xnxnD/2023-07-01-06-42-42.png)","metadata":{}},{"cell_type":"code","source":"#import wandb\n\n#wandb.login() \n\n#run = wandb.init(\n    # Set the project where this run will be logged\n #   project=\"HuBMAP-Mask-RCNN\",\n    # Track hyperparameters and run metadata\n  #  config={\n   #     \"learning_rate\": 0.0035,\n    #    \"epochs\": 15,\n   # })","metadata":{"_kg_hide-output":false,"execution":{"iopub.status.busy":"2024-04-06T05:07:50.127441Z","iopub.execute_input":"2024-04-06T05:07:50.129164Z","iopub.status.idle":"2024-04-06T05:07:50.136026Z","shell.execute_reply.started":"2024-04-06T05:07:50.129138Z","shell.execute_reply":"2024-04-06T05:07:50.135265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #bcf5a9; font-family:verdana; color: #1c3d11; border: 2px #1c3d11 solid\">\n    <b>Finally, we can start learning</b>\n    <br>Yes, yes I know. I was just talking about high-level and how abstraction can be annoying, but look around. We use pure pytorch without wrappers. However, all work with losses is registered under the hood of the model class. The model itself is just as seriously provided to us and everyone can assemble it as a lego constructor. In general, you do not need to be afraid of abstraction, there is no escape from it, but I am against high-level if it allows you to remain in the dark and continue using the tool.<br>\n</div>","metadata":{}},{"cell_type":"code","source":"from tqdm.notebook import tqdm\nimport torch.nn as nn\nfrom torch import optim\nfrom typing import List, Tuple,Dict","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:50.140656Z","iopub.execute_input":"2024-04-06T05:07:50.140898Z","iopub.status.idle":"2024-04-06T05:07:50.145382Z","shell.execute_reply.started":"2024-04-06T05:07:50.140876Z","shell.execute_reply":"2024-04-06T05:07:50.144481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calculate_iou(predicted_mask, true_mask):\n    # Convert masks to numpy arrays\n    predicted_mask = predicted_mask.cpu().numpy()\n    true_mask = true_mask.cpu().numpy()\n\n    # Calculate intersection and union\n    intersection = np.logical_and(predicted_mask, true_mask).sum()\n    union = np.logical_or(predicted_mask, true_mask).sum()\n\n    # Calculate IoU\n    iou = intersection / union if union > 0 else 0\n    return iou","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:02:54.957510Z","iopub.execute_input":"2024-04-06T06:02:54.958223Z","iopub.status.idle":"2024-04-06T06:02:54.963775Z","shell.execute_reply.started":"2024-04-06T06:02:54.958191Z","shell.execute_reply":"2024-04-06T06:02:54.962765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Trainer:\n    def __init__(self,\n                 model: nn.Module,\n                train_dataloader: DataLoader,\n                 val_dataloader: DataLoader,\n                 early_stop: dict = {\"monitor\": \"loss_mask\", \"patience\": 5},\n                 save_every_epoch: int = 1,\n                 save_dirpath: str = \"/kaggle/working/runs\"\n                ):\n        \n        # Callbacks | Early stoping & Model checkpoint\n        self.patience = early_stop[\"patience\"]\n        self.monitor = early_stop[\"monitor\"]\n        self.track_list = []\n        self.save_every_epoch = save_every_epoch\n        self.save_dirpath = save_dirpath\n        \n        self.device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n        self.train_dataloader = train_dataloader\n        self.val_dataloader = val_dataloader\n        self.train_batches = len(train_dataloader)\n        self.val_batches =  len(val_dataloader)\n        \n        self.model = model\n        self.setup_model()\n        \n        self.optim_dict = self.configure_optimizers()\n        self.optimizer = self.optim_dict[\"optimizer\"]\n        self.lr_scheduler = self.optim_dict[\"lr_scheduler\"]\n        \n        self.step_outputs = {\n            \"loss_objectness\": 0,\n            \"loss_mask\": 0,\n            \"loss_classifier\": 0,\n            \"loss_rpn_box_reg\": 0,\n            \"loss_box_reg\": 0,\n            \"loss\": 0\n        }\n        \n    def configure_optimizers(self) -> dict:\n        # construct an optimizer\n        params = [\n            p\n            for p in self.model.parameters()\n            if p.requires_grad\n        ]\n\n        optimizer = optim.SGD(\n            params,\n            lr=0.0001,\n            momentum=0.9,\n            weight_decay=0.0001\n        )\n\n        # and a learning rate scheduler\n        lr_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5, verbose=True)\n\n        return {\n            \"lr_scheduler\": lr_scheduler,\n            \"optimizer\": optimizer\n        }\n    \n    def setup_model(self) -> None:\n        for param in self.model.parameters():\n            param.requires_grad = True\n        self.model.to(self.device)\n        self.model.train()\n    \n    def to_device(self, batch: tuple) -> tuple:\n        images, targets = batch\n        images = list(image.to(self.device) for image in images)\n\n        targets = [\n            {key: value.to(self.device) \n             for key, value in target.items()}\n            for target in targets\n        ]\n        \n        return images, targets\n    \n    def training_step(self, batch) -> dict:\n        images, targets = self.to_device(batch)\n        self.optimizer.zero_grad() \n        outputs = self.model(images, targets)\n        loss = sum([loss for loss in outputs.values()])\n        outputs[\"loss\"] = loss\n        loss.backward()\n        self.optimizer.step()\n        self.lr_scheduler.step()\n        return outputs\n    \n    def validation_step(self, batch) -> dict:\n        images, targets = self.to_device(batch)\n        with torch.no_grad():\n            outputs = self.model(images, targets)\n            loss = sum([loss for loss in outputs.values()])\n            outputs[\"loss\"] = loss\n        return outputs\n    \n    def shared_epoch_end(self, stage: str, epoch: int) -> float:\n        tracked_loss = self.step_outputs[self.monitor]    \n        loss_objectness = self.step_outputs[\"loss_objectness\"]\n        loss_mask = self.step_outputs[\"loss_mask\"]\n        loss_classifier = self.step_outputs[\"loss_classifier\"]\n        loss_rpn_box_reg = self.step_outputs[\"loss_rpn_box_reg\"]\n        loss_box_reg = self.step_outputs[\"loss_box_reg\"]\n        loss = self.step_outputs[\"loss\"]\n        \n        \n        print(\n            f\"\"\"\n            || End {epoch} {stage} epoch ||\n            loss_objectness: {loss_objectness:.2f}\n            loss_mask: {loss_mask:.2f}\n            loss_classifier: {loss_classifier:.2f}\n            loss_rpn_box_reg: {loss_rpn_box_reg:.2f}\n            loss_box_reg: {loss_box_reg:.2f} \n            loss: {loss:.2f}\\n\n            \"\"\"\n        )\n              \n        self.step_outputs = self.step_outputs.fromkeys(self.step_outputs, 0)\n        if stage == \"val\":\n            return tracked_loss\n              \n    def on_train_epoch_end(self, epoch: int) -> None:\n        return self.shared_epoch_end(stage=\"train\", epoch=epoch)\n\n    def on_validation_epoch_end(self, epoch: int) -> None:\n        tracked_loss = self.shared_epoch_end(stage=\"val\", epoch=epoch)\n        patience = 0\n        \n        if epoch > self.patience:\n            last_tracked = list(reversed(self.track_list))[:self.patience]\n            for i in last_tracked:\n                if i <= tracked_loss:\n                    patience += 1\n                    \n        self.track_list.append(tracked_loss)\n        return tracked_loss, (self.patience - patience)\n\n    def train(self, max_epochs: int) -> None:\n        \n        for epoch in range(1, max_epochs + 1):\n            for batch_idx, batch in tqdm(enumerate(self.train_dataloader, 1), desc=\"Training\", total=self.train_batches, colour=\"#068e58\"):\n                outputs = self.training_step(batch)\n                for key, value in outputs.items():\n                    self.step_outputs[key] += float(value.detach().cpu().numpy()) / self.train_batches\n            self.on_train_epoch_end(epoch)\n\n            for batch_idx, batch in tqdm(enumerate(val_dataloader, 1), desc=\"Validation\", total=self.val_batches, colour=\"#013385\"):\n                outputs = self.validation_step(batch)\n                for key, value in outputs.items():\n                    self.step_outputs[key] += float(value.detach().cpu().numpy()) / self.val_batches\n            tracked_loss, patience = self.on_validation_epoch_end(epoch)\n            \n            if epoch % self.save_every_epoch == 0:\n                if not os.path.exists(self.save_dirpath):\n                    os.mkdir(self.save_dirpath)\n                path = os.path.join(self.save_dirpath, f\"epoch_{epoch}_{self.monitor}_{tracked_loss:.2f}.pt\")\n                torch.save(model.state_dict(), path) \n                print(\"\\nThe model passed the save checkpoint successfully!\\n\")\n                \n            if patience == 0:\n                print(\"Our patience has run out! Model training stopped beforehand.\")\n                break\n                \n    def evaluate(self, dataloader = val_dataloader):\n        self.model.eval()  # Set model to evaluation mode\n        total_iou = 0\n        total_samples = 0\n\n        with torch.no_grad():\n            for images, targets in dataloader:\n                images = [image.to(self.device) for image in images]\n                targets = [{k: v.to(self.device) for k, v in t.items()} for t in targets]\n\n                outputs = self.model(images)\n\n                # Compute accuracy\n                for output, target in zip(outputs, targets):\n                    predicted_labels = output['masks']\n                    true_labels = target['masks']\n                    \n                    return predicted_labels, true_labels\n                    # Ensure both predicted and true labels have the same size\n                    if len(predicted_labels) != len(true_labels):\n                        continue\n\n                    iou = calculate_iou(predicted_labels, true_labels)\n                    total_iou += iou\n                    total_samples += 1\n\n        mean_iou = total_iou / total_samples if total_samples != 0 else 0  # Handle division by zero\n        return mean_iou","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:02:55.503045Z","iopub.execute_input":"2024-04-06T06:02:55.503369Z","iopub.status.idle":"2024-04-06T06:02:55.540979Z","shell.execute_reply.started":"2024-04-06T06:02:55.503344Z","shell.execute_reply":"2024-04-06T06:02:55.540035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer = Trainer(\n    model=model,\n    train_dataloader=train_dataloader,\n    val_dataloader=val_dataloader,\n    early_stop = {\"monitor\": \"loss_mask\", \"patience\": 5},\n    save_every_epoch=1\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T06:02:56.673716Z","iopub.execute_input":"2024-04-06T06:02:56.674066Z","iopub.status.idle":"2024-04-06T06:02:56.685346Z","shell.execute_reply.started":"2024-04-06T06:02:56.674038Z","shell.execute_reply":"2024-04-06T06:02:56.684484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#trainer.evaluate()\n","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:50.392566Z","iopub.execute_input":"2024-04-06T05:07:50.392872Z","iopub.status.idle":"2024-04-06T05:07:50.396892Z","shell.execute_reply.started":"2024-04-06T05:07:50.392846Z","shell.execute_reply":"2024-04-06T05:07:50.396018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import matplotlib.pyplot as plt\n# import numpy as np\n\n# y_hat, y = trainer.evaluate()\n\n# #Assuming your tensor is named 'image_tensor'\n# image_array = y_hat.cpu().detach().numpy()  # Convert tensor to numpy array\n# image_to_show = np.transpose(image_array, (1, 2, 0))  # Assuming you want to display the first image in the batch\n# plt.imshow(image_array[0][0], cmap='gray')  # Displaying the first image assuming it's grayscale\n# plt.axis('off')\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:07:50.398414Z","iopub.execute_input":"2024-04-06T05:07:50.399084Z","iopub.status.idle":"2024-04-06T05:07:50.406334Z","shell.execute_reply.started":"2024-04-06T05:07:50.399058Z","shell.execute_reply":"2024-04-06T05:07:50.405620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer.train(max_epochs=5)","metadata":{"_kg_hide-output":true,"scrolled":true,"execution":{"iopub.status.busy":"2024-04-06T06:02:59.184005Z","iopub.execute_input":"2024-04-06T06:02:59.184355Z","iopub.status.idle":"2024-04-06T06:03:00.938849Z","shell.execute_reply.started":"2024-04-06T06:02:59.184326Z","shell.execute_reply":"2024-04-06T06:03:00.936687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#torch.save(model.state_dict(), '/kaggle/working/runs/saved_model_adam_opt.pth')","metadata":{"execution":{"iopub.status.busy":"2024-04-06T04:07:48.728909Z","iopub.status.idle":"2024-04-06T04:07:48.729237Z","shell.execute_reply.started":"2024-04-06T04:07:48.729086Z","shell.execute_reply":"2024-04-06T04:07:48.729101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #bcf5a9; font-family:verdana; color: #1c3d11; border: 2px #1c3d11 solid\">\n    <b>Wrapper class for Mask-RCNN model</b>\n    <br>So it will be more convenient to look at the fruits of our labors, as well as make a submit<br>\n</div>","metadata":{}},{"cell_type":"code","source":"# class BestMaskRCNN:\n#     def __init__(self, \n#                  model: nn.Module,\n#                  checkpoint_path: str,\n#                  conf: float = 0.05\n#                 ):\n#         self.device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n#         self.checkpoint_path = checkpoint_path\n#         self.model = self.get_model(model)\n#         self.conf = conf\n#         self.transforms = A.Compose([\n#             A.Resize(512, 512, p=1), \n#             A.Normalize(),\n#             ToTensorV2()\n#         ])\n        \n#     def to_cpu(self, outputs: dict) -> tuple:\n#         outputs = {\n#             key: value.cpu().numpy()\n#             for key, value in outputs.items()\n#         }       \n#         return outputs\n    \n#     def get_model(self, model: nn.Module) -> nn.Module:\n#         checkpoint = torch.load(self.checkpoint_path) \n#         model.load_state_dict(checkpoint) \n#         model.eval()\n#         model.to(self.device)\n#         for param in model.parameters():\n#             param.requires_grad = False\n#         return model\n    \n#     def get_image(self, path: str):\n#         image = cv2.imread(path, cv2.COLOR_BGR2RGB)  \n#         return self.transforms(image=image)[\"image\"]\n    \n#     def forward(self, path: str):\n#         image = self.get_image(path)\n        \n#         image = torch.as_tensor(\n#             np.expand_dims(image.numpy(), 0),\n#             dtype=image.dtype\n#         ).to(self.device)\n        \n#         outputs = self.model(image)[0]\n#         outputs = self.to_cpu(outputs)\n#         return outputs\n    \n#     def __call__(self, source: str) -> list[dict, ...]:\n#         sublist = []\n#         result = self.forward(source)\n\n#         for i in range(len(result[\"masks\"])):\n#             conf = round(float(result[\"scores\"][i]), 2)\n#             mask = result[\"masks\"][i].transpose(1,2,0)\n\n#             if int(result[\"labels\"][i]) == 1 and conf >= self.conf:\n#                 sublist.append({\"mask\": mask, \"confidence\": conf})\n#             else:\n#                 continue\n#         return sublist","metadata":{"execution":{"iopub.status.busy":"2024-04-06T04:07:48.730615Z","iopub.status.idle":"2024-04-06T04:07:48.730915Z","shell.execute_reply.started":"2024-04-06T04:07:48.730765Z","shell.execute_reply":"2024-04-06T04:07:48.730779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#model = BestMaskRCNN(\n#    model=get_model(4),\n#    checkpoint_path=\"/kaggle/working/runs/epoch_11_loss_mask_0.19.pt\"\n\n#)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T04:07:48.733634Z","iopub.status.idle":"2024-04-06T04:07:48.733994Z","shell.execute_reply.started":"2024-04-06T04:07:48.733807Z","shell.execute_reply":"2024-04-06T04:07:48.733823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" model.load_state_dict(torch.load('/kaggle/input/modelsaved/saved_model (2).pth'))","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:24:30.023906Z","iopub.execute_input":"2024-04-06T05:24:30.024636Z","iopub.status.idle":"2024-04-06T05:24:32.188892Z","shell.execute_reply.started":"2024-04-06T05:24:30.024579Z","shell.execute_reply":"2024-04-06T05:24:32.187871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-04-06T05:24:49.711168Z","iopub.execute_input":"2024-04-06T05:24:49.711769Z","iopub.status.idle":"2024-04-06T05:24:49.722856Z","shell.execute_reply.started":"2024-04-06T05:24:49.711737Z","shell.execute_reply":"2024-04-06T05:24:49.721918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for batch in val_dataloader:\n    images, labels = batch\nimages[0],labels[0]","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:02.349156Z","iopub.execute_input":"2024-04-06T05:28:02.349966Z","iopub.status.idle":"2024-04-06T05:28:07.535657Z","shell.execute_reply.started":"2024-04-06T05:28:02.349934Z","shell.execute_reply":"2024-04-06T05:28:07.534626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\n\n# Assuming your model is already defined and loaded onto a GPU\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel.to(device)\n\n# Assuming `images` is your list of input tensors\nfor i in range(len(images)):\n    images[i] = images[i].to(device)\n\n# Now perform the forward pass\noutputs = model(images)","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:07.539310Z","iopub.execute_input":"2024-04-06T05:28:07.539657Z","iopub.status.idle":"2024-04-06T05:28:07.888722Z","shell.execute_reply.started":"2024-04-06T05:28:07.539594Z","shell.execute_reply":"2024-04-06T05:28:07.887774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks_predicted0=outputs[0]['masks']\nmasks_real0=labels[0]['masks']","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:19.671972Z","iopub.execute_input":"2024-04-06T05:28:19.672685Z","iopub.status.idle":"2024-04-06T05:28:19.677046Z","shell.execute_reply.started":"2024-04-06T05:28:19.672654Z","shell.execute_reply":"2024-04-06T05:28:19.676084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks_predicted0","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:21.089756Z","iopub.execute_input":"2024-04-06T05:28:21.090089Z","iopub.status.idle":"2024-04-06T05:28:21.096141Z","shell.execute_reply.started":"2024-04-06T05:28:21.090066Z","shell.execute_reply":"2024-04-06T05:28:21.095164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\n# Assuming the tensor representing the mask is named mask_tensor\nmask_tensor = masks_predicted0\n\n# Convert the tensor to a numpy array\nmask_np = mask_tensor.cpu().detach().numpy()\n\n# Threshold each mask to convert to binary masks (0 or 1)\nthresholded_masks = (mask_np > 0.5).astype(np.float32)  # Adjust threshold as needed\n\n# Sum all the thresholded masks to create a combined mask\ncombined_mask = np.sum(thresholded_masks, axis=0)\n\n# Plot the combined mask\nplt.imshow(combined_mask[0], cmap='gray')  # Assuming the combined mask is a single channel\nplt.axis('off')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:25.935902Z","iopub.execute_input":"2024-04-06T05:28:25.936268Z","iopub.status.idle":"2024-04-06T05:28:26.045203Z","shell.execute_reply.started":"2024-04-06T05:28:25.936240Z","shell.execute_reply":"2024-04-06T05:28:26.043990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks_real0","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:33.990482Z","iopub.execute_input":"2024-04-06T05:28:33.991332Z","iopub.status.idle":"2024-04-06T05:28:34.001652Z","shell.execute_reply.started":"2024-04-06T05:28:33.991298Z","shell.execute_reply":"2024-04-06T05:28:34.000671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\n# Assuming the tensor representing the mask is named mask_tensor\nmask_tensor = masks_real0\n\n# Convert the tensor to a numpy array\nmask_np = mask_tensor.cpu().detach().numpy()\n\n# Plot all the images overlayed on each other\ncombined_mask = np.zeros_like(mask_np[0])  # Create an empty array to accumulate the masks\n\nfor mask in mask_np:\n    combined_mask += mask\n\nplt.imshow(combined_mask, cmap='gray')\nplt.axis('off')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-04-06T05:28:35.951417Z","iopub.execute_input":"2024-04-06T05:28:35.952285Z","iopub.status.idle":"2024-04-06T05:28:36.061335Z","shell.execute_reply.started":"2024-04-06T05:28:35.952251Z","shell.execute_reply":"2024-04-06T05:28:36.060137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}