{
  "id": 54696,
  "title": "UNet vs Mask RCNN",
  "url": "/competitions/data-science-bowl-2018/discussion/54696",
  "author_name": "Mohammad Shadab Alam",
  "post_date": "2018-04-17T00:27:17.793000",
  "votes": 11,
  "comment_count": 31,
  "views": 0,
  "content": "<p>Just curious to know which approach worked well. Feel free to mention any other approach which produced desired results \nWe used a single MRCNN model.</p>",
  "messages": [
    {
      "id": 315265,
      "postDate": "2018-04-17T00:27:17.793Z",
      "content": "<p>Just curious to know which approach worked well. Feel free to mention any other approach which produced desired results \nWe used a single MRCNN model.</p>",
      "rawMarkdown": "Just curious to know which approach worked well. Feel free to mention any other approach which produced desired results \nWe used a single MRCNN model.",
      "votes": 11
    },
    {
      "id": 315345,
      "postDate": "2018-04-17T01:54:57.993Z",
      "content": "<p>I used mask rcnn(lb 0.590). It is my first time join kaggle competition. Open discussion helps me a lot. Thanks to those who have made many contributions to the community. My solution benefits a lot from many of methods discussed.</p>",
      "rawMarkdown": "I used mask rcnn(lb 0.590). It is my first time join kaggle competition. Open discussion helps me a lot. Thanks to those who have made many contributions to the community. My solution benefits a lot from many of methods discussed.",
      "votes": 8,
      "replies": [
        {
          "id": 315559,
          "postDate": "2018-04-17T09:19:53.463Z",
          "content": "<p>It's a quite amazing score you got in this competitions, It's awesome! I am a newbie of deeplearing and I would like to ask you some questions  May I add your wechat (if you are chinese : ） )? <br>\nmy email is bintan@fudan.edu.cn </p>",
          "rawMarkdown": "It's a quite amazing score you got in this competitions, It's awesome! I am a newbie of deeplearing and I would like to ask you some questions  May I add your wechat (if you are chinese : ） )?  \nmy email is bintan@fudan.edu.cn "
        },
        {
          "id": 316185,
          "postDate": "2018-04-18T11:03:29.540Z",
          "content": "<p>Hi bintan. Of course you can. My wechat: (removed)</p>",
          "rawMarkdown": "Hi bintan. Of course you can. My wechat: (removed)"
        }
      ]
    },
    {
      "id": 315612,
      "postDate": "2018-04-17T10:53:32.630Z",
      "content": "<p>as you guys have known, my approach is ensemble test-time augmentations with one of mask rcnn.</p>\n\n<p>my stage2 submission is private LB 0.574. Post submission with greater threshold to reject false positive clusters give private LB 0.607. See:</p>\n\n<p><a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54735\">https://www.kaggle.com/c/data-science-bowl-2018/discussion/54735</a> </p>",
      "rawMarkdown": "as you guys have known, my approach is ensemble test-time augmentations with one of mask rcnn.\n\nmy stage2 submission is private LB 0.574. Post submission with greater threshold to reject false positive clusters give private LB 0.607. See:\n\n\nhttps://www.kaggle.com/c/data-science-bowl-2018/discussion/54735 ",
      "votes": 4
    },
    {
      "id": 315880,
      "postDate": "2018-04-17T18:08:54.657Z",
      "content": "<p>Mask-RCNN + TTA Ensemble + Cross-Validation with stratified folds based on image modality clustering:</p>\n\n<ul>\n<li>Stage1 LB = 0.516 (Place 51)</li>\n<li>Stage2 LB = 0.578 (Place 14)</li>\n</ul>\n\n<p>Maybe I could post my detailed solution if anyone is interested in.</p>",
      "rawMarkdown": "Mask-RCNN + TTA Ensemble + Cross-Validation with stratified folds based on image modality clustering:\n\n* Stage1 LB = 0.516 (Place 51)\n* Stage2 LB = 0.578 (Place 14)\n\nMaybe I could post my detailed solution if anyone is interested in.",
      "votes": 1,
      "replies": [
        {
          "id": 315889,
          "postDate": "2018-04-17T18:28:02.427Z",
          "content": "<p>Thanks for sharing @MPWARE Team. It would great if you could post a detailed solution with the training schedule. I am sure a lot of us will find it very useful. </p>",
          "rawMarkdown": "Thanks for sharing @MPWARE Team. It would great if you could post a detailed solution with the training schedule. I am sure a lot of us will find it very useful. ",
          "votes": 2
        },
        {
          "id": 315937,
          "postDate": "2018-04-17T20:36:22.687Z",
          "content": "<blockquote>\n  <p>Maybe I could post my detailed solution if anyone is interested in.</p>\n</blockquote>\n\n<p>Please do.</p>",
          "rawMarkdown": "&gt; Maybe I could post my detailed solution if anyone is interested in.\n\nPlease do.",
          "votes": 1
        },
        {
          "id": 316194,
          "postDate": "2018-04-18T11:59:34.597Z",
          "content": "<p>Done <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54835\">here</a>.</p>",
          "rawMarkdown": "Done [here][1].\n\n\n  [1]: https://www.kaggle.com/c/data-science-bowl-2018/discussion/54835",
          "votes": 1
        }
      ]
    },
    {
      "id": 315388,
      "postDate": "2018-04-17T03:36:08.523Z",
      "content": "<p>Mask RCNN. No ensemble. </p>\n\n<p>0.502 with the chosen model, but 0.536 if using raw output without ensemble or post-processing. </p>\n\n<p>Dataset: style transfer data augmentation. no external data. </p>\n\n<p>I clustered the data into subclasses using <a href=\"https://github.com/elcorto/imagecluster/\">imagecluster</a> and used <a href=\"https://github.com/NVIDIA/FastPhotoStyle\">FastPhotoStyle</a> from NVIDIA to transfer color styles between images. This can help augment less popular color classes, by either transferring styles between images of the same class or transferring from color images to grey images. </p>\n\n<p>For stage 1, I mainly used style transfer to augment color images (50% of training data were from style transfer). This got me a public LB of 0.464, which was not very impressive at the end of stage 1. So I did not select this model for final submission, but rather used this as initialization to train another model with all stage 1 data and more balanced style-transfer augmentation (equal proportion of all classes) for stage 2. And at stage 1 I found using multi-scale prediction may help performance. </p>\n\n<p>So the final solution was intended to be two outputs of same style-transfer augmented model (single-scale prediction + multi-scale prediction). In the end, I only chose the multi-scale model for submission, whereas the raw output without postprocessing got 0.536 (by late submission). </p>",
      "rawMarkdown": "Mask RCNN. No ensemble. \n\n0.502 with the chosen model, but 0.536 if using raw output without ensemble or post-processing. \n\nDataset: style transfer data augmentation. no external data. \n\nI clustered the data into subclasses using [imagecluster][2] and used [FastPhotoStyle][1] from NVIDIA to transfer color styles between images. This can help augment less popular color classes, by either transferring styles between images of the same class or transferring from color images to grey images. \n\nFor stage 1, I mainly used style transfer to augment color images (50% of training data were from style transfer). This got me a public LB of 0.464, which was not very impressive at the end of stage 1. So I did not select this model for final submission, but rather used this as initialization to train another model with all stage 1 data and more balanced style-transfer augmentation (equal proportion of all classes) for stage 2. And at stage 1 I found using multi-scale prediction may help performance. \n\nSo the final solution was intended to be two outputs of same style-transfer augmented model (single-scale prediction + multi-scale prediction). In the end, I only chose the multi-scale model for submission, whereas the raw output without postprocessing got 0.536 (by late submission). \n\n\n  [1]: https://github.com/NVIDIA/FastPhotoStyle\n  [2]: https://github.com/elcorto/imagecluster/ \"imagecluster\"",
      "votes": 1
    },
    {
      "id": 315276,
      "postDate": "2018-04-17T00:36:39Z",
      "content": "<p>I just posted this question. I got 0.479 with UNet. This is my first experience with NN and deep learning so I'm happy with the results.</p>",
      "rawMarkdown": "I just posted this question. I got 0.479 with UNet. This is my first experience with NN and deep learning so I'm happy with the results.",
      "votes": 1
    },
    {
      "id": 315271,
      "postDate": "2018-04-17T00:33:28.327Z",
      "content": "<p>We use single mask rcnn, but with special post process to filter noises (i.e. small FPs) based on clustering and outlier detection of mask sizes, which  boosted us a lot (kill lots of noises). Less FPs is the key to get high mAP as Heng said. I should thank him a lot</p>",
      "rawMarkdown": "We use single mask rcnn, but with special post process to filter noises (i.e. small FPs) based on clustering and outlier detection of mask sizes, which  boosted us a lot (kill lots of noises). Less FPs is the key to get high mAP as Heng said. I should thank him a lot",
      "votes": 1,
      "replies": [
        {
          "id": 315274,
          "postDate": "2018-04-17T00:35:16.247Z",
          "content": "<p>Yeah. This was fantastic advice. Heng deserves a service medal.</p>",
          "rawMarkdown": "Yeah. This was fantastic advice. Heng deserves a service medal.",
          "votes": 7
        },
        {
          "id": 315324,
          "postDate": "2018-04-17T01:15:52.050Z",
          "content": "<p>As far as I know his team is 1 place from Gold, I wish he could have a gold medal, he deserves it. Otherwise please set a service medal for contributed Kagglers like him lol</p>",
          "rawMarkdown": "As far as I know his team is 1 place from Gold, I wish he could have a gold medal, he deserves it. Otherwise please set a service medal for contributed Kagglers like him lol"
        }
      ]
    },
    {
      "id": 315523,
      "postDate": "2018-04-17T08:00:13.557Z",
      "content": "<p>Looking at the leaderboard, I think Mask RCNN is better suited for this competition. My team used a FCN based approach that resulted in 0.53 on the private leaderboard (0.559 on the public). We really <strong>should</strong> have read Heng's post on less FPs. This improved our private score to 0.56 (just remove small instances):</p>\n\n<pre><code>python remove_small.py --submission_fn submissions_stage_2/ensemble_123_all_ids.csv --area_threshold 25\n</code></pre>\n\n<h1>remove_small.py</h1>\n\n<pre><code>import warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)\nimport pandas as pd\nimport numpy as np\nimport cv2\nfrom tqdm import tqdm\nimport argparse\nimport skimage.segmentation\n\n\n# from https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\ndef rle_encoding(x):\n  dots = np.where(x.T.flatten() == 1)[0]\n  run_lengths = []\n  prev = -2\n  for b in dots:\n    if (b &gt; prev + 1):\n      run_lengths.extend((b + 1, 0))\n    run_lengths[-1] += 1\n    prev = b\n  return run_lengths\n\n\n# rle decoding\ndef rles_to_instance(rles, h, w):\n  instance = np.zeros((h * w), dtype=np.int32)\n  for j, rl in enumerate(rles):\n    start, length = rl.split(' ')[::2], rl.split(' ')[1::2]\n    start, length = np.int32(start), np.int32(length)\n    # print(len(start), len(length))\n    for s, l in zip(start, length):\n      # caution kaggle wants 1 indexed -.-\n      s -= 1\n      instance[s: s + l] = j + 1\n  return instance.reshape((w, h)).T\n\n\ndef instances_to_rles(instances):\n  for i in range(1, instances.max() + 1):\n    yield rle_encoding(instances == i)\n\n\ndef main():\n  parser = argparse.ArgumentParser()\n  parser.add_argument(\n      '--submission_fn',\n      type=str,\n      default='submissions/submit_000.csv',\n      help=\"\"\"\\\n      Which submission should be changed.\\\n      \"\"\")\n  parser.add_argument(\n      '--area_threshold',\n      type=int,\n      default=25,\n      help=\"\"\"\\\n      Only keep instances bigger than this.\\\n      \"\"\")\n\n  args, unparsed = parser.parse_known_args()\n  sub = pd.read_csv(args.submission_fn)\n  unique_test_ids = np.unique(sub.ImageId.values)\n  # shuffle\n  np.random.seed(32)\n  perm = np.random.permutation(len(unique_test_ids))\n  # corrected submission\n  no_small_rles = []\n  no_small_sub_ids = []\n  for i in tqdm(perm):\n    test_id = unique_test_ids[i]\n    rles = sub.EncodedPixels[sub.ImageId == test_id].values\n    test_fn = 'data/test/%s/images/%s.png' % (test_id, test_id)\n    img = cv2.imread(test_fn)\n    h, w = img.shape[:2]\n    try:\n      instances = rles_to_instance(rles, h, w)\n    except AttributeError:\n      no_small_rles.extend([\"\"])\n      no_small_sub_ids.extend([test_id])\n      continue\n    no_small = instances.copy()\n    instance_labels = [il for il in np.unique(instances)\n                       if il not in [0]]\n\n    for instance_label in instance_labels:\n      instance = np.uint8(instances == instance_label)\n      area = instance.sum()\n      if area &lt; args.area_threshold:\n        # print(\"Removing small instance: %d.\" % (area))\n        no_small[instance == 1] = 0\n        no_small, _, _ = skimage.segmentation.relabel_sequential(\n            no_small)  # Relabel objects\n\n    rle = list(instances_to_rles(no_small))\n    # filter out empty\n    rle = [rl for rl in rle if len(rl)]\n    no_small_rles.extend(rle)\n    no_small_sub_ids.extend([test_id] * len(rle))\n\n  # save\n  out_fn = args.submission_fn.replace('.csv', '_big_only.csv')\n  sub = pd.DataFrame()\n  sub['ImageId'] = no_small_sub_ids\n  sub['EncodedPixels'] = pd.Series(\n      no_small_rles).apply(lambda x: ' '.join(str(y) for y in x))\n  sub.to_csv(out_fn, index=False)\n  print(\"Done! Wrote to: %s.\" % (out_fn))\n\n\nif __name__ == '__main__':\n  main()\n</code></pre>",
      "rawMarkdown": "Looking at the leaderboard, I think Mask RCNN is better suited for this competition. My team used a FCN based approach that resulted in 0.53 on the private leaderboard (0.559 on the public). We really **should** have read Heng's post on less FPs. This improved our private score to 0.56 (just remove small instances):\n\n    python remove_small.py --submission_fn submissions_stage_2/ensemble_123_all_ids.csv --area_threshold 25\n\n# remove_small.py\n    import warnings\n    warnings.simplefilter(action='ignore', category=FutureWarning)\n    import pandas as pd\n    import numpy as np\n    import cv2\n    from tqdm import tqdm\n    import argparse\n    import skimage.segmentation\n    \n    \n    # from https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\n    def rle_encoding(x):\n      dots = np.where(x.T.flatten() == 1)[0]\n      run_lengths = []\n      prev = -2\n      for b in dots:\n        if (b &gt; prev + 1):\n          run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n      return run_lengths\n    \n    \n    # rle decoding\n    def rles_to_instance(rles, h, w):\n      instance = np.zeros((h * w), dtype=np.int32)\n      for j, rl in enumerate(rles):\n        start, length = rl.split(' ')[::2], rl.split(' ')[1::2]\n        start, length = np.int32(start), np.int32(length)\n        # print(len(start), len(length))\n        for s, l in zip(start, length):\n          # caution kaggle wants 1 indexed -.-\n          s -= 1\n          instance[s: s + l] = j + 1\n      return instance.reshape((w, h)).T\n    \n    \n    def instances_to_rles(instances):\n      for i in range(1, instances.max() + 1):\n        yield rle_encoding(instances == i)\n    \n    \n    def main():\n      parser = argparse.ArgumentParser()\n      parser.add_argument(\n          '--submission_fn',\n          type=str,\n          default='submissions/submit_000.csv',\n          help=\"\"\"\\\n          Which submission should be changed.\\\n          \"\"\")\n      parser.add_argument(\n          '--area_threshold',\n          type=int,\n          default=25,\n          help=\"\"\"\\\n          Only keep instances bigger than this.\\\n          \"\"\")\n    \n      args, unparsed = parser.parse_known_args()\n      sub = pd.read_csv(args.submission_fn)\n      unique_test_ids = np.unique(sub.ImageId.values)\n      # shuffle\n      np.random.seed(32)\n      perm = np.random.permutation(len(unique_test_ids))\n      # corrected submission\n      no_small_rles = []\n      no_small_sub_ids = []\n      for i in tqdm(perm):\n        test_id = unique_test_ids[i]\n        rles = sub.EncodedPixels[sub.ImageId == test_id].values\n        test_fn = 'data/test/%s/images/%s.png' % (test_id, test_id)\n        img = cv2.imread(test_fn)\n        h, w = img.shape[:2]\n        try:\n          instances = rles_to_instance(rles, h, w)\n        except AttributeError:\n          no_small_rles.extend([\"\"])\n          no_small_sub_ids.extend([test_id])\n          continue\n        no_small = instances.copy()\n        instance_labels = [il for il in np.unique(instances)\n                           if il not in [0]]\n    \n        for instance_label in instance_labels:\n          instance = np.uint8(instances == instance_label)\n          area = instance.sum()\n          if area &lt; args.area_threshold:\n            # print(\"Removing small instance: %d.\" % (area))\n            no_small[instance == 1] = 0\n            no_small, _, _ = skimage.segmentation.relabel_sequential(\n                no_small)  # Relabel objects\n    \n        rle = list(instances_to_rles(no_small))\n        # filter out empty\n        rle = [rl for rl in rle if len(rl)]\n        no_small_rles.extend(rle)\n        no_small_sub_ids.extend([test_id] * len(rle))\n    \n      # save\n      out_fn = args.submission_fn.replace('.csv', '_big_only.csv')\n      sub = pd.DataFrame()\n      sub['ImageId'] = no_small_sub_ids\n      sub['EncodedPixels'] = pd.Series(\n          no_small_rles).apply(lambda x: ' '.join(str(y) for y in x))\n      sub.to_csv(out_fn, index=False)\n      print(\"Done! Wrote to: %s.\" % (out_fn))\n    \n    \n    if __name__ == '__main__':\n      main()\n    ",
      "votes": 2
    },
    {
      "id": 315344,
      "postDate": "2018-04-17T01:54:47.430Z",
      "content": "<p>I used Unet ensemble (private LB 0.533)</p>",
      "rawMarkdown": "I used Unet ensemble (private LB 0.533)",
      "votes": 2
    },
    {
      "id": 315277,
      "postDate": "2018-04-17T00:37:05.063Z",
      "content": "<p>Not a great score, but modified UNet trained just with the stage-1 images  (Private LB 0.470). </p>",
      "rawMarkdown": "Not a great score, but modified UNet trained just with the stage-1 images  (Private LB 0.470). ",
      "votes": 2,
      "replies": [
        {
          "id": 315296,
          "postDate": "2018-04-17T00:53:48.027Z",
          "content": "<p>Just to provide some perspective, that’s likely around the score a Ph.D. biologist would earn working with traditional methods (like CellProfiler or ImageJ)! 0.47 might not look impressive when compared to the leaderboard scores, it’s extremely impressive to the people who will eventually use these methods!</p>",
          "rawMarkdown": "Just to provide some perspective, that’s likely around the score a Ph.D. biologist would earn working with traditional methods (like CellProfiler or ImageJ)! 0.47 might not look impressive when compared to the leaderboard scores, it’s extremely impressive to the people who will eventually use these methods!",
          "votes": 14
        },
        {
          "id": 315302,
          "postDate": "2018-04-17T01:00:23.413Z",
          "content": "<p>Wow that's great to hear. I may then summarize later what I did in a bit more detail.</p>",
          "rawMarkdown": "Wow that's great to hear. I may then summarize later what I did in a bit more detail.",
          "votes": 3
        },
        {
          "id": 315360,
          "postDate": "2018-04-17T02:24:31.737Z",
          "content": "<p>Allen, what is your score for the stage2?</p>",
          "rawMarkdown": "Allen, what is your score for the stage2?"
        },
        {
          "id": 315409,
          "postDate": "2018-04-17T04:28:53.163Z",
          "content": "<p><strong>My modified U-Net:</strong></p>\n\n<p>I was constrained by a low memory GPU (A driving factor for the choice of U-Net over Mask-RCNN. Also I was learning both for the first time and U-Net was easier to understand).  Therefore I tried to offload processing outside of the GPU. Here's a summary of my approach:</p>\n\n<p><strong>1) Pre-processing:</strong></p>\n\n<p>a) Conversion of all images to a standard format. If chromatic image, first convert it \nto monochromatic on HSV domain. Then apply local contrast equalization. Next, if necessary, invert the image luminance\nto have light objects on dark background. Finally, threshold to remove faint objects. I thought this way the\nnetwork would have less to learn and better generalize.</p>\n\n<p>b) Augmentation of the input images by random crops, flips and 90 degree rotations. No resizing. \nThe crop size was always fixed to the U-Net input size of 256x256. Only the provided images in stage-1 were used for training. Neither pre-trained networks nor external images were used.</p>\n\n<p><strong>2) U-Net</strong> was based on Kjetil Åmdal-Sævik <a href=\"https://www.kaggle.com/keegil/keras-u-net-starter-lb-0-277?scriptVersionId=2164855\"><strong>public kernel</strong></a>. One difference was the\naddition of a Gaussian layer right after the input. It functioned as additional augmentation. Cross \nvalidation showed very helpful.</p>\n\n<p><strong>3) Two networks were trained.</strong> One for the union of masks and another for the union of 1-pixel wide\nedge of masks. Therefore for each input image I was producing two separate outputs: A for the union of masks and B for the union of mask edges.</p>\n\n<p><strong>4) Post-processing:</strong></p>\n\n<p>Threshold A to produce TA. Threshold B to produce TB. Produce a marker M = TA - TB.\nThen finally watershed TA using M as marker. </p>\n\n<hr>\n\n<p>I tried different things. I think it is helpful to list things that didn't work for me</p>\n\n<ol>\n<li>Augmentation with arbitrary scaling and rotations.</li>\n<li>Despite the input to the network to be always monochromatic by design, having only 1 channel was worse. I think using 3 (RGB fed with mono) produced a form of ensembling.</li>\n<li>Initially I had only one network and tried to generate the markers for the watershed just using A and locating maxima. The two network approach boosted the public score by 0.05. </li>\n</ol>\n\n<hr>\n\n<p>There are many I'd like to thank but in no particular order:</p>\n\n<ol>\n<li>Heng CherKeng for his incredible posts.</li>\n<li>Allen Goodman for hinting that pre-trained networks might not be necessary.</li>\n<li>Anne Caperpenter for proposing the core idea above.</li>\n<li>CPMP for hinting U-Net was a good horse (At least for me. I usually check what he's trying)</li>\n<li>Booze Allen and Kaggle for sponsoring this fun contest.</li>\n</ol>",
          "rawMarkdown": "**My modified U-Net:**\n\nI was constrained by a low memory GPU (A driving factor for the choice of U-Net over Mask-RCNN. Also I was learning both for the first time and U-Net was easier to understand).  Therefore I tried to offload processing outside of the GPU. Here's a summary of my approach:\n\n**1) Pre-processing:**\n\na) Conversion of all images to a standard format. If chromatic image, first convert it \nto monochromatic on HSV domain. Then apply local contrast equalization. Next, if necessary, invert the image luminance\nto have light objects on dark background. Finally, threshold to remove faint objects. I thought this way the\nnetwork would have less to learn and better generalize.\n\nb) Augmentation of the input images by random crops, flips and 90 degree rotations. No resizing. \nThe crop size was always fixed to the U-Net input size of 256x256. Only the provided images in stage-1 were used for training. Neither pre-trained networks nor external images were used.\n\n**2) U-Net** was based on Kjetil Åmdal-Sævik [**public kernel**](https://www.kaggle.com/keegil/keras-u-net-starter-lb-0-277?scriptVersionId=2164855). One difference was the\naddition of a Gaussian layer right after the input. It functioned as additional augmentation. Cross \nvalidation showed very helpful.\n\n**3) Two networks were trained.** One for the union of masks and another for the union of 1-pixel wide\nedge of masks. Therefore for each input image I was producing two separate outputs: A for the union of masks and B for the union of mask edges.\n\n**4) Post-processing:**\n\nThreshold A to produce TA. Threshold B to produce TB. Produce a marker M = TA - TB.\nThen finally watershed TA using M as marker. \n\n----\n\nI tried different things. I think it is helpful to list things that didn't work for me\n\n1. Augmentation with arbitrary scaling and rotations.\n2. Despite the input to the network to be always monochromatic by design, having only 1 channel was worse. I think using 3 (RGB fed with mono) produced a form of ensembling.\n3. Initially I had only one network and tried to generate the markers for the watershed just using A and locating maxima. The two network approach boosted the public score by 0.05. \n\n----\nThere are many I'd like to thank but in no particular order:\n\n1. Heng CherKeng for his incredible posts.\n2. Allen Goodman for hinting that pre-trained networks might not be necessary.\n3. Anne Caperpenter for proposing the core idea above.\n4. CPMP for hinting U-Net was a good horse (At least for me. I usually check what he's trying)\n5. Booze Allen and Kaggle for sponsoring this fun contest.\n",
          "votes": 3
        }
      ]
    },
    {
      "id": 315272,
      "postDate": "2018-04-17T00:34:24.543Z",
      "content": "<p>They both did well. I’ll let the winners speak for themselves when they are announced, but I managed to survey a number of submissions in the top 50. While region-based CNNs (like Mask RCNN) dominated, a number of noteworthy fully convolutional submissions (like UNet and SegNet) were competitive!</p>\n\n<p>I was also pleased to see a number of solutions that leaned on watershed (in conjunction with a fully convolutional network) since watershed (and mathematical morphology) played such an important role in the history of biological imaging. Georges Matheron and Jean Serra would be proud!</p>",
      "rawMarkdown": "They both did well. I’ll let the winners speak for themselves when they are announced, but I managed to survey a number of submissions in the top 50. While region-based CNNs (like Mask RCNN) dominated, a number of noteworthy fully convolutional submissions (like UNet and SegNet) were competitive!\n\nI was also pleased to see a number of solutions that leaned on watershed (in conjunction with a fully convolutional network) since watershed (and mathematical morphology) played such an important role in the history of biological imaging. Georges Matheron and Jean Serra would be proud!",
      "votes": 2,
      "replies": [
        {
          "id": 315279,
          "postDate": "2018-04-17T00:38:48.513Z",
          "content": "<p>Will we learn what images the final score were based on?</p>",
          "rawMarkdown": "Will we learn what images the final score were based on?"
        },
        {
          "id": 315290,
          "postDate": "2018-04-17T00:49:48.203Z",
          "content": "<p>I don’t know. We still need to talk about whether we want to keep test hidden so we can rerun the competition in the future. I’ll keep the forum posted. I expect that we’ll decide in the next week or two.</p>",
          "rawMarkdown": "I don’t know. We still need to talk about whether we want to keep test hidden so we can rerun the competition in the future. I’ll keep the forum posted. I expect that we’ll decide in the next week or two.",
          "votes": 1
        },
        {
          "id": 315304,
          "postDate": "2018-04-17T01:00:34.730Z",
          "content": "<p>Hi Allen, here by top50 you mean public lb or private lb? </p>",
          "rawMarkdown": "Hi Allen, here by top50 you mean public lb or private lb? "
        }
      ]
    },
    {
      "id": 315266,
      "postDate": "2018-04-17T00:28:40.567Z",
      "content": "<p>We used Unet (Private LB 0.545)</p>",
      "rawMarkdown": "We used Unet (Private LB 0.545)",
      "replies": [
        {
          "id": 315357,
          "postDate": "2018-04-17T02:20:45.817Z",
          "content": "<p>I have a question about Unet. How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?</p>",
          "rawMarkdown": "I have a question about Unet. How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?",
          "votes": 1
        },
        {
          "id": 315390,
          "postDate": "2018-04-17T03:44:37.643Z",
          "content": "<p>I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.</p>",
          "rawMarkdown": "I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.",
          "votes": 1
        },
        {
          "id": 315643,
          "postDate": "2018-04-17T11:50:12.157Z",
          "content": "<blockquote>\n  <p>How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?</p>\n</blockquote>\n\n<p>Unet does not split adjacent masks, which is why you need to modify it one way or another to split the output.  See top team write up or my write up for some ways to do it.</p>",
          "rawMarkdown": "&gt; How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?\n\nUnet does not split adjacent masks, which is why you need to modify it one way or another to split the output.  See top team write up or my write up for some ways to do it."
        },
        {
          "id": 315644,
          "postDate": "2018-04-17T11:51:05.230Z",
          "content": "<blockquote>\n  <p>I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.</p>\n</blockquote>\n\n<p>You too had this great idea!  I didn't alas.  Congrats.</p>",
          "rawMarkdown": "&gt; I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.\n\nYou too had this great idea!  I didn't alas.  Congrats."
        },
        {
          "id": 315718,
          "postDate": "2018-04-17T14:18:38.247Z",
          "content": "<p>@CPMP, unfortunately I didn't think to use the parts I removed for weighted binary cross entropy loss like someone said they did.</p>",
          "rawMarkdown": "@CPMP, unfortunately I didn't think to use the parts I removed for weighted binary cross entropy loss like someone said they did."
        }
      ]
    },
    {
      "id": 315309,
      "postDate": "2018-04-17T01:05:19.870Z",
      "rawMarkdown": "",
      "votes": 1,
      "isDeleted": true
    }
  ],
  "comments": [
    {
      "id": 315345,
      "author_name": "Zheng Li",
      "author_url": "",
      "post_date": "2018-04-17T01:54:57.993000",
      "content": "<p>I used mask rcnn(lb 0.590). It is my first time join kaggle competition. Open discussion helps me a lot. Thanks to those who have made many contributions to the community. My solution benefits a lot from many of methods discussed.</p>",
      "votes": 8,
      "replies": [
        {
          "id": 315559,
          "author_name": "bintan_FDU",
          "author_url": "",
          "post_date": "2018-04-17T09:19:53.463000",
          "content": "<p>It's a quite amazing score you got in this competitions, It's awesome! I am a newbie of deeplearing and I would like to ask you some questions  May I add your wechat (if you are chinese : ） )? <br>\nmy email is bintan@fudan.edu.cn </p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 316185,
          "author_name": "Zheng Li",
          "author_url": "",
          "post_date": "2018-04-18T11:03:29.540000",
          "content": "<p>Hi bintan. Of course you can. My wechat: (removed)</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 315612,
      "author_name": "hengck23",
      "author_url": "",
      "post_date": "2018-04-17T10:53:32.630000",
      "content": "<p>as you guys have known, my approach is ensemble test-time augmentations with one of mask rcnn.</p>\n\n<p>my stage2 submission is private LB 0.574. Post submission with greater threshold to reject false positive clusters give private LB 0.607. See:</p>\n\n<p><a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54735\">https://www.kaggle.com/c/data-science-bowl-2018/discussion/54735</a> </p>",
      "votes": 4,
      "replies": []
    },
    {
      "id": 315880,
      "author_name": "MPWARE",
      "author_url": "",
      "post_date": "2018-04-17T18:08:54.657000",
      "content": "<p>Mask-RCNN + TTA Ensemble + Cross-Validation with stratified folds based on image modality clustering:</p>\n\n<ul>\n<li>Stage1 LB = 0.516 (Place 51)</li>\n<li>Stage2 LB = 0.578 (Place 14)</li>\n</ul>\n\n<p>Maybe I could post my detailed solution if anyone is interested in.</p>",
      "votes": 1,
      "replies": [
        {
          "id": 315889,
          "author_name": "Mehul Sampat",
          "author_url": "",
          "post_date": "2018-04-17T18:28:02.427000",
          "content": "<p>Thanks for sharing @MPWARE Team. It would great if you could post a detailed solution with the training schedule. I am sure a lot of us will find it very useful. </p>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 315937,
          "author_name": "CPMP",
          "author_url": "",
          "post_date": "2018-04-17T20:36:22.687000",
          "content": "<blockquote>\n  <p>Maybe I could post my detailed solution if anyone is interested in.</p>\n</blockquote>\n\n<p>Please do.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 316194,
          "author_name": "MPWARE",
          "author_url": "",
          "post_date": "2018-04-18T11:59:34.597000",
          "content": "<p>Done <a href=\"https://www.kaggle.com/c/data-science-bowl-2018/discussion/54835\">here</a>.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 315388,
      "author_name": "yueqi",
      "author_url": "",
      "post_date": "2018-04-17T03:36:08.523000",
      "content": "<p>Mask RCNN. No ensemble. </p>\n\n<p>0.502 with the chosen model, but 0.536 if using raw output without ensemble or post-processing. </p>\n\n<p>Dataset: style transfer data augmentation. no external data. </p>\n\n<p>I clustered the data into subclasses using <a href=\"https://github.com/elcorto/imagecluster/\">imagecluster</a> and used <a href=\"https://github.com/NVIDIA/FastPhotoStyle\">FastPhotoStyle</a> from NVIDIA to transfer color styles between images. This can help augment less popular color classes, by either transferring styles between images of the same class or transferring from color images to grey images. </p>\n\n<p>For stage 1, I mainly used style transfer to augment color images (50% of training data were from style transfer). This got me a public LB of 0.464, which was not very impressive at the end of stage 1. So I did not select this model for final submission, but rather used this as initialization to train another model with all stage 1 data and more balanced style-transfer augmentation (equal proportion of all classes) for stage 2. And at stage 1 I found using multi-scale prediction may help performance. </p>\n\n<p>So the final solution was intended to be two outputs of same style-transfer augmented model (single-scale prediction + multi-scale prediction). In the end, I only chose the multi-scale model for submission, whereas the raw output without postprocessing got 0.536 (by late submission). </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 315276,
      "author_name": "David Ermer",
      "author_url": "",
      "post_date": "2018-04-17T00:36:39",
      "content": "<p>I just posted this question. I got 0.479 with UNet. This is my first experience with NN and deep learning so I'm happy with the results.</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 315271,
      "author_name": "xuan",
      "author_url": "",
      "post_date": "2018-04-17T00:33:28.327000",
      "content": "<p>We use single mask rcnn, but with special post process to filter noises (i.e. small FPs) based on clustering and outlier detection of mask sizes, which  boosted us a lot (kill lots of noises). Less FPs is the key to get high mAP as Heng said. I should thank him a lot</p>",
      "votes": 1,
      "replies": [
        {
          "id": 315274,
          "author_name": "Allen Goodman",
          "author_url": "",
          "post_date": "2018-04-17T00:35:16.247000",
          "content": "<p>Yeah. This was fantastic advice. Heng deserves a service medal.</p>",
          "votes": 7,
          "replies": []
        },
        {
          "id": 315324,
          "author_name": "xuan",
          "author_url": "",
          "post_date": "2018-04-17T01:15:52.050000",
          "content": "<p>As far as I know his team is 1 place from Gold, I wish he could have a gold medal, he deserves it. Otherwise please set a service medal for contributed Kagglers like him lol</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 315523,
      "author_name": "See--",
      "author_url": "",
      "post_date": "2018-04-17T08:00:13.557000",
      "content": "<p>Looking at the leaderboard, I think Mask RCNN is better suited for this competition. My team used a FCN based approach that resulted in 0.53 on the private leaderboard (0.559 on the public). We really <strong>should</strong> have read Heng's post on less FPs. This improved our private score to 0.56 (just remove small instances):</p>\n\n<pre><code>python remove_small.py --submission_fn submissions_stage_2/ensemble_123_all_ids.csv --area_threshold 25\n</code></pre>\n\n<h1>remove_small.py</h1>\n\n<pre><code>import warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)\nimport pandas as pd\nimport numpy as np\nimport cv2\nfrom tqdm import tqdm\nimport argparse\nimport skimage.segmentation\n\n\n# from https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\ndef rle_encoding(x):\n  dots = np.where(x.T.flatten() == 1)[0]\n  run_lengths = []\n  prev = -2\n  for b in dots:\n    if (b &gt; prev + 1):\n      run_lengths.extend((b + 1, 0))\n    run_lengths[-1] += 1\n    prev = b\n  return run_lengths\n\n\n# rle decoding\ndef rles_to_instance(rles, h, w):\n  instance = np.zeros((h * w), dtype=np.int32)\n  for j, rl in enumerate(rles):\n    start, length = rl.split(' ')[::2], rl.split(' ')[1::2]\n    start, length = np.int32(start), np.int32(length)\n    # print(len(start), len(length))\n    for s, l in zip(start, length):\n      # caution kaggle wants 1 indexed -.-\n      s -= 1\n      instance[s: s + l] = j + 1\n  return instance.reshape((w, h)).T\n\n\ndef instances_to_rles(instances):\n  for i in range(1, instances.max() + 1):\n    yield rle_encoding(instances == i)\n\n\ndef main():\n  parser = argparse.ArgumentParser()\n  parser.add_argument(\n      '--submission_fn',\n      type=str,\n      default='submissions/submit_000.csv',\n      help=\"\"\"\\\n      Which submission should be changed.\\\n      \"\"\")\n  parser.add_argument(\n      '--area_threshold',\n      type=int,\n      default=25,\n      help=\"\"\"\\\n      Only keep instances bigger than this.\\\n      \"\"\")\n\n  args, unparsed = parser.parse_known_args()\n  sub = pd.read_csv(args.submission_fn)\n  unique_test_ids = np.unique(sub.ImageId.values)\n  # shuffle\n  np.random.seed(32)\n  perm = np.random.permutation(len(unique_test_ids))\n  # corrected submission\n  no_small_rles = []\n  no_small_sub_ids = []\n  for i in tqdm(perm):\n    test_id = unique_test_ids[i]\n    rles = sub.EncodedPixels[sub.ImageId == test_id].values\n    test_fn = 'data/test/%s/images/%s.png' % (test_id, test_id)\n    img = cv2.imread(test_fn)\n    h, w = img.shape[:2]\n    try:\n      instances = rles_to_instance(rles, h, w)\n    except AttributeError:\n      no_small_rles.extend([\"\"])\n      no_small_sub_ids.extend([test_id])\n      continue\n    no_small = instances.copy()\n    instance_labels = [il for il in np.unique(instances)\n                       if il not in [0]]\n\n    for instance_label in instance_labels:\n      instance = np.uint8(instances == instance_label)\n      area = instance.sum()\n      if area &lt; args.area_threshold:\n        # print(\"Removing small instance: %d.\" % (area))\n        no_small[instance == 1] = 0\n        no_small, _, _ = skimage.segmentation.relabel_sequential(\n            no_small)  # Relabel objects\n\n    rle = list(instances_to_rles(no_small))\n    # filter out empty\n    rle = [rl for rl in rle if len(rl)]\n    no_small_rles.extend(rle)\n    no_small_sub_ids.extend([test_id] * len(rle))\n\n  # save\n  out_fn = args.submission_fn.replace('.csv', '_big_only.csv')\n  sub = pd.DataFrame()\n  sub['ImageId'] = no_small_sub_ids\n  sub['EncodedPixels'] = pd.Series(\n      no_small_rles).apply(lambda x: ' '.join(str(y) for y in x))\n  sub.to_csv(out_fn, index=False)\n  print(\"Done! Wrote to: %s.\" % (out_fn))\n\n\nif __name__ == '__main__':\n  main()\n</code></pre>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 315344,
      "author_name": "OsciiArt",
      "author_url": "",
      "post_date": "2018-04-17T01:54:47.430000",
      "content": "<p>I used Unet ensemble (private LB 0.533)</p>",
      "votes": 2,
      "replies": []
    },
    {
      "id": 315277,
      "author_name": "Oscar Takeshita",
      "author_url": "",
      "post_date": "2018-04-17T00:37:05.063000",
      "content": "<p>Not a great score, but modified UNet trained just with the stage-1 images  (Private LB 0.470). </p>",
      "votes": 2,
      "replies": [
        {
          "id": 315296,
          "author_name": "Allen Goodman",
          "author_url": "",
          "post_date": "2018-04-17T00:53:48.027000",
          "content": "<p>Just to provide some perspective, that’s likely around the score a Ph.D. biologist would earn working with traditional methods (like CellProfiler or ImageJ)! 0.47 might not look impressive when compared to the leaderboard scores, it’s extremely impressive to the people who will eventually use these methods!</p>",
          "votes": 14,
          "replies": []
        },
        {
          "id": 315302,
          "author_name": "Oscar Takeshita",
          "author_url": "",
          "post_date": "2018-04-17T01:00:23.413000",
          "content": "<p>Wow that's great to hear. I may then summarize later what I did in a bit more detail.</p>",
          "votes": 3,
          "replies": []
        },
        {
          "id": 315360,
          "author_name": "Alex Shvets",
          "author_url": "",
          "post_date": "2018-04-17T02:24:31.737000",
          "content": "<p>Allen, what is your score for the stage2?</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 315409,
          "author_name": "Oscar Takeshita",
          "author_url": "",
          "post_date": "2018-04-17T04:28:53.163000",
          "content": "<p><strong>My modified U-Net:</strong></p>\n\n<p>I was constrained by a low memory GPU (A driving factor for the choice of U-Net over Mask-RCNN. Also I was learning both for the first time and U-Net was easier to understand).  Therefore I tried to offload processing outside of the GPU. Here's a summary of my approach:</p>\n\n<p><strong>1) Pre-processing:</strong></p>\n\n<p>a) Conversion of all images to a standard format. If chromatic image, first convert it \nto monochromatic on HSV domain. Then apply local contrast equalization. Next, if necessary, invert the image luminance\nto have light objects on dark background. Finally, threshold to remove faint objects. I thought this way the\nnetwork would have less to learn and better generalize.</p>\n\n<p>b) Augmentation of the input images by random crops, flips and 90 degree rotations. No resizing. \nThe crop size was always fixed to the U-Net input size of 256x256. Only the provided images in stage-1 were used for training. Neither pre-trained networks nor external images were used.</p>\n\n<p><strong>2) U-Net</strong> was based on Kjetil Åmdal-Sævik <a href=\"https://www.kaggle.com/keegil/keras-u-net-starter-lb-0-277?scriptVersionId=2164855\"><strong>public kernel</strong></a>. One difference was the\naddition of a Gaussian layer right after the input. It functioned as additional augmentation. Cross \nvalidation showed very helpful.</p>\n\n<p><strong>3) Two networks were trained.</strong> One for the union of masks and another for the union of 1-pixel wide\nedge of masks. Therefore for each input image I was producing two separate outputs: A for the union of masks and B for the union of mask edges.</p>\n\n<p><strong>4) Post-processing:</strong></p>\n\n<p>Threshold A to produce TA. Threshold B to produce TB. Produce a marker M = TA - TB.\nThen finally watershed TA using M as marker. </p>\n\n<hr>\n\n<p>I tried different things. I think it is helpful to list things that didn't work for me</p>\n\n<ol>\n<li>Augmentation with arbitrary scaling and rotations.</li>\n<li>Despite the input to the network to be always monochromatic by design, having only 1 channel was worse. I think using 3 (RGB fed with mono) produced a form of ensembling.</li>\n<li>Initially I had only one network and tried to generate the markers for the watershed just using A and locating maxima. The two network approach boosted the public score by 0.05. </li>\n</ol>\n\n<hr>\n\n<p>There are many I'd like to thank but in no particular order:</p>\n\n<ol>\n<li>Heng CherKeng for his incredible posts.</li>\n<li>Allen Goodman for hinting that pre-trained networks might not be necessary.</li>\n<li>Anne Caperpenter for proposing the core idea above.</li>\n<li>CPMP for hinting U-Net was a good horse (At least for me. I usually check what he's trying)</li>\n<li>Booze Allen and Kaggle for sponsoring this fun contest.</li>\n</ol>",
          "votes": 3,
          "replies": []
        }
      ]
    },
    {
      "id": 315272,
      "author_name": "Allen Goodman",
      "author_url": "",
      "post_date": "2018-04-17T00:34:24.543000",
      "content": "<p>They both did well. I’ll let the winners speak for themselves when they are announced, but I managed to survey a number of submissions in the top 50. While region-based CNNs (like Mask RCNN) dominated, a number of noteworthy fully convolutional submissions (like UNet and SegNet) were competitive!</p>\n\n<p>I was also pleased to see a number of solutions that leaned on watershed (in conjunction with a fully convolutional network) since watershed (and mathematical morphology) played such an important role in the history of biological imaging. Georges Matheron and Jean Serra would be proud!</p>",
      "votes": 2,
      "replies": [
        {
          "id": 315279,
          "author_name": "David Ermer",
          "author_url": "",
          "post_date": "2018-04-17T00:38:48.513000",
          "content": "<p>Will we learn what images the final score were based on?</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 315290,
          "author_name": "Allen Goodman",
          "author_url": "",
          "post_date": "2018-04-17T00:49:48.203000",
          "content": "<p>I don’t know. We still need to talk about whether we want to keep test hidden so we can rerun the competition in the future. I’ll keep the forum posted. I expect that we’ll decide in the next week or two.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 315304,
          "author_name": "Yan Wang",
          "author_url": "",
          "post_date": "2018-04-17T01:00:34.730000",
          "content": "<p>Hi Allen, here by top50 you mean public lb or private lb? </p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 315266,
      "author_name": "CPMP",
      "author_url": "",
      "post_date": "2018-04-17T00:28:40.567000",
      "content": "<p>We used Unet (Private LB 0.545)</p>",
      "votes": 0,
      "replies": [
        {
          "id": 315357,
          "author_name": "zhangqiang",
          "author_url": "",
          "post_date": "2018-04-17T02:20:45.817000",
          "content": "<p>I have a question about Unet. How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 315390,
          "author_name": "David Ermer",
          "author_url": "",
          "post_date": "2018-04-17T03:44:37.643000",
          "content": "<p>I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.</p>",
          "votes": 1,
          "replies": []
        },
        {
          "id": 315643,
          "author_name": "CPMP",
          "author_url": "",
          "post_date": "2018-04-17T11:50:12.157000",
          "content": "<blockquote>\n  <p>How does Unet split two connected cells into two cells? What is the training data in your training? If you feed the mask to Unet, is there any connect cells?</p>\n</blockquote>\n\n<p>Unet does not split adjacent masks, which is why you need to modify it one way or another to split the output.  See top team write up or my write up for some ways to do it.</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 315644,
          "author_name": "CPMP",
          "author_url": "",
          "post_date": "2018-04-17T11:51:05.230000",
          "content": "<blockquote>\n  <p>I preprocessed the masks and removed the sections that were touching. So no there weren't and connected cells in the masks.</p>\n</blockquote>\n\n<p>You too had this great idea!  I didn't alas.  Congrats.</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 315718,
          "author_name": "David Ermer",
          "author_url": "",
          "post_date": "2018-04-17T14:18:38.247000",
          "content": "<p>@CPMP, unfortunately I didn't think to use the parts I removed for weighted binary cross entropy loss like someone said they did.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 315309,
      "author_name": "",
      "author_url": "",
      "post_date": "2018-04-17T01:05:19.870000",
      "content": "",
      "votes": 1,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "315265": "Just curious to know which approach worked well. Feel free to mention any other approach which produced desired results \nWe used a single MRCNN model.",
    "315345": "I used mask rcnn(lb 0.590). It is my first time join kaggle competition. Open discussion helps me a lot. Thanks to those who have made many contributions to the community. My solution benefits a lot from many of methods discussed.",
    "315612": "as you guys have known, my approach is ensemble test-time augmentations with one of mask rcnn.\n\nmy stage2 submission is private LB 0.574. Post submission with greater threshold to reject false positive clusters give private LB 0.607. See:\n\n\nhttps://www.kaggle.com/c/data-science-bowl-2018/discussion/54735 ",
    "315880": "Mask-RCNN + TTA Ensemble + Cross-Validation with stratified folds based on image modality clustering:\n\n* Stage1 LB = 0.516 (Place 51)\n* Stage2 LB = 0.578 (Place 14)\n\nMaybe I could post my detailed solution if anyone is interested in.",
    "315388": "Mask RCNN. No ensemble. \n\n0.502 with the chosen model, but 0.536 if using raw output without ensemble or post-processing. \n\nDataset: style transfer data augmentation. no external data. \n\nI clustered the data into subclasses using [imagecluster][2] and used [FastPhotoStyle][1] from NVIDIA to transfer color styles between images. This can help augment less popular color classes, by either transferring styles between images of the same class or transferring from color images to grey images. \n\nFor stage 1, I mainly used style transfer to augment color images (50% of training data were from style transfer). This got me a public LB of 0.464, which was not very impressive at the end of stage 1. So I did not select this model for final submission, but rather used this as initialization to train another model with all stage 1 data and more balanced style-transfer augmentation (equal proportion of all classes) for stage 2. And at stage 1 I found using multi-scale prediction may help performance. \n\nSo the final solution was intended to be two outputs of same style-transfer augmented model (single-scale prediction + multi-scale prediction). In the end, I only chose the multi-scale model for submission, whereas the raw output without postprocessing got 0.536 (by late submission). \n\n\n  [1]: https://github.com/NVIDIA/FastPhotoStyle\n  [2]: https://github.com/elcorto/imagecluster/ \"imagecluster\"",
    "315276": "I just posted this question. I got 0.479 with UNet. This is my first experience with NN and deep learning so I'm happy with the results.",
    "315271": "We use single mask rcnn, but with special post process to filter noises (i.e. small FPs) based on clustering and outlier detection of mask sizes, which  boosted us a lot (kill lots of noises). Less FPs is the key to get high mAP as Heng said. I should thank him a lot",
    "315523": "Looking at the leaderboard, I think Mask RCNN is better suited for this competition. My team used a FCN based approach that resulted in 0.53 on the private leaderboard (0.559 on the public). We really **should** have read Heng's post on less FPs. This improved our private score to 0.56 (just remove small instances):\n\n    python remove_small.py --submission_fn submissions_stage_2/ensemble_123_all_ids.csv --area_threshold 25\n\n# remove_small.py\n    import warnings\n    warnings.simplefilter(action='ignore', category=FutureWarning)\n    import pandas as pd\n    import numpy as np\n    import cv2\n    from tqdm import tqdm\n    import argparse\n    import skimage.segmentation\n    \n    \n    # from https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\n    def rle_encoding(x):\n      dots = np.where(x.T.flatten() == 1)[0]\n      run_lengths = []\n      prev = -2\n      for b in dots:\n        if (b &gt; prev + 1):\n          run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n      return run_lengths\n    \n    \n    # rle decoding\n    def rles_to_instance(rles, h, w):\n      instance = np.zeros((h * w), dtype=np.int32)\n      for j, rl in enumerate(rles):\n        start, length = rl.split(' ')[::2], rl.split(' ')[1::2]\n        start, length = np.int32(start), np.int32(length)\n        # print(len(start), len(length))\n        for s, l in zip(start, length):\n          # caution kaggle wants 1 indexed -.-\n          s -= 1\n          instance[s: s + l] = j + 1\n      return instance.reshape((w, h)).T\n    \n    \n    def instances_to_rles(instances):\n      for i in range(1, instances.max() + 1):\n        yield rle_encoding(instances == i)\n    \n    \n    def main():\n      parser = argparse.ArgumentParser()\n      parser.add_argument(\n          '--submission_fn',\n          type=str,\n          default='submissions/submit_000.csv',\n          help=\"\"\"\\\n          Which submission should be changed.\\\n          \"\"\")\n      parser.add_argument(\n          '--area_threshold',\n          type=int,\n          default=25,\n          help=\"\"\"\\\n          Only keep instances bigger than this.\\\n          \"\"\")\n    \n      args, unparsed = parser.parse_known_args()\n      sub = pd.read_csv(args.submission_fn)\n      unique_test_ids = np.unique(sub.ImageId.values)\n      # shuffle\n      np.random.seed(32)\n      perm = np.random.permutation(len(unique_test_ids))\n      # corrected submission\n      no_small_rles = []\n      no_small_sub_ids = []\n      for i in tqdm(perm):\n        test_id = unique_test_ids[i]\n        rles = sub.EncodedPixels[sub.ImageId == test_id].values\n        test_fn = 'data/test/%s/images/%s.png' % (test_id, test_id)\n        img = cv2.imread(test_fn)\n        h, w = img.shape[:2]\n        try:\n          instances = rles_to_instance(rles, h, w)\n        except AttributeError:\n          no_small_rles.extend([\"\"])\n          no_small_sub_ids.extend([test_id])\n          continue\n        no_small = instances.copy()\n        instance_labels = [il for il in np.unique(instances)\n                           if il not in [0]]\n    \n        for instance_label in instance_labels:\n          instance = np.uint8(instances == instance_label)\n          area = instance.sum()\n          if area &lt; args.area_threshold:\n            # print(\"Removing small instance: %d.\" % (area))\n            no_small[instance == 1] = 0\n            no_small, _, _ = skimage.segmentation.relabel_sequential(\n                no_small)  # Relabel objects\n    \n        rle = list(instances_to_rles(no_small))\n        # filter out empty\n        rle = [rl for rl in rle if len(rl)]\n        no_small_rles.extend(rle)\n        no_small_sub_ids.extend([test_id] * len(rle))\n    \n      # save\n      out_fn = args.submission_fn.replace('.csv', '_big_only.csv')\n      sub = pd.DataFrame()\n      sub['ImageId'] = no_small_sub_ids\n      sub['EncodedPixels'] = pd.Series(\n          no_small_rles).apply(lambda x: ' '.join(str(y) for y in x))\n      sub.to_csv(out_fn, index=False)\n      print(\"Done! Wrote to: %s.\" % (out_fn))\n    \n    \n    if __name__ == '__main__':\n      main()\n    ",
    "315344": "I used Unet ensemble (private LB 0.533)",
    "315277": "Not a great score, but modified UNet trained just with the stage-1 images  (Private LB 0.470). ",
    "315272": "They both did well. I’ll let the winners speak for themselves when they are announced, but I managed to survey a number of submissions in the top 50. While region-based CNNs (like Mask RCNN) dominated, a number of noteworthy fully convolutional submissions (like UNet and SegNet) were competitive!\n\nI was also pleased to see a number of solutions that leaned on watershed (in conjunction with a fully convolutional network) since watershed (and mathematical morphology) played such an important role in the history of biological imaging. Georges Matheron and Jean Serra would be proud!",
    "315266": "We used Unet (Private LB 0.545)",
    "315309": ""
  }
}