{
  "id": 55141,
  "title": "Combining the outputs of a multi-channel unet",
  "url": "/competitions/data-science-bowl-2018/discussion/55141",
  "author_name": "",
  "post_date": "2018-04-22T17:12:26.713975600Z",
  "votes": 3,
  "comment_count": 2,
  "views": 0,
  "content": "<p>Hi,</p>\n\n<p>I'm trying to implement a unet with 2 output channels (the predicted mask and the contours) but I haven't been able to combine the predictions from the two output channels effectively. For now, I'm subtracting the contours from the mask (mask - contours), then using otsu thresholding, but this gives masks that are pixelated and detached. I've attached two images showing predicted masks that have this problem.</p>\n\n<p>Is this a good way of combining the two output channels or should I consider changing the targets of the output channels (eg: only predict contours between overlapping cells)?</p>\n\n<p>Thanks</p>",
  "messages": [
    {
      "id": "317844",
      "postDate": "04/22/2018 17:12:26",
      "content": "<p>Hi,</p>\n\n<p>I'm trying to implement a unet with 2 output channels (the predicted mask and the contours) but I haven't been able to combine the predictions from the two output channels effectively. For now, I'm subtracting the contours from the mask (mask - contours), then using otsu thresholding, but this gives masks that are pixelated and detached. I've attached two images showing predicted masks that have this problem.</p>\n\n<p>Is this a good way of combining the two output channels or should I consider changing the targets of the output channels (eg: only predict contours between overlapping cells)?</p>\n\n<p>Thanks</p>",
      "rawMarkdown": "Hi,\n\nI'm trying to implement a unet with 2 output channels (the predicted mask and the contours) but I haven't been able to combine the predictions from the two output channels effectively. For now, I'm subtracting the contours from the mask (mask - contours), then using otsu thresholding, but this gives masks that are pixelated and detached. I've attached two images showing predicted masks that have this problem.\n\nIs this a good way of combining the two output channels or should I consider changing the targets of the output channels (eg: only predict contours between overlapping cells)?\n\nThanks",
      "votes": null
    },
    {
      "id": "317852",
      "postDate": "04/22/2018 17:26:46",
      "content": "<p>@bkKaggle, for best results, you'll likely want to perform some post-processing such as watershed or random-walker, based on the raw predicted mask and contours. Please look at the post from Nicole in the following discussion:\n<a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\">Unet Nuke solution details</a></p>\n\n<p>In particular, look at the 'Post-processing' section discussed by Nicole. There's a link to the github containing the code as well, if needed.</p>\n\n<p>Hope this helps!</p>",
      "rawMarkdown": "bkKaggle, for best results, you'll likely want to perform some post-processing such as watershed or random-walker, based on the raw predicted mask and contours. Please look at the post from Nicole in the following discussion:\n[Unet Nuke solution details][1]\n\nIn particular, look at the 'Post-processing' section discussed by Nicole. There's a link to the github containing the code as well, if needed.\n\nHope this helps!\n\n  [1]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742",
      "votes": null
    },
    {
      "id": "317873",
      "postDate": "04/22/2018 18:18:53",
      "content": "<p>@bkKaggle, from the predicted contours you posted, your u-net probably still underfit, that's why otsu-threshold didn't do a good job on your predicted contours. I'd suggest you train your u-net for more epochs with early-stopping. After your u-net has been well trained, you can see <code>post_process_image()</code> in \n<a href=\"https://github.com/nicolefinnie/kaggle-dsb2018/blob/master/src/modules/image_processing.py\">our image processing</a>  which is very similar to what you try to achieve.</p>\n\n<p>If you want to change your output channel to touching boundaries (there's no any single overlapping masks in the train data, only touching/adjacent cells), you need to implement a pixelwise weight loss function, you can see <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\"> @CPMP's solution</a> in the post Liam pointed out.  The reason is that there are not enough pixels on touching boundaries, most pixels of an image would be predicted 0 (black) if you use a simple binary loss function, and your U-net wouldn't be able to learn to predict touching boundaries well before it overfits on masks, so putting weights on touching boundaries is necessary. </p>\n\n<p>Also, you can check out <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54426\">Ildoo Kim's solution</a>, he also had the touching boundaries as an output channel and used tensorflow weight loss function, see <a href=\"https://github.com/ildoonet/data-science-bowl-2018/blob/curtis/basic-improve/network_unet_valid.py#L129\">Ildoo Kim's weight loss function</a></p>",
      "rawMarkdown": "bkKaggle, from the predicted contours you posted, your u-net probably still underfit, that's why otsu-threshold didn't do a good job on your predicted contours. I'd suggest you train your u-net for more epochs with early-stopping. After your u-net has been well trained, you can see `post_process_image()` in \n[our image processing][1]  which is very similar to what you try to achieve.\n \n\nIf you want to change your output channel to touching boundaries (there's no any single overlapping masks in the train data, only touching/adjacent cells), you need to implement a pixelwise weight loss function, you can see [ @CPMP's solution][2] in the post Liam pointed out.  The reason is that there are not enough pixels on touching boundaries, most pixels of an image would be predicted 0 (black) if you use a simple binary loss function, and your U-net wouldn't be able to learn to predict touching boundaries well before it overfits on masks, so putting weights on touching boundaries is necessary. \n\nAlso, you can check out [Ildoo Kim's solution][3], he also had the touching boundaries as an output channel and used tensorflow weight loss function, see [Ildoo Kim's weight loss function][4]\n\n\n  [1]: https://github.com/nicolefinnie/kaggle-dsb2018/blob/master/src/modules/image_processing.py\n  [2]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\n  [3]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54426\n  [4]: https://github.com/ildoonet/data-science-bowl-2018/blob/curtis/basic-improve/network_unet_valid.py#L129",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 317852,
      "author_name": "jliamfinnie",
      "author_url": "",
      "post_date": "04/22/2018 17:26:46",
      "content": "<p>@bkKaggle, for best results, you'll likely want to perform some post-processing such as watershed or random-walker, based on the raw predicted mask and contours. Please look at the post from Nicole in the following discussion:\n<a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\">Unet Nuke solution details</a></p>\n\n<p>In particular, look at the 'Post-processing' section discussed by Nicole. There's a link to the github containing the code as well, if needed.</p>\n\n<p>Hope this helps!</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 317873,
      "author_name": "nicolefinnie",
      "author_url": "",
      "post_date": "04/22/2018 18:18:53",
      "content": "<p>@bkKaggle, from the predicted contours you posted, your u-net probably still underfit, that's why otsu-threshold didn't do a good job on your predicted contours. I'd suggest you train your u-net for more epochs with early-stopping. After your u-net has been well trained, you can see <code>post_process_image()</code> in \n<a href=\"https://github.com/nicolefinnie/kaggle-dsb2018/blob/master/src/modules/image_processing.py\">our image processing</a>  which is very similar to what you try to achieve.</p>\n\n<p>If you want to change your output channel to touching boundaries (there's no any single overlapping masks in the train data, only touching/adjacent cells), you need to implement a pixelwise weight loss function, you can see <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\"> @CPMP's solution</a> in the post Liam pointed out.  The reason is that there are not enough pixels on touching boundaries, most pixels of an image would be predicted 0 (black) if you use a simple binary loss function, and your U-net wouldn't be able to learn to predict touching boundaries well before it overfits on masks, so putting weights on touching boundaries is necessary. </p>\n\n<p>Also, you can check out <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54426\">Ildoo Kim's solution</a>, he also had the touching boundaries as an output channel and used tensorflow weight loss function, see <a href=\"https://github.com/ildoonet/data-science-bowl-2018/blob/curtis/basic-improve/network_unet_valid.py#L129\">Ildoo Kim's weight loss function</a></p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "317844": "Hi,\n\nI'm trying to implement a unet with 2 output channels (the predicted mask and the contours) but I haven't been able to combine the predictions from the two output channels effectively. For now, I'm subtracting the contours from the mask (mask - contours), then using otsu thresholding, but this gives masks that are pixelated and detached. I've attached two images showing predicted masks that have this problem.\n\nIs this a good way of combining the two output channels or should I consider changing the targets of the output channels (eg: only predict contours between overlapping cells)?\n\nThanks",
    "317852": "bkKaggle, for best results, you'll likely want to perform some post-processing such as watershed or random-walker, based on the raw predicted mask and contours. Please look at the post from Nicole in the following discussion:\n[Unet Nuke solution details][1]\n\nIn particular, look at the 'Post-processing' section discussed by Nicole. There's a link to the github containing the code as well, if needed.\n\nHope this helps!\n\n  [1]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742",
    "317873": "bkKaggle, from the predicted contours you posted, your u-net probably still underfit, that's why otsu-threshold didn't do a good job on your predicted contours. I'd suggest you train your u-net for more epochs with early-stopping. After your u-net has been well trained, you can see `post_process_image()` in \n[our image processing][1]  which is very similar to what you try to achieve.\n \n\nIf you want to change your output channel to touching boundaries (there's no any single overlapping masks in the train data, only touching/adjacent cells), you need to implement a pixelwise weight loss function, you can see [ @CPMP's solution][2] in the post Liam pointed out.  The reason is that there are not enough pixels on touching boundaries, most pixels of an image would be predicted 0 (black) if you use a simple binary loss function, and your U-net wouldn't be able to learn to predict touching boundaries well before it overfits on masks, so putting weights on touching boundaries is necessary. \n\nAlso, you can check out [Ildoo Kim's solution][3], he also had the touching boundaries as an output channel and used tensorflow weight loss function, see [Ildoo Kim's weight loss function][4]\n\n\n  [1]: https://github.com/nicolefinnie/kaggle-dsb2018/blob/master/src/modules/image_processing.py\n  [2]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54742\n  [3]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54426\n  [4]: https://github.com/ildoonet/data-science-bowl-2018/blob/curtis/basic-improve/network_unet_valid.py#L129"
  },
  "source": "meta"
}