Addax-Data-Science's picture
Upload 162 files
d9bb75c verified
Raw
History Blame Contribute Delete
3.36 kB
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This software may be used and distributed in accordance with
# the terms of the DINOv3 License Agreement.
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 # concatenate CLS to patch tokens
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.
"""
# accept lists (for cls token)
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