{
  "id": 71659,
  "title": "11th place solution",
  "url": "/competitions/airbus-ship-detection/discussion/71659",
  "author_name": "Igor Praznik",
  "post_date": "2018-11-15T11:59:03.442000",
  "votes": 37,
  "comment_count": 10,
  "views": 0,
  "content": "<p>First of all congratulations to the winners!</p>\n\n<p><strong>Data</strong></p>\n\n<p>The main challenge of this completion, from my point of view, was very unbalanced data for ship/no ship, split/no split cases, very different types of images from distance, quality etc point of view.</p>\n\n<p>For the training I took only images with ships from the training set and created two types of labels for them to prepare the separating of close ships:</p>\n\n<ul>\n<li>full ship contours</li>\n<li>only separation line</li>\n</ul>\n\n<p>one channel for body, one contour or split</p>\n\n<p>Examples:\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10682/c_edec35a72.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10683/c_52554d6ee.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10680/s_edec35a72.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10681/s_52554d6ee.png\" alt=\"enter image description here\"></p>\n\n<p>On the beginning I used only split masks, but there were too few training images where the splitting needed and the model trained not so well. In final models I used only contour labels, but may be better idea would be to use both in different channels to improve the quality of the splitting. </p>\n\n<p><strong>Model</strong></p>\n\n<p><strong>Classification (ship/no ship)</strong></p>\n\n<p>First result of segmentation was not so good, as there were a lot of FP, mostly clouds and waves on empty images. As there were much more empty images than images with ships, I’ve decided to train a simple classifier for the first phase and use segmentation model only for images with ships in the second phase.</p>\n\n<p><strong>Segmentation</strong></p>\n\n<p>Encoder: Resnet34, se_resnext50</p>\n\n<p>Decoder: hypercolumn, scSE, classification-based attention</p>\n\n<p><strong>Training image augmentation</strong></p>\n\n<p>From imgaug I used: flips(horizontal and vertical), \nPerspectiveTransform, CropAndPad, Affine(scale, translate_percent, rotate, shear), \nOne of (ContrastNormalization, Color(Multiply, Grayscale))\nOne of (GaussianBlur, AverageBlur, MedianBlur, BilateralBlur, AdditiveGaussianNoise, ElasticTransformation)</p>\n\n<p><strong>Training</strong></p>\n\n<p>Optimizer: Adam </p>\n\n<p>Loss function: Lovasz(elu+1)</p>\n\n<p>step1 30-60 epoch (with reduce on plateau)\nstep2 10-20 epoch fine tuning with smaller LR</p>\n\n<p>9/10 images were used for training, 1/10 for validation. </p>\n\n<p>StratifiedKFold was used to split folds by ship size, close ships.</p>\n\n<p>The training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.</p>\n\n<p>The validation was done on full size images.</p>\n\n<p><strong>TTA</strong></p>\n\n<p>Original image + vflip+hflip</p>\n\n<p><strong>Postprocessing</strong></p>\n\n<p>The watershed was used to split the labels</p>\n\n<p><strong>Final ensemble</strong></p>\n\n<p>The local validation score for se_resnext50 based models was much better, than Resnet34, but on public LB vice versa. Looks like better encoder se_resnext50 just overfitted on the this data for me.</p>\n\n<p>The final score is a simple average of 3 x Resnet34 and 1 x se_resnext50.</p>\n\n<p><strong>Hardware</strong></p>\n\n<p>1 x 1080Ti</p>\n\n<p><strong>Software</strong></p>\n\n<p>Before the leak break I was using Keras, but during the TGS Salt moved to pytorch. Final models are only pytorch.</p>\n\n<p><strong>Did not work for me</strong></p>\n\n<p>In the postprocessing I tried to do the labels “more rectangle”, but it made the score only worse.</p>\n\n<p><strong>Should try</strong></p>\n\n<p>Another heavier encoders, like dpn, densenet, with more augmentations against overfitting. </p>",
  "messages": [
    {
      "id": 421773,
      "postDate": "2018-11-15T11:59:03.443Z",
      "content": "<p>First of all congratulations to the winners!</p>\n\n<p><strong>Data</strong></p>\n\n<p>The main challenge of this completion, from my point of view, was very unbalanced data for ship/no ship, split/no split cases, very different types of images from distance, quality etc point of view.</p>\n\n<p>For the training I took only images with ships from the training set and created two types of labels for them to prepare the separating of close ships:</p>\n\n<ul>\n<li>full ship contours</li>\n<li>only separation line</li>\n</ul>\n\n<p>one channel for body, one contour or split</p>\n\n<p>Examples:\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10682/c_edec35a72.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10683/c_52554d6ee.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10680/s_edec35a72.png\" alt=\"enter image description here\">\n<img src=\"https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10681/s_52554d6ee.png\" alt=\"enter image description here\"></p>\n\n<p>On the beginning I used only split masks, but there were too few training images where the splitting needed and the model trained not so well. In final models I used only contour labels, but may be better idea would be to use both in different channels to improve the quality of the splitting. </p>\n\n<p><strong>Model</strong></p>\n\n<p><strong>Classification (ship/no ship)</strong></p>\n\n<p>First result of segmentation was not so good, as there were a lot of FP, mostly clouds and waves on empty images. As there were much more empty images than images with ships, I’ve decided to train a simple classifier for the first phase and use segmentation model only for images with ships in the second phase.</p>\n\n<p><strong>Segmentation</strong></p>\n\n<p>Encoder: Resnet34, se_resnext50</p>\n\n<p>Decoder: hypercolumn, scSE, classification-based attention</p>\n\n<p><strong>Training image augmentation</strong></p>\n\n<p>From imgaug I used: flips(horizontal and vertical), \nPerspectiveTransform, CropAndPad, Affine(scale, translate_percent, rotate, shear), \nOne of (ContrastNormalization, Color(Multiply, Grayscale))\nOne of (GaussianBlur, AverageBlur, MedianBlur, BilateralBlur, AdditiveGaussianNoise, ElasticTransformation)</p>\n\n<p><strong>Training</strong></p>\n\n<p>Optimizer: Adam </p>\n\n<p>Loss function: Lovasz(elu+1)</p>\n\n<p>step1 30-60 epoch (with reduce on plateau)\nstep2 10-20 epoch fine tuning with smaller LR</p>\n\n<p>9/10 images were used for training, 1/10 for validation. </p>\n\n<p>StratifiedKFold was used to split folds by ship size, close ships.</p>\n\n<p>The training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.</p>\n\n<p>The validation was done on full size images.</p>\n\n<p><strong>TTA</strong></p>\n\n<p>Original image + vflip+hflip</p>\n\n<p><strong>Postprocessing</strong></p>\n\n<p>The watershed was used to split the labels</p>\n\n<p><strong>Final ensemble</strong></p>\n\n<p>The local validation score for se_resnext50 based models was much better, than Resnet34, but on public LB vice versa. Looks like better encoder se_resnext50 just overfitted on the this data for me.</p>\n\n<p>The final score is a simple average of 3 x Resnet34 and 1 x se_resnext50.</p>\n\n<p><strong>Hardware</strong></p>\n\n<p>1 x 1080Ti</p>\n\n<p><strong>Software</strong></p>\n\n<p>Before the leak break I was using Keras, but during the TGS Salt moved to pytorch. Final models are only pytorch.</p>\n\n<p><strong>Did not work for me</strong></p>\n\n<p>In the postprocessing I tried to do the labels “more rectangle”, but it made the score only worse.</p>\n\n<p><strong>Should try</strong></p>\n\n<p>Another heavier encoders, like dpn, densenet, with more augmentations against overfitting. </p>",
      "rawMarkdown": "First of all congratulations to the winners!\n\n**Data**\n\nThe main challenge of this completion, from my point of view, was very unbalanced data for ship/no ship, split/no split cases, very different types of images from distance, quality etc point of view.\n\nFor the training I took only images with ships from the training set and created two types of labels for them to prepare the separating of close ships:\n\n* full ship contours\n* only separation line\n\none channel for body, one contour or split\n\nExamples:\n![enter image description here][1]\n![enter image description here][2]\n![enter image description here][3]\n![enter image description here][4]\n\nOn the beginning I used only split masks, but there were too few training images where the splitting needed and the model trained not so well. In final models I used only contour labels, but may be better idea would be to use both in different channels to improve the quality of the splitting. \n\n**Model**\n\n**Classification (ship/no ship)**\n\nFirst result of segmentation was not so good, as there were a lot of FP, mostly clouds and waves on empty images. As there were much more empty images than images with ships, I’ve decided to train a simple classifier for the first phase and use segmentation model only for images with ships in the second phase.\n\n**Segmentation**\n\nEncoder: Resnet34, se_resnext50\n\nDecoder: hypercolumn, scSE, classification-based attention\n\n**Training image augmentation**\n\nFrom imgaug I used: flips(horizontal and vertical), \nPerspectiveTransform, CropAndPad, Affine(scale, translate_percent, rotate, shear), \nOne of (ContrastNormalization, Color(Multiply, Grayscale))\nOne of (GaussianBlur, AverageBlur, MedianBlur, BilateralBlur, AdditiveGaussianNoise, ElasticTransformation)\n\n**Training**\n\nOptimizer: Adam \n\nLoss function: Lovasz(elu+1)\n\nstep1 30-60 epoch (with reduce on plateau)\nstep2 10-20 epoch fine tuning with smaller LR\n\n9/10 images were used for training, 1/10 for validation. \n\nStratifiedKFold was used to split folds by ship size, close ships.\n\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\n\nThe validation was done on full size images.\n\n**TTA**\n\nOriginal image + vflip+hflip\n\n**Postprocessing**\n\nThe watershed was used to split the labels\n\n**Final ensemble**\n\nThe local validation score for se_resnext50 based models was much better, than Resnet34, but on public LB vice versa. Looks like better encoder se_resnext50 just overfitted on the this data for me.\n\nThe final score is a simple average of 3 x Resnet34 and 1 x se_resnext50.\n\n**Hardware**\n\n1 x 1080Ti\n\n**Software**\n\nBefore the leak break I was using Keras, but during the TGS Salt moved to pytorch. Final models are only pytorch.\n\n**Did not work for me**\n\nIn the postprocessing I tried to do the labels “more rectangle”, but it made the score only worse.\n\n**Should try**\n\nAnother heavier encoders, like dpn, densenet, with more augmentations against overfitting. \n\n\n  [1]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10682/c_edec35a72.png\n  [2]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10683/c_52554d6ee.png\n  [3]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10680/s_edec35a72.png\n  [4]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10681/s_52554d6ee.png",
      "votes": 37
    },
    {
      "id": 421780,
      "postDate": "2018-11-15T12:10:22.880Z",
      "content": "<p>Thanks for sharing your solution. Would you mind sharing your pytorch code for this solution? Thanks!</p>",
      "rawMarkdown": "Thanks for sharing your solution. Would you mind sharing your pytorch code for this solution? Thanks!",
      "votes": 12,
      "replies": [
        {
          "id": 421858,
          "postDate": "2018-11-15T14:02:52.193Z",
          "content": "<p>will try to clean up and share in next days</p>",
          "rawMarkdown": "will try to clean up and share in next days",
          "votes": 2
        },
        {
          "id": 422049,
          "postDate": "2018-11-15T18:08:54.223Z",
          "content": "<p>yes m curious to see how ensemble the models predictions.....as i havent done this before....</p>",
          "rawMarkdown": "yes m curious to see how ensemble the models predictions.....as i havent done this before...."
        },
        {
          "id": 457548,
          "postDate": "2019-01-17T17:04:21.147Z",
          "content": "<p>Can you share your code?</p>",
          "rawMarkdown": "Can you share your code?"
        }
      ]
    },
    {
      "id": 427685,
      "postDate": "2018-11-26T00:32:22.403Z",
      "content": "<p>Congrats <a href=\"/praznik\">@praznik</a>, and thanks for sharing.</p>",
      "rawMarkdown": "Congrats @praznik, and thanks for sharing."
    },
    {
      "id": 422010,
      "postDate": "2018-11-15T17:06:12.407Z",
      "content": "<p>very nice.. congrats for your top 11 position....\ni had question\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\nHow we can be ensured ship was getting captured in this size...if you end up taking up blank you will get to more loss..\nlet me know if my understanding is correct..</p>",
      "rawMarkdown": "very nice.. congrats for your top 11 position....\ni had question\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\nHow we can be ensured ship was getting captured in this size...if you end up taking up blank you will get to more loss..\nlet me know if my understanding is correct..\n",
      "replies": [
        {
          "id": 422552,
          "postDate": "2018-11-16T11:53:52.173Z",
          "content": "<p>the best way is to use a full size image, but the traing could be too slow. The size of the crop is the compromise between speed of training, batch size, GPU memory and amount of information for the model to train. Even if there will be only a part of the ship, it will be stiil usefull for the model to train, as it trains on the pixel basis and there are also original images only with parts of ships. If there is a crop without ships, it's still good for the model to train negative case, to avoid false positives, but it's important to provide enough various data for model to train, balance positive and negative cases. This is why in some cases I calculate the centers of ships and crop aroun them, to have for most cases at least parts of ships.</p>\n\n<p>The label image is also cropped by given coordinates and the loss is calculated for crops as well.</p>",
          "rawMarkdown": "the best way is to use a full size image, but the traing could be too slow. The size of the crop is the compromise between speed of training, batch size, GPU memory and amount of information for the model to train. Even if there will be only a part of the ship, it will be stiil usefull for the model to train, as it trains on the pixel basis and there are also original images only with parts of ships. If there is a crop without ships, it's still good for the model to train negative case, to avoid false positives, but it's important to provide enough various data for model to train, balance positive and negative cases. This is why in some cases I calculate the centers of ships and crop aroun them, to have for most cases at least parts of ships.\n\nThe label image is also cropped by given coordinates and the loss is calculated for crops as well.",
          "votes": 1
        }
      ]
    },
    {
      "id": 421955,
      "postDate": "2018-11-15T15:52:37.590Z",
      "content": "<p>Congratulations. Great and clean work.</p>",
      "rawMarkdown": "Congratulations. Great and clean work."
    },
    {
      "id": 421917,
      "postDate": "2018-11-15T15:06:17.320Z",
      "content": "<p>Congrats and many thanks to your shared solutions!</p>",
      "rawMarkdown": "Congrats and many thanks to your shared solutions!"
    },
    {
      "id": 423226,
      "postDate": "2018-11-17T18:15:43.837Z",
      "rawMarkdown": "",
      "votes": 7,
      "isDeleted": true
    }
  ],
  "comments": [
    {
      "id": 421780,
      "author_name": "",
      "author_url": "",
      "post_date": "2018-11-15T12:10:22.880000",
      "content": "<p>Thanks for sharing your solution. Would you mind sharing your pytorch code for this solution? Thanks!</p>",
      "votes": 12,
      "replies": [
        {
          "id": 421858,
          "author_name": "Igor Praznik",
          "author_url": "",
          "post_date": "2018-11-15T14:02:52.193000",
          "content": "<p>will try to clean up and share in next days</p>",
          "votes": 2,
          "replies": []
        },
        {
          "id": 422049,
          "author_name": "Jaideep",
          "author_url": "",
          "post_date": "2018-11-15T18:08:54.223000",
          "content": "<p>yes m curious to see how ensemble the models predictions.....as i havent done this before....</p>",
          "votes": 0,
          "replies": []
        },
        {
          "id": 457548,
          "author_name": "QiWei",
          "author_url": "",
          "post_date": "2019-01-17T17:04:21.147000",
          "content": "<p>Can you share your code?</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 427685,
      "author_name": "YaGana Sheriff-Hussaini",
      "author_url": "",
      "post_date": "2018-11-26T00:32:22.403000",
      "content": "<p>Congrats <a href=\"/praznik\">@praznik</a>, and thanks for sharing.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 422010,
      "author_name": "Jaideep",
      "author_url": "",
      "post_date": "2018-11-15T17:06:12.407000",
      "content": "<p>very nice.. congrats for your top 11 position....\ni had question\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\nHow we can be ensured ship was getting captured in this size...if you end up taking up blank you will get to more loss..\nlet me know if my understanding is correct..</p>",
      "votes": 0,
      "replies": [
        {
          "id": 422552,
          "author_name": "Igor Praznik",
          "author_url": "",
          "post_date": "2018-11-16T11:53:52.173000",
          "content": "<p>the best way is to use a full size image, but the traing could be too slow. The size of the crop is the compromise between speed of training, batch size, GPU memory and amount of information for the model to train. Even if there will be only a part of the ship, it will be stiil usefull for the model to train, as it trains on the pixel basis and there are also original images only with parts of ships. If there is a crop without ships, it's still good for the model to train negative case, to avoid false positives, but it's important to provide enough various data for model to train, balance positive and negative cases. This is why in some cases I calculate the centers of ships and crop aroun them, to have for most cases at least parts of ships.</p>\n\n<p>The label image is also cropped by given coordinates and the loss is calculated for crops as well.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 421955,
      "author_name": "Mohammad Azam Khan",
      "author_url": "",
      "post_date": "2018-11-15T15:52:37.590000",
      "content": "<p>Congratulations. Great and clean work.</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 421917,
      "author_name": "wsdgh",
      "author_url": "",
      "post_date": "2018-11-15T15:06:17.320000",
      "content": "<p>Congrats and many thanks to your shared solutions!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 423226,
      "author_name": "",
      "author_url": "",
      "post_date": "2018-11-17T18:15:43.837000",
      "content": "",
      "votes": 7,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "421773": "First of all congratulations to the winners!\n\n**Data**\n\nThe main challenge of this completion, from my point of view, was very unbalanced data for ship/no ship, split/no split cases, very different types of images from distance, quality etc point of view.\n\nFor the training I took only images with ships from the training set and created two types of labels for them to prepare the separating of close ships:\n\n* full ship contours\n* only separation line\n\none channel for body, one contour or split\n\nExamples:\n![enter image description here][1]\n![enter image description here][2]\n![enter image description here][3]\n![enter image description here][4]\n\nOn the beginning I used only split masks, but there were too few training images where the splitting needed and the model trained not so well. In final models I used only contour labels, but may be better idea would be to use both in different channels to improve the quality of the splitting. \n\n**Model**\n\n**Classification (ship/no ship)**\n\nFirst result of segmentation was not so good, as there were a lot of FP, mostly clouds and waves on empty images. As there were much more empty images than images with ships, I’ve decided to train a simple classifier for the first phase and use segmentation model only for images with ships in the second phase.\n\n**Segmentation**\n\nEncoder: Resnet34, se_resnext50\n\nDecoder: hypercolumn, scSE, classification-based attention\n\n**Training image augmentation**\n\nFrom imgaug I used: flips(horizontal and vertical), \nPerspectiveTransform, CropAndPad, Affine(scale, translate_percent, rotate, shear), \nOne of (ContrastNormalization, Color(Multiply, Grayscale))\nOne of (GaussianBlur, AverageBlur, MedianBlur, BilateralBlur, AdditiveGaussianNoise, ElasticTransformation)\n\n**Training**\n\nOptimizer: Adam \n\nLoss function: Lovasz(elu+1)\n\nstep1 30-60 epoch (with reduce on plateau)\nstep2 10-20 epoch fine tuning with smaller LR\n\n9/10 images were used for training, 1/10 for validation. \n\nStratifiedKFold was used to split folds by ship size, close ships.\n\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\n\nThe validation was done on full size images.\n\n**TTA**\n\nOriginal image + vflip+hflip\n\n**Postprocessing**\n\nThe watershed was used to split the labels\n\n**Final ensemble**\n\nThe local validation score for se_resnext50 based models was much better, than Resnet34, but on public LB vice versa. Looks like better encoder se_resnext50 just overfitted on the this data for me.\n\nThe final score is a simple average of 3 x Resnet34 and 1 x se_resnext50.\n\n**Hardware**\n\n1 x 1080Ti\n\n**Software**\n\nBefore the leak break I was using Keras, but during the TGS Salt moved to pytorch. Final models are only pytorch.\n\n**Did not work for me**\n\nIn the postprocessing I tried to do the labels “more rectangle”, but it made the score only worse.\n\n**Should try**\n\nAnother heavier encoders, like dpn, densenet, with more augmentations against overfitting. \n\n\n  [1]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10682/c_edec35a72.png\n  [2]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10683/c_52554d6ee.png\n  [3]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10680/s_edec35a72.png\n  [4]: https://storage.googleapis.com/kaggle-forum-message-attachments/421773/10681/s_52554d6ee.png",
    "421780": "Thanks for sharing your solution. Would you mind sharing your pytorch code for this solution? Thanks!",
    "427685": "Congrats @praznik, and thanks for sharing.",
    "422010": "very nice.. congrats for your top 11 position....\ni had question\nThe training was running on the crops 224x224. Every batch was the mix of random crops around the centers of ships and totally random crops.\nHow we can be ensured ship was getting captured in this size...if you end up taking up blank you will get to more loss..\nlet me know if my understanding is correct..\n",
    "421955": "Congratulations. Great and clean work.",
    "421917": "Congrats and many thanks to your shared solutions!",
    "423226": ""
  }
}