| |
| |
| |
| |
|
|
| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
|
|
|
|
| class LinearHead(nn.Module): |
| """Linear layer .""" |
|
|
| def __init__( |
| self, |
| in_channels, |
| n_output_channels, |
| use_batchnorm=True, |
| use_cls_token=False, |
| ): |
| super().__init__() |
| self.in_channels = in_channels |
| self.channels = sum(in_channels) |
| if use_cls_token: |
| self.channels *= 2 |
| self.n_output_channels = n_output_channels |
| self.use_cls_token = use_cls_token |
| self.batchnorm_layer = nn.SyncBatchNorm(self.channels) if use_batchnorm else nn.Identity(self.channels) |
| self.conv = nn.Conv2d(self.channels, self.n_output_channels, kernel_size=1, padding=0, stride=1) |
| self.dropout = nn.Dropout2d(0.1) |
| nn.init.normal_(self.conv.weight, mean=0, std=0.01) |
| nn.init.constant_(self.conv.bias, 0) |
|
|
| def _transform_inputs(self, inputs): |
| """Transform inputs for decoder. |
| Args: |
| inputs (list[Tensor]): List of multi-level img features. |
| Returns: |
| Tensor: The transformed inputs |
| """ |
| inputs = [ |
| torch.nn.functional.interpolate( |
| input=x, |
| size=inputs[0].shape[2:], |
| mode="bilinear", |
| align_corners=False, |
| ) |
| for x in inputs |
| ] |
| inputs = torch.cat(inputs, dim=1) |
| return inputs |
|
|
| def _forward_feature(self, inputs): |
| """Forward function for feature maps before classifying each pixel with |
| ``self.cls_seg`` fc. |
| Args: |
| inputs (list[Tensor]): List of multi-level img features. |
| Returns: |
| feats (Tensor): A tensor of shape (batch_size, self.channels, |
| H, W) which is feature map for last layer of decoder head. |
| """ |
| |
| inputs = list(inputs) |
| for i, x in enumerate(inputs): |
| if self.use_cls_token: |
| assert len(x) == 2, "Missing class tokens" |
| x, cls_token = x[0], x[1] |
| if len(x.shape) == 2: |
| x = x[:, :, None, None] |
| cls_token = cls_token[:, :, None, None].expand_as(x) |
| inputs[i] = torch.cat((x, cls_token), 1) |
| else: |
| if len(x.shape) == 2: |
| x = x[:, :, None, None] |
| inputs[i] = x |
| x = self._transform_inputs(inputs) |
| return x |
|
|
| def forward(self, inputs): |
| """Forward function.""" |
| output = self._forward_feature(inputs) |
| output = self.dropout(output) |
| output = self.batchnorm_layer(output) |
| output = self.conv(output) |
| return output |
|
|
| def predict(self, x, rescale_to=(512, 512)): |
| """ |
| Predict function used in evaluation. |
| No dropout is used, and the output is rescaled to the ground truth |
| for computing metrics. |
| """ |
| x = self._forward_feature(x) |
| x = self.batchnorm_layer(x) |
| x = self.conv(x) |
| x = F.interpolate(input=x, size=rescale_to, mode="bilinear") |
| return x |
|
|