Multiple Instance Learning (MIL) model, with a backbone classification model. Currently, it only works for 2D images, a typical use case is for classification of the digital pathology whole slide images. The expected shape of input data is `[B, N, C, H, W]`, where `B` is the batch_s
| 22 | |
| 23 | |
| 24 | class MILModel(nn.Module): |
| 25 | """ |
| 26 | Multiple Instance Learning (MIL) model, with a backbone classification model. |
| 27 | Currently, it only works for 2D images, a typical use case is for classification of the |
| 28 | digital pathology whole slide images. The expected shape of input data is `[B, N, C, H, W]`, |
| 29 | where `B` is the batch_size of PyTorch Dataloader and `N` is the number of instances |
| 30 | extracted from every original image in the batch. A tutorial example is available at: |
| 31 | https://github.com/Project-MONAI/tutorials/tree/master/pathology/multiple_instance_learning. |
| 32 | |
| 33 | Args: |
| 34 | num_classes: number of output classes. |
| 35 | mil_mode: MIL algorithm, available values (Defaults to ``"att"``): |
| 36 | |
| 37 | - ``"mean"`` - average features from all instances, equivalent to pure CNN (non MIL). |
| 38 | - ``"max"`` - retain only the instance with the max probability for loss calculation. |
| 39 | - ``"att"`` - attention based MIL https://arxiv.org/abs/1802.04712. |
| 40 | - ``"att_trans"`` - transformer MIL https://arxiv.org/abs/2111.01556. |
| 41 | - ``"att_trans_pyramid"`` - transformer pyramid MIL https://arxiv.org/abs/2111.01556. |
| 42 | |
| 43 | pretrained: init backbone with pretrained weights, defaults to ``True``. |
| 44 | backbone: Backbone classifier CNN (either ``None``, a ``nn.Module`` that returns features, |
| 45 | or a string name of a torchvision model). |
| 46 | Defaults to ``None``, in which case ResNet50 is used. |
| 47 | backbone_num_features: Number of output features of the backbone CNN |
| 48 | Defaults to ``None`` (necessary only when using a custom backbone) |
| 49 | trans_blocks: number of the blocks in `TransformEncoder` layer. |
| 50 | trans_dropout: dropout rate in `TransformEncoder` layer. |
| 51 | """ |
| 52 | |
| 53 | def __init__( |
| 54 | self, |
| 55 | num_classes: int, |
| 56 | mil_mode: str = "att", |
| 57 | pretrained: bool = True, |
| 58 | backbone: str | nn.Module | None = None, |
| 59 | backbone_num_features: int | None = None, |
| 60 | trans_blocks: int = 4, |
| 61 | trans_dropout: float = 0.0, |
| 62 | ) -> None: |
| 63 | super().__init__() |
| 64 | |
| 65 | if num_classes <= 0: |
| 66 | raise ValueError("Number of classes must be positive: " + str(num_classes)) |
| 67 | |
| 68 | if mil_mode.lower() not in ["mean", "max", "att", "att_trans", "att_trans_pyramid"]: |
| 69 | raise ValueError("Unsupported mil_mode: " + str(mil_mode)) |
| 70 | |
| 71 | self.mil_mode = mil_mode.lower() |
| 72 | self.attention = nn.Sequential() |
| 73 | self.transformer: nn.Module | None = None |
| 74 | |
| 75 | if backbone is None: |
| 76 | net = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1 if pretrained else None) |
| 77 | nfc = net.fc.in_features # save the number of final features |
| 78 | net.fc = torch.nn.Identity() # remove final linear layer |
| 79 | |
| 80 | self.extra_outputs: dict[str, torch.Tensor] = {} |
| 81 |
no outgoing calls
searching dependent graphs…