code: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import math
  import torch.nn as nn
  from collections import OrderedDict
  from functools import partial
  
  from lib.models.tools.module_helper import ModuleHelper 
  
  
  
  class GlobalAvgPool2d(nn.Module):
      def __init__(self):
          """Global average pooling over the input's spatial dimensions"""
          super(GlobalAvgPool2d, self).__init__()
  
      def forward(self, inputs):
          in_size = inputs.size()
          return inputs.view((in_size[0], in_size[1], -1)).mean(dim=2)
  
  
  class IdentityResidualBlock(nn.Module):
      def __init__(self,
                   in_channels,
                   channels,
                   stride=1,
                   dilation=1,
                   groups=1,
                   bn_type=None,
                   dropout=None):
          """Configurable identity-mapping residual block
  
          Parameters
          ----------
          in_channels : int
              Number of input channels.
          channels : list of int
              Number of channels in the internal feature maps. Can either have two or three elements: if three construct
              a residual block with two `3 x 3` convolutions, otherwise construct a bottleneck block with `1 x 1`, then
              `3 x 3` then `1 x 1` convolutions.
          stride : int
              Stride of the first `3 x 3` convolution
          dilation : int
              Dilation to apply to the `3 x 3` convolutions.
          groups : int
              Number of convolution groups. This is used to create ResNeXt-style blocks and is only compatible with
              bottleneck blocks.
          bn_type : callable
              Function to create normalization / activation Module.
          dropout: callable
              Function to create Dropout Module.
          """
          super(IdentityResidualBlock, self).__init__()
  
          # Check parameters for inconsistencies
          if len(channels) != 2 and len(channels) != 3:
              raise ValueError("channels must contain either two or three values")
          if len(channels) == 2 and groups != 1:
              raise ValueError("groups > 1 are only valid if len(channels) == 3")
  
          is_bottleneck = len(channels) == 3
          need_proj_conv = stride != 1 or in_channels != channels[-1]
  
          self.bn1 = ModuleHelper.BNReLU(in_channels, bn_type=bn_type)
          if not is_bottleneck:
              layers = [
                  ("conv1", nn.Conv2d(in_channels, channels[0], 3, stride=stride, padding=dilation, bias=False,
                                      dilation=dilation)),
                  ("bn2", ModuleHelper.BNReLU(channels[0], bn_type=bn_type)),
                  ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False,
                                      dilation=dilation))
              ]
              if dropout is not None:
                  layers = layers[0:2] + [("dropout", dropout())] + layers[2:]
          else:
              layers = [
                  ("conv1", nn.Conv2d(in_channels, channels[0], 1, stride=stride, padding=0, bias=False)),
                  ("bn2", ModuleHelper.BNReLU(channels[0], bn_type=bn_type)),
                  ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False,
                                      groups=groups, dilation=dilation)),
                  ("bn3", ModuleHelper.BNReLU(channels[1], bn_type=bn_type)),
                  ("conv3", nn.Conv2d(channels[1], channels[2], 1, stride=1, padding=0, bias=False))
              ]
              if dropout is not None:
                  layers = layers[0:4] + [("dropout", dropout())] + layers[4:]
          self.convs = nn.Sequential(OrderedDict(layers))
  
          if need_proj_conv:
              self.proj_conv = nn.Conv2d(in_channels, channels[-1], 1, stride=stride, padding=0, bias=False)
  
      def forward(self, x):
          if hasattr(self, "proj_conv"):
              bn1 = self.bn1(x)
              shortcut = self.proj_conv(bn1)
          else:
              shortcut = x.clone()
              bn1 = self.bn1(x)
  
          out = self.convs(bn1)
          out.add_(shortcut)
  
          return out
  
  
  class WiderResNetA2(nn.Module):
      def __init__(self,
                   structure=[3, 3, 6, 3, 1, 1],
                   bn_type=None,
                   classes=0,
                   dilation=True):
          """Wider ResNet with pre-activation (identity mapping) blocks
  
          This variant uses down-sampling by max-pooling in the first two blocks and by strided convolution in the others.
  
          Parameters
          ----------
          structure : list of int
              Number of residual blocks in each of the six modules of the network.
          bn_type : callable
              Function to create normalization / activation Module.
          classes : int
              If not `0` also include global average pooling and a fully-connected layer with `classes` outputs at the end
              of the network.
          dilation : bool
              If `True` apply dilation to the last three modules and change the down-sampling factor from 32 to 8.
          """
          super(WiderResNetA2, self).__init__()
          self.structure = structure
          self.dilation = dilation
  
          if len(structure) != 6:
              raise ValueError("Expected a structure with six values")
  
          # Initial layers
          self.mod1 = nn.Sequential(OrderedDict([
              ("conv1", nn.Conv2d(3, 64, 3, stride=1, padding=1, bias=False))
          ]))
  
          # Groups of residual blocks
          in_channels = 64
          channels = [(128, 128), (256, 256), (512, 512), (512, 1024), (512, 1024, 2048), (1024, 2048, 4096)]
          for mod_id, num in enumerate(structure):
              # Create blocks for module
              blocks = []
              for block_id in range(num):
                  if not dilation:
                      dil = 1
                      stride = 2 if block_id == 0 and 2 <= mod_id <= 4 else 1
                  else:
                      if mod_id == 3:
                          dil = 2
                      elif mod_id > 3:
                          dil = 4
                      else:
                          dil = 1
                      stride = 2 if block_id == 0 and mod_id == 2 else 1
  
                  if mod_id == 4:
                      drop = None
                  elif mod_id == 5:
                      drop = None
                  else:
                      drop = None
  
                  blocks.append((
                      "block%d" % (block_id + 1),
                      IdentityResidualBlock(in_channels, channels[mod_id], bn_type=bn_type, stride=stride, dilation=dil,
                                            dropout=drop)
                  ))
  
                  # Update channels and p_keep
                  in_channels = channels[mod_id][-1]
  
              # Create module
              if mod_id < 2:
                  self.add_module("pool%d" % (mod_id + 2), nn.MaxPool2d(3, stride=2, padding=1, ceil_mode=True))
              self.add_module("mod%d" % (mod_id + 2), nn.Sequential(OrderedDict(blocks)))
  
          self.bn_out = ModuleHelper.BNReLU(in_channels, bn_type=bn_type)
  
  
      def forward(self, img):
          tuple_features = list()
          out = self.mod1(img)
          out = self.mod2(self.pool2(out))
          out = self.mod3(self.pool3(out))
          out = self.mod4(out)
          tuple_features.append(out)
          out = self.mod5(out)
          tuple_features.append(out)
          out = self.mod6(out)
          tuple_features.append(out)
          out = self.mod7(out)
          out = self.bn_out(out)
          tuple_features.append(out)
          return tuple_features
  
apis: torch.nn.MaxPool2d torch.nn.Conv2d