{
  "id": 419779,
  "title": "Segmentation-models-pytorch",
  "url": "/competitions/hubmap-hacking-the-human-vasculature/discussion/419779",
  "author_name": "kapedalex",
  "post_date": "2023-06-27T14:30:38.995000",
  "votes": 0,
  "comment_count": 8,
  "views": 0,
  "content": "<p>Based on advice I tried to use Segmentation-models-pytorch for this task. Here is link:<br>\n<a href=\"https://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb\" target=\"_blank\">https://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb</a></p>\n<p>Below is an extract of useful code: model, loss, optimizer, TrainEpochs, Dataloaders. Only thing changed is  CLASSES = ['blood_vessel', 'glomerulus', 'unsure'].</p>\n<pre><code>ENCODER = \nENCODER_WEIGHTS = \nCLASSES = [, , ]\nACTIVATION =  # could be None  logits    multiclass segmentation\nDEVICE = \n\nmodel = smp.FPN(\n    =ENCODER, \n    =ENCODER_WEIGHTS, \n    =len(CLASSES), \n    =ACTIVATION,\n)\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\n\n segmentation_models_pytorch import utils\n\nloss = smp.utils.losses.DiceLoss()\nmetrics = [\n    smp.utils.metrics.IoU(=0.5),\n]\n\noptimizer = torch.optim.Adam([ \n    dict(=model.parameters(), =0.0001),\n])\n</code></pre>\n<pre><code>train_epoch = smp.utils.train.TrainEpoch(\n    model, \n    =loss, \n    =metrics, \n    =optimizer,\n    =DEVICE,\n    =,\n)\n\nvalid_epoch = smp.utils.train.ValidEpoch(\n    model, \n    =loss, \n    =metrics, \n    =DEVICE,\n    =,\n)\n</code></pre>\n<pre><code> torch.utils.data  DataLoader\n torch.utils.data  Dataset  BaseDataset\n\n ():\n\n    CLASSES = [, , ]\n\n     ():\n        self.ids = os.listdir(images_dir)\n        self.images_fps = [os.path.join(images_dir, image_id)  image_id  self.ids]\n        self.masks_fps = [os.path.join(masks_dir, image_id)  image_id  self.ids]\n\n        \n        self.class_values = [self.CLASSES.index(cls.lower())  cls  classes]\n        (self.class_values)\n\n        self.augmentation = augmentation\n        self.preprocessing = preprocessing\n\n     ():\n\n        \n        image = cv2.imread(self.images_fps[i])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(self.masks_fps[i], )\n        \n        masks = [(mask == v)  v  self.class_values]\n        mask = np.stack(masks, axis=-).astype()\n\n        \n         self.augmentation:\n            sample = self.augmentation(image=image, mask=mask)\n            image, mask = sample[], sample[]\n\n        \n         self.preprocessing:\n            sample = self.preprocessing(image=image, mask=mask)\n            image, mask = sample[], sample[]\n\n         image, mask\n\n     ():\n         (self.ids)\n</code></pre>\n<h1>Then I try to teach it, using only annotated data. Problem is, that ALL predictions are just red squares. What I miss?</h1>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fb3627d139c3ef770771ef54605f484d4%2F1.jpg?generation=1687875857220799&amp;alt=media\" alt=\"\"></p>\n<pre><code>x_valid_dir = \ny_valid_dir = \nx_train_dir = \ny_train_dir = \n\n\ntrain_dataset = Dataset(\n    x_train_dir, \n    y_train_dir, \n    =get_training_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    =get_validation_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\ntrain_loader = DataLoader(train_dataset, =8, =, =12)\nvalid_loader = DataLoader(valid_dataset, =1, =, =4)\n</code></pre>\n<pre><code>max_score = \n\n   (, ):\n\n    ((i))\n    train_logs = train_epoch(train_loader)\n    valid_logs = valid_epoch(valid_loader)\n\n     max_score &lt; valid_logs:\n        max_score = valid_logs\n        torch(model, )\n        ()\n\n      == :\n        optimizer = e-\n        ()\n</code></pre>\n<pre><code>best_model = torch.load()\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    =get_validation_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\nvalid_loader = DataLoader(valid_dataset, =1, =, =4)\npredictions = []\n image, _  valid_loader:\n    image = image.(DEVICE)\n    pr_mask = best_model.predict(image)\n    pr_mask = (pr_mask.squeeze().cpu().numpy().round())\n    predictions.append(pr_mask)\n</code></pre>\n<pre><code> i  predictions:\n    plt.imshow(.(i, (, , )))\n    plt.(=False)\n\n    # Wait  user input\n     = input()\n\n    # Check  the 'q'  was pressed\n      == 'q':\n        \n\nplt.()\n</code></pre>\n<p>Examples of images and masks are below. We can see that train and valid data is ok.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fd4c36abdf71808d1a37a0455cde7213d%2F2.jpg?generation=1687875869381267&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fff7dd5ff5ae506fe868eb717d351097a%2F3.jpg?generation=1687875931997715&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F066022c384861e992b98d533953f5540%2F4.jpg?generation=1687875988408869&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F4dcddce33eaa4c70a228096529fa2bb5%2F5.jpg?generation=1687876000422419&amp;alt=media\" alt=\"\"></p>",
  "messages": [
    {
      "id": 2320687,
      "postDate": "2023-06-28T03:05:47.047Z",
      "content": "<p>you need to use argmax on the output, else it will just be a stacked masks</p>",
      "rawMarkdown": "you need to use argmax on the output, else it will just be a stacked masks",
      "votes": 1,
      "replies": [
        {
          "id": 2321416,
          "postDate": "2023-06-28T14:52:57.163Z",
          "content": "<p>Thank you, but this does not help. I have changed one line in output:</p>\n<pre><code>for image, _ in valid_loader:\n  image = image.(DEVICE)\n  pr_mask = best_model.(image)\n  pr_mask = torch.(pr_mask, dim=) # argmax here\n  pr_mask = (pr_mask.().().().())\n  predictions.(pr_mask)    \n</code></pre>\n<p>Now all squares are purple as background.<br>\nBefore argmax tensors are like</p>\n<pre><code>tensor([[[[9.9973e, 9.9984e, 9.9990e,  ..., 9.9987e,\n         9.9976e, 9.9955e],\n        [9.9988e, 9.9994e, 9.9997e,  ..., 9.9995e,\n         9.9991e, 9.9981e],\n        [9.9994e, 9.9997e, 9.9999e,  ..., 9.9998e,\n         9.9996e, 9.9992e],\n</code></pre>\n<p>And after it and squeeze all becomes 0.</p>\n<pre><code>\nhas_not_zero = (predictions != )()\n\n</code></pre>\n<p>Output is<br>\n(512, 512)<br>\nFalse<br>\nIf we do not argmax, there will be really small numbers</p>\n<pre><code>\npredictions\n​\nindexes = np(predictions &gt; )\n idx  indexes:\n  (idx)\n</code></pre>\n<p>Output is<br>\n(3, 512, 512)<br>\n[0 0 0]<br>\n[0 0 1]<br>\n[0 0 2]<br>\n[ 0  0 16]<br>\n[0 1 0]<br>\n[  0 510 511]<br>\n[  0 511 510]</p>\n<h1>As I see, results on valid does not change at all:</h1>\n<p>Epoch: 0<br>\ntrain: 100%|██████████| 184/184 [01:59&lt;00:00,  1.53it/s, dice_loss - 0.1374, iou_score - 0.7633]<br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 23.07it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nModel saved!<br>\nEpoch: 1<br>\ntrain: 100%|██████████| 184/184 [01:52&lt;00:00,  1.63it/s, dice_loss - 0.1279, iou_score - 0.777] <br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 20.97it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 2<br>\ntrain: 100%|██████████| 184/184 [01:52&lt;00:00,  1.63it/s, dice_loss - 0.1283, iou_score - 0.7765]<br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 22.92it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 3<br>\ntrain: 100%|██████████| 184/184 [01:54&lt;00:00,  1.61it/s, dice_loss - 0.1276, iou_score - 0.7771]<br>\nvalid: 100%|██████████| 163/163 [00:06&lt;00:00, 23.72it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 4<br>\ntrain: 100%|██████████| 184/184 [01:53&lt;00:00,  1.62it/s, dice_loss - 0.1306, iou_score - 0.7726]<br>\nvalid: 100%|██████████| 163/163 [00:06&lt;00:00, 23.71it/s, dice_loss - 0.02045, iou_score - 0.9608]</p>",
          "rawMarkdown": "\n\nThank you, but this does not help. I have changed one line in output:\n```\nfor image, _ in valid_loader:\n    image = image.to(DEVICE)\n    pr_mask = best_model.predict(image)\n    pr_mask = torch.argmax(pr_mask, dim=1) # argmax here\n    pr_mask = (pr_mask.squeeze().cpu().numpy().round())\n    predictions.append(pr_mask)    \n```\nNow all squares are purple as background.\n\nBefore argmax tensors are like\n```\n tensor([[[[9.9973e-01, 9.9984e-01, 9.9990e-01,  ..., 9.9987e-01,\n           9.9976e-01, 9.9955e-01],\n          [9.9988e-01, 9.9994e-01, 9.9997e-01,  ..., 9.9995e-01,\n           9.9991e-01, 9.9981e-01],\n          [9.9994e-01, 9.9997e-01, 9.9999e-01,  ..., 9.9998e-01,\n           9.9996e-01, 9.9992e-01],\n```\nAnd after it and squeeze all becomes 0.\n```\nprint(predictions[1].shape)\nhas_not_zero = (predictions[1] != 0).any()\nprint(has_not_zero)\n```\n\nOutput is\n(512, 512)\nFalse\n\nIf we do not argmax, there will be really small numbers\n```\nprint(predictions[1].shape)\npredictions[1]\n​\nindexes = np.argwhere(predictions[1][1:] > 0.0001)\nfor idx in indexes:\n    print(idx)\n```\nOutput is\n(3, 512, 512)\n[0 0 0]\n[0 0 1]\n[0 0 2]\n[ 0  0 16]\n[0 1 0]\n[  0 510 511]\n[  0 511 510]\n\n# As I see, results on valid does not change at all:\n\nEpoch: 0\ntrain: 100%|██████████| 184/184 [01:59<00:00,  1.53it/s, dice_loss - 0.1374, iou_score - 0.7633]\nvalid: 100%|██████████| 163/163 [00:07<00:00, 23.07it/s, dice_loss - 0.02045, iou_score - 0.9608]\nModel saved!\n\nEpoch: 1\ntrain: 100%|██████████| 184/184 [01:52<00:00,  1.63it/s, dice_loss - 0.1279, iou_score - 0.777] \nvalid: 100%|██████████| 163/163 [00:07<00:00, 20.97it/s, dice_loss - 0.02045, iou_score - 0.9608]\n\nEpoch: 2\ntrain: 100%|██████████| 184/184 [01:52<00:00,  1.63it/s, dice_loss - 0.1283, iou_score - 0.7765]\nvalid: 100%|██████████| 163/163 [00:07<00:00, 22.92it/s, dice_loss - 0.02045, iou_score - 0.9608]\n\nEpoch: 3\ntrain: 100%|██████████| 184/184 [01:54<00:00,  1.61it/s, dice_loss - 0.1276, iou_score - 0.7771]\nvalid: 100%|██████████| 163/163 [00:06<00:00, 23.72it/s, dice_loss - 0.02045, iou_score - 0.9608]\n\nEpoch: 4\ntrain: 100%|██████████| 184/184 [01:53<00:00,  1.62it/s, dice_loss - 0.1306, iou_score - 0.7726]\nvalid: 100%|██████████| 163/163 [00:06<00:00, 23.71it/s, dice_loss - 0.02045, iou_score - 0.9608]\n\n",
          "replies": [
            {
              "id": 2325068,
              "postDate": "2023-07-01T05:35:08.363Z",
              "content": "<p>you have to choose the class that you want to output, i.e if your output has only one class then pred = pr_mask[:, 1], after this you can choose a threshold</p>",
              "rawMarkdown": "you have to choose the class that you want to output, i.e if your output has only one class then pred = pr_mask[:, 1], after this you can choose a threshold"
            },
            {
              "id": 2325554,
              "postDate": "2023-07-01T12:54:27.293Z",
              "content": "<p>Does not help at all… <br>\ntorch.Size([512])<br>\ntensor([0.9999, 0.9999, 0.9999, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,<br>\n        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,</p>",
              "rawMarkdown": "Does not help at all... \ntorch.Size([512])\ntensor([0.9999, 0.9999, 0.9999, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,\n        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,"
            },
            {
              "id": 2325561,
              "postDate": "2023-07-01T12:59:02.303Z",
              "content": "<p>may i know the shape of the output?</p>",
              "rawMarkdown": "may i know the shape of the output?"
            },
            {
              "id": 2325829,
              "postDate": "2023-07-01T15:55:31.150Z",
              "content": "<p>I decided to make it public, so you can test, here you are) Also changed output to be closer to original, but issue still there.</p>\n<p><a href=\"https://www.kaggle.com/code/kapedalex/segmentation-cars2hubmap\" target=\"_blank\">https://www.kaggle.com/code/kapedalex/segmentation-cars2hubmap</a></p>",
              "rawMarkdown": "I decided to make it public, so you can test, here you are) Also changed output to be closer to original, but issue still there.\n\nhttps://www.kaggle.com/code/kapedalex/segmentation-cars2hubmap"
            },
            {
              "id": 2327763,
              "postDate": "2023-07-03T06:46:45.723Z",
              "rawMarkdown": "",
              "isDeleted": true
            },
            {
              "id": 2501864,
              "postDate": "2023-10-27T18:04:10.070Z",
              "content": "<p>I'm experiencing the same problem in a different framework. I'm trying to do sem seg on an aerial dataset, I've tryied many networks. The loss converge but there is only 1 layer  (class) of the ouput tensor where all the energy is and this leads to a black output.  Did you eventually find out why? </p>",
              "rawMarkdown": "I'm experiencing the same problem in a different framework. I'm trying to do sem seg on an aerial dataset, I've tryied many networks. The loss converge but there is only 1 layer  (class) of the ouput tensor where all the energy is and this leads to a black output.  Did you eventually find out why? "
            }
          ]
        }
      ]
    },
    {
      "id": 2320156,
      "postDate": "2023-06-27T14:30:38.997Z",
      "content": "<p>Based on advice I tried to use Segmentation-models-pytorch for this task. Here is link:<br>\n<a href=\"https://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb\" target=\"_blank\">https://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb</a></p>\n<p>Below is an extract of useful code: model, loss, optimizer, TrainEpochs, Dataloaders. Only thing changed is  CLASSES = ['blood_vessel', 'glomerulus', 'unsure'].</p>\n<pre><code>ENCODER = \nENCODER_WEIGHTS = \nCLASSES = [, , ]\nACTIVATION =  # could be None  logits    multiclass segmentation\nDEVICE = \n\nmodel = smp.FPN(\n    =ENCODER, \n    =ENCODER_WEIGHTS, \n    =len(CLASSES), \n    =ACTIVATION,\n)\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\n\n segmentation_models_pytorch import utils\n\nloss = smp.utils.losses.DiceLoss()\nmetrics = [\n    smp.utils.metrics.IoU(=0.5),\n]\n\noptimizer = torch.optim.Adam([ \n    dict(=model.parameters(), =0.0001),\n])\n</code></pre>\n<pre><code>train_epoch = smp.utils.train.TrainEpoch(\n    model, \n    =loss, \n    =metrics, \n    =optimizer,\n    =DEVICE,\n    =,\n)\n\nvalid_epoch = smp.utils.train.ValidEpoch(\n    model, \n    =loss, \n    =metrics, \n    =DEVICE,\n    =,\n)\n</code></pre>\n<pre><code> torch.utils.data  DataLoader\n torch.utils.data  Dataset  BaseDataset\n\n ():\n\n    CLASSES = [, , ]\n\n     ():\n        self.ids = os.listdir(images_dir)\n        self.images_fps = [os.path.join(images_dir, image_id)  image_id  self.ids]\n        self.masks_fps = [os.path.join(masks_dir, image_id)  image_id  self.ids]\n\n        \n        self.class_values = [self.CLASSES.index(cls.lower())  cls  classes]\n        (self.class_values)\n\n        self.augmentation = augmentation\n        self.preprocessing = preprocessing\n\n     ():\n\n        \n        image = cv2.imread(self.images_fps[i])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(self.masks_fps[i], )\n        \n        masks = [(mask == v)  v  self.class_values]\n        mask = np.stack(masks, axis=-).astype()\n\n        \n         self.augmentation:\n            sample = self.augmentation(image=image, mask=mask)\n            image, mask = sample[], sample[]\n\n        \n         self.preprocessing:\n            sample = self.preprocessing(image=image, mask=mask)\n            image, mask = sample[], sample[]\n\n         image, mask\n\n     ():\n         (self.ids)\n</code></pre>\n<h1>Then I try to teach it, using only annotated data. Problem is, that ALL predictions are just red squares. What I miss?</h1>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fb3627d139c3ef770771ef54605f484d4%2F1.jpg?generation=1687875857220799&amp;alt=media\" alt=\"\"></p>\n<pre><code>x_valid_dir = \ny_valid_dir = \nx_train_dir = \ny_train_dir = \n\n\ntrain_dataset = Dataset(\n    x_train_dir, \n    y_train_dir, \n    =get_training_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    =get_validation_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\ntrain_loader = DataLoader(train_dataset, =8, =, =12)\nvalid_loader = DataLoader(valid_dataset, =1, =, =4)\n</code></pre>\n<pre><code>max_score = \n\n   (, ):\n\n    ((i))\n    train_logs = train_epoch(train_loader)\n    valid_logs = valid_epoch(valid_loader)\n\n     max_score &lt; valid_logs:\n        max_score = valid_logs\n        torch(model, )\n        ()\n\n      == :\n        optimizer = e-\n        ()\n</code></pre>\n<pre><code>best_model = torch.load()\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    =get_validation_augmentation(), \n    =get_preprocessing(preprocessing_fn),\n    =CLASSES,\n)\n\nvalid_loader = DataLoader(valid_dataset, =1, =, =4)\npredictions = []\n image, _  valid_loader:\n    image = image.(DEVICE)\n    pr_mask = best_model.predict(image)\n    pr_mask = (pr_mask.squeeze().cpu().numpy().round())\n    predictions.append(pr_mask)\n</code></pre>\n<pre><code> i  predictions:\n    plt.imshow(.(i, (, , )))\n    plt.(=False)\n\n    # Wait  user input\n     = input()\n\n    # Check  the 'q'  was pressed\n      == 'q':\n        \n\nplt.()\n</code></pre>\n<p>Examples of images and masks are below. We can see that train and valid data is ok.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fd4c36abdf71808d1a37a0455cde7213d%2F2.jpg?generation=1687875869381267&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fff7dd5ff5ae506fe868eb717d351097a%2F3.jpg?generation=1687875931997715&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F066022c384861e992b98d533953f5540%2F4.jpg?generation=1687875988408869&amp;alt=media\" alt=\"\"></p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F4dcddce33eaa4c70a228096529fa2bb5%2F5.jpg?generation=1687876000422419&amp;alt=media\" alt=\"\"></p>",
      "rawMarkdown": "Based on advice I tried to use Segmentation-models-pytorch for this task. Here is link:\nhttps://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb\n\nBelow is an extract of useful code: model, loss, optimizer, TrainEpochs, Dataloaders. Only thing changed is  CLASSES = ['blood_vessel', 'glomerulus', 'unsure'].\n\n```\nENCODER = 'se_resnext50_32x4d'\nENCODER_WEIGHTS = 'imagenet'\nCLASSES = ['blood_vessel', 'glomerulus', 'unsure']\nACTIVATION = 'softmax2d' # could be None for logits or 'softmax2d' for multiclass segmentation\nDEVICE = 'cuda'\n\nmodel = smp.FPN(\n    encoder_name=ENCODER, \n    encoder_weights=ENCODER_WEIGHTS, \n    classes=len(CLASSES), \n    activation=ACTIVATION,\n)\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\n\nfrom segmentation_models_pytorch import utils\n\nloss = smp.utils.losses.DiceLoss()\nmetrics = [\n    smp.utils.metrics.IoU(threshold=0.5),\n]\n\noptimizer = torch.optim.Adam([ \n    dict(params=model.parameters(), lr=0.0001),\n])\n```\n```\ntrain_epoch = smp.utils.train.TrainEpoch(\n    model, \n    loss=loss, \n    metrics=metrics, \n    optimizer=optimizer,\n    device=DEVICE,\n    verbose=True,\n)\n\nvalid_epoch = smp.utils.train.ValidEpoch(\n    model, \n    loss=loss, \n    metrics=metrics, \n    device=DEVICE,\n    verbose=True,\n)\n```\n```\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import Dataset as BaseDataset\n\nclass Dataset(BaseDataset):\n    \n    CLASSES = ['blood_vessel', 'glomerulus', 'unsure']\n    \n    def __init__(\n            self, \n            images_dir, \n            masks_dir, \n            classes=None, \n            augmentation=None, \n            preprocessing=None,\n    ):\n        self.ids = os.listdir(images_dir)\n        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]\n        self.masks_fps = [os.path.join(masks_dir, image_id) for image_id in self.ids]\n        \n        # convert str names to class values on masks\n        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]\n        print(self.class_values)\n        \n        self.augmentation = augmentation\n        self.preprocessing = preprocessing\n    \n    def __getitem__(self, i):\n        \n        # read data\n        image = cv2.imread(self.images_fps[i])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(self.masks_fps[i], 0)\n        # extract certain classes from mask (e.g. cars)\n        masks = [(mask == v) for v in self.class_values]\n        mask = np.stack(masks, axis=-1).astype('float')\n        \n        # apply augmentations\n        if self.augmentation:\n            sample = self.augmentation(image=image, mask=mask)\n            image, mask = sample['image'], sample['mask']\n        \n        # apply preprocessing\n        if self.preprocessing:\n            sample = self.preprocessing(image=image, mask=mask)\n            image, mask = sample['image'], sample['mask']\n            \n        return image, mask\n        \n    def __len__(self):\n        return len(self.ids)\n```\n#Then I try to teach it, using only annotated data. Problem is, that ALL predictions are just red squares. What I miss?\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fb3627d139c3ef770771ef54605f484d4%2F1.jpg?generation=1687875857220799&alt=media)\n\n```\nx_valid_dir = '/kaggle/working/validation_data/x_valid'\ny_valid_dir = '/kaggle/working/validation_data/y_valid'\nx_train_dir = '/kaggle/working/validation_data/x_train'\ny_train_dir = '/kaggle/working/validation_data/y_train'\n\n# Create the Dataset and DataLoader for training and validation\ntrain_dataset = Dataset(\n    x_train_dir, \n    y_train_dir, \n    augmentation=get_training_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    augmentation=get_validation_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\ntrain_loader = DataLoader(train_dataset, batch_size=8, shuffle=True, num_workers=12)\nvalid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4)\n```\n```\nmax_score = 0\n\nfor i in range(0, 3):\n    \n    print('\\nEpoch: {}'.format(i))\n    train_logs = train_epoch.run(train_loader)\n    valid_logs = valid_epoch.run(valid_loader)\n    \n    if max_score < valid_logs['iou_score']:\n        max_score = valid_logs['iou_score']\n        torch.save(model, './best_model.pth')\n        print('Model saved!')\n        \n    if i == 25:\n        optimizer.param_groups[0]['lr'] = 1e-5\n        print('Decrease decoder learning rate to 1e-5!')\n```\n```\nbest_model = torch.load('./best_model.pth')\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    augmentation=get_validation_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\nvalid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4)\npredictions = []\nfor image, _ in valid_loader:\n    image = image.to(DEVICE)\n    pr_mask = best_model.predict(image)\n    pr_mask = (pr_mask.squeeze().cpu().numpy().round())\n    predictions.append(pr_mask)\n```\n\n```\nfor i in predictions:\n    plt.imshow(np.transpose(i, (1, 2, 0)))\n    plt.show(block=False)\n    \n    # Wait for user input\n    key = input(\"Press 'q' to quit or any other key to continue: \")\n    \n    # Check if the 'q' key was pressed\n    if key == 'q':\n        break\n\nplt.close()\n```\nExamples of images and masks are below. We can see that train and valid data is ok.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fd4c36abdf71808d1a37a0455cde7213d%2F2.jpg?generation=1687875869381267&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fff7dd5ff5ae506fe868eb717d351097a%2F3.jpg?generation=1687875931997715&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F066022c384861e992b98d533953f5540%2F4.jpg?generation=1687875988408869&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F4dcddce33eaa4c70a228096529fa2bb5%2F5.jpg?generation=1687876000422419&alt=media)"
    }
  ],
  "comments": [
    {
      "id": 2320687,
      "author_name": "Feng Qilong",
      "author_url": "",
      "post_date": "2023-06-28T03:05:47.047000",
      "content": "<p>you need to use argmax on the output, else it will just be a stacked masks</p>",
      "votes": 1,
      "replies": [
        {
          "id": 2321416,
          "author_name": "kapedalex",
          "author_url": "",
          "post_date": "2023-06-28T14:52:57.163000",
          "content": "<p>Thank you, but this does not help. I have changed one line in output:</p>\n<pre><code>for image, _ in valid_loader:\n  image = image.(DEVICE)\n  pr_mask = best_model.(image)\n  pr_mask = torch.(pr_mask, dim=) # argmax here\n  pr_mask = (pr_mask.().().().())\n  predictions.(pr_mask)    \n</code></pre>\n<p>Now all squares are purple as background.<br>\nBefore argmax tensors are like</p>\n<pre><code>tensor([[[[9.9973e, 9.9984e, 9.9990e,  ..., 9.9987e,\n         9.9976e, 9.9955e],\n        [9.9988e, 9.9994e, 9.9997e,  ..., 9.9995e,\n         9.9991e, 9.9981e],\n        [9.9994e, 9.9997e, 9.9999e,  ..., 9.9998e,\n         9.9996e, 9.9992e],\n</code></pre>\n<p>And after it and squeeze all becomes 0.</p>\n<pre><code>\nhas_not_zero = (predictions != )()\n\n</code></pre>\n<p>Output is<br>\n(512, 512)<br>\nFalse<br>\nIf we do not argmax, there will be really small numbers</p>\n<pre><code>\npredictions\n​\nindexes = np(predictions &gt; )\n idx  indexes:\n  (idx)\n</code></pre>\n<p>Output is<br>\n(3, 512, 512)<br>\n[0 0 0]<br>\n[0 0 1]<br>\n[0 0 2]<br>\n[ 0  0 16]<br>\n[0 1 0]<br>\n[  0 510 511]<br>\n[  0 511 510]</p>\n<h1>As I see, results on valid does not change at all:</h1>\n<p>Epoch: 0<br>\ntrain: 100%|██████████| 184/184 [01:59&lt;00:00,  1.53it/s, dice_loss - 0.1374, iou_score - 0.7633]<br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 23.07it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nModel saved!<br>\nEpoch: 1<br>\ntrain: 100%|██████████| 184/184 [01:52&lt;00:00,  1.63it/s, dice_loss - 0.1279, iou_score - 0.777] <br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 20.97it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 2<br>\ntrain: 100%|██████████| 184/184 [01:52&lt;00:00,  1.63it/s, dice_loss - 0.1283, iou_score - 0.7765]<br>\nvalid: 100%|██████████| 163/163 [00:07&lt;00:00, 22.92it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 3<br>\ntrain: 100%|██████████| 184/184 [01:54&lt;00:00,  1.61it/s, dice_loss - 0.1276, iou_score - 0.7771]<br>\nvalid: 100%|██████████| 163/163 [00:06&lt;00:00, 23.72it/s, dice_loss - 0.02045, iou_score - 0.9608]<br>\nEpoch: 4<br>\ntrain: 100%|██████████| 184/184 [01:53&lt;00:00,  1.62it/s, dice_loss - 0.1306, iou_score - 0.7726]<br>\nvalid: 100%|██████████| 163/163 [00:06&lt;00:00, 23.71it/s, dice_loss - 0.02045, iou_score - 0.9608]</p>",
          "votes": 0,
          "replies": [
            {
              "id": 2325068,
              "author_name": "Feng Qilong",
              "author_url": "",
              "post_date": "2023-07-01T05:35:08.363000",
              "content": "<p>you have to choose the class that you want to output, i.e if your output has only one class then pred = pr_mask[:, 1], after this you can choose a threshold</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 2325554,
              "author_name": "kapedalex",
              "author_url": "",
              "post_date": "2023-07-01T12:54:27.293000",
              "content": "<p>Does not help at all… <br>\ntorch.Size([512])<br>\ntensor([0.9999, 0.9999, 0.9999, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,<br>\n        1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 2325561,
              "author_name": "Feng Qilong",
              "author_url": "",
              "post_date": "2023-07-01T12:59:02.303000",
              "content": "<p>may i know the shape of the output?</p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 2325829,
              "author_name": "kapedalex",
              "author_url": "",
              "post_date": "2023-07-01T15:55:31.150000",
              "content": "<p>I decided to make it public, so you can test, here you are) Also changed output to be closer to original, but issue still there.</p>\n<p><a href=\"https://www.kaggle.com/code/kapedalex/segmentation-cars2hubmap\" target=\"_blank\">https://www.kaggle.com/code/kapedalex/segmentation-cars2hubmap</a></p>",
              "votes": 0,
              "replies": []
            },
            {
              "id": 2327763,
              "author_name": "",
              "author_url": "",
              "post_date": "2023-07-03T06:46:45.723000",
              "content": "",
              "votes": 0,
              "replies": []
            },
            {
              "id": 2501864,
              "author_name": "PietroBrugnolo11",
              "author_url": "",
              "post_date": "2023-10-27T18:04:10.070000",
              "content": "<p>I'm experiencing the same problem in a different framework. I'm trying to do sem seg on an aerial dataset, I've tryied many networks. The loss converge but there is only 1 layer  (class) of the ouput tensor where all the energy is and this leads to a black output.  Did you eventually find out why? </p>",
              "votes": 0,
              "replies": []
            }
          ]
        }
      ]
    }
  ],
  "raw_markdown_by_id": {
    "2320687": "you need to use argmax on the output, else it will just be a stacked masks",
    "2320156": "Based on advice I tried to use Segmentation-models-pytorch for this task. Here is link:\nhttps://github.com/qubvel/segmentation_models.pytorch/blob/master/examples/cars%20segmentation%20(camvid).ipynb\n\nBelow is an extract of useful code: model, loss, optimizer, TrainEpochs, Dataloaders. Only thing changed is  CLASSES = ['blood_vessel', 'glomerulus', 'unsure'].\n\n```\nENCODER = 'se_resnext50_32x4d'\nENCODER_WEIGHTS = 'imagenet'\nCLASSES = ['blood_vessel', 'glomerulus', 'unsure']\nACTIVATION = 'softmax2d' # could be None for logits or 'softmax2d' for multiclass segmentation\nDEVICE = 'cuda'\n\nmodel = smp.FPN(\n    encoder_name=ENCODER, \n    encoder_weights=ENCODER_WEIGHTS, \n    classes=len(CLASSES), \n    activation=ACTIVATION,\n)\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\n\nfrom segmentation_models_pytorch import utils\n\nloss = smp.utils.losses.DiceLoss()\nmetrics = [\n    smp.utils.metrics.IoU(threshold=0.5),\n]\n\noptimizer = torch.optim.Adam([ \n    dict(params=model.parameters(), lr=0.0001),\n])\n```\n```\ntrain_epoch = smp.utils.train.TrainEpoch(\n    model, \n    loss=loss, \n    metrics=metrics, \n    optimizer=optimizer,\n    device=DEVICE,\n    verbose=True,\n)\n\nvalid_epoch = smp.utils.train.ValidEpoch(\n    model, \n    loss=loss, \n    metrics=metrics, \n    device=DEVICE,\n    verbose=True,\n)\n```\n```\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import Dataset as BaseDataset\n\nclass Dataset(BaseDataset):\n    \n    CLASSES = ['blood_vessel', 'glomerulus', 'unsure']\n    \n    def __init__(\n            self, \n            images_dir, \n            masks_dir, \n            classes=None, \n            augmentation=None, \n            preprocessing=None,\n    ):\n        self.ids = os.listdir(images_dir)\n        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]\n        self.masks_fps = [os.path.join(masks_dir, image_id) for image_id in self.ids]\n        \n        # convert str names to class values on masks\n        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]\n        print(self.class_values)\n        \n        self.augmentation = augmentation\n        self.preprocessing = preprocessing\n    \n    def __getitem__(self, i):\n        \n        # read data\n        image = cv2.imread(self.images_fps[i])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        mask = cv2.imread(self.masks_fps[i], 0)\n        # extract certain classes from mask (e.g. cars)\n        masks = [(mask == v) for v in self.class_values]\n        mask = np.stack(masks, axis=-1).astype('float')\n        \n        # apply augmentations\n        if self.augmentation:\n            sample = self.augmentation(image=image, mask=mask)\n            image, mask = sample['image'], sample['mask']\n        \n        # apply preprocessing\n        if self.preprocessing:\n            sample = self.preprocessing(image=image, mask=mask)\n            image, mask = sample['image'], sample['mask']\n            \n        return image, mask\n        \n    def __len__(self):\n        return len(self.ids)\n```\n#Then I try to teach it, using only annotated data. Problem is, that ALL predictions are just red squares. What I miss?\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fb3627d139c3ef770771ef54605f484d4%2F1.jpg?generation=1687875857220799&alt=media)\n\n```\nx_valid_dir = '/kaggle/working/validation_data/x_valid'\ny_valid_dir = '/kaggle/working/validation_data/y_valid'\nx_train_dir = '/kaggle/working/validation_data/x_train'\ny_train_dir = '/kaggle/working/validation_data/y_train'\n\n# Create the Dataset and DataLoader for training and validation\ntrain_dataset = Dataset(\n    x_train_dir, \n    y_train_dir, \n    augmentation=get_training_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    augmentation=get_validation_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\ntrain_loader = DataLoader(train_dataset, batch_size=8, shuffle=True, num_workers=12)\nvalid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4)\n```\n```\nmax_score = 0\n\nfor i in range(0, 3):\n    \n    print('\\nEpoch: {}'.format(i))\n    train_logs = train_epoch.run(train_loader)\n    valid_logs = valid_epoch.run(valid_loader)\n    \n    if max_score < valid_logs['iou_score']:\n        max_score = valid_logs['iou_score']\n        torch.save(model, './best_model.pth')\n        print('Model saved!')\n        \n    if i == 25:\n        optimizer.param_groups[0]['lr'] = 1e-5\n        print('Decrease decoder learning rate to 1e-5!')\n```\n```\nbest_model = torch.load('./best_model.pth')\nvalid_dataset = Dataset(\n    x_valid_dir, \n    y_valid_dir, \n    augmentation=get_validation_augmentation(), \n    preprocessing=get_preprocessing(preprocessing_fn),\n    classes=CLASSES,\n)\n\nvalid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4)\npredictions = []\nfor image, _ in valid_loader:\n    image = image.to(DEVICE)\n    pr_mask = best_model.predict(image)\n    pr_mask = (pr_mask.squeeze().cpu().numpy().round())\n    predictions.append(pr_mask)\n```\n\n```\nfor i in predictions:\n    plt.imshow(np.transpose(i, (1, 2, 0)))\n    plt.show(block=False)\n    \n    # Wait for user input\n    key = input(\"Press 'q' to quit or any other key to continue: \")\n    \n    # Check if the 'q' key was pressed\n    if key == 'q':\n        break\n\nplt.close()\n```\nExamples of images and masks are below. We can see that train and valid data is ok.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fd4c36abdf71808d1a37a0455cde7213d%2F2.jpg?generation=1687875869381267&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2Fff7dd5ff5ae506fe868eb717d351097a%2F3.jpg?generation=1687875931997715&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F066022c384861e992b98d533953f5540%2F4.jpg?generation=1687875988408869&alt=media)\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F10796179%2F4dcddce33eaa4c70a228096529fa2bb5%2F5.jpg?generation=1687876000422419&alt=media)"
  }
}