{
  "id": 35448,
  "title": "My  segment and count solution",
  "url": "/competitions/noaa-fisheries-steller-sea-lion-population-count/writeups/bestfitting-my-segment-and-count-solution",
  "author_name": "",
  "post_date": "2019-09-15T07:06:34.730Z",
  "votes": 61,
  "comment_count": 30,
  "views": 2,
  "content": "<p>Congratulations to outrunner,konstantin,thanks to threeplusone for the lion coordinates,thanks to kaggle and noaa for hosted a very good competition.<br></p>\n\n<p>Here is my brief overview of my solution.<br></p>\n\n<p><strong>My goal of this competition:</strong><br>\nI want to try my best to find and count all sealions .<br></p>\n\n<p><strong>Challenges:</strong><br>\n1.Scale variance of the test data which lead to no stable local cross-validate method.<br>\n2.Pups hard to find.<br>\n3.In some images sealions are close to each other,and those images have large weights to RMSE.<br>\n4.Sealion types almost can only be distinguished by their size,especially adult-females and juveniles.<br></p>\n\n<p><strong>Result:</strong><br>\n1.My model can find almost all sealions and get their outlines(masks) except pups.<br>\n2.I did not find a way to handle scale variance.<br></p>\n\n<p>Best private/public scores:13.03/14.03<br></p>\n\n<p><strong>Some demos:</strong><br>\nSome dotted test set images:<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/3190.png\" alt=\"3190 color dotted\">\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/361-580.png\" alt=\"361 color dotted\">\nThe masks,outlines predicted by my models:<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/48-mask-outline.png\" alt=\"outline demo 1  \">\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/6983-mask-outline.png\" alt=\"outline demo 2 \">\nThe sealion-outline-star relation<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/star-demo.png\" alt=\"relation \">\n<strong>The way to find all sealions:</strong><br></p>\n\n<p>My final solution base on two UNet:<br>\nThe first one, to predict dot on sealions,I called it star-unet<br>\nThe second one:to predict the the mask of each type of the sealions(I labeled all training set sealions mask) I called it outline-unet<br>\n<br>\nThe two net’s structure are almost the same,the difference is the first net is  logistic regression and the second is 6-way softmax regression.<br></p>\n\n<p>As to star-unet,I generated the mask by setting the value of the mask to 255 at the center of the sealions,and then  decreasing to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.<br></p>\n\n<p>As to outline-unet:I labeled the sealion’s outline step by step.I labeled 3 images and trained the net on them first,and let the net predict the mask of the some train-set images,and I modified the predicted images’ mask,when I have labeled 100 images,the result were very good.<br></p>\n\n<p><strong>The way to count the sealions:</strong><br>\nBecause my segment net is very good,so I decided to count the sealions based on them,I used a lot of functions of skimage(especially morphology) and scipy.ndimage. <br>\nIt’s not a easy job to split the sealions outline when they are connected,I used the star predicted by star-unet and used a lot of skills on morphology’s closing/opening and scipy.ndimage.label,and finally found more than 1 million sealions. I guess the recall-rate &gt;80% except pups.<br>\n<br>\nAs to pups,I predicted the mask with different scales and ensembled them.<br>\n<br>\n<strong>The pities:</strong><br>\nI failed to find a good way to get the scale factor of every test image.I planed to find the sealions with large area in every test image and compared to the average areas of the adult-males and get the correct scale of every test image(or similar ways)BUT I had no time to finish it,because I under-estimated the difficulty of this competition.I got 15.74 public LB  using two Faster-RCNN network and then I entered another competition, when I was back, there were only 3 weeks left and the test-set is a big one.<br>\n<br>\nSo,my final submission is simple ensemble of the prediction with different scale factors.It’s not much better than single model.My best single model is 13.21/14.26. <br>\n<br>\n<strong>Other methods I tried</strong>:<br>\nI trained two Faster-RCNN networks with Resnet-101,but I found it can not handle sealions that stay close, I can not count them and  can only estimate them,I thought I should find better way,so they are not appeared in final ensemble.</p>",
  "messages": [
    {
      "id": "197053",
      "postDate": "06/28/2017 17:45:31",
      "content": "<p>Congratulations to outrunner,konstantin,thanks to threeplusone for the lion coordinates,thanks to kaggle and noaa for hosted a very good competition.<br></p>\n\n<p>Here is my brief overview of my solution.<br></p>\n\n<p><strong>My goal of this competition:</strong><br>\nI want to try my best to find and count all sealions .<br></p>\n\n<p><strong>Challenges:</strong><br>\n1.Scale variance of the test data which lead to no stable local cross-validate method.<br>\n2.Pups hard to find.<br>\n3.In some images sealions are close to each other,and those images have large weights to RMSE.<br>\n4.Sealion types almost can only be distinguished by their size,especially adult-females and juveniles.<br></p>\n\n<p><strong>Result:</strong><br>\n1.My model can find almost all sealions and get their outlines(masks) except pups.<br>\n2.I did not find a way to handle scale variance.<br></p>\n\n<p>Best private/public scores:13.03/14.03<br></p>\n\n<p><strong>Some demos:</strong><br>\nSome dotted test set images:<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/3190.png\" alt=\"3190 color dotted\">\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/361-580.png\" alt=\"361 color dotted\">\nThe masks,outlines predicted by my models:<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/48-mask-outline.png\" alt=\"outline demo 1  \">\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/6983-mask-outline.png\" alt=\"outline demo 2 \">\nThe sealion-outline-star relation<br>\n<img src=\"https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/star-demo.png\" alt=\"relation \">\n<strong>The way to find all sealions:</strong><br></p>\n\n<p>My final solution base on two UNet:<br>\nThe first one, to predict dot on sealions,I called it star-unet<br>\nThe second one:to predict the the mask of each type of the sealions(I labeled all training set sealions mask) I called it outline-unet<br>\n<br>\nThe two net’s structure are almost the same,the difference is the first net is  logistic regression and the second is 6-way softmax regression.<br></p>\n\n<p>As to star-unet,I generated the mask by setting the value of the mask to 255 at the center of the sealions,and then  decreasing to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.<br></p>\n\n<p>As to outline-unet:I labeled the sealion’s outline step by step.I labeled 3 images and trained the net on them first,and let the net predict the mask of the some train-set images,and I modified the predicted images’ mask,when I have labeled 100 images,the result were very good.<br></p>\n\n<p><strong>The way to count the sealions:</strong><br>\nBecause my segment net is very good,so I decided to count the sealions based on them,I used a lot of functions of skimage(especially morphology) and scipy.ndimage. <br>\nIt’s not a easy job to split the sealions outline when they are connected,I used the star predicted by star-unet and used a lot of skills on morphology’s closing/opening and scipy.ndimage.label,and finally found more than 1 million sealions. I guess the recall-rate &gt;80% except pups.<br>\n<br>\nAs to pups,I predicted the mask with different scales and ensembled them.<br>\n<br>\n<strong>The pities:</strong><br>\nI failed to find a good way to get the scale factor of every test image.I planed to find the sealions with large area in every test image and compared to the average areas of the adult-males and get the correct scale of every test image(or similar ways)BUT I had no time to finish it,because I under-estimated the difficulty of this competition.I got 15.74 public LB  using two Faster-RCNN network and then I entered another competition, when I was back, there were only 3 weeks left and the test-set is a big one.<br>\n<br>\nSo,my final submission is simple ensemble of the prediction with different scale factors.It’s not much better than single model.My best single model is 13.21/14.26. <br>\n<br>\n<strong>Other methods I tried</strong>:<br>\nI trained two Faster-RCNN networks with Resnet-101,but I found it can not handle sealions that stay close, I can not count them and  can only estimate them,I thought I should find better way,so they are not appeared in final ensemble.</p>",
      "rawMarkdown": "Congratulations to outrunner,konstantin,thanks to threeplusone for the lion coordinates,thanks to kaggle and noaa for hosted a very good competition.<br>\n\nHere is my brief overview of my solution.<br>\n\n**My goal of this competition:**<br>\nI want to try my best to find and count all sealions .<br>\n\n**Challenges:**<br>\n1.Scale variance of the test data which lead to no stable local cross-validate method.<br>\n2.Pups hard to find.<br>\n3.In some images sealions are close to each other,and those images have large weights to RMSE.<br>\n4.Sealion types almost can only be distinguished by their size,especially adult-females and juveniles.<br>\n\n**Result:**<br>\n1.My model can find almost all sealions and get their outlines(masks) except pups.<br>\n2.I did not find a way to handle scale variance.<br>\n\nBest private/public scores:13.03/14.03<br>\n\n**Some demos:**<br>\nSome dotted test set images:<br>\n![3190 color dotted][1]\n![361 color dotted][2]\nThe masks,outlines predicted by my models:<br>\n![outline demo 1  ][3]\n![outline demo 2 ][4]\nThe sealion-outline-star relation<br>\n![relation ][5]\n**The way to find all sealions:**<br>\n\nMy final solution base on two UNet:<br>\nThe first one, to predict dot on sealions,I called it star-unet<br>\nThe second one:to predict the the mask of each type of the sealions(I labeled all training set sealions mask) I called it outline-unet<br>\n<br>\nThe two net’s structure are almost the same,the difference is the first net is  logistic regression and the second is 6-way softmax regression.<br>\n \nAs to star-unet,I generated the mask by setting the value of the mask to 255 at the center of the sealions,and then  decreasing to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.<br>\n\nAs to outline-unet:I labeled the sealion’s outline step by step.I labeled 3 images and trained the net on them first,and let the net predict the mask of the some train-set images,and I modified the predicted images’ mask,when I have labeled 100 images,the result were very good.<br>\n\n\n**The way to count the sealions:**<br>\nBecause my segment net is very good,so I decided to count the sealions based on them,I used a lot of functions of skimage(especially morphology) and scipy.ndimage. <br>\nIt’s not a easy job to split the sealions outline when they are connected,I used the star predicted by star-unet and used a lot of skills on morphology’s closing/opening and scipy.ndimage.label,and finally found more than 1 million sealions. I guess the recall-rate &gt;80% except pups.<br>\n<br>\nAs to pups,I predicted the mask with different scales and ensembled them.<br>\n<br>\n**The pities:**<br>\nI failed to find a good way to get the scale factor of every test image.I planed to find the sealions with large area in every test image and compared to the average areas of the adult-males and get the correct scale of every test image(or similar ways)BUT I had no time to finish it,because I under-estimated the difficulty of this competition.I got 15.74 public LB  using two Faster-RCNN network and then I entered another competition, when I was back, there were only 3 weeks left and the test-set is a big one.<br>\n<br>\nSo,my final submission is simple ensemble of the prediction with different scale factors.It’s not much better than single model.My best single model is 13.21/14.26. <br>\n<br>\n**Other methods I tried**:<br>\nI trained two Faster-RCNN networks with Resnet-101,but I found it can not handle sealions that stay close, I can not count them and  can only estimate them,I thought I should find better way,so they are not appeared in final ensemble.\n\n\n  [1]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/3190.png\n  [2]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/361-580.png\n  [3]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/48-mask-outline.png\n  [4]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/6983-mask-outline.png\n  [5]:https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/star-demo.png",
      "votes": null
    },
    {
      "id": "197063",
      "postDate": "06/28/2017 18:08:57",
      "content": "<p>Congrats for the third position and really nice explaination ! </p>\n\n<p>Will you be sharing the code afterwards? </p>",
      "rawMarkdown": "Congrats for the third position and really nice explaination ! \n\nWill you be sharing the code afterwards?",
      "votes": null
    },
    {
      "id": "197075",
      "postDate": "06/28/2017 18:28:52",
      "content": "<p>Wow, really impressive segmentation results and a nice labelling approach! Thanks for sharing and congrats!</p>",
      "rawMarkdown": "Wow, really impressive segmentation results and a nice labelling approach! Thanks for sharing and congrats!",
      "votes": null
    },
    {
      "id": "197083",
      "postDate": "06/28/2017 18:57:18",
      "content": "<p>Congrats. really impressive.</p>\n\n<p>Would you mind describing the \" 2-way logistic regression \" in more details ?</p>",
      "rawMarkdown": "Congrats. really impressive.\n\nWould you mind describing the \" 2-way logistic regression \" in more details ?",
      "votes": null
    },
    {
      "id": "197085",
      "postDate": "06/28/2017 19:03:54",
      "content": "<p>Sorry,I mean logistic regession on each pixel to get the probability ,I delete the '2 way' from the post.</p>",
      "rawMarkdown": "Sorry,I mean logistic regession on each pixel to get the probability ,I delete the '2 way' from the post.",
      "votes": null
    },
    {
      "id": "197090",
      "postDate": "06/28/2017 19:24:09",
      "content": "<p>Congrats! <br>\n I like the idea of imputing masks and then refining them manually iteratively. <br>\nLacking of proper groud-truth masks was a big issue when we tried to do a segmentation. </p>",
      "rawMarkdown": "Congrats!  \n I like the idea of imputing masks and then refining them manually iteratively.    \nLacking of proper groud-truth masks was a big issue when we tried to do a segmentation.",
      "votes": null
    },
    {
      "id": "197091",
      "postDate": "06/28/2017 19:24:11",
      "content": "<p>Thanks,as to codes,there are thousands lines of my codes,they are written in a hurry and I has no time to clean and refactor now,Planet competetion is waiting for me.:)<br>But I want to share my model struture and training strategy here:<br></p>\n\n<p>My Unet structure is simple:<br>\nN_Cls = 6<br>\nISZ = 320<br>\nsmooth = 1e-12<br>\ndef get_unet():<br>\n    inputs = Input((3, ISZ, ISZ))<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(inputs)<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv1)<br>\n    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)<br>\n<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(pool1)<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv2)<br>\n    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)<br>\n<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(pool2)<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv3)<br>\n    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)<br>\n<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(pool3)<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv4)<br>\n    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)<br>\n<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(pool4)<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(conv5)<br>\n<br>\n    up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(up6)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv6)<br>\n<br>\n    up7 = merge([UpSampling2D(size=(2, 2))(conv6), conv3], mode='concat', concat_axis=1)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(up7)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv7)<br>\n<br>\n    up8 = merge([UpSampling2D(size=(2, 2))(conv7), conv2], mode='concat', concat_axis=1)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(up8)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv8)<br>\n<br>\n    up9 = merge([UpSampling2D(size=(2, 2))(conv8), conv1], mode='concat', concat_axis=1)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(up9)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv9)<br>\n<br></p>\n\n<pre><code>conv10 = Convolution2D(6, 1, 1, activation='relu',border_mode='same')(conv9)&lt;br&gt;\nconv10 = core.Reshape((6,ISZ*ISZ))(conv10)&lt;br&gt;\nconv10 = core.Permute((2,1))(conv10)&lt;br&gt;\n#############\nconv11 = core.Activation('softmax')(conv10)&lt;br&gt;\nmodel = Model(input=inputs, output=[conv11])&lt;br&gt;\n</code></pre>\n\n<p><br>\nmodel.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy',metrics=[dice_coef,'accuracy'])<br></p>\n\n<p>dice_coef:<br></p>\n\n<p>def dice_coef(y_true, y_pred):<br>\n    y_true_f = K.flatten(y_true)<br>\n    y_pred_f = K.flatten(y_pred)<br>\n    intersection = K.sum(y_true_f * y_pred_f)<br>\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)<br></p>\n\n<p>def dice_coef_loss(y_true, y_pred):<br>\n    return 1-dice_coef(y_true, y_pred)<br></p>",
      "rawMarkdown": "Thanks,as to codes,there are thousands lines of my codes,they are written in a hurry and I has no time to clean and refactor now,Planet competetion is waiting for me.:)<br>But I want to share my model struture and training strategy here:<br>\n\nMy Unet structure is simple:<br>\nN_Cls = 6<br>\nISZ = 320<br>\nsmooth = 1e-12<br>\ndef get_unet():<br>\n    inputs = Input((3, ISZ, ISZ))<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(inputs)<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv1)<br>\n    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)<br>\n<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(pool1)<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv2)<br>\n    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)<br>\n<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(pool2)<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv3)<br>\n    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)<br>\n<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(pool3)<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv4)<br>\n    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)<br>\n<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(pool4)<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(conv5)<br>\n<br>\n    up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(up6)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv6)<br>\n<br>\n    up7 = merge([UpSampling2D(size=(2, 2))(conv6), conv3], mode='concat', concat_axis=1)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(up7)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv7)<br>\n<br>\n    up8 = merge([UpSampling2D(size=(2, 2))(conv7), conv2], mode='concat', concat_axis=1)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(up8)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv8)<br>\n<br>\n    up9 = merge([UpSampling2D(size=(2, 2))(conv8), conv1], mode='concat', concat_axis=1)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(up9)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv9)<br>\n<br>\n\n    conv10 = Convolution2D(6, 1, 1, activation='relu',border_mode='same')(conv9)<br>\n    conv10 = core.Reshape((6,ISZ*ISZ))(conv10)<br>\n    conv10 = core.Permute((2,1))(conv10)<br>\n    #############\n    conv11 = core.Activation('softmax')(conv10)<br>\n    model = Model(input=inputs, output=[conv11])<br>\n<br>\nmodel.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy',metrics=[dice_coef,'accuracy'])<br>\n\ndice_coef:<br>\n\ndef dice_coef(y_true, y_pred):<br>\n    y_true_f = K.flatten(y_true)<br>\n    y_pred_f = K.flatten(y_pred)<br>\n    intersection = K.sum(y_true_f * y_pred_f)<br>\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)<br>\n\ndef dice_coef_loss(y_true, y_pred):<br>\n    return 1-dice_coef(y_true, y_pred)<br>",
      "votes": null
    },
    {
      "id": "197095",
      "postDate": "06/28/2017 19:33:27",
      "content": "<p>Something important of the training:<br></p>\n\n<ol>\n<li>use adam with lr rate 0.0001 when  use softmax,use adam with lr rate 0.001</li>\n<li>I train the UNET with 320*320 patch.</li>\n<li>I don't train the unet with patches without sealions in first 40 epochs.Then I predict the patches without sealions,I use those patches which have False-Positive samples for 5 epochs.(Sample 10000 of them every epochs)<br>\n<br>\nAnd I trained a resnet-50 UNET,but I found it ok too,but I have no time to use it.</li>\n</ol>",
      "rawMarkdown": "Something important of the training:<br>\n\n 1. use adam with lr rate 0.0001 when  use softmax,use adam with lr rate 0.001\n 2. I train the UNET with 320*320 patch.\n 3. I don't train the unet with patches without sealions in first 40 epochs.Then I predict the patches without sealions,I use those patches which have False-Positive samples for 5 epochs.(Sample 10000 of them every epochs)<br>\n<br>\nAnd I trained a resnet-50 UNET,but I found it ok too,but I have no time to use it.",
      "votes": null
    },
    {
      "id": "197099",
      "postDate": "06/28/2017 19:38:57",
      "content": "<p>Thanks.Yes,perhaps,we under-estimated the UNET,labeling the sealions is not the hardest part of this competition.</p>",
      "rawMarkdown": "Thanks.Yes,perhaps,we under-estimated the UNET,labeling the sealions is not the hardest part of this competition.",
      "votes": null
    },
    {
      "id": "197101",
      "postDate": "06/28/2017 19:44:14",
      "content": "<p>thanks,if we can get the more information(for example,height or zoom of the images taken),then we can calibrate the image to same resolution and the result will be much better,although  we can calibrate by area of the adult males,perhaps.</p>",
      "rawMarkdown": "thanks,if we can get the more information(for example,height or zoom of the images taken),then we can calibrate the image to same resolution and the result will be much better,although  we can calibrate by area of the adult males,perhaps.",
      "votes": null
    },
    {
      "id": "197107",
      "postDate": "06/28/2017 20:00:49",
      "content": "<p>Wonderful solution. I had asked myself if UNET was able to this job, when i had contact with them on Data science Bowl. I was nowhere near of implementing something like this. Congratulations </p>",
      "rawMarkdown": "Wonderful solution. I had asked myself if UNET was able to this job, when i had contact with them on Data science Bowl. I was nowhere near of implementing something like this. Congratulations",
      "votes": null
    },
    {
      "id": "197108",
      "postDate": "06/28/2017 20:01:25",
      "content": "",
      "rawMarkdown": "",
      "votes": null
    },
    {
      "id": "197131",
      "postDate": "06/28/2017 21:49:57",
      "content": "<p>Congratulations Bestfitting</p>\n\n<p>Nice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.</p>",
      "rawMarkdown": "Congratulations Bestfitting\n\nNice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.",
      "votes": null
    },
    {
      "id": "197132",
      "postDate": "06/28/2017 21:50:16",
      "content": "<p>Congratulations Bestfitting</p>\n\n<p>Nice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.</p>\n\n<p>Good luck on planet !</p>",
      "rawMarkdown": "Congratulations Bestfitting\n\nNice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.\n\nGood luck on planet !",
      "votes": null
    },
    {
      "id": "197203",
      "postDate": "06/29/2017 01:49:12",
      "content": "<p>Thanks for sharing, the predict outline looks amazing.</p>",
      "rawMarkdown": "Thanks for sharing, the predict outline looks amazing.",
      "votes": null
    },
    {
      "id": "197292",
      "postDate": "06/29/2017 07:58:10",
      "content": "<p>Thanks for sharing, sorry, I can't understand for that the second u-net have 6-way softmax regression, why is not 5-way?</p>",
      "rawMarkdown": "Thanks for sharing, sorry, I can't understand for that the second u-net have 6-way softmax regression, why is not 5-way?",
      "votes": null
    },
    {
      "id": "197316",
      "postDate": "06/29/2017 09:53:08",
      "content": "<p>Congratulations! Very cool idea with mask generation!</p>",
      "rawMarkdown": "Congratulations! Very cool idea with mask generation!",
      "votes": null
    },
    {
      "id": "197320",
      "postDate": "06/29/2017 10:24:49",
      "content": "<p>Thanks ! that was really helpful.</p>",
      "rawMarkdown": "Thanks ! that was really helpful.",
      "votes": null
    },
    {
      "id": "197371",
      "postDate": "06/29/2017 13:18:32",
      "content": "<p>@bestfitting:\nIn your step by step outline labeling, did you start with squares, bounding boxes or polygons ? can you please give more details on how you correct the masks ?</p>",
      "rawMarkdown": "bestfitting:\nIn your step by step outline labeling, did you start with squares, bounding boxes or polygons ? can you please give more details on how you correct the masks ?",
      "votes": null
    },
    {
      "id": "197640",
      "postDate": "06/30/2017 01:03:45",
      "content": "<p>Thanks!<br>I got the idea when I was watching an TV program about the galaxies ,stars and planets...:)</p>",
      "rawMarkdown": "Thanks!<br>I got the idea when I was watching an TV program about the galaxies ,stars and planets...:)",
      "votes": null
    },
    {
      "id": "197644",
      "postDate": "06/30/2017 01:12:04",
      "content": "<p>Thanks,I read a lot of papers related and checked different structures and found the UNET is so powerfule.</p>",
      "rawMarkdown": "Thanks,I read a lot of papers related and checked different structures and found the UNET is so powerfule.",
      "votes": null
    },
    {
      "id": "197647",
      "postDate": "06/30/2017 01:15:14",
      "content": "<p>JuGL,we have 5 types of sealions and we should add a type to indicate there is no sealion on that pixel.</p>",
      "rawMarkdown": "JuGL,we have 5 types of sealions and we should add a type to indicate there is no sealion on that pixel.",
      "votes": null
    },
    {
      "id": "197648",
      "postDate": "06/30/2017 01:15:30",
      "content": "<p>thanks</p>",
      "rawMarkdown": "thanks",
      "votes": null
    },
    {
      "id": "197650",
      "postDate": "06/30/2017 01:17:54",
      "content": "<p>I did not find a good tool to label image ,so I used GIMP to label the sealions.I added layer on train set images,and extracted the mask from new layer using GIMP python APIs.</p>",
      "rawMarkdown": "I did not find a good tool to label image ,so I used GIMP to label the sealions.I added layer on train set images,and extracted the mask from new layer using GIMP python APIs.",
      "votes": null
    },
    {
      "id": "197652",
      "postDate": "06/30/2017 01:22:05",
      "content": "<p>I also read solutions of the Data science Bowl,they are very good.You can get very useful information from them and implement your net.</p>",
      "rawMarkdown": "I also read solutions of the Data science Bowl,they are very good.You can get very useful information from them and implement your net.",
      "votes": null
    },
    {
      "id": "197654",
      "postDate": "06/30/2017 01:28:12",
      "content": "<p>how do you set label for the added type</p>",
      "rawMarkdown": "how do you set label for the added type",
      "votes": null
    },
    {
      "id": "197659",
      "postDate": "06/30/2017 01:39:41",
      "content": "<p>The label is 320*320*6<br>\n0:background 1:adult-males 2:subadult-males...5:pups</p>",
      "rawMarkdown": "The label is 320*320*6<br>\n0:background 1:adult-males 2:subadult-males...5:pups",
      "votes": null
    },
    {
      "id": "198014",
      "postDate": "06/30/2017 18:35:13",
      "content": "<p>Congratulations! So glad to see such a rigorous and insightful approach!</p>",
      "rawMarkdown": "Congratulations! So glad to see such a rigorous and insightful approach!",
      "votes": null
    },
    {
      "id": "198501",
      "postDate": "07/02/2017 18:13:52",
      "content": "<p>Congratulations and thanks for taking the time to explain your approach! May I ask how you made the outlines of the images 4 to 100? Did you make an annotating software or did you use something existing? I am asking because I ran out of time with a similar approach and would really like to know if there is a faster way to draw outlines... :)</p>",
      "rawMarkdown": "Congratulations and thanks for taking the time to explain your approach! May I ask how you made the outlines of the images 4 to 100? Did you make an annotating software or did you use something existing? I am asking because I ran out of time with a similar approach and would really like to know if there is a faster way to draw outlines... :)",
      "votes": null
    },
    {
      "id": "198576",
      "postDate": "07/03/2017 02:40:37",
      "content": "<p>kglspl,I selected the images easy to fit (with no complex background and having a lot of sealions),they were cutted into a lot of 320*320 small images to input to unet.Then I predicted similar images(easy to fit) and did it iterately.<br>\nAs to mask tools,I just used GIMP and added layers to it,then I  read the mask layers via GIMP python api .I think the solution is ok. </p>",
      "rawMarkdown": "kglspl,I selected the images easy to fit (with no complex background and having a lot of sealions),they were cutted into a lot of 320*320 small images to input to unet.Then I predicted similar images(easy to fit) and did it iterately.<br>\nAs to mask tools,I just used GIMP and added layers to it,then I  read the mask layers via GIMP python api .I think the solution is ok.",
      "votes": null
    },
    {
      "id": "198577",
      "postDate": "07/03/2017 02:41:10",
      "content": "<p>thanks</p>",
      "rawMarkdown": "thanks",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 197063,
      "author_name": "syeddanish",
      "author_url": "",
      "post_date": "06/28/2017 18:08:57",
      "content": "<p>Congrats for the third position and really nice explaination ! </p>\n\n<p>Will you be sharing the code afterwards? </p>",
      "votes": null,
      "replies": [
        {
          "id": 197091,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/28/2017 19:24:11",
          "content": "<p>Thanks,as to codes,there are thousands lines of my codes,they are written in a hurry and I has no time to clean and refactor now,Planet competetion is waiting for me.:)<br>But I want to share my model struture and training strategy here:<br></p>\n\n<p>My Unet structure is simple:<br>\nN_Cls = 6<br>\nISZ = 320<br>\nsmooth = 1e-12<br>\ndef get_unet():<br>\n    inputs = Input((3, ISZ, ISZ))<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(inputs)<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv1)<br>\n    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)<br>\n<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(pool1)<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv2)<br>\n    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)<br>\n<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(pool2)<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv3)<br>\n    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)<br>\n<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(pool3)<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv4)<br>\n    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)<br>\n<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(pool4)<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(conv5)<br>\n<br>\n    up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(up6)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv6)<br>\n<br>\n    up7 = merge([UpSampling2D(size=(2, 2))(conv6), conv3], mode='concat', concat_axis=1)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(up7)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv7)<br>\n<br>\n    up8 = merge([UpSampling2D(size=(2, 2))(conv7), conv2], mode='concat', concat_axis=1)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(up8)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv8)<br>\n<br>\n    up9 = merge([UpSampling2D(size=(2, 2))(conv8), conv1], mode='concat', concat_axis=1)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(up9)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv9)<br>\n<br></p>\n\n<pre><code>conv10 = Convolution2D(6, 1, 1, activation='relu',border_mode='same')(conv9)&lt;br&gt;\nconv10 = core.Reshape((6,ISZ*ISZ))(conv10)&lt;br&gt;\nconv10 = core.Permute((2,1))(conv10)&lt;br&gt;\n#############\nconv11 = core.Activation('softmax')(conv10)&lt;br&gt;\nmodel = Model(input=inputs, output=[conv11])&lt;br&gt;\n</code></pre>\n\n<p><br>\nmodel.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy',metrics=[dice_coef,'accuracy'])<br></p>\n\n<p>dice_coef:<br></p>\n\n<p>def dice_coef(y_true, y_pred):<br>\n    y_true_f = K.flatten(y_true)<br>\n    y_pred_f = K.flatten(y_pred)<br>\n    intersection = K.sum(y_true_f * y_pred_f)<br>\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)<br></p>\n\n<p>def dice_coef_loss(y_true, y_pred):<br>\n    return 1-dice_coef(y_true, y_pred)<br></p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 197095,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/28/2017 19:33:27",
          "content": "<p>Something important of the training:<br></p>\n\n<ol>\n<li>use adam with lr rate 0.0001 when  use softmax,use adam with lr rate 0.001</li>\n<li>I train the UNET with 320*320 patch.</li>\n<li>I don't train the unet with patches without sealions in first 40 epochs.Then I predict the patches without sealions,I use those patches which have False-Positive samples for 5 epochs.(Sample 10000 of them every epochs)<br>\n<br>\nAnd I trained a resnet-50 UNET,but I found it ok too,but I have no time to use it.</li>\n</ol>",
          "votes": null,
          "replies": []
        },
        {
          "id": 197320,
          "author_name": "syeddanish",
          "author_url": "",
          "post_date": "06/29/2017 10:24:49",
          "content": "<p>Thanks ! that was really helpful.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197075,
      "author_name": "lopuhin",
      "author_url": "",
      "post_date": "06/28/2017 18:28:52",
      "content": "<p>Wow, really impressive segmentation results and a nice labelling approach! Thanks for sharing and congrats!</p>",
      "votes": null,
      "replies": [
        {
          "id": 197101,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/28/2017 19:44:14",
          "content": "<p>thanks,if we can get the more information(for example,height or zoom of the images taken),then we can calibrate the image to same resolution and the result will be much better,although  we can calibrate by area of the adult males,perhaps.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 198501,
          "author_name": "kglspl",
          "author_url": "",
          "post_date": "07/02/2017 18:13:52",
          "content": "<p>Congratulations and thanks for taking the time to explain your approach! May I ask how you made the outlines of the images 4 to 100? Did you make an annotating software or did you use something existing? I am asking because I ran out of time with a similar approach and would really like to know if there is a faster way to draw outlines... :)</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 198576,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "07/03/2017 02:40:37",
          "content": "<p>kglspl,I selected the images easy to fit (with no complex background and having a lot of sealions),they were cutted into a lot of 320*320 small images to input to unet.Then I predicted similar images(easy to fit) and did it iterately.<br>\nAs to mask tools,I just used GIMP and added layers to it,then I  read the mask layers via GIMP python api .I think the solution is ok. </p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197083,
      "author_name": "chabir",
      "author_url": "",
      "post_date": "06/28/2017 18:57:18",
      "content": "<p>Congrats. really impressive.</p>\n\n<p>Would you mind describing the \" 2-way logistic regression \" in more details ?</p>",
      "votes": null,
      "replies": [
        {
          "id": 197085,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/28/2017 19:03:54",
          "content": "<p>Sorry,I mean logistic regession on each pixel to get the probability ,I delete the '2 way' from the post.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197090,
      "author_name": "asanakoev",
      "author_url": "",
      "post_date": "06/28/2017 19:24:09",
      "content": "<p>Congrats! <br>\n I like the idea of imputing masks and then refining them manually iteratively. <br>\nLacking of proper groud-truth masks was a big issue when we tried to do a segmentation. </p>",
      "votes": null,
      "replies": [
        {
          "id": 197099,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/28/2017 19:38:57",
          "content": "<p>Thanks.Yes,perhaps,we under-estimated the UNET,labeling the sealions is not the hardest part of this competition.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197107,
      "author_name": "abriosi",
      "author_url": "",
      "post_date": "06/28/2017 20:00:49",
      "content": "<p>Wonderful solution. I had asked myself if UNET was able to this job, when i had contact with them on Data science Bowl. I was nowhere near of implementing something like this. Congratulations </p>",
      "votes": null,
      "replies": [
        {
          "id": 197652,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:22:05",
          "content": "<p>I also read solutions of the Data science Bowl,they are very good.You can get very useful information from them and implement your net.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197108,
      "author_name": "abriosi",
      "author_url": "",
      "post_date": "06/28/2017 20:01:25",
      "content": "",
      "votes": null,
      "replies": []
    },
    {
      "id": 197131,
      "author_name": "darraghdog",
      "author_url": "",
      "post_date": "06/28/2017 21:49:57",
      "content": "<p>Congratulations Bestfitting</p>\n\n<p>Nice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 197132,
      "author_name": "darraghdog",
      "author_url": "",
      "post_date": "06/28/2017 21:50:16",
      "content": "<p>Congratulations Bestfitting</p>\n\n<p>Nice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.</p>\n\n<p>Good luck on planet !</p>",
      "votes": null,
      "replies": [
        {
          "id": 197640,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:03:45",
          "content": "<p>Thanks!<br>I got the idea when I was watching an TV program about the galaxies ,stars and planets...:)</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197203,
      "author_name": "outrunner",
      "author_url": "",
      "post_date": "06/29/2017 01:49:12",
      "content": "<p>Thanks for sharing, the predict outline looks amazing.</p>",
      "votes": null,
      "replies": [
        {
          "id": 197644,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:12:04",
          "content": "<p>Thanks,I read a lot of papers related and checked different structures and found the UNET is so powerfule.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197292,
      "author_name": "juguangliang",
      "author_url": "",
      "post_date": "06/29/2017 07:58:10",
      "content": "<p>Thanks for sharing, sorry, I can't understand for that the second u-net have 6-way softmax regression, why is not 5-way?</p>",
      "votes": null,
      "replies": [
        {
          "id": 197647,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:15:14",
          "content": "<p>JuGL,we have 5 types of sealions and we should add a type to indicate there is no sealion on that pixel.</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 197654,
          "author_name": "juguangliang",
          "author_url": "",
          "post_date": "06/30/2017 01:28:12",
          "content": "<p>how do you set label for the added type</p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 197659,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:39:41",
          "content": "<p>The label is 320*320*6<br>\n0:background 1:adult-males 2:subadult-males...5:pups</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197316,
      "author_name": "noonv13",
      "author_url": "",
      "post_date": "06/29/2017 09:53:08",
      "content": "<p>Congratulations! Very cool idea with mask generation!</p>",
      "votes": null,
      "replies": [
        {
          "id": 197648,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:15:30",
          "content": "<p>thanks</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 197371,
      "author_name": "chabir",
      "author_url": "",
      "post_date": "06/29/2017 13:18:32",
      "content": "<p>@bestfitting:\nIn your step by step outline labeling, did you start with squares, bounding boxes or polygons ? can you please give more details on how you correct the masks ?</p>",
      "votes": null,
      "replies": [
        {
          "id": 197650,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "06/30/2017 01:17:54",
          "content": "<p>I did not find a good tool to label image ,so I used GIMP to label the sealions.I added layer on train set images,and extracted the mask from new layer using GIMP python APIs.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 198014,
      "author_name": "lujing",
      "author_url": "",
      "post_date": "06/30/2017 18:35:13",
      "content": "<p>Congratulations! So glad to see such a rigorous and insightful approach!</p>",
      "votes": null,
      "replies": [
        {
          "id": 198577,
          "author_name": "bestfitting",
          "author_url": "",
          "post_date": "07/03/2017 02:41:10",
          "content": "<p>thanks</p>",
          "votes": null,
          "replies": []
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "197053": "Congratulations to outrunner,konstantin,thanks to threeplusone for the lion coordinates,thanks to kaggle and noaa for hosted a very good competition.<br>\n\nHere is my brief overview of my solution.<br>\n\n**My goal of this competition:**<br>\nI want to try my best to find and count all sealions .<br>\n\n**Challenges:**<br>\n1.Scale variance of the test data which lead to no stable local cross-validate method.<br>\n2.Pups hard to find.<br>\n3.In some images sealions are close to each other,and those images have large weights to RMSE.<br>\n4.Sealion types almost can only be distinguished by their size,especially adult-females and juveniles.<br>\n\n**Result:**<br>\n1.My model can find almost all sealions and get their outlines(masks) except pups.<br>\n2.I did not find a way to handle scale variance.<br>\n\nBest private/public scores:13.03/14.03<br>\n\n**Some demos:**<br>\nSome dotted test set images:<br>\n![3190 color dotted][1]\n![361 color dotted][2]\nThe masks,outlines predicted by my models:<br>\n![outline demo 1  ][3]\n![outline demo 2 ][4]\nThe sealion-outline-star relation<br>\n![relation ][5]\n**The way to find all sealions:**<br>\n\nMy final solution base on two UNet:<br>\nThe first one, to predict dot on sealions,I called it star-unet<br>\nThe second one:to predict the the mask of each type of the sealions(I labeled all training set sealions mask) I called it outline-unet<br>\n<br>\nThe two net’s structure are almost the same,the difference is the first net is  logistic regression and the second is 6-way softmax regression.<br>\n \nAs to star-unet,I generated the mask by setting the value of the mask to 255 at the center of the sealions,and then  decreasing to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.<br>\n\nAs to outline-unet:I labeled the sealion’s outline step by step.I labeled 3 images and trained the net on them first,and let the net predict the mask of the some train-set images,and I modified the predicted images’ mask,when I have labeled 100 images,the result were very good.<br>\n\n\n**The way to count the sealions:**<br>\nBecause my segment net is very good,so I decided to count the sealions based on them,I used a lot of functions of skimage(especially morphology) and scipy.ndimage. <br>\nIt’s not a easy job to split the sealions outline when they are connected,I used the star predicted by star-unet and used a lot of skills on morphology’s closing/opening and scipy.ndimage.label,and finally found more than 1 million sealions. I guess the recall-rate &gt;80% except pups.<br>\n<br>\nAs to pups,I predicted the mask with different scales and ensembled them.<br>\n<br>\n**The pities:**<br>\nI failed to find a good way to get the scale factor of every test image.I planed to find the sealions with large area in every test image and compared to the average areas of the adult-males and get the correct scale of every test image(or similar ways)BUT I had no time to finish it,because I under-estimated the difficulty of this competition.I got 15.74 public LB  using two Faster-RCNN network and then I entered another competition, when I was back, there were only 3 weeks left and the test-set is a big one.<br>\n<br>\nSo,my final submission is simple ensemble of the prediction with different scale factors.It’s not much better than single model.My best single model is 13.21/14.26. <br>\n<br>\n**Other methods I tried**:<br>\nI trained two Faster-RCNN networks with Resnet-101,but I found it can not handle sealions that stay close, I can not count them and  can only estimate them,I thought I should find better way,so they are not appeared in final ensemble.\n\n\n  [1]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/3190.png\n  [2]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/361-580.png\n  [3]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/48-mask-outline.png\n  [4]: https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/6983-mask-outline.png\n  [5]:https://raw.githubusercontent.com/bestfitting/kaggle/master/sealions/star-demo.png",
    "197063": "Congrats for the third position and really nice explaination ! \n\nWill you be sharing the code afterwards?",
    "197075": "Wow, really impressive segmentation results and a nice labelling approach! Thanks for sharing and congrats!",
    "197083": "Congrats. really impressive.\n\nWould you mind describing the \" 2-way logistic regression \" in more details ?",
    "197085": "Sorry,I mean logistic regession on each pixel to get the probability ,I delete the '2 way' from the post.",
    "197090": "Congrats!  \n I like the idea of imputing masks and then refining them manually iteratively.    \nLacking of proper groud-truth masks was a big issue when we tried to do a segmentation.",
    "197091": "Thanks,as to codes,there are thousands lines of my codes,they are written in a hurry and I has no time to clean and refactor now,Planet competetion is waiting for me.:)<br>But I want to share my model struture and training strategy here:<br>\n\nMy Unet structure is simple:<br>\nN_Cls = 6<br>\nISZ = 320<br>\nsmooth = 1e-12<br>\ndef get_unet():<br>\n    inputs = Input((3, ISZ, ISZ))<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(inputs)<br>\n    conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv1)<br>\n    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)<br>\n<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(pool1)<br>\n    conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv2)<br>\n    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)<br>\n<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(pool2)<br>\n    conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv3)<br>\n    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)<br>\n<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(pool3)<br>\n    conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv4)<br>\n    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)<br>\n<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(pool4)<br>\n    conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(conv5)<br>\n<br>\n    up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(up6)<br>\n    conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv6)<br>\n<br>\n    up7 = merge([UpSampling2D(size=(2, 2))(conv6), conv3], mode='concat', concat_axis=1)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(up7)<br>\n    conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv7)<br>\n<br>\n    up8 = merge([UpSampling2D(size=(2, 2))(conv7), conv2], mode='concat', concat_axis=1)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(up8)<br>\n    conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv8)<br>\n<br>\n    up9 = merge([UpSampling2D(size=(2, 2))(conv8), conv1], mode='concat', concat_axis=1)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(up9)<br>\n    conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv9)<br>\n<br>\n\n    conv10 = Convolution2D(6, 1, 1, activation='relu',border_mode='same')(conv9)<br>\n    conv10 = core.Reshape((6,ISZ*ISZ))(conv10)<br>\n    conv10 = core.Permute((2,1))(conv10)<br>\n    #############\n    conv11 = core.Activation('softmax')(conv10)<br>\n    model = Model(input=inputs, output=[conv11])<br>\n<br>\nmodel.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy',metrics=[dice_coef,'accuracy'])<br>\n\ndice_coef:<br>\n\ndef dice_coef(y_true, y_pred):<br>\n    y_true_f = K.flatten(y_true)<br>\n    y_pred_f = K.flatten(y_pred)<br>\n    intersection = K.sum(y_true_f * y_pred_f)<br>\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)<br>\n\ndef dice_coef_loss(y_true, y_pred):<br>\n    return 1-dice_coef(y_true, y_pred)<br>",
    "197095": "Something important of the training:<br>\n\n 1. use adam with lr rate 0.0001 when  use softmax,use adam with lr rate 0.001\n 2. I train the UNET with 320*320 patch.\n 3. I don't train the unet with patches without sealions in first 40 epochs.Then I predict the patches without sealions,I use those patches which have False-Positive samples for 5 epochs.(Sample 10000 of them every epochs)<br>\n<br>\nAnd I trained a resnet-50 UNET,but I found it ok too,but I have no time to use it.",
    "197099": "Thanks.Yes,perhaps,we under-estimated the UNET,labeling the sealions is not the hardest part of this competition.",
    "197101": "thanks,if we can get the more information(for example,height or zoom of the images taken),then we can calibrate the image to same resolution and the result will be much better,although  we can calibrate by area of the adult males,perhaps.",
    "197107": "Wonderful solution. I had asked myself if UNET was able to this job, when i had contact with them on Data science Bowl. I was nowhere near of implementing something like this. Congratulations",
    "197108": "",
    "197131": "Congratulations Bestfitting\n\nNice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.",
    "197132": "Congratulations Bestfitting\n\nNice :) --&gt;&gt; generated the mask by set the value of the mask to 255 at the center of the sealions,and then the decrease to 255*0.8,255*0.6,255*0.4 as the position go far away from the center.\n\nGood luck on planet !",
    "197203": "Thanks for sharing, the predict outline looks amazing.",
    "197292": "Thanks for sharing, sorry, I can't understand for that the second u-net have 6-way softmax regression, why is not 5-way?",
    "197316": "Congratulations! Very cool idea with mask generation!",
    "197320": "Thanks ! that was really helpful.",
    "197371": "bestfitting:\nIn your step by step outline labeling, did you start with squares, bounding boxes or polygons ? can you please give more details on how you correct the masks ?",
    "197640": "Thanks!<br>I got the idea when I was watching an TV program about the galaxies ,stars and planets...:)",
    "197644": "Thanks,I read a lot of papers related and checked different structures and found the UNET is so powerfule.",
    "197647": "JuGL,we have 5 types of sealions and we should add a type to indicate there is no sealion on that pixel.",
    "197648": "thanks",
    "197650": "I did not find a good tool to label image ,so I used GIMP to label the sealions.I added layer on train set images,and extracted the mask from new layer using GIMP python APIs.",
    "197652": "I also read solutions of the Data science Bowl,they are very good.You can get very useful information from them and implement your net.",
    "197654": "how do you set label for the added type",
    "197659": "The label is 320*320*6<br>\n0:background 1:adult-males 2:subadult-males...5:pups",
    "198014": "Congratulations! So glad to see such a rigorous and insightful approach!",
    "198501": "Congratulations and thanks for taking the time to explain your approach! May I ask how you made the outlines of the images 4 to 100? Did you make an annotating software or did you use something existing? I am asking because I ran out of time with a similar approach and would really like to know if there is a faster way to draw outlines... :)",
    "198576": "kglspl,I selected the images easy to fit (with no complex background and having a lot of sealions),they were cutted into a lot of 320*320 small images to input to unet.Then I predicted similar images(easy to fit) and did it iterately.<br>\nAs to mask tools,I just used GIMP and added layers to it,then I  read the mask layers via GIMP python api .I think the solution is ok.",
    "198577": "thanks"
  },
  "source": "meta"
}