{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":61446,"databundleVersionId":6962461,"sourceType":"competition"},{"sourceId":7365548,"sourceType":"datasetVersion","datasetId":4278933},{"sourceId":7365580,"sourceType":"datasetVersion","datasetId":4278957},{"sourceId":7366930,"sourceType":"datasetVersion","datasetId":4279846},{"sourceId":7373193,"sourceType":"datasetVersion","datasetId":4284077},{"sourceId":7380135,"sourceType":"datasetVersion","datasetId":4288848},{"sourceId":7380450,"sourceType":"datasetVersion","datasetId":4289061},{"sourceId":7381301,"sourceType":"datasetVersion","datasetId":4289652},{"sourceId":150248402,"sourceType":"kernelVersion"}],"dockerImageVersionId":30627,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import","metadata":{}},{"cell_type":"markdown","source":"Version 34: trying to understand why this didn't score for submission. Copying over all code from version 22","metadata":{}},{"cell_type":"code","source":"\n\n!mkdir -p /root/.cache/torch/hub/checkpoints/\n!cp /kaggle/input/mit-b2-model/* /root/.cache/torch/hub/checkpoints/\n\nimport IPython\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib\nimport matplotlib.pyplot as plt\n\nimport rasterio\nfrom rasterio.plot import show\n\nimport torch\nimport torchvision\nfrom torchvision.transforms import ToTensor\nimport torch.nn.functional as F\n\nimport os\n\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\n\nimport torch.nn as nn\n#import torch.nn.functional as F\n\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nimport cv2\n\nfrom torchvision.transforms import Resize\n\nimport tifffile\n\nfrom glob import glob\n\nfrom tqdm import tqdm\n\nfrom torch.nn.parallel import DataParallel\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-02-07T02:44:55.355937Z","iopub.execute_input":"2024-02-07T02:44:55.356637Z","iopub.status.idle":"2024-02-07T02:45:04.928405Z","shell.execute_reply.started":"2024-02-07T02:44:55.356603Z","shell.execute_reply":"2024-02-07T02:45:04.927372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python -m pip install --no-index --find-links=/kaggle/input/pip-download-for-segmentation-models-pytorch segmentation-models-pytorch\nimport segmentation_models_pytorch as smp\n","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:04.930132Z","iopub.execute_input":"2024-02-07T02:45:04.930595Z","iopub.status.idle":"2024-02-07T02:45:26.964298Z","shell.execute_reply.started":"2024-02-07T02:45:04.930568Z","shell.execute_reply":"2024-02-07T02:45:26.963316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# config","metadata":{}},{"cell_type":"code","source":"class CFG:\n    # ============== pred target =============\n    target_size = 1\n\n    # ============== model CFG =============\n    model_name = 'Unet'\n    #backbone = 'se_resnext50_32x4d'\n    backbone = 'mit_b2'\n\n    in_chans = 3 #1 #5 # 65\n    # ============== training CFG =============\n    image_size = 512\n    input_size=512\n\n    train_batch_size = 16\n    valid_batch_size = train_batch_size * 2\n\n    epochs = 40\n    lr = 6e-5\n    chopping_percentile=1e-3\n    # ============== fold =============\n    valid_id = 1\n\n\n    # ============== augmentation =============\n    train_aug_list = [\n        A.Rotate(limit=45, p=0.5),  #orthogonal rotations are done with numpy for speed\n        #A.HorizontalFlip(p=0.5),   #Flips are done with numpy for speed\n        #A.VerticalFlip(p=0.5),\n        A.RandomScale(scale_limit=(0.8,1.25),interpolation=cv2.INTER_CUBIC,p=0.5),\n        A.RandomCrop(input_size, input_size,p=1),\n        A.RandomGamma(p=0.75),\n        A.RandomBrightnessContrast(p=0.5,),\n        A.GaussianBlur(p=0.5),\n        A.MotionBlur(p=0.5),\n        A.GridDistortion(num_steps=5, distort_limit=0.3, p=0.5),\n        ToTensorV2(transpose_mask=True),\n    ]\n    train_aug = A.Compose(train_aug_list)\n    valid_aug_list = [\n        A.RandomCrop(input_size, input_size,p=1),\n        ToTensorV2(transpose_mask=True),\n\n    ]\n    valid_aug = A.Compose(valid_aug_list)","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:26.965719Z","iopub.execute_input":"2024-02-07T02:45:26.966015Z","iopub.status.idle":"2024-02-07T02:45:26.975228Z","shell.execute_reply.started":"2024-02-07T02:45:26.965983Z","shell.execute_reply":"2024-02-07T02:45:26.974349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    rle = ' '.join(str(x) for x in runs)\n    if rle=='':\n        rle = '1 0'\n    return rle","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:26.978140Z","iopub.execute_input":"2024-02-07T02:45:26.978769Z","iopub.status.idle":"2024-02-07T02:45:26.992635Z","shell.execute_reply.started":"2024-02-07T02:45:26.978736Z","shell.execute_reply":"2024-02-07T02:45:26.991843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi\n","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:26.993715Z","iopub.execute_input":"2024-02-07T02:45:26.994048Z","iopub.status.idle":"2024-02-07T02:45:28.069453Z","shell.execute_reply.started":"2024-02-07T02:45:26.994016Z","shell.execute_reply":"2024-02-07T02:45:28.068187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def apply_block_threshold(image_block, chopping_percentile):\n\n    #squash the largest elements\n    TH=image_block.reshape(-1).numpy()\n    index = -int(len(TH) * CFG.chopping_percentile)\n    TH = np.partition(TH, index)[index] #performs much faster than torch.topk\n    image_block[image_block>TH]=int(TH)\n\n    #squash the smallest elements\n    TH=image_block.reshape(-1).numpy()\n    index = -int(len(TH) * CFG.chopping_percentile)\n    TH = np.partition(TH, -index)[-index]\n    image_block[image_block<TH]=int(TH)\n\n    return image_block\n\n\n# def apply_min_max_norm(image_block):\n    \n#     image_block = image_block.to(torch.float32)\n    \n#     min_ = image_block.min()\n#     max_ = image_block.max()\n    \n#     image_block -= min_\n    \n#     image_block /= (max_ - min_ + 1e-9)\n\n#     return image_block\n\n\ndef min_max_normalization(x:torch.Tensor)->torch.Tensor:\n    \"\"\"input.shape=(batch,f1,...)\"\"\"\n    shape=x.shape\n    if x.ndim>2:\n        x=x.reshape(x.shape[0],-1)\n    \n    min_=x.min(dim=-1,keepdim=True)[0]\n    max_=x.max(dim=-1,keepdim=True)[0]\n    if min_.mean()==0 and max_.mean()==1:\n        return x.reshape(shape)\n    \n    x=(x-min_)/(max_-min_+1e-9)\n    return x.reshape(shape)\n\n\ndef apply_norm_with_clip(image):\n\n    mean = image.mean()\n    std = image.std()\n\n    image = (image - mean)/(std + 1e-5)\n\n    image[image>5]=(image[image>5]-5)*1e-3 +5\n    image[image<-3]=(image[image<-3]+3)*1e-3 - 3\n\n    return image\n\n\ndef add_noise(image, max_rand_rate=0.5):\n\n    rand_rate = max_rand_rate*np.random.rand()*torch.rand(1, dtype=torch.float32)\n\n    cache=(1 + rand_rate**2)**0.5\n\n    return (image + torch.randn(size=image.shape, dtype=torch.float32)*rand_rate)/cache\n\n\ndef load_data_block(paths):\n    aux_set = AuxSet(paths)\n    aux_loader = DataLoader(aux_set, batch_size=16, num_workers=2)\n    data = []\n    for batch in aux_loader:\n\n        data.append(batch)\n\n    x = torch.cat(data, dim=0)\n\n    del data\n\n    x = apply_block_threshold(x, CFG.chopping_percentile)\n    #x = (apply_min_max_norm_in_place(x*255)).to(torch.uint8)\n    #x = (apply_min_max_norm_chunk(x*255)).to(torch.uint8)\n    #x = (apply_min_max_norm(x*255)).to(torch.uint8)\n    #x=(min_max_normalization(x.to(torch.float16)[None])[0]*255).to(torch.uint8)\n\n\n    return x\n\n\n# auxiliary data loader; Helps to mitigate RAM issues when creating blocks\nclass AuxSet(Dataset):\n\n    def __init__(self, paths):\n        self.paths = paths\n\n    def __len__(self):\n        return len(self.paths)\n\n    def __getitem__(self, index):\n        img = cv2.imread(self.paths[index], cv2.IMREAD_GRAYSCALE)\n        img = torch.from_numpy(img).to(torch.uint8)\n\n        return img\n\n    ","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:28.071173Z","iopub.execute_input":"2024-02-07T02:45:28.071585Z","iopub.status.idle":"2024-02-07T02:45:28.089977Z","shell.execute_reply.started":"2024-02-07T02:45:28.071554Z","shell.execute_reply":"2024-02-07T02:45:28.088800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class EvaluateSet(Dataset):\n\n    def __init__(self, image_block, perm, tile_size=[512, 512], overlap=0.5):\n        self.image_block = image_block\n        self.perm = perm\n        self.tile_size = np.array(tile_size)\n        self.overlap = overlap\n\n        data_dicts = []\n\n        for slice_number, image_slice in enumerate(image_block):\n            image_shape = image_slice.shape\n            height, width = image_shape\n\n            min_overlap = float(self.overlap)\n            max_stride = self.tile_size * (1.0 - min_overlap)\n\n            num_patches = np.ceil(np.array([height, width]) / max_stride).astype(np.int64)\n\n            starts = [np.int64(np.linspace(0, width - self.tile_size[1], num_patches[1])), np.int64(np.linspace(0, height - self.tile_size[0], num_patches[0]))]\n            stops = [starts[0] + self.tile_size[0], starts[1] + self.tile_size[1]]\n\n            num_empty = 0\n            for y1, y2 in zip(starts[1], stops[1]):\n                for x1, x2 in zip(starts[0], stops[0]):\n\n                    data_dicts.append({'slice_number' : slice_number, 'perm' : perm,\n                                      'y_range' : (y1, y2), 'x_range' : (x1, x2), 'orig_shape' : image_shape})\n\n        self.data_dicts = data_dicts\n\n    def __getitem__(self, idx):\n\n        data_dict = self.data_dicts[idx]\n\n        image = self.image_block[data_dict['slice_number']]\n\n        image = apply_norm_with_clip(image.to(torch.float32))\n\n        x1, x2 = (data_dict['x_range'][0], data_dict['x_range'][1])\n        y1, y2 = (data_dict['y_range'][0], data_dict['y_range'][1])\n\n        image_tile = image[y1:y2, x1:x2]\n\n        if CFG.backbone=='mit_b2':\n            image_tile = image_tile.squeeze(dim=0).repeat((3,1,1)) #only takes in 3 channels\n\n        return image_tile, data_dict\n\n\n    def __len__(self):\n        return len(self.data_dicts)\n\n\ndef custom_collater(data):\n\n    batch_size = len(data)\n    tile_dim = data[0][0].shape #(1, height, width)\n\n    image_tile_batch = torch.zeros(batch_size, CFG.in_chans, tile_dim[-2], tile_dim[-1])\n    \n    data_dict_list = []\n    for idx, (image_tile, data_dict) in enumerate(data):\n\n        image_tile_batch[idx] = image_tile\n        data_dict_list.append(data_dict)\n\n\n    return [image_tile_batch, data_dict_list]","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:28.091864Z","iopub.execute_input":"2024-02-07T02:45:28.092375Z","iopub.status.idle":"2024-02-07T02:45:28.111749Z","shell.execute_reply.started":"2024-02-07T02:45:28.092201Z","shell.execute_reply":"2024-02-07T02:45:28.110853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate(model, evaluate_block, perms, thresh=0.5, TTA=False):\n\n    model.to(device)\n\n    model.eval()\n\n    output_blocks = []\n    for perm in perms:\n        x = evaluate_block.permute(perm)\n        \n        if x.shape[-1] < CFG.image_size or x.shape[-2] < CFG.image_size:\n            continue #skip this perm because we can't tile it.\n\n        reconstructed_masks = np.zeros_like(x, dtype=np.uint8)\n\n        dataset = EvaluateSet(x, perm, tile_size=[CFG.image_size, CFG.image_size], overlap=0.5)\n\n        dataloader = DataLoader(dataset, batch_size=16, collate_fn=custom_collater, shuffle=False, num_workers=2)\n\n        num_batches = len(dataloader)\n        out = display(IPython.display.Pretty('Begin evaluation'), display_id=True)\n\n\n        for batch_idx, (data, data_dicts) in enumerate(dataloader):\n            out.update(IPython.display.Pretty(f'evaluation on batch {batch_idx+1}/{num_batches}; perm {perm}'))\n\n            data = data.to(device)        \n            \n            with torch.set_grad_enabled(False):\n                \n                if TTA==True:\n                    output0 = model(data)\n                    output1 = torch.rot90(model(torch.rot90(data, 1, dims=[-1, -2])), -1, dims=[-1, -2])\n                    output2 = torch.rot90(model(torch.rot90(data, 2, dims=[-1, -2])), -2, dims=[-1, -2])\n                    output3 = torch.rot90(model(torch.rot90(data, 3, dims=[-1, -2])), -3, dims=[-1, -2])\n                    \n                    output4 = torch.flip(model(torch.flip(data, dims=[-1])), dims=[-1])\n                    output5 = torch.flip(model(torch.flip(data, dims=[-2])), dims=[-2])\n                    \n                    #max returns max value and indicies where they occur. don't need the latter, but given for free\n                    output=torch.mean(torch.stack([output0, output1, output2, output3, output4, output5],dim=0), dim=0)\n                    print(output.shape)\n                    \n                else:\n                    output = model(data)\n                \n                output_probs = nn.Sigmoid()(output).unsqueeze(dim=1)\n\n                preds = (output_probs > thresh)\n\n                ## reassemble tiles\n                for pred, data_dict in zip(preds, data_dicts):\n\n                    slice_number = data_dict['slice_number']\n                    perm = data_dict['perm']\n\n                    y1, y2 = data_dict['y_range']\n                    x1, x2 = data_dict['x_range']\n\n                    pred_tile = pred[0].to('cpu').numpy().astype(np.uint8)\n                    \n                    reconstructed_masks[slice_number][y1:y2, x1:x2] = np.logical_or(reconstructed_masks[slice_number][y1:y2, x1:x2], pred_tile)\n          \n        output_blocks.append(reconstructed_masks)\n      \n    return output_blocks","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:28.112995Z","iopub.execute_input":"2024-02-07T02:45:28.113363Z","iopub.status.idle":"2024-02-07T02:45:28.133053Z","shell.execute_reply.started":"2024-02-07T02:45:28.113331Z","shell.execute_reply":"2024-02-07T02:45:28.132113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomModel(nn.Module):\n    def __init__(self, CFG, weight=None):\n        super().__init__()\n        self.model = smp.Unet(\n            encoder_name=CFG.backbone,\n            encoder_weights=weight,\n            in_channels=CFG.in_chans,\n            classes=CFG.target_size,\n            activation=None,\n        )\n\n    def forward(self, image):\n        output = self.model(image)\n        # output = output.squeeze(-1)\n        return output[:,0]#.sigmoid()\n\n\ndef build_model(weight=None):\n    from dotenv import load_dotenv\n    load_dotenv()\n\n    print('model_name', CFG.model_name)\n    print('backbone', CFG.backbone)\n\n    model = CustomModel(CFG, weight)\n\n    return model.cuda()","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:28.134435Z","iopub.execute_input":"2024-02-07T02:45:28.135034Z","iopub.status.idle":"2024-02-07T02:45:28.147202Z","shell.execute_reply.started":"2024-02-07T02:45:28.135001Z","shell.execute_reply":"2024-02-07T02:45:28.146257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model=build_model()\nmodel=DataParallel(model)\nmodel_path = '/kaggle/input/4batchsegformer40epoch/last_model.pth'","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:28.150619Z","iopub.execute_input":"2024-02-07T02:45:28.150961Z","iopub.status.idle":"2024-02-07T02:45:29.433527Z","shell.execute_reply.started":"2024-02-07T02:45:28.150936Z","shell.execute_reply":"2024-02-07T02:45:29.432698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ncheckpoint = torch.load(model_path)\nmodel.load_state_dict(checkpoint['model_state_dict'])","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:29.434915Z","iopub.execute_input":"2024-02-07T02:45:29.435313Z","iopub.status.idle":"2024-02-07T02:45:32.615964Z","shell.execute_reply.started":"2024-02-07T02:45:29.435282Z","shell.execute_reply":"2024-02-07T02:45:32.615038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATASET_FOLDER = \"/kaggle/input/blood-vessel-segmentation\"\nkidneys = glob(os.path.join(DATASET_FOLDER, 'test', \"*\"))\n\n\nprint(kidneys)","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:32.617330Z","iopub.execute_input":"2024-02-07T02:45:32.617684Z","iopub.status.idle":"2024-02-07T02:45:32.625249Z","shell.execute_reply.started":"2024-02-07T02:45:32.617651Z","shell.execute_reply":"2024-02-07T02:45:32.624339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ids = []\nrles = []\nfor kidney in kidneys:\n\n    perms = [(0,1,2), (1,2,0), (2,0,1)]\n    inverse_perms = [(0,1,2), (2,0,1), (1,2,0)]\n    \n    #perms = [(0,1,2)]\n    #inverse_perms = [(0,1,2)]\n    \n\n    print(f'loading kidney {kidney}')\n    kidney_image_names = sorted(glob(os.path.join(kidney, \"images\", \"*.tif\")))\n    kidney_image_block = load_data_block(kidney_image_names)\n    \n    orig_shape = kidney_image_block.shape\n    \n    print(f'evaluating kidney {kidney}')\n    output_blocks = evaluate(model, kidney_image_block, perms, thresh=0.5, TTA=True)\n\n    del kidney_image_block\n    \n    print('combining blocks')\n    overall_block = np.zeros(orig_shape, dtype=np.uint8)\n    for index, block in enumerate(output_blocks):\n        \n        overall_block += torch.tensor(block).permute(inverse_perms[index]).numpy().astype(np.uint8)\n\n    submission_block = np.zeros_like(overall_block, dtype=np.uint8)\n    submission_block[overall_block >= len(perms) / 2] = 1 #if most want it turned on, turn it on.\n    submission_block[overall_block < len(perms) / 2] = 0\n    \n    \n    for slice_number, mask in enumerate(submission_block):\n        \n        identifier=kidney_image_names[slice_number].split(\"/\")[-3:]\n        identifier.pop(1)\n        identifier=\"_\".join(identifier)\n        \n        ids.append(identifier[:-4])\n        rles.append(rle_encode(mask))\n        #rles.append('1 0')\n\n    del output_blocks \n    del overall_block\n    del submission_block\n\n\n    \n        \n    \n    \n","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:32.626646Z","iopub.execute_input":"2024-02-07T02:45:32.626994Z","iopub.status.idle":"2024-02-07T02:45:38.356291Z","shell.execute_reply.started":"2024-02-07T02:45:32.626960Z","shell.execute_reply":"2024-02-07T02:45:38.355115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"id\": ids,\n    \"rle\": rles\n})\n\n\nsubmission.to_csv(\"submission.csv\", index=False)\n","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:38.358251Z","iopub.execute_input":"2024-02-07T02:45:38.359229Z","iopub.status.idle":"2024-02-07T02:45:38.375812Z","shell.execute_reply.started":"2024-02-07T02:45:38.359183Z","shell.execute_reply":"2024-02-07T02:45:38.374945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2024-02-07T02:45:38.376945Z","iopub.execute_input":"2024-02-07T02:45:38.377237Z","iopub.status.idle":"2024-02-07T02:45:38.394894Z","shell.execute_reply.started":"2024-02-07T02:45:38.377212Z","shell.execute_reply":"2024-02-07T02:45:38.393915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}