{
  "id": 52252,
  "title": "Simple ensemble by combining two csv submission files",
  "url": "/competitions/data-science-bowl-2018/discussion/52252",
  "author_name": "",
  "post_date": "2018-03-18T02:28:12.570357100Z",
  "votes": 3,
  "comment_count": 7,
  "views": 0,
  "content": "<p>Hello all, \nI appreciate all the help received so far to get an LB score of 0.42. Now is the time to focus on ensembling, and I just want to start with combining two csv files from a SegUnet and Matterport's Mask RCNN. \nDoes anyone have any links that directly solve this? Has anyone already combined csv files to improve their scores? </p>",
  "messages": [
    {
      "id": "297821",
      "postDate": "03/18/2018 02:28:12",
      "content": "<p>Hello all, \nI appreciate all the help received so far to get an LB score of 0.42. Now is the time to focus on ensembling, and I just want to start with combining two csv files from a SegUnet and Matterport's Mask RCNN. \nDoes anyone have any links that directly solve this? Has anyone already combined csv files to improve their scores? </p>",
      "rawMarkdown": "Hello all, \nI appreciate all the help received so far to get an LB score of 0.42. Now is the time to focus on ensembling, and I just want to start with combining two csv files from a SegUnet and Matterport's Mask RCNN. \nDoes anyone have any links that directly solve this? Has anyone already combined csv files to improve their scores?",
      "votes": null
    },
    {
      "id": "298138",
      "postDate": "03/18/2018 22:42:02",
      "content": "<p>Well you can’t use NMS if you only have the CSV submission files, but...</p>\n\n<p>One thing you could try is transforming your CSVs back into bounding boxes (first translate the mask encoding into a binary numpy mask, then extract the bounding boxes from these masks).</p>\n\n<p>Once you have the boxes maybe you could use these as region proposals.</p>\n\n<p>If you have multiple models, then you can NMS to ensemble them since you have scores + boxes (as Heng has suggested elsewhere).</p>",
      "rawMarkdown": "Well you can’t use NMS if you only have the CSV submission files, but...\n\nOne thing you could try is transforming your CSVs back into bounding boxes (first translate the mask encoding into a binary numpy mask, then extract the bounding boxes from these masks).\n\nOnce you have the boxes maybe you could use these as region proposals.\n\nIf you have multiple models, then you can NMS to ensemble them since you have scores + boxes (as Heng has suggested elsewhere).",
      "votes": null
    },
    {
      "id": "298639",
      "postDate": "03/19/2018 20:26:15",
      "content": "<p>Tried simple NMS on 3 CSV (RLE decode each mask first) without real success (yet).\nSimple NMS implementation: <a href=\"https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/\">https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/</a></p>",
      "rawMarkdown": "Tried simple NMS on 3 CSV (RLE decode each mask first) without real success (yet).\nSimple NMS implementation: https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/",
      "votes": null
    },
    {
      "id": "298983",
      "postDate": "03/20/2018 08:18:09",
      "content": "<p>some work for decoding and extracting bbox I have done but it's not finished yet. Maybe anyone can continue to contribute the NMS implementation.</p>\n\n<pre><code>def rle_decode(rle_str, mask_shape, mask_dtype=np.uint8):\n    s = rle_str.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    mask = np.zeros(np.prod(mask_shape), dtype=mask_dtype)\n    for lo, hi in zip(starts, ends):\n        mask[lo:hi] = 1\n    return mask.reshape(mask_shape[::-1]).T\n\ndef read_rles_file(file_path):\n    is_header = True\n    id_rle_map = {}\n    for line in open(file_path).readlines():\n        if is_header:\n            is_header = False\n            continue\n        id, rle = line.split(',')\n        id = id.strip()\n        rle = rle.strip()\n        assert len(id) &amp;gt; 0\n        assert len(rle) &amp;gt; 0\n        rles = id_rle_map.get(id)\n        if not rles:\n            rles = set([])\n            id_rle_map[id] = rles\n        rles.add(rle)\n    ids = id_rle_map.keys()\n    print('Read sample RLEs for', len(ids), 'images')\n    return id_rle_map\n\n#from https://github.com/matterport/Mask_RCNN\ndef extract_bboxes(mask):\n    \"\"\"Compute bounding boxes from masks.\n    mask: [height, width, num_instances]. Mask pixels are either 1 or 0.\n\n    Returns: bbox array [num_instances, (y1, x1, y2, x2)].\n    \"\"\"\n    boxes = np.zeros([mask.shape[-1], 4], dtype=np.int32)\n    for i in range(mask.shape[-1]):\n        m = mask[:, :, i]\n        # Bounding box.\n        horizontal_indicies = np.where(np.any(m, axis=0))[0]\n        vertical_indicies = np.where(np.any(m, axis=1))[0]\n        if horizontal_indicies.shape[0]:\n            x1, x2 = horizontal_indicies[[0, -1]]\n            y1, y2 = vertical_indicies[[0, -1]]\n            # x2 and y2 should not be part of the box. Increment by 1.\n            x2 += 1\n            y2 += 1\n        else:\n            # No mask for this instance. Might happen due to\n            # resizing or cropping. Set bbox to zeros\n            x1, x2, y1, y2 = 0, 0, 0, 0\n        boxes[i] = np.array([y1, x1, y2, x2])\n    return boxes.astype(np.int32)\n\ndef extract_bboxes_from_rles(rles):\n    masks_ = []\n    for r in rles:\n        rle_ = rle_decode(r, shape)\n        masks_.append(rle_)\n    masks = np.asarray(masks_)\n    return extract_bboxes(np.moveaxis(masks,0, -1))\n</code></pre>",
      "rawMarkdown": "some work for decoding and extracting bbox I have done but it's not finished yet. Maybe anyone can continue to contribute the NMS implementation.\n\n    def rle_decode(rle_str, mask_shape, mask_dtype=np.uint8):\n        s = rle_str.split()\n        starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n        starts -= 1\n        ends = starts + lengths\n        mask = np.zeros(np.prod(mask_shape), dtype=mask_dtype)\n        for lo, hi in zip(starts, ends):\n            mask[lo:hi] = 1\n        return mask.reshape(mask_shape[::-1]).T\n\n    def read_rles_file(file_path):\n        is_header = True\n        id_rle_map = {}\n        for line in open(file_path).readlines():\n            if is_header:\n                is_header = False\n                continue\n            id, rle = line.split(',')\n            id = id.strip()\n            rle = rle.strip()\n            assert len(id) &gt; 0\n            assert len(rle) &gt; 0\n            rles = id_rle_map.get(id)\n            if not rles:\n                rles = set([])\n                id_rle_map[id] = rles\n            rles.add(rle)\n        ids = id_rle_map.keys()\n        print('Read sample RLEs for', len(ids), 'images')\n        return id_rle_map\n\n    #from https://github.com/matterport/Mask_RCNN\n    def extract_bboxes(mask):\n        \"\"\"Compute bounding boxes from masks.\n        mask: [height, width, num_instances]. Mask pixels are either 1 or 0.\n    \n        Returns: bbox array [num_instances, (y1, x1, y2, x2)].\n        \"\"\"\n        boxes = np.zeros([mask.shape[-1], 4], dtype=np.int32)\n        for i in range(mask.shape[-1]):\n            m = mask[:, :, i]\n            # Bounding box.\n            horizontal_indicies = np.where(np.any(m, axis=0))[0]\n            vertical_indicies = np.where(np.any(m, axis=1))[0]\n            if horizontal_indicies.shape[0]:\n                x1, x2 = horizontal_indicies[[0, -1]]\n                y1, y2 = vertical_indicies[[0, -1]]\n                # x2 and y2 should not be part of the box. Increment by 1.\n                x2 += 1\n                y2 += 1\n            else:\n                # No mask for this instance. Might happen due to\n                # resizing or cropping. Set bbox to zeros\n                x1, x2, y1, y2 = 0, 0, 0, 0\n            boxes[i] = np.array([y1, x1, y2, x2])\n        return boxes.astype(np.int32)\n\n    def extract_bboxes_from_rles(rles):\n        masks_ = []\n        for r in rles:\n            rle_ = rle_decode(r, shape)\n            masks_.append(rle_)\n        masks = np.asarray(masks_)\n        return extract_bboxes(np.moveaxis(masks,0, -1))",
      "votes": null
    },
    {
      "id": "299168",
      "postDate": "03/20/2018 16:12:29",
      "content": "<p>Hi all, I have tried to ensemble three CSV files: original one, fliplr, flipup masks using NMS. However, the performance is poor (down from 0.49 to 0.46). The ideal is that I tested with three kind of image: original image, flip left right image, and flip up down image. After that, I obtained three masks and its bounding box. I used NMS for find best bounding box and look at the its masks. Finally, my score reduce :(. Any suggestion?</p>",
      "rawMarkdown": "Hi all, I have tried to ensemble three CSV files: original one, fliplr, flipup masks using NMS. However, the performance is poor (down from 0.49 to 0.46). The ideal is that I tested with three kind of image: original image, flip left right image, and flip up down image. After that, I obtained three masks and its bounding box. I used NMS for find best bounding box and look at the its masks. Finally, my score reduce :(. Any suggestion?",
      "votes": null
    },
    {
      "id": "299213",
      "postDate": "03/20/2018 17:04:52",
      "content": "<p>Here is my kernel for basic NMS ensemble:\n<a href=\"https://www.kaggle.com/mpware/ensembling-on-instance-segmentation/\">https://www.kaggle.com/mpware/ensembling-on-instance-segmentation/</a></p>\n\n<p>@john1231983 same conclusion as you currently. Basic NMS does not help.</p>",
      "rawMarkdown": "Here is my kernel for basic NMS ensemble:\nhttps://www.kaggle.com/mpware/ensembling-on-instance-segmentation/\n\n@john1231983 same conclusion as you currently. Basic NMS does not help.",
      "votes": null
    },
    {
      "id": "300767",
      "postDate": "03/21/2018 22:06:45",
      "content": "<p>Kernel updated: <a href=\"https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419\">https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419</a>\nStarting from 2 CSVs, LB 0.421 and LB 0.413, basic NMS ensembling leads to 0.419 only.</p>",
      "rawMarkdown": "Kernel updated: https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419\nStarting from 2 CSVs, LB 0.421 and LB 0.413, basic NMS ensembling leads to 0.419 only.",
      "votes": null
    },
    {
      "id": "300820",
      "postDate": "03/22/2018 00:25:30",
      "content": "<p>cool. I'll test it and see how it goes.</p>",
      "rawMarkdown": "cool. I'll test it and see how it goes.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 298138,
      "author_name": "spnrpa",
      "author_url": "",
      "post_date": "03/18/2018 22:42:02",
      "content": "<p>Well you can’t use NMS if you only have the CSV submission files, but...</p>\n\n<p>One thing you could try is transforming your CSVs back into bounding boxes (first translate the mask encoding into a binary numpy mask, then extract the bounding boxes from these masks).</p>\n\n<p>Once you have the boxes maybe you could use these as region proposals.</p>\n\n<p>If you have multiple models, then you can NMS to ensemble them since you have scores + boxes (as Heng has suggested elsewhere).</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 298639,
      "author_name": "mpware",
      "author_url": "",
      "post_date": "03/19/2018 20:26:15",
      "content": "<p>Tried simple NMS on 3 CSV (RLE decode each mask first) without real success (yet).\nSimple NMS implementation: <a href=\"https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/\">https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/</a></p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 298983,
      "author_name": "dxchen",
      "author_url": "",
      "post_date": "03/20/2018 08:18:09",
      "content": "<p>some work for decoding and extracting bbox I have done but it's not finished yet. Maybe anyone can continue to contribute the NMS implementation.</p>\n\n<pre><code>def rle_decode(rle_str, mask_shape, mask_dtype=np.uint8):\n    s = rle_str.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    mask = np.zeros(np.prod(mask_shape), dtype=mask_dtype)\n    for lo, hi in zip(starts, ends):\n        mask[lo:hi] = 1\n    return mask.reshape(mask_shape[::-1]).T\n\ndef read_rles_file(file_path):\n    is_header = True\n    id_rle_map = {}\n    for line in open(file_path).readlines():\n        if is_header:\n            is_header = False\n            continue\n        id, rle = line.split(',')\n        id = id.strip()\n        rle = rle.strip()\n        assert len(id) &amp;gt; 0\n        assert len(rle) &amp;gt; 0\n        rles = id_rle_map.get(id)\n        if not rles:\n            rles = set([])\n            id_rle_map[id] = rles\n        rles.add(rle)\n    ids = id_rle_map.keys()\n    print('Read sample RLEs for', len(ids), 'images')\n    return id_rle_map\n\n#from https://github.com/matterport/Mask_RCNN\ndef extract_bboxes(mask):\n    \"\"\"Compute bounding boxes from masks.\n    mask: [height, width, num_instances]. Mask pixels are either 1 or 0.\n\n    Returns: bbox array [num_instances, (y1, x1, y2, x2)].\n    \"\"\"\n    boxes = np.zeros([mask.shape[-1], 4], dtype=np.int32)\n    for i in range(mask.shape[-1]):\n        m = mask[:, :, i]\n        # Bounding box.\n        horizontal_indicies = np.where(np.any(m, axis=0))[0]\n        vertical_indicies = np.where(np.any(m, axis=1))[0]\n        if horizontal_indicies.shape[0]:\n            x1, x2 = horizontal_indicies[[0, -1]]\n            y1, y2 = vertical_indicies[[0, -1]]\n            # x2 and y2 should not be part of the box. Increment by 1.\n            x2 += 1\n            y2 += 1\n        else:\n            # No mask for this instance. Might happen due to\n            # resizing or cropping. Set bbox to zeros\n            x1, x2, y1, y2 = 0, 0, 0, 0\n        boxes[i] = np.array([y1, x1, y2, x2])\n    return boxes.astype(np.int32)\n\ndef extract_bboxes_from_rles(rles):\n    masks_ = []\n    for r in rles:\n        rle_ = rle_decode(r, shape)\n        masks_.append(rle_)\n    masks = np.asarray(masks_)\n    return extract_bboxes(np.moveaxis(masks,0, -1))\n</code></pre>",
      "votes": null,
      "replies": [
        {
          "id": 300767,
          "author_name": "mpware",
          "author_url": "",
          "post_date": "03/21/2018 22:06:45",
          "content": "<p>Kernel updated: <a href=\"https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419\">https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419</a>\nStarting from 2 CSVs, LB 0.421 and LB 0.413, basic NMS ensembling leads to 0.419 only.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 300820,
          "author_name": "dxchen",
          "author_url": "",
          "post_date": "03/22/2018 00:25:30",
          "content": "<p>cool. I'll test it and see how it goes.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 299168,
      "author_name": "john1231983",
      "author_url": "",
      "post_date": "03/20/2018 16:12:29",
      "content": "<p>Hi all, I have tried to ensemble three CSV files: original one, fliplr, flipup masks using NMS. However, the performance is poor (down from 0.49 to 0.46). The ideal is that I tested with three kind of image: original image, flip left right image, and flip up down image. After that, I obtained three masks and its bounding box. I used NMS for find best bounding box and look at the its masks. Finally, my score reduce :(. Any suggestion?</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 299213,
      "author_name": "mpware",
      "author_url": "",
      "post_date": "03/20/2018 17:04:52",
      "content": "<p>Here is my kernel for basic NMS ensemble:\n<a href=\"https://www.kaggle.com/mpware/ensembling-on-instance-segmentation/\">https://www.kaggle.com/mpware/ensembling-on-instance-segmentation/</a></p>\n\n<p>@john1231983 same conclusion as you currently. Basic NMS does not help.</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "297821": "Hello all, \nI appreciate all the help received so far to get an LB score of 0.42. Now is the time to focus on ensembling, and I just want to start with combining two csv files from a SegUnet and Matterport's Mask RCNN. \nDoes anyone have any links that directly solve this? Has anyone already combined csv files to improve their scores?",
    "298138": "Well you can’t use NMS if you only have the CSV submission files, but...\n\nOne thing you could try is transforming your CSVs back into bounding boxes (first translate the mask encoding into a binary numpy mask, then extract the bounding boxes from these masks).\n\nOnce you have the boxes maybe you could use these as region proposals.\n\nIf you have multiple models, then you can NMS to ensemble them since you have scores + boxes (as Heng has suggested elsewhere).",
    "298639": "Tried simple NMS on 3 CSV (RLE decode each mask first) without real success (yet).\nSimple NMS implementation: https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/",
    "298983": "some work for decoding and extracting bbox I have done but it's not finished yet. Maybe anyone can continue to contribute the NMS implementation.\n\n    def rle_decode(rle_str, mask_shape, mask_dtype=np.uint8):\n        s = rle_str.split()\n        starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n        starts -= 1\n        ends = starts + lengths\n        mask = np.zeros(np.prod(mask_shape), dtype=mask_dtype)\n        for lo, hi in zip(starts, ends):\n            mask[lo:hi] = 1\n        return mask.reshape(mask_shape[::-1]).T\n\n    def read_rles_file(file_path):\n        is_header = True\n        id_rle_map = {}\n        for line in open(file_path).readlines():\n            if is_header:\n                is_header = False\n                continue\n            id, rle = line.split(',')\n            id = id.strip()\n            rle = rle.strip()\n            assert len(id) &gt; 0\n            assert len(rle) &gt; 0\n            rles = id_rle_map.get(id)\n            if not rles:\n                rles = set([])\n                id_rle_map[id] = rles\n            rles.add(rle)\n        ids = id_rle_map.keys()\n        print('Read sample RLEs for', len(ids), 'images')\n        return id_rle_map\n\n    #from https://github.com/matterport/Mask_RCNN\n    def extract_bboxes(mask):\n        \"\"\"Compute bounding boxes from masks.\n        mask: [height, width, num_instances]. Mask pixels are either 1 or 0.\n    \n        Returns: bbox array [num_instances, (y1, x1, y2, x2)].\n        \"\"\"\n        boxes = np.zeros([mask.shape[-1], 4], dtype=np.int32)\n        for i in range(mask.shape[-1]):\n            m = mask[:, :, i]\n            # Bounding box.\n            horizontal_indicies = np.where(np.any(m, axis=0))[0]\n            vertical_indicies = np.where(np.any(m, axis=1))[0]\n            if horizontal_indicies.shape[0]:\n                x1, x2 = horizontal_indicies[[0, -1]]\n                y1, y2 = vertical_indicies[[0, -1]]\n                # x2 and y2 should not be part of the box. Increment by 1.\n                x2 += 1\n                y2 += 1\n            else:\n                # No mask for this instance. Might happen due to\n                # resizing or cropping. Set bbox to zeros\n                x1, x2, y1, y2 = 0, 0, 0, 0\n            boxes[i] = np.array([y1, x1, y2, x2])\n        return boxes.astype(np.int32)\n\n    def extract_bboxes_from_rles(rles):\n        masks_ = []\n        for r in rles:\n            rle_ = rle_decode(r, shape)\n            masks_.append(rle_)\n        masks = np.asarray(masks_)\n        return extract_bboxes(np.moveaxis(masks,0, -1))",
    "299168": "Hi all, I have tried to ensemble three CSV files: original one, fliplr, flipup masks using NMS. However, the performance is poor (down from 0.49 to 0.46). The ideal is that I tested with three kind of image: original image, flip left right image, and flip up down image. After that, I obtained three masks and its bounding box. I used NMS for find best bounding box and look at the its masks. Finally, my score reduce :(. Any suggestion?",
    "299213": "Here is my kernel for basic NMS ensemble:\nhttps://www.kaggle.com/mpware/ensembling-on-instance-segmentation/\n\n@john1231983 same conclusion as you currently. Basic NMS does not help.",
    "300767": "Kernel updated: https://www.kaggle.com/mpware/ensembling-on-instance-segmentation-lb-0-419\nStarting from 2 CSVs, LB 0.421 and LB 0.413, basic NMS ensembling leads to 0.419 only.",
    "300820": "cool. I'll test it and see how it goes."
  },
  "source": "meta"
}