{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Hi all,\nsince I've seen many people struggling with getting the right scoring method, I'm sharing my version of the mDice coefficient that I'm using with this competition as a pure torch `nn.Module`. \n\n","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\n\nclass Dice(nn.Module):\n\n    def __init__(self):\n        super().__init__()\n\n    def forward(self, pred_masks: torch.Tensor, gt_masks: torch.Tensor, smooth=1e-5):\n        \"\"\"\n        This method expect boolean pred and gt masks in the shape of (B, C, H, W).\n        In this competition, we are dealing with semantic segmentation and I choose to use \n        one channel with two values: 0 for background, 1 for mask.\n        \"\"\"\n        batch_size = pred_masks.shape[0]\n        pred_masks = pred_masks.view(batch_size, -1)\n        gt_masks = gt_masks.view(batch_size, -1)\n\n        intersection = (pred_masks * gt_masks).sum(1)\n        dice = (2. * intersection) / (pred_masks.sum(1) + gt_masks.sum(1) + smooth)\n\n        dice = dice.mean()\n\n        return dice","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-06T08:30:16.414831Z","iopub.execute_input":"2023-06-06T08:30:16.415245Z","iopub.status.idle":"2023-06-06T08:30:16.423078Z","shell.execute_reply.started":"2023-06-06T08:30:16.415216Z","shell.execute_reply":"2023-06-06T08:30:16.42187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I use this method in this way:","metadata":{}},{"cell_type":"code","source":"dice_fun = Dice()\n\n# Create random gt_mask\ngt_masks = torch.rand((5, 1, 256, 256)) > 0.5\n\n# Create random logits\npred_logits = torch.rand((5, 1, 256, 256)) * 20\n\n# Create boolean pred mask\nthreshold = 0.3\npred_masks = torch.sigmoid(pred_logits)\npred_masks = pred_masks > threshold\n\nrandom_dice = dice_fun(pred_masks, gt_masks)\ngt_dice = dice_fun(gt_masks, gt_masks)\n\nprint(f\"Dice between random masks: {random_dice:.4f}\")\nprint(f\"Dice between equal masks: {gt_dice:.4f}\")","metadata":{"execution":{"iopub.status.busy":"2023-06-06T08:30:16.425096Z","iopub.execute_input":"2023-06-06T08:30:16.425709Z","iopub.status.idle":"2023-06-06T08:30:16.451289Z","shell.execute_reply.started":"2023-06-06T08:30:16.425679Z","shell.execute_reply":"2023-06-06T08:30:16.450219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Please note that, in order to have the mDice score on your entire validation/test dataset, you have to accumulate the inputs and predictions over the batch dimension. Ideally, you should use this metric with tensors of shape `Nx1xHxW`, where `N` is the number of items in your val/test set.","metadata":{}},{"cell_type":"markdown","source":"Enjoy and upvote if you found this notebook useful!","metadata":{}}]}