| import torch |
| import torch.nn as nn |
| from itertools import chain |
| from typing import Callable |
| from torch.utils.checkpoint import checkpoint |
|
|
| import numpy.random as random |
| import torch.nn.functional as F |
| |
|
|
|
|
| |
|
|
| |
|
|
| |
| |
|
|
|
|
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| class MinkowskiDropPath(nn.Module): |
| """Drop Path for sparse tensors.""" |
|
|
| def __init__(self, drop_prob: float = 0.0, scale_by_keep: bool = True): |
| super(MinkowskiDropPath, self).__init__() |
| self.drop_prob = drop_prob |
| self.scale_by_keep = scale_by_keep |
|
|
| def forward(self, x): |
| if self.drop_prob == 0.0 or not self.training: |
| return x |
| cm = x.coordinate_manager |
| in_key = x.coordinate_map_key |
| keep_prob = 1 - self.drop_prob |
| mask = ( |
| torch.cat( |
| [ |
| ( |
| torch.ones(len(_)) |
| if random.uniform(0, 1) > self.drop_prob |
| else torch.zeros(len(_)) |
| ) |
| for _ in x.decomposed_coordinates |
| ] |
| ) |
| .view(-1, 1) |
| .to(x.device) |
| ) |
| if keep_prob > 0.0 and self.scale_by_keep: |
| mask.div_(keep_prob) |
| return SparseTensor( |
| x.F * mask, coordinate_map_key=in_key, coordinate_manager=cm |
| ) |
|
|
|
|
| class MinkowskiLayerNorm(nn.Module): |
| """Channel-wise layer normalization for sparse tensors.""" |
|
|
| def __init__( |
| self, |
| normalized_shape, |
| eps=1e-6, |
| ): |
| super(MinkowskiLayerNorm, self).__init__() |
| self.ln = nn.LayerNorm(normalized_shape, eps=eps) |
|
|
| def forward(self, input): |
| output = self.ln(input.F) |
| return SparseTensor( |
| output, |
| coordinate_map_key=input.coordinate_map_key, |
| coordinate_manager=input.coordinate_manager, |
| ) |
|
|
|
|
| class LayerNorm(nn.Module): |
| """LayerNorm that supports two data formats: channels_last (default) or channels_first. |
| The ordering of the dimensions in the inputs. channels_last corresponds to inputs with |
| shape (batch_size, height, width, channels) while channels_first corresponds to inputs |
| with shape (batch_size, channels, height, width). |
| """ |
|
|
| def __init__(self, normalized_shape, eps=1e-6, data_format="channels_last"): |
| super().__init__() |
| self.weight = nn.Parameter(torch.ones(normalized_shape)) |
| self.bias = nn.Parameter(torch.zeros(normalized_shape)) |
| self.eps = eps |
| self.data_format = data_format |
| if self.data_format not in ["channels_last", "channels_first"]: |
| raise NotImplementedError |
| self.normalized_shape = (normalized_shape,) |
|
|
| def forward(self, x): |
| if self.data_format == "channels_last": |
| return F.layer_norm( |
| x, self.normalized_shape, self.weight, self.bias, self.eps |
| ) |
| elif self.data_format == "channels_first": |
| if len(x.shape) == 3: |
| u = x.mean(1, keepdim=True) |
| s = (x - u).pow(2).mean(1, keepdim=True) |
| x = (x - u) / torch.sqrt(s + self.eps) |
| x = self.weight * x + self.bias |
| return x |
| else: |
| u = x.mean(1, keepdim=True) |
| s = (x - u).pow(2).mean(1, keepdim=True) |
| x = (x - u) / torch.sqrt(s + self.eps) |
| x = self.weight[:, None, None, None] * x + self.bias[:, None, None, None] |
| return x |
|
|
|
|
| class GRN(nn.Module): |
| """GRN (Global Response Normalization) layer""" |
|
|
| def __init__(self, dim): |
| super().__init__() |
| self.gamma = nn.Parameter(torch.zeros(1, 1, 1, 1, dim)) |
| self.beta = nn.Parameter(torch.zeros(1, 1, 1, 1, dim)) |
|
|
| def forward(self, x): |
| Gx = torch.norm(x, p=2, dim=(1, 2, 3), keepdim=True) |
| Nx = Gx / (Gx.mean(dim=-1, keepdim=True) + 1e-6) |
| return self.gamma * (x * Nx) + self.beta + x |
|
|
|
|
| def get_tokens(embed_dim: int, n_tokens: int) -> nn.Parameter: |
| """Return a learnable token of shape (1, n_tokens, embed_dim). |
| |
| Args: |
| embed_dim: number of embedding channels. |
| n_tokens: number of tokens. |
| |
| Returns: |
| token: learnable token. |
| """ |
| token = nn.Parameter(torch.zeros(1, n_tokens, embed_dim)) |
| |
| nn.init.trunc_normal_(token, std=0.02, b=2.0) |
| return token |
|
|
|
|
| def init_weights(m): |
| if isinstance(m, nn.Linear): |
| |
| torch.nn.init.xavier_uniform_(m.weight) |
| if isinstance(m, nn.Linear) and m.bias is not None: |
| nn.init.constant_(m.bias, 0) |
| elif isinstance(m, nn.LayerNorm): |
| nn.init.constant_(m.bias, 0) |
| nn.init.constant_(m.weight, 1.0) |
|
|
|
|
| """Gradient checkpointing utilities. |
| |
| Copied from |
| https://github.com/huggingface/pytorch-image-models/blob/f8979d4f50b7920c78511746f7315df8f1857bc5/timm/models/_manipulate.py |
| and added use_reentrant=False following warnings in pytorch docs. |
| """ |
|
|
|
|
| def checkpoint_seq( |
| functions: nn.Sequential, |
| x: torch.Tensor, |
| every: int = 1, |
| flatten: bool = False, |
| skip_last: bool = False, |
| preserve_rng_state: bool = True, |
| ) -> torch.Tensor: |
| r"""A helper function for checkpointing sequential models. |
| |
| Sequential models execute a list of modules/functions in order |
| (sequentially). Therefore, we can divide such a sequence into segments |
| and checkpoint each segment. All segments except run in :func:`torch.no_grad` |
| manner, i.e., not storing the intermediate activations. The inputs of each |
| checkpointed segment will be saved for re-running the segment in the backward pass. |
| |
| See :func:`~torch.utils.checkpoint.checkpoint` on how checkpointing works. |
| |
| .. warning:: |
| Checkpointing currently only supports :func:`torch.autograd.backward` |
| and only if its `inputs` argument is not passed. :func:`torch.autograd.grad` |
| is not supported. |
| |
| .. warning: |
| At least one of the inputs needs to have :code:`requires_grad=True` if |
| grads are needed for model inputs, otherwise the checkpointed part of the |
| model won't have gradients. |
| |
| Args: |
| functions: A :class:`torch.nn.Sequential` or the list of modules or functions to run sequentially. |
| x: A Tensor that is input to :attr:`functions` |
| every: checkpoint every-n functions (default: 1) |
| flatten (bool): flatten nn.Sequential of nn.Sequentials |
| skip_last (bool): skip checkpointing the last function in the sequence if True |
| preserve_rng_state (bool, optional, default=True): Omit stashing and restoring |
| the RNG state during each checkpoint. |
| |
| Returns: |
| Output of running :attr:`functions` sequentially on :attr:`*inputs` |
| |
| Example: |
| >>> model = nn.Sequential(...) |
| >>> input_var = checkpoint_seq(model, input_var, every=2) |
| """ |
|
|
| def run_function( |
| start: int, end: int, functions: nn.Sequential |
| ) -> Callable[[torch.Tensor], torch.Tensor]: |
| def forward(_x: torch.Tensor) -> torch.Tensor: |
| for j in range(start, end + 1): |
| _x = functions[j](_x) |
| return _x |
|
|
| return forward |
|
|
| if isinstance(functions, torch.nn.Sequential): |
| functions = functions.children() |
| if flatten: |
| functions = chain.from_iterable(functions) |
| if not isinstance(functions, (tuple, list)): |
| functions = tuple(functions) |
|
|
| num_checkpointed = len(functions) |
| if skip_last: |
| num_checkpointed -= 1 |
| end = -1 |
| for start in range(0, num_checkpointed, every): |
| end = min(start + every - 1, num_checkpointed - 1) |
| x = checkpoint( |
| run_function(start, end, functions), |
| x, |
| use_reentrant=False, |
| preserve_rng_state=preserve_rng_state, |
| ) |
| if skip_last: |
| return run_function(end + 1, len(functions) - 1, functions)(x) |
| return x |
|
|