content: import torch.nn as nn
  import torch.utils.checkpoint as cp
  from mmcv.cnn import ConvModule, constant_init, kaiming_init
  from mmcv.runner import load_checkpoint
  from torch.nn.modules.batchnorm import _BatchNorm
  from torch.nn.modules.utils import _ntuple
  
  from mmaction.models.registry import BACKBONES
  from mmaction.utils import get_root_logger
  
  
  class Bottleneck2dAudio(nn.Module):
      """Bottleneck2D block for ResNet2D.
  
      Args:
          inplanes (int): Number of channels for the input in first conv3d layer.
          planes (int): Number of channels produced by some norm/conv3d layers.
          stride (int | tuple[int]): Stride in the conv layer. Default: 1.
          dilation (int): Spacing between kernel elements. Default: 1.
          downsample (nn.Module): Downsample layer. Default: None.
          factorize (bool): Whether to factorize kernel. Default: True.
          norm_cfg (dict):
              Config for norm layers. required keys are `type` and
              `requires_grad`. Default: None.
          with_cp (bool): Use checkpoint or not. Using checkpoint will save some
              memory while slowing down the training speed. Default: False.
      """
      expansion = 4
  
      def __init__(self,
                   inplanes,
                   planes,
                   stride=2,
                   dilation=1,
                   downsample=None,
                   factorize=True,
                   norm_cfg=None,
                   with_cp=False):
          super().__init__()
  
          self.inplanes = inplanes
          self.planes = planes
          self.stride = stride
          self.dilation = dilation
          self.factorize = factorize
          self.norm_cfg = norm_cfg
          self.with_cp = with_cp
  
          self.conv1_stride = 1
          self.conv2_stride = stride
  
          conv1_kernel_size = (1, 1)
          conv1_padding = 0
          conv2_kernel_size = (3, 3)
          conv2_padding = (dilation, dilation)
          self.conv1 = ConvModule(
              inplanes,
              planes,
              kernel_size=conv1_kernel_size,
              padding=conv1_padding,
              dilation=dilation,
              norm_cfg=self.norm_cfg,
              bias=False)
          self.conv2 = ConvModule(
              planes,
              planes,
              kernel_size=conv2_kernel_size,
              stride=stride,
              padding=conv2_padding,
              dilation=dilation,
              bias=False,
              conv_cfg=dict(type='ConvAudio') if factorize else dict(
                  type='Conv'),
              norm_cfg=None,
              act_cfg=None)
          self.conv3 = ConvModule(
              2 * planes if factorize else planes,
              planes * self.expansion,
              kernel_size=1,
              bias=False,
              norm_cfg=self.norm_cfg,
              act_cfg=None)
  
          self.relu = nn.ReLU(inplace=True)
          self.downsample = downsample
  
      def forward(self, x):
  
          def _inner_forward(x):
              identity = x
              out = self.conv1(x)
              out = self.conv2(out)
              out = self.conv3(out)
  
              if self.downsample is not None:
                  identity = self.downsample(x)
              out += identity
  
              return out
  
          if self.with_cp and x.requires_grad:
              out = cp.checkpoint(_inner_forward, x)
          else:
              out = _inner_forward(x)
  
          out = self.relu(out)
  
          return out
  
  
  @BACKBONES.register_module()
  class ResNetAudio(nn.Module):
      """ResNet 2d audio backbone. Reference:
  
          <https://arxiv.org/abs/2001.08740>`_.
  
      Args:
          depth (int): Depth of resnet, from {50, 101, 152}.
          pretrained (str | None): Name of pretrained model.
          in_channels (int): Channel num of input features. Default: 1.
          base_channels (int): Channel num of stem output features. Default: 32.
          num_stages (int): Resnet stages. Default: 4.
          strides (Sequence[int]): Strides of residual blocks of each stage.
              Default: (1, 2, 2, 2).
          dilations (Sequence[int]): Dilation of each stage.
              Default: (1, 1, 1, 1).
          conv1_kernel (int): Kernel size of the first conv layer. Default: 9.
          conv1_stride (int | tuple[int]): Stride of the first conv layer.
              Default: 1.
          frozen_stages (int): Stages to be frozen (all param fixed). -1 means
              not freezing any parameters.
          factorize (Sequence[int]): factorize Dims of each block for audio.
              Default: (1, 1, 0, 0).
          norm_eval (bool): Whether to set BN layers to eval mode, namely, freeze
              running stats (mean and var). Default: False.
          with_cp (bool): Use checkpoint or not. Using checkpoint will save some
              memory while slowing down the training speed. Default: False.
          conv_cfg (dict): Config for norm layers. Default: dict(type='Conv').
          norm_cfg (dict):
              Config for norm layers. required keys are `type` and
              `requires_grad`. Default: dict(type='BN2d', requires_grad=True).
          act_cfg (dict): Config for activate layers.
              Default: dict(type='ReLU', inplace=True).
          zero_init_residual (bool):
              Whether to use zero initialization for residual block,
              Default: True.
      """
  
      arch_settings = {
          # 18: (BasicBlock2dAudio, (2, 2, 2, 2)),
          # 34: (BasicBlock2dAudio, (3, 4, 6, 3)),
          50: (Bottleneck2dAudio, (3, 4, 6, 3)),
          101: (Bottleneck2dAudio, (3, 4, 23, 3)),
          152: (Bottleneck2dAudio, (3, 8, 36, 3))
      }
  
      def __init__(self,
                   depth,
                   pretrained,
                   in_channels=1,
                   num_stages=4,
                   base_channels=32,
                   strides=(1, 2, 2, 2),
                   dilations=(1, 1, 1, 1),
                   conv1_kernel=9,
                   conv1_stride=1,
                   frozen_stages=-1,
                   factorize=(1, 1, 0, 0),
                   norm_eval=False,
                   with_cp=False,
                   conv_cfg=dict(type='Conv'),
                   norm_cfg=dict(type='BN2d', requires_grad=True),
                   act_cfg=dict(type='ReLU', inplace=True),
                   zero_init_residual=True):
          super().__init__()
          if depth not in self.arch_settings:
              raise KeyError(f'invalid depth {depth} for resnet')
          self.depth = depth
          self.pretrained = pretrained
          self.in_channels = in_channels
          self.base_channels = base_channels
          self.num_stages = num_stages
          assert num_stages >= 1 and num_stages <= 4
          self.dilations = dilations
          self.conv1_kernel = conv1_kernel
          self.conv1_stride = conv1_stride
          self.frozen_stages = frozen_stages
          self.stage_factorization = _ntuple(num_stages)(factorize)
          self.norm_eval = norm_eval
          self.with_cp = with_cp
          self.conv_cfg = conv_cfg
          self.norm_cfg = norm_cfg
          self.act_cfg = act_cfg
          self.zero_init_residual = zero_init_residual
  
          self.block, stage_blocks = self.arch_settings[depth]
          self.stage_blocks = stage_blocks[:num_stages]
          self.inplanes = self.base_channels
  
          self._make_stem_layer()
  
          self.res_layers = []
          for i, num_blocks in enumerate(self.stage_blocks):
              stride = strides[i]
              dilation = dilations[i]
              planes = self.base_channels * 2**i
              res_layer = self.make_res_layer(
                  self.block,
                  self.inplanes,
                  planes,
                  num_blocks,
                  stride=stride,
                  dilation=dilation,
                  factorize=self.stage_factorization[i],
                  norm_cfg=self.norm_cfg,
                  with_cp=with_cp)
              self.inplanes = planes * self.block.expansion
              layer_name = f'layer{i + 1}'
              self.add_module(layer_name, res_layer)
              self.res_layers.append(layer_name)
  
          self.feat_dim = self.block.expansion * self.base_channels * 2**(
              len(self.stage_blocks) - 1)
  
      def make_res_layer(self,
                         block,
                         inplanes,
                         planes,
                         blocks,
                         stride=1,
                         dilation=1,
                         factorize=1,
                         norm_cfg=None,
                         with_cp=False):
          """Build residual layer for ResNetAudio.
  
          Args:
              block (nn.Module): Residual module to be built.
              inplanes (int): Number of channels for the input feature
                  in each block.
              planes (int): Number of channels for the output feature
                  in each block.
              blocks (int): Number of residual blocks.
              strides (Sequence[int]): Strides of residual blocks of each stage.
                  Default: (1, 2, 2, 2).
              dilation (int): Spacing between kernel elements. Default: 1.
              factorize (int | Sequence[int]): Determine whether to factorize
                  for each block. Default: 1.
              norm_cfg (dict):
                  Config for norm layers. required keys are `type` and
                  `requires_grad`. Default: None.
              with_cp (bool): Use checkpoint or not. Using checkpoint will save
                  some memory while slowing down the training speed.
                  Default: False.
  
          Returns:
              A residual layer for the given config.
          """
          factorize = factorize if not isinstance(
              factorize, int) else (factorize, ) * blocks
          assert len(factorize) == blocks
          downsample = None
          if stride != 1 or inplanes != planes * block.expansion:
              downsample = ConvModule(
                  inplanes,
                  planes * block.expansion,
                  kernel_size=1,
                  stride=stride,
                  bias=False,
                  norm_cfg=norm_cfg,
                  act_cfg=None)
  
          layers = []
          layers.append(
              block(
                  inplanes,
                  planes,
                  stride,
                  dilation,
                  downsample,
                  factorize=(factorize[0] == 1),
                  norm_cfg=norm_cfg,
                  with_cp=with_cp))
          inplanes = planes * block.expansion
          for i in range(1, blocks):
              layers.append(
                  block(
                      inplanes,
                      planes,
                      1,
                      dilation,
                      factorize=(factorize[i] == 1),
                      norm_cfg=norm_cfg,
                      with_cp=with_cp))
  
          return nn.Sequential(*layers)
  
      def _make_stem_layer(self):
          """Construct the stem layers consists of a conv+norm+act module and a
          pooling layer."""
          self.conv1 = ConvModule(
              self.in_channels,
              self.base_channels,
              kernel_size=self.conv1_kernel,
              stride=self.conv1_stride,
              bias=False,
              conv_cfg=dict(type='ConvAudio', op='sum'),
              norm_cfg=self.norm_cfg,
              act_cfg=self.act_cfg)
  
      def _freeze_stages(self):
          """Prevent all the parameters from being optimized before
          ``self.frozen_stages``."""
          if self.frozen_stages >= 0:
              self.conv1.bn.eval()
              for m in [self.conv1.conv, self.conv1.bn]:
                  for param in m.parameters():
                      param.requires_grad = False
  
          for i in range(1, self.frozen_stages + 1):
              m = getattr(self, f'layer{i}')
              m.eval()
              for param in m.parameters():
                  param.requires_grad = False
  
      def init_weights(self):
          """Initiate the parameters either from existing checkpoint or from
          scratch."""
          if isinstance(self.pretrained, str):
              logger = get_root_logger()
              logger.info(f'load model from: {self.pretrained}')
  
              load_checkpoint(self, self.pretrained, strict=False, logger=logger)
  
          elif self.pretrained is None:
              for m in self.modules():
                  if isinstance(m, nn.Conv2d):
                      kaiming_init(m)
                  elif isinstance(m, _BatchNorm):
                      constant_init(m, 1)
  
              if self.zero_init_residual:
                  for m in self.modules():
                      if isinstance(m, Bottleneck2dAudio):
                          constant_init(m.conv3.bn, 0)
  
          else:
              raise TypeError('pretrained must be a str or None')
  
      def forward(self, x):
          """Defines the computation performed at every call.
  
          Args:
              x (torch.Tensor): The input data.
  
          Returns:
              torch.Tensor: The feature of the input samples extracted
              by the backbone.
          """
          x = self.conv1(x)
          for layer_name in self.res_layers:
              res_layer = getattr(self, layer_name)
              x = res_layer(x)
          return x
  
      def train(self, mode=True):
          """Set the optimization status when training."""
          super().train(mode)
          self._freeze_stages()
          if mode and self.norm_eval:
              for m in self.modules():
                  if isinstance(m, _BatchNorm):
                      m.eval()
  