{
  "id": 238862,
  "title": "3rd place solution - MPWARE part",
  "url": "/competitions/hpa-single-cell-image-classification/discussion/238862",
  "author_name": "MPWARE",
  "post_date": "2021-05-13T17:11:21.455000",
  "votes": 43,
  "comment_count": 14,
  "views": 0,
  "content": "<p>First of all I would like to thank the host for this really interesting competition and also for the accurate answers to questions in the forum. High quality data provided is something I would like to highlight too. I would like to warmly thank my teammates <a href=\"https://www.kaggle.com/zfturbo\" target=\"_blank\">@zfturbo</a> and <a href=\"https://www.kaggle.com/christofhenkel\" target=\"_blank\">@christofhenkel</a> for the great collaboration, firework of ideas and their patience with me.</p>\n<p>Our solution is an ensemble of different independant models. Hereafter my part.</p>\n<h1>Introduction</h1>\n<p>Early in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) <a href=\"https://paperswithcode.com/sota/weakly-supervised-semantic-segmentation-on\" target=\"_blank\">SOA</a> approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest.  However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both <a href=\"https://arxiv.org/pdf/2101.11253.pdf\" target=\"_blank\">Puzzle-CAM</a> [1] and <a href=\"https://arxiv.org/pdf/2103.07246.pdf\" target=\"_blank\">DRS</a> (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble). </p>\n<p>I teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.</p>\n<p>Close to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone. </p>\n<h1>Training</h1>\n<p>Siamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps. </p>\n<p><strong>Pipeline:</strong></p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\" alt=\"Model\"></p>\n<p><em>Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.</em></p>\n<p><strong>Augmentations:</strong></p>\n<p>Simple augmentations that apply to RGBY images:</p>\n<ul>\n<li>Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise</li>\n<li>Flips/Rotations: HorizontalFlip, RandomRotate90</li>\n<li>Rotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear</li>\n<li>Blurs: GaussianBlur, MotionBlur, MedianBlur</li>\n<li>Colors: RandomGamma, RandomBrightnessContrast</li>\n</ul>\n<p><strong>Sampling strategy:</strong></p>\n<p>Classes distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\" alt=\"Distribution\"></p>\n<p>A weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).</p>\n<p><strong>Data:</strong></p>\n<p>Train set and external data had been used to train different model variants:</p>\n<ul>\n<li>89k images: Train set + External public data shared by host</li>\n<li>98k images: Train set + External public data shared by host + HPA 2018</li>\n</ul>\n<p>Each single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.</p>\n<p>External data was key for this competition to increase volume and make models better.</p>\n<p><strong>Cross validation:</strong></p>\n<p>Train dataset is split in 4 folds with a <a href=\"https://github.com/trent-b/iterative-stratification\" target=\"_blank\">MultilabelStratifiedKFold</a> strategy.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\" alt=\"CV\"></p>\n<p><strong>Training procedure:</strong></p>\n<p>4 main models trained with different <a href=\"https://github.com/rwightman/pytorch-image-models\" target=\"_blank\">backbones</a> (but only variants of #1 in the final ensemble).</p>\n<ol>\n<li>seresnext50_32x4d</li>\n<li>gluon_seresnext101_32x4d, </li>\n<li>cspresnext50</li>\n<li>regnety_64</li>\n</ol>\n<p>Weighted ComboLoss:</p>\n<ul>\n<li>BCEWithLogitsLoss (each with weight=1.0)</li>\n<li>L1Loss (weight from 0.25 to 0.5 got good results)</li>\n</ul>\n<p>LR and hyperparameters:</p>\n<ul>\n<li>Optimizer: Adam, LR= 0.0003, beta1=0.9</li>\n<li>LR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8</li>\n<li>Epochs: 48</li>\n<li>Batch size: From 32 to 36</li>\n<li>FP16 enabled</li>\n<li>Single cycle</li>\n</ul>\n<p>Criteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\" alt=\"CV\"></p>\n<h1>Inference</h1>\n<p>Inference is based on two stages ensembled at the end. </p>\n<p><strong>Stage #1:</strong></p>\n<p>It’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\" alt=\"stage1\"></p>\n<p>Note: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.</p>\n<p><strong>Stage #2:</strong></p>\n<p>It is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070737945441.png\" alt=\"stage2\"></p>\n<p>Stage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.</p>\n<p>From a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.</p>\n<h1>Misc</h1>\n<p><strong>What could be improved?</strong></p>\n<p>DRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.</p>\n<p><strong>What did not work (or not better than this solution)?</strong></p>\n<ul>\n<li>YoloV5 model based on OOF and RGB image</li>\n<li>Post process probabilities to move to rank probabilities on ensemble</li>\n<li>TTA (it worked indeed but gave tiny improvement) </li>\n<li>Larger full image</li>\n</ul>\n<p><strong>Update</strong>: Source code available: <a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
  "messages": [
    {
      "id": 1306225,
      "postDate": "2021-05-13T17:11:21.457Z",
      "content": "<p>First of all I would like to thank the host for this really interesting competition and also for the accurate answers to questions in the forum. High quality data provided is something I would like to highlight too. I would like to warmly thank my teammates <a href=\"https://www.kaggle.com/zfturbo\" target=\"_blank\">@zfturbo</a> and <a href=\"https://www.kaggle.com/christofhenkel\" target=\"_blank\">@christofhenkel</a> for the great collaboration, firework of ideas and their patience with me.</p>\n<p>Our solution is an ensemble of different independant models. Hereafter my part.</p>\n<h1>Introduction</h1>\n<p>Early in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) <a href=\"https://paperswithcode.com/sota/weakly-supervised-semantic-segmentation-on\" target=\"_blank\">SOA</a> approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest.  However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both <a href=\"https://arxiv.org/pdf/2101.11253.pdf\" target=\"_blank\">Puzzle-CAM</a> [1] and <a href=\"https://arxiv.org/pdf/2103.07246.pdf\" target=\"_blank\">DRS</a> (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble). </p>\n<p>I teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.</p>\n<p>Close to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone. </p>\n<h1>Training</h1>\n<p>Siamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps. </p>\n<p><strong>Pipeline:</strong></p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\" alt=\"Model\"></p>\n<p><em>Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.</em></p>\n<p><strong>Augmentations:</strong></p>\n<p>Simple augmentations that apply to RGBY images:</p>\n<ul>\n<li>Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise</li>\n<li>Flips/Rotations: HorizontalFlip, RandomRotate90</li>\n<li>Rotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear</li>\n<li>Blurs: GaussianBlur, MotionBlur, MedianBlur</li>\n<li>Colors: RandomGamma, RandomBrightnessContrast</li>\n</ul>\n<p><strong>Sampling strategy:</strong></p>\n<p>Classes distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\" alt=\"Distribution\"></p>\n<p>A weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).</p>\n<p><strong>Data:</strong></p>\n<p>Train set and external data had been used to train different model variants:</p>\n<ul>\n<li>89k images: Train set + External public data shared by host</li>\n<li>98k images: Train set + External public data shared by host + HPA 2018</li>\n</ul>\n<p>Each single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.</p>\n<p>External data was key for this competition to increase volume and make models better.</p>\n<p><strong>Cross validation:</strong></p>\n<p>Train dataset is split in 4 folds with a <a href=\"https://github.com/trent-b/iterative-stratification\" target=\"_blank\">MultilabelStratifiedKFold</a> strategy.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\" alt=\"CV\"></p>\n<p><strong>Training procedure:</strong></p>\n<p>4 main models trained with different <a href=\"https://github.com/rwightman/pytorch-image-models\" target=\"_blank\">backbones</a> (but only variants of #1 in the final ensemble).</p>\n<ol>\n<li>seresnext50_32x4d</li>\n<li>gluon_seresnext101_32x4d, </li>\n<li>cspresnext50</li>\n<li>regnety_64</li>\n</ol>\n<p>Weighted ComboLoss:</p>\n<ul>\n<li>BCEWithLogitsLoss (each with weight=1.0)</li>\n<li>L1Loss (weight from 0.25 to 0.5 got good results)</li>\n</ul>\n<p>LR and hyperparameters:</p>\n<ul>\n<li>Optimizer: Adam, LR= 0.0003, beta1=0.9</li>\n<li>LR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8</li>\n<li>Epochs: 48</li>\n<li>Batch size: From 32 to 36</li>\n<li>FP16 enabled</li>\n<li>Single cycle</li>\n</ul>\n<p>Criteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\" alt=\"CV\"></p>\n<h1>Inference</h1>\n<p>Inference is based on two stages ensembled at the end. </p>\n<p><strong>Stage #1:</strong></p>\n<p>It’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\" alt=\"stage1\"></p>\n<p>Note: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.</p>\n<p><strong>Stage #2:</strong></p>\n<p>It is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.</p>\n<p><img src=\"https://nsa40.casimages.com/img/2021/05/13/210513070737945441.png\" alt=\"stage2\"></p>\n<p>Stage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.</p>\n<p>From a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.</p>\n<h1>Misc</h1>\n<p><strong>What could be improved?</strong></p>\n<p>DRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.</p>\n<p><strong>What did not work (or not better than this solution)?</strong></p>\n<ul>\n<li>YoloV5 model based on OOF and RGB image</li>\n<li>Post process probabilities to move to rank probabilities on ensemble</li>\n<li>TTA (it worked indeed but gave tiny improvement) </li>\n<li>Larger full image</li>\n</ul>\n<p><strong>Update</strong>: Source code available: <a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
      "rawMarkdown": "First of all I would like to thank the host for this really interesting competition and also for the accurate answers to questions in the forum. High quality data provided is something I would like to highlight too. I would like to warmly thank my teammates @zfturbo and @christofhenkel for the great collaboration, firework of ideas and their patience with me.\n\nOur solution is an ensemble of different independant models. Hereafter my part.\n\n# Introduction\n\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) [SOA](https://paperswithcode.com/sota/weakly-supervised-semantic-segmentation-on) approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest.  However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both [Puzzle-CAM](https://arxiv.org/pdf/2101.11253.pdf) [1] and [DRS](https://arxiv.org/pdf/2103.07246.pdf) (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble). \n\nI teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.\n\nClose to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone. \n\n\n# Training\n\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps. \n\n**Pipeline:**\n\n![Model](https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png)\n\n_Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency._\n\n**Augmentations:**\n\nSimple augmentations that apply to RGBY images:\n\n\n\n*   Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise\n*   Flips/Rotations: HorizontalFlip, RandomRotate90\n*   Rotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear\n*   Blurs: GaussianBlur, MotionBlur, MedianBlur\n*   Colors: RandomGamma, RandomBrightnessContrast\n\n**Sampling strategy:**\n\nClasses distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.\n\n\n\n\n![Distribution](https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png)\n\n\nA weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).\n\n**Data:**\n\nTrain set and external data had been used to train different model variants:\n\n\n\n*   89k images: Train set + External public data shared by host\n*   98k images: Train set + External public data shared by host + HPA 2018\n\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.\n\nExternal data was key for this competition to increase volume and make models better.\n\n**Cross validation:**\n\nTrain dataset is split in 4 folds with a [MultilabelStratifiedKFold](https://github.com/trent-b/iterative-stratification) strategy.\n\n\n\n![CV](https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png)\n\n\n**Training procedure:**\n\n4 main models trained with different [backbones](https://github.com/rwightman/pytorch-image-models) (but only variants of #1 in the final ensemble).\n\n\n\n1. seresnext50_32x4d\n2. gluon_seresnext101_32x4d, \n3. cspresnext50\n4. regnety_64\n\nWeighted ComboLoss:\n\n\n\n*   BCEWithLogitsLoss (each with weight=1.0)\n*   L1Loss (weight from 0.25 to 0.5 got good results)\n\nLR and hyperparameters:\n\n\n\n*   Optimizer: Adam, LR= 0.0003, beta1=0.9\n*   LR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8\n*   Epochs: 48\n*   Batch size: From 32 to 36\n*   FP16 enabled\n*   Single cycle\n\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:\n\n\n\n![CV](https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png)\n\n\n\n\n\n# Inference\n\nInference is based on two stages ensembled at the end. \n\n**Stage #1:**\n\nIt’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.\n\n\n\n![stage1](https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png)\n\n\n<span style=\"text-decoration:underline;\">Note</span>: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.\n\n**Stage #2:**\n\nIt is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.\n\n\n\n![stage2](https://nsa40.casimages.com/img/2021/05/13/210513070737945441.png)\n\n\nStage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.\n\nFrom a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.\n\n\n# Misc\n\n**What could be improved?**\n\nDRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.\n\n**What did not work (or not better than this solution)?**\n\n\n\n*   YoloV5 model based on OOF and RGB image\n*   Post process probabilities to move to rank probabilities on ensemble\n*   TTA (it worked indeed but gave tiny improvement) \n*   Larger full image\n\n**Update**: Source code available: https://github.com/MPWARE-TEAM/HPA2021",
      "votes": 43
    },
    {
      "id": 1610746,
      "postDate": "2021-12-07T13:44:32.993Z",
      "content": "<p>日本語訳</p>\n<p>Introduction<br>\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) SOA approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest. However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both Puzzle-CAM [1] and DRS (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble).</p>\n<p>I teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.</p>\n<p>Close to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone.<br>\nこのコンテストの早い段階で、新しいことを学ぶためにWSSS（弱教師ありセマンティックセグメンテーション）SOAアプローチから始めることにしました。 マルチラベルを使用した完全な画像トレーニングとセグメンテーションの構築を試みます。 多くのソリューションはCAMの使用率に基づいています。 つまり、パイプラインの最後で、CAMを成長させ、関心領域の画像全体に広げます。 ただし、セルマスクはすでに利用可能であったため、完全なWSSSプロセスを実行する必要はなく、予測されたラベルを取得するために、ある時点でCAMとセルを交差させるだけで済みました。 私はPuzzle-CAM [1]とDRS（Discriminative Region Suppression）[2]の両方のアプローチを試しました。 私はついに、RGBY画像でトレーニングされた修正されたPuzzle-CAMと2段階の推論（完全な画像とセルごとの基本的なアンサンブル）で最良の結果を得ました。</p>\n<p>私は早い段階で、異なるアプローチを使用したZFturboとチームを組み、両方のソリューションが非常にうまく調和しました。 改善する次のステップは、ZFTurboのモデルに利益をもたらす可能性のある私の最高のモデルバリアントのいくつかから（各クラスのセル予測ごとに）OOFを生成し、次にアンサンブルに生成することでした。</p>\n<p>競争の終わり近くに、推論の余地があり（パイプラインは約6時間30分で実行されていました）、新しいモデルを統合することが役立つはずであることに同意し、新しいモデル/アイデアをもたらしたディーターと合併して、 マネーゾーン。<br>\nTraining<br>\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps.</p>\n<p>Pipeline:</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png</a></p>\n<p>Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.</p>\n<p>Augmentations:</p>\n<p>Simple augmentations that apply to RGBY images:</p>\n<p>Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise<br>\nFlips/Rotations: HorizontalFlip, RandomRotate90<br>\nRotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear<br>\nBlurs: GaussianBlur, MotionBlur, MedianBlur<br>\nColors: RandomGamma, RandomBrightnessContrast<br>\nSampling strategy:</p>\n<p>Classes distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png</a></p>\n<p>A weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).</p>\n<p>Data:</p>\n<p>Train set and external data had been used to train different model variants:</p>\n<p>89k images: Train set + External public data shared by host<br>\n98k images: Train set + External public data shared by host + HPA 2018<br>\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.</p>\n<p>External data was key for this competition to increase volume and make models better.</p>\n<p>Cross validation:</p>\n<p>Train dataset is split in 4 folds with a MultilabelStratifiedKFold strategy.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png</a></p>\n<p>Training procedure:</p>\n<p>4 main models trained with different backbones (but only variants of #1 in the final ensemble).</p>\n<p>seresnext50_32x4d<br>\ngluon_seresnext101_32x4d,<br>\ncspresnext50<br>\nregnety_64<br>\nWeighted ComboLoss:</p>\n<p>BCEWithLogitsLoss (each with weight=1.0)<br>\nL1Loss (weight from 0.25 to 0.5 got good results)<br>\nLR and hyperparameters:</p>\n<p>Optimizer: Adam, LR= 0.0003, beta1=0.9<br>\nLR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8<br>\nEpochs: 48<br>\nBatch size: From 32 to 36<br>\nFP16 enabled<br>\nSingle cycle<br>\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png</a></p>\n<p>Inference<br>\nInference is based on two stages ensembled at the end.</p>\n<p>Stage #1:</p>\n<p>It’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png</a></p>\n<p>Note: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.</p>\n<p>Stage #2:</p>\n<p>It is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.</p>\n<p>imagehttps://nsa40.casimages.com/img/2021/05/13/210513070737945441.png</p>\n<p>Stage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.</p>\n<p>From a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.</p>\n<p>Misc<br>\nWhat could be improved?</p>\n<p>DRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.</p>\n<p>What did not work (or not better than this solution)?</p>\n<p>YoloV5 model based on OOF and RGB image<br>\nPost process probabilities to move to rank probabilities on ensemble<br>\nTTA (it worked indeed but gave tiny improvement)<br>\nLarger full image<br>\nUpdate: Source code available: <a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
      "rawMarkdown": "日本語訳\n\nIntroduction\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) SOA approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest. However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both Puzzle-CAM [1] and DRS (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble).\n\nI teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.\n\nClose to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone.\nこのコンテストの早い段階で、新しいことを学ぶためにWSSS（弱教師ありセマンティックセグメンテーション）SOAアプローチから始めることにしました。 マルチラベルを使用した完全な画像トレーニングとセグメンテーションの構築を試みます。 多くのソリューションはCAMの使用率に基づいています。 つまり、パイプラインの最後で、CAMを成長させ、関心領域の画像全体に広げます。 ただし、セルマスクはすでに利用可能であったため、完全なWSSSプロセスを実行する必要はなく、予測されたラベルを取得するために、ある時点でCAMとセルを交差させるだけで済みました。 私はPuzzle-CAM [1]とDRS（Discriminative Region Suppression）[2]の両方のアプローチを試しました。 私はついに、RGBY画像でトレーニングされた修正されたPuzzle-CAMと2段階の推論（完全な画像とセルごとの基本的なアンサンブル）で最良の結果を得ました。\n\n私は早い段階で、異なるアプローチを使用したZFturboとチームを組み、両方のソリューションが非常にうまく調和しました。 改善する次のステップは、ZFTurboのモデルに利益をもたらす可能性のある私の最高のモデルバリアントのいくつかから（各クラスのセル予測ごとに）OOFを生成し、次にアンサンブルに生成することでした。\n\n競争の終わり近くに、推論の余地があり（パイプラインは約6時間30分で実行されていました）、新しいモデルを統合することが役立つはずであることに同意し、新しいモデル/アイデアをもたらしたディーターと合併して、 マネーゾーン。\nTraining\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps.\n\nPipeline:\n\nhttps://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\n\nNotice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.\n\nAugmentations:\n\nSimple augmentations that apply to RGBY images:\n\nNoise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise\nFlips/Rotations: HorizontalFlip, RandomRotate90\nRotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear\nBlurs: GaussianBlur, MotionBlur, MedianBlur\nColors: RandomGamma, RandomBrightnessContrast\nSampling strategy:\n\nClasses distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\n\nA weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).\n\nData:\n\nTrain set and external data had been used to train different model variants:\n\n89k images: Train set + External public data shared by host\n98k images: Train set + External public data shared by host + HPA 2018\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.\n\nExternal data was key for this competition to increase volume and make models better.\n\nCross validation:\n\nTrain dataset is split in 4 folds with a MultilabelStratifiedKFold strategy.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\n\nTraining procedure:\n\n4 main models trained with different backbones (but only variants of #1 in the final ensemble).\n\nseresnext50_32x4d\ngluon_seresnext101_32x4d,\ncspresnext50\nregnety_64\nWeighted ComboLoss:\n\nBCEWithLogitsLoss (each with weight=1.0)\nL1Loss (weight from 0.25 to 0.5 got good results)\nLR and hyperparameters:\n\nOptimizer: Adam, LR= 0.0003, beta1=0.9\nLR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8\nEpochs: 48\nBatch size: From 32 to 36\nFP16 enabled\nSingle cycle\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:\n\nhttps://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\n\nInference\nInference is based on two stages ensembled at the end.\n\nStage #1:\n\nIt’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\n\nNote: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.\n\nStage #2:\n\nIt is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.\n\nimagehttps://nsa40.casimages.com/img/2021/05/13/210513070737945441.png\n\nStage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.\n\nFrom a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.\n\nMisc\nWhat could be improved?\n\nDRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.\n\nWhat did not work (or not better than this solution)?\n\nYoloV5 model based on OOF and RGB image\nPost process probabilities to move to rank probabilities on ensemble\nTTA (it worked indeed but gave tiny improvement)\nLarger full image\nUpdate: Source code available: https://github.com/MPWARE-TEAM/HPA2021"
    },
    {
      "id": 1313114,
      "postDate": "2021-05-18T12:10:54.740Z",
      "content": "<p>Training model (my part) open sourced on GitHub:<br>\n<a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
      "rawMarkdown": "Training model (my part) open sourced on GitHub:\nhttps://github.com/MPWARE-TEAM/HPA2021",
      "votes": 1
    },
    {
      "id": 1311363,
      "postDate": "2021-05-17T11:03:48.083Z",
      "content": "<p>Congrats <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> </p>",
      "rawMarkdown": "Congrats @mpware ",
      "votes": 1
    },
    {
      "id": 1308077,
      "postDate": "2021-05-15T00:45:10.870Z",
      "content": "<p>Congratulations MPWARE and team. Great solution and write up!</p>",
      "rawMarkdown": "Congratulations MPWARE and team. Great solution and write up!",
      "votes": 1,
      "replies": [
        {
          "id": 1308552,
          "postDate": "2021-05-15T09:50:21.230Z",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> !</p>",
          "rawMarkdown": "Thanks @cdeotte !",
          "votes": 1
        }
      ]
    },
    {
      "id": 1306879,
      "postDate": "2021-05-14T06:03:06.763Z",
      "content": "<p>Congrats, <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> ! And thank you for the detailed write-up about your amazing work!</p>",
      "rawMarkdown": "Congrats, @mpware ! And thank you for the detailed write-up about your amazing work!",
      "votes": 1
    },
    {
      "id": 1306572,
      "postDate": "2021-05-13T22:12:48.343Z",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> ! Very interesting approach. One more gold to be GM !</p>",
      "rawMarkdown": "Congratz @mpware ! Very interesting approach. One more gold to be GM !",
      "votes": 1,
      "replies": [
        {
          "id": 1308554,
          "postDate": "2021-05-15T09:51:51.303Z",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/tikutiku\" target=\"_blank\">@tikutiku</a> , you're on the right track to become GM too.</p>",
          "rawMarkdown": "Thanks @tikutiku , you're on the right track to become GM too.",
          "votes": 1
        }
      ]
    },
    {
      "id": 1306545,
      "postDate": "2021-05-13T21:34:06.067Z",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> !!!</p>",
      "rawMarkdown": "Congratz @mpware !!!",
      "votes": 1
    },
    {
      "id": 1306351,
      "postDate": "2021-05-13T17:58:01.693Z",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> :)<br>\nWell deserved, especially after the HubMAP upset !</p>",
      "rawMarkdown": "Congratz @mpware :)\nWell deserved, especially after the HubMAP upset !",
      "votes": 1,
      "replies": [
        {
          "id": 1306354,
          "postDate": "2021-05-13T18:00:53.660Z",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/theoviel\" target=\"_blank\">@theoviel</a> ! So true.</p>",
          "rawMarkdown": "Thanks @theoviel ! So true.",
          "votes": 1
        }
      ]
    },
    {
      "id": 1318973,
      "postDate": "2021-05-22T18:19:35.717Z",
      "content": "<p>Congratulations!</p>",
      "rawMarkdown": "Congratulations!"
    },
    {
      "id": 1310362,
      "postDate": "2021-05-16T15:51:35.140Z",
      "content": "<p>Models weights shared (even models not used in our ensemble):</p>\n<ul>\n<li>SEResNeXt: <a href=\"https://www.kaggle.com/mpware/hpa-models\" target=\"_blank\">https://www.kaggle.com/mpware/hpa-models</a></li>\n<li>DRS: <a href=\"https://www.kaggle.com/mpware/hpa-drs\" target=\"_blank\">https://www.kaggle.com/mpware/hpa-drs</a></li>\n</ul>",
      "rawMarkdown": "Models weights shared (even models not used in our ensemble):\n- SEResNeXt: https://www.kaggle.com/mpware/hpa-models\n- DRS: https://www.kaggle.com/mpware/hpa-drs"
    },
    {
      "id": 1310584,
      "postDate": "2021-05-16T18:31:57.073Z",
      "content": "<p>Thanks for sharing!</p>",
      "rawMarkdown": "Thanks for sharing!",
      "votes": 1
    }
  ],
  "comments": [
    {
      "id": 1610746,
      "author_name": "pixyz0130",
      "author_url": "",
      "post_date": "2021-12-07T13:44:32.993000",
      "content": "<p>日本語訳</p>\n<p>Introduction<br>\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) SOA approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest. However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both Puzzle-CAM [1] and DRS (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble).</p>\n<p>I teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.</p>\n<p>Close to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone.<br>\nこのコンテストの早い段階で、新しいことを学ぶためにWSSS（弱教師ありセマンティックセグメンテーション）SOAアプローチから始めることにしました。 マルチラベルを使用した完全な画像トレーニングとセグメンテーションの構築を試みます。 多くのソリューションはCAMの使用率に基づいています。 つまり、パイプラインの最後で、CAMを成長させ、関心領域の画像全体に広げます。 ただし、セルマスクはすでに利用可能であったため、完全なWSSSプロセスを実行する必要はなく、予測されたラベルを取得するために、ある時点でCAMとセルを交差させるだけで済みました。 私はPuzzle-CAM [1]とDRS（Discriminative Region Suppression）[2]の両方のアプローチを試しました。 私はついに、RGBY画像でトレーニングされた修正されたPuzzle-CAMと2段階の推論（完全な画像とセルごとの基本的なアンサンブル）で最良の結果を得ました。</p>\n<p>私は早い段階で、異なるアプローチを使用したZFturboとチームを組み、両方のソリューションが非常にうまく調和しました。 改善する次のステップは、ZFTurboのモデルに利益をもたらす可能性のある私の最高のモデルバリアントのいくつかから（各クラスのセル予測ごとに）OOFを生成し、次にアンサンブルに生成することでした。</p>\n<p>競争の終わり近くに、推論の余地があり（パイプラインは約6時間30分で実行されていました）、新しいモデルを統合することが役立つはずであることに同意し、新しいモデル/アイデアをもたらしたディーターと合併して、 マネーゾーン。<br>\nTraining<br>\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps.</p>\n<p>Pipeline:</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png</a></p>\n<p>Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.</p>\n<p>Augmentations:</p>\n<p>Simple augmentations that apply to RGBY images:</p>\n<p>Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise<br>\nFlips/Rotations: HorizontalFlip, RandomRotate90<br>\nRotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear<br>\nBlurs: GaussianBlur, MotionBlur, MedianBlur<br>\nColors: RandomGamma, RandomBrightnessContrast<br>\nSampling strategy:</p>\n<p>Classes distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png</a></p>\n<p>A weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).</p>\n<p>Data:</p>\n<p>Train set and external data had been used to train different model variants:</p>\n<p>89k images: Train set + External public data shared by host<br>\n98k images: Train set + External public data shared by host + HPA 2018<br>\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.</p>\n<p>External data was key for this competition to increase volume and make models better.</p>\n<p>Cross validation:</p>\n<p>Train dataset is split in 4 folds with a MultilabelStratifiedKFold strategy.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png</a></p>\n<p>Training procedure:</p>\n<p>4 main models trained with different backbones (but only variants of #1 in the final ensemble).</p>\n<p>seresnext50_32x4d<br>\ngluon_seresnext101_32x4d,<br>\ncspresnext50<br>\nregnety_64<br>\nWeighted ComboLoss:</p>\n<p>BCEWithLogitsLoss (each with weight=1.0)<br>\nL1Loss (weight from 0.25 to 0.5 got good results)<br>\nLR and hyperparameters:</p>\n<p>Optimizer: Adam, LR= 0.0003, beta1=0.9<br>\nLR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8<br>\nEpochs: 48<br>\nBatch size: From 32 to 36<br>\nFP16 enabled<br>\nSingle cycle<br>\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png</a></p>\n<p>Inference<br>\nInference is based on two stages ensembled at the end.</p>\n<p>Stage #1:</p>\n<p>It’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.</p>\n<p><a href=\"https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\" target=\"_blank\">https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png</a></p>\n<p>Note: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.</p>\n<p>Stage #2:</p>\n<p>It is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.</p>\n<p>imagehttps://nsa40.casimages.com/img/2021/05/13/210513070737945441.png</p>\n<p>Stage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.</p>\n<p>From a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.</p>\n<p>Misc<br>\nWhat could be improved?</p>\n<p>DRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.</p>\n<p>What did not work (or not better than this solution)?</p>\n<p>YoloV5 model based on OOF and RGB image<br>\nPost process probabilities to move to rank probabilities on ensemble<br>\nTTA (it worked indeed but gave tiny improvement)<br>\nLarger full image<br>\nUpdate: Source code available: <a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1313114,
      "author_name": "MPWARE",
      "author_url": "",
      "post_date": "2021-05-18T12:10:54.740000",
      "content": "<p>Training model (my part) open sourced on GitHub:<br>\n<a href=\"https://github.com/MPWARE-TEAM/HPA2021\" target=\"_blank\">https://github.com/MPWARE-TEAM/HPA2021</a></p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1311363,
      "author_name": "Kushagra Singh",
      "author_url": "",
      "post_date": "2021-05-17T11:03:48.083000",
      "content": "<p>Congrats <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> </p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1308077,
      "author_name": "Chris Deotte",
      "author_url": "",
      "post_date": "2021-05-15T00:45:10.870000",
      "content": "<p>Congratulations MPWARE and team. Great solution and write up!</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1308552,
          "author_name": "MPWARE",
          "author_url": "",
          "post_date": "2021-05-15T09:50:21.230000",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/cdeotte\" target=\"_blank\">@cdeotte</a> !</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1306879,
      "author_name": "Raman",
      "author_url": "",
      "post_date": "2021-05-14T06:03:06.763000",
      "content": "<p>Congrats, <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> ! And thank you for the detailed write-up about your amazing work!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1306572,
      "author_name": "Tom",
      "author_url": "",
      "post_date": "2021-05-13T22:12:48.343000",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> ! Very interesting approach. One more gold to be GM !</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1308554,
          "author_name": "MPWARE",
          "author_url": "",
          "post_date": "2021-05-15T09:51:51.303000",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/tikutiku\" target=\"_blank\">@tikutiku</a> , you're on the right track to become GM too.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1306545,
      "author_name": "FabienDaniel",
      "author_url": "",
      "post_date": "2021-05-13T21:34:06.067000",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> !!!</p>",
      "votes": 1,
      "replies": []
    },
    {
      "id": 1306351,
      "author_name": "Theo Viel",
      "author_url": "",
      "post_date": "2021-05-13T17:58:01.693000",
      "content": "<p>Congratz <a href=\"https://www.kaggle.com/mpware\" target=\"_blank\">@mpware</a> :)<br>\nWell deserved, especially after the HubMAP upset !</p>",
      "votes": 1,
      "replies": [
        {
          "id": 1306354,
          "author_name": "MPWARE",
          "author_url": "",
          "post_date": "2021-05-13T18:00:53.660000",
          "content": "<p>Thanks <a href=\"https://www.kaggle.com/theoviel\" target=\"_blank\">@theoviel</a> ! So true.</p>",
          "votes": 1,
          "replies": []
        }
      ]
    },
    {
      "id": 1318973,
      "author_name": "Alif Rahman",
      "author_url": "",
      "post_date": "2021-05-22T18:19:35.717000",
      "content": "<p>Congratulations!</p>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1310362,
      "author_name": "MPWARE",
      "author_url": "",
      "post_date": "2021-05-16T15:51:35.140000",
      "content": "<p>Models weights shared (even models not used in our ensemble):</p>\n<ul>\n<li>SEResNeXt: <a href=\"https://www.kaggle.com/mpware/hpa-models\" target=\"_blank\">https://www.kaggle.com/mpware/hpa-models</a></li>\n<li>DRS: <a href=\"https://www.kaggle.com/mpware/hpa-drs\" target=\"_blank\">https://www.kaggle.com/mpware/hpa-drs</a></li>\n</ul>",
      "votes": 0,
      "replies": []
    },
    {
      "id": 1310584,
      "author_name": "Alif Rahman",
      "author_url": "",
      "post_date": "2021-05-16T18:31:57.073000",
      "content": "<p>Thanks for sharing!</p>",
      "votes": 1,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1306225": "First of all I would like to thank the host for this really interesting competition and also for the accurate answers to questions in the forum. High quality data provided is something I would like to highlight too. I would like to warmly thank my teammates @zfturbo and @christofhenkel for the great collaboration, firework of ideas and their patience with me.\n\nOur solution is an ensemble of different independant models. Hereafter my part.\n\n# Introduction\n\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) [SOA](https://paperswithcode.com/sota/weakly-supervised-semantic-segmentation-on) approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest.  However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both [Puzzle-CAM](https://arxiv.org/pdf/2101.11253.pdf) [1] and [DRS](https://arxiv.org/pdf/2103.07246.pdf) (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble). \n\nI teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.\n\nClose to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone. \n\n\n# Training\n\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps. \n\n**Pipeline:**\n\n![Model](https://nsa40.casimages.com/img/2021/05/13/21051307014745767.png)\n\n_Notice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency._\n\n**Augmentations:**\n\nSimple augmentations that apply to RGBY images:\n\n\n\n*   Noise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise\n*   Flips/Rotations: HorizontalFlip, RandomRotate90\n*   Rotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear\n*   Blurs: GaussianBlur, MotionBlur, MedianBlur\n*   Colors: RandomGamma, RandomBrightnessContrast\n\n**Sampling strategy:**\n\nClasses distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.\n\n\n\n\n![Distribution](https://nsa40.casimages.com/img/2021/05/13/210513070340273015.png)\n\n\nA weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).\n\n**Data:**\n\nTrain set and external data had been used to train different model variants:\n\n\n\n*   89k images: Train set + External public data shared by host\n*   98k images: Train set + External public data shared by host + HPA 2018\n\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.\n\nExternal data was key for this competition to increase volume and make models better.\n\n**Cross validation:**\n\nTrain dataset is split in 4 folds with a [MultilabelStratifiedKFold](https://github.com/trent-b/iterative-stratification) strategy.\n\n\n\n![CV](https://nsa40.casimages.com/img/2021/05/13/210513070514669583.png)\n\n\n**Training procedure:**\n\n4 main models trained with different [backbones](https://github.com/rwightman/pytorch-image-models) (but only variants of #1 in the final ensemble).\n\n\n\n1. seresnext50_32x4d\n2. gluon_seresnext101_32x4d, \n3. cspresnext50\n4. regnety_64\n\nWeighted ComboLoss:\n\n\n\n*   BCEWithLogitsLoss (each with weight=1.0)\n*   L1Loss (weight from 0.25 to 0.5 got good results)\n\nLR and hyperparameters:\n\n\n\n*   Optimizer: Adam, LR= 0.0003, beta1=0.9\n*   LR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8\n*   Epochs: 48\n*   Batch size: From 32 to 36\n*   FP16 enabled\n*   Single cycle\n\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:\n\n\n\n![CV](https://nsa40.casimages.com/img/2021/05/13/21051307055127008.png)\n\n\n\n\n\n# Inference\n\nInference is based on two stages ensembled at the end. \n\n**Stage #1:**\n\nIt’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.\n\n\n\n![stage1](https://nsa40.casimages.com/img/2021/05/13/210513070630451026.png)\n\n\n<span style=\"text-decoration:underline;\">Note</span>: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.\n\n**Stage #2:**\n\nIt is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.\n\n\n\n![stage2](https://nsa40.casimages.com/img/2021/05/13/210513070737945441.png)\n\n\nStage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.\n\nFrom a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.\n\n\n# Misc\n\n**What could be improved?**\n\nDRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.\n\n**What did not work (or not better than this solution)?**\n\n\n\n*   YoloV5 model based on OOF and RGB image\n*   Post process probabilities to move to rank probabilities on ensemble\n*   TTA (it worked indeed but gave tiny improvement) \n*   Larger full image\n\n**Update**: Source code available: https://github.com/MPWARE-TEAM/HPA2021",
    "1610746": "日本語訳\n\nIntroduction\nEarly in this competition I decided to start with WSSS (Weakly-Supervised Semantic Segmentation) SOA approaches to learn something new. Full image training with multi labels and try to build a segmentation. Many solutions are based on CAM utilization. In short, at the end of the pipeline, make CAM grow and spread over the image on the regions of interest. However, as cell masks were already available, I didn’t need to go with the full WSSS process and just intersect at some point CAM with cells to get predicted labels. I’ve experimented with both Puzzle-CAM [1] and DRS (Discriminative Region Suppression) [2] approaches. I finally got best results with a modified Puzzle-CAM trained on RGBY images and with a two stages inference (full image and per cell basic ensemble).\n\nI teamed up early with ZFturbo that used a different approach and both solutions ensembled quite well. Next step to improve was to generate OOF (per cell prediction for each class) from some of my best model variants that could benefit ZFTurbo's models and then to our ensemble.\n\nClose to the end of competition we had room left on inference (our pipeline was running in around 6h30 only) and we agreed that integrating new models should help and we merged with Dieter that brought new models/ideas that made the difference to be in the money zone.\nこのコンテストの早い段階で、新しいことを学ぶためにWSSS（弱教師ありセマンティックセグメンテーション）SOAアプローチから始めることにしました。 マルチラベルを使用した完全な画像トレーニングとセグメンテーションの構築を試みます。 多くのソリューションはCAMの使用率に基づいています。 つまり、パイプラインの最後で、CAMを成長させ、関心領域の画像全体に広げます。 ただし、セルマスクはすでに利用可能であったため、完全なWSSSプロセスを実行する必要はなく、予測されたラベルを取得するために、ある時点でCAMとセルを交差させるだけで済みました。 私はPuzzle-CAM [1]とDRS（Discriminative Region Suppression）[2]の両方のアプローチを試しました。 私はついに、RGBY画像でトレーニングされた修正されたPuzzle-CAMと2段階の推論（完全な画像とセルごとの基本的なアンサンブル）で最良の結果を得ました。\n\n私は早い段階で、異なるアプローチを使用したZFturboとチームを組み、両方のソリューションが非常にうまく調和しました。 改善する次のステップは、ZFTurboのモデルに利益をもたらす可能性のある私の最高のモデルバリアントのいくつかから（各クラスのセル予測ごとに）OOFを生成し、次にアンサンブルに生成することでした。\n\n競争の終わり近くに、推論の余地があり（パイプラインは約6時間30分で実行されていました）、新しいモデルを統合することが役立つはずであることに同意し、新しいモデル/アイデアをもたらしたディーターと合併して、 マネーゾーン。\nTraining\nSiamese network with CNN backbone followed by classifier to build activation maps per class. GAP moved that end to get full image predictions. Combo loss that takes into account both full and puzzled/recomposed features and distance between activation maps.\n\nPipeline:\n\nhttps://nsa40.casimages.com/img/2021/05/13/21051307014745767.png\n\nNotice the Classifier/GAP swap used in WSSS compared to regular classifiers and L1 loss for overall consistency.\n\nAugmentations:\n\nSimple augmentations that apply to RGBY images:\n\nNoise: GaussNoise, CoarseDropout, IAAAdditiveGaussianNoise\nFlips/Rotations: HorizontalFlip, RandomRotate90\nRotate/Distorsion: GridDistortion, ShiftScaleRotate, ElasticTransform, OpticalDistortion, IAAAffine/Shear\nBlurs: GaussianBlur, MotionBlur, MedianBlur\nColors: RandomGamma, RandomBrightnessContrast\nSampling strategy:\n\nClasses distribution is depicted below. Classes are quite imbalanced especially for Aggresome (class 15) and Mitotic spindle (class 11). Nucleoplasm (class 0) and Cytosol (class 16) are over-represented.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070340273015.png\n\nA weighted random sampling has been applied to balance each class during training. Basically, less weight for nucleoplasm and more weights for Mitotic spindle. However, to counterbalance the rare classes 11 and 15 important oversampling due to this strategy, we’ve clipped weights value to the one computed on Intermediate filaments (class 8).\n\nData:\n\nTrain set and external data had been used to train different model variants:\n\n89k images: Train set + External public data shared by host\n98k images: Train set + External public data shared by host + HPA 2018\nEach single layer image has been merged and resized to create RGBY 512x512 images (protein + context). A few similar images have been found on sanity check but not removed.\n\nExternal data was key for this competition to increase volume and make models better.\n\nCross validation:\n\nTrain dataset is split in 4 folds with a MultilabelStratifiedKFold strategy.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070514669583.png\n\nTraining procedure:\n\n4 main models trained with different backbones (but only variants of #1 in the final ensemble).\n\nseresnext50_32x4d\ngluon_seresnext101_32x4d,\ncspresnext50\nregnety_64\nWeighted ComboLoss:\n\nBCEWithLogitsLoss (each with weight=1.0)\nL1Loss (weight from 0.25 to 0.5 got good results)\nLR and hyperparameters:\n\nOptimizer: Adam, LR= 0.0003, beta1=0.9\nLR scheduler: ReduceLROnPlateau, factor = 0.3, patience = 8\nEpochs: 48\nBatch size: From 32 to 36\nFP16 enabled\nSingle cycle\nCriteria to save model’s weights is based on best ComboLoss only, F1 and mAP scores are just monitored:\n\nhttps://nsa40.casimages.com/img/2021/05/13/21051307055127008.png\n\nInference\nInference is based on two stages ensembled at the end.\n\nStage #1:\n\nIt’s the inference related to a model trained with activation maps output normalized to [0-1.0] range and resized to input image size. HPA segmentation pipeline is executed in parallel to get cell masks instances. Each cell is intersected with CAM (overlap + magnitude score) and weighed with the per-class probability outputted from the sigmoid.\n\nhttps://nsa40.casimages.com/img/2021/05/13/210513070630451026.png\n\nNote: HPA segmentation pipeline provided by the host has been modified to make it faster (around x6). As the host recommended scale factor = 0.25, it globally matches with 512x512 images and we’ve modified the morphology post-processing to detect instances based on 512x512 and not on original image size. The gain is on speed but we lose on quality, some cells remain merged with this optimization but they should be split. The impact on score has been estimated to around -0.002 which is an acceptable trade off.\n\nStage #2:\n\nIt is another inference that comes for free by simply re-using the model and fed by each cell instance (from stage#1) crop.\n\nimagehttps://nsa40.casimages.com/img/2021/05/13/210513070737945441.png\n\nStage#1 vs stage#2 predictions are different by design, stage#1 are sparse whereas stage#2 are more flatten. Both acting together gave some regularization to the results.\n\nFrom a performance point of view, this single model (both stages + HPA segmentation) on 559 images ran in around 2h with one P100 GPU. Additional averaging with different model variants (different input dataset, different backbones, seed) got public LB around 0.52/0.53.\n\nMisc\nWhat could be improved?\n\nDRS approach was also giving interesting results, the single model (with vgg16 backbone) was slow to train and got a lower score compared to Puzzle-CAM (but acceptable). Inference was slow too that’s why we didn’t get a chance to ensemble it at the end but it might be worth assessing as CAM generated are different.\n\nWhat did not work (or not better than this solution)?\n\nYoloV5 model based on OOF and RGB image\nPost process probabilities to move to rank probabilities on ensemble\nTTA (it worked indeed but gave tiny improvement)\nLarger full image\nUpdate: Source code available: https://github.com/MPWARE-TEAM/HPA2021",
    "1313114": "Training model (my part) open sourced on GitHub:\nhttps://github.com/MPWARE-TEAM/HPA2021",
    "1311363": "Congrats @mpware ",
    "1308077": "Congratulations MPWARE and team. Great solution and write up!",
    "1306879": "Congrats, @mpware ! And thank you for the detailed write-up about your amazing work!",
    "1306572": "Congratz @mpware ! Very interesting approach. One more gold to be GM !",
    "1306545": "Congratz @mpware !!!",
    "1306351": "Congratz @mpware :)\nWell deserved, especially after the HubMAP upset !",
    "1318973": "Congratulations!",
    "1310362": "Models weights shared (even models not used in our ensemble):\n- SEResNeXt: https://www.kaggle.com/mpware/hpa-models\n- DRS: https://www.kaggle.com/mpware/hpa-drs",
    "1310584": "Thanks for sharing!"
  }
}