text: ##################################################################################
  # Fast-SCNN: Fast Semantic Segmentation Network
  # Paper-Link: https://arxiv.org/pdf/1902.04502.pdf
  ##################################################################################
  
  
  import torch
  import torch.nn as nn
  import torch.nn.functional as F
  from torchsummary import summary
  
  __all__ = ["FastSCNNG6"]
  
  
  class _ConvBNReLU(nn.Module):
      """Conv-BN-ReLU"""
  
      def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=0, **kwargs):
          super(_ConvBNReLU, self).__init__()
          self.conv = nn.Sequential(
              nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding, bias=False),
              nn.BatchNorm2d(out_channels),
              nn.ReLU(True)
          )
  
      def forward(self, x):
          return self.conv(x)
  
  
  class _DSConv(nn.Module):
      """Depthwise Separable Convolutions"""
  
      def __init__(self, dw_channels, out_channels, kernel_size=3, stride=1, padding=1):
          super(_DSConv, self).__init__()
          self.conv = nn.Sequential(
              nn.Conv2d(dw_channels, dw_channels, kernel_size, stride, padding, groups=dw_channels, bias=False),
              nn.BatchNorm2d(dw_channels),
              nn.ReLU(True),
              nn.Conv2d(dw_channels, out_channels, 1, bias=False),
              nn.BatchNorm2d(out_channels),
              nn.ReLU(True)
          )
  
      def forward(self, x):
          return self.conv(x)
  
  class _DWConv(nn.Module):
      """Depthwise Convolutions"""
  
      def __init__(self, dw_channels, out_channels, kernel_size=3, stride=1, padding=1):
          super(_DWConv, self).__init__()
          self.conv = nn.Sequential(
              nn.Conv2d(dw_channels, out_channels, kernel_size, stride, padding, groups=dw_channels, bias=False),
              nn.BatchNorm2d(out_channels),
              nn.ReLU(True)
          )
  
      def forward(self, x):
          return self.conv(x)
  
  
  class LinearBottleneck(nn.Module):
      """LinearBottleneck used in MobileNetV2"""
  
      def __init__(self, in_channels, out_channels, t=6, kernel_size=3, stride=1, padding=1):
          super(LinearBottleneck, self).__init__()
          self.use_shortcut = stride == 1 and in_channels == out_channels
          if stride == 2:
              self.block = nn.Sequential(
                  # pw
                  _ConvBNReLU(in_channels, in_channels * t, 1),
                  # dw
                  _DWConv(in_channels * t, in_channels * t, kernel_size, stride, padding),
                  _DWConv(in_channels * t, in_channels * t, 3, 1, 1),
                  # pw-linear
                  nn.Conv2d(in_channels * t, out_channels, 1, bias=False),
                  nn.BatchNorm2d(out_channels)
              )
          else:
              self.block = nn.Sequential(
                  # pw
                  _ConvBNReLU(in_channels, in_channels * t, 1),
                  # dw
                  _DWConv(in_channels * t, in_channels * t, kernel_size, stride, padding),
                  # pw-linear
                  nn.Conv2d(in_channels * t, out_channels, 1, bias=False),
                  nn.BatchNorm2d(out_channels)
              )
  
      def forward(self, x):
          out = self.block(x)
          if self.use_shortcut:
              out = x + out
          return out
  
  
  class PyramidPooling(nn.Module):
      """Pyramid pooling module"""
  
      def __init__(self, in_channels, out_channels, **kwargs):
          super(PyramidPooling, self).__init__()
          inter_channels = int(in_channels / 4)
          self.conv1 = _ConvBNReLU(in_channels, inter_channels, 1, **kwargs)
          self.conv2 = _ConvBNReLU(in_channels, inter_channels, 1, **kwargs)
          self.conv3 = _ConvBNReLU(in_channels, inter_channels, 1, **kwargs)
          self.conv4 = _ConvBNReLU(in_channels, inter_channels, 1, **kwargs)
          self.out = _ConvBNReLU(in_channels * 2, out_channels, 1)
  
      def pool(self, x, size):
          avgpool = nn.AdaptiveAvgPool2d(size)
          return avgpool(x)
  
      def upsample(self, x, size):
          return F.interpolate(x, size, mode='bilinear', align_corners=True)
  
      def forward(self, x):
          size = x.size()[2:]
          feat1 = self.upsample(self.conv1(self.pool(x, 1)), size)
          feat2 = self.upsample(self.conv2(self.pool(x, 2)), size)
          feat3 = self.upsample(self.conv3(self.pool(x, 3)), size)
          feat4 = self.upsample(self.conv4(self.pool(x, 6)), size)
          x = torch.cat([x, feat1, feat2, feat3, feat4], dim=1)
          x = self.out(x)
          return x
  
  
  class LearningToDownsample(nn.Module):
      """Learning to downsample module"""
  
      def __init__(self, dw_channels1=32, dw_channels2=48, out_channels=64, **kwargs):
          super(LearningToDownsample, self).__init__()
          self.conv = _ConvBNReLU(3, dw_channels1, 3, 2, 1)
          self.conv1 = _DSConv(dw_channels1, dw_channels1, 3, 1, 1)
          self.dsconv1 = _DSConv(dw_channels1, dw_channels2, 3, 2, 1)
          self.dsconv1_1 = _DSConv(dw_channels2, dw_channels2, 3, 1, 1)
          self.dsconv2 = _DSConv(dw_channels2, out_channels, 3, 2, 1)
          self.dsconv2_1 = _DSConv(out_channels, out_channels, 3, 1, 1)
  
      def forward(self, x):
          x = self.conv(x)
          x = self.conv1(x)
          x = self.dsconv1(x)
          x = self.dsconv1_1(x)
          x = self.dsconv2(x)
          x = self.dsconv2_1(x)
          return x
  
  
  class GlobalFeatureExtractor(nn.Module):
      """Global feature extractor module"""
  
      def __init__(self, in_channels=64, block_channels=(64, 96, 128),
                   out_channels=128, t=6, num_blocks=(3, 3, 3), **kwargs):
          super(GlobalFeatureExtractor, self).__init__()
          self.bottleneck1 = self._make_layer(LinearBottleneck, in_channels, block_channels[0], num_blocks[0], t, 3, 2, 1)
          self.bottleneck2 = self._make_layer(LinearBottleneck, block_channels[0], block_channels[1], num_blocks[1], t, 3,
                                              2, 1)
          self.bottleneck3 = self._make_layer(LinearBottleneck, block_channels[1], block_channels[2], num_blocks[2], t, 3,
                                              1, 1)
          self.ppm = PyramidPooling(block_channels[2], out_channels)
  
      def _make_layer(self, block, inplanes, planes, blocks, t=6, kernel_size=3, stride=1, padding=1):
          layers = []
          layers.append(block(inplanes, planes, t, kernel_size, stride, padding))
          for i in range(1, blocks):
              layers.append(block(planes, planes, t, 3, 1, 1))
          return nn.Sequential(*layers)
  
      def forward(self, x):
          x = self.bottleneck1(x)
          x = self.bottleneck2(x)
          x = self.bottleneck3(x)
          x = self.ppm(x)
          return x
  
  
  class FeatureFusionModule(nn.Module):
      """Feature fusion module"""
  
      def __init__(self, highter_in_channels, lower_in_channels, out_channels, scale_factor=4, **kwargs):
          super(FeatureFusionModule, self).__init__()
          self.scale_factor = scale_factor
          self.dwconv = _DWConv(lower_in_channels, out_channels)
          self.conv_lower_res = nn.Sequential(
              nn.Conv2d(out_channels, out_channels, 1),
              nn.BatchNorm2d(out_channels)
          )
          self.conv_higher_res = nn.Sequential(
              nn.Conv2d(highter_in_channels, out_channels, 1),
              nn.BatchNorm2d(out_channels)
          )
          self.relu = nn.ReLU(True)
  
      def forward(self, higher_res_feature, lower_res_feature):
          _, _, h, w = higher_res_feature.size()
          lower_res_feature = F.interpolate(lower_res_feature, size=(h, w), mode='bilinear', align_corners=True)
          lower_res_feature = self.dwconv(lower_res_feature)
          lower_res_feature = self.conv_lower_res(lower_res_feature)
  
          higher_res_feature = self.conv_higher_res(higher_res_feature)
          out = higher_res_feature + lower_res_feature
          return self.relu(out)
  
  
  class Classifer(nn.Module):
      """Classifer"""
  
      def __init__(self, dw_channels, num_classes):
          super(Classifer, self).__init__()
          self.dsconv1 = _DSConv(dw_channels, dw_channels)
          self.dsconv2 = _DSConv(dw_channels, dw_channels)
          self.conv = nn.Sequential(
              nn.Dropout(0.1),
              nn.Conv2d(dw_channels, num_classes, 1)
          )
  
      def forward(self, x):
          x = self.dsconv1(x)
          x = self.dsconv2(x)
          x = self.conv(x)
          return x
  
  
  # 该网络基本和context的网络相同，区别在于，将头部的shallownet变成了公共部分，然后再deepnet中增加了PPM
  class FastSCNNG6(nn.Module):
      def __init__(self, classes, aux=False, **kwargs):
          super(FastSCNNG6, self).__init__()
          self.aux = aux
          self.learning_to_downsample = LearningToDownsample(32, 48, 64)  # 与contextnet的Shallow_net相似
          self.global_feature_extractor = GlobalFeatureExtractor(64, [64, 96, 128], 128, 6,
                                                                 [3, 3, 3])  # 与contextnet的deepnet相似，多了PPM
          self.feature_fusion = FeatureFusionModule(64, 128, 128)  # 与context一样
          self.classifier = Classifer(128, classes)  # 与context一样
          if self.aux:
              self.auxlayer = nn.Sequential(
                  nn.Conv2d(64, 32, 3, padding=1, bias=False),
                  nn.BatchNorm2d(32),
                  nn.ReLU(True),
                  nn.Dropout(0.1),
                  nn.Conv2d(32, classes, 1)
              )
  
      def forward(self, x):
          size = x.size()[2:]
          higher_res_features = self.learning_to_downsample(x)
          x = self.global_feature_extractor(higher_res_features)
          x = self.feature_fusion(higher_res_features, x)
          x = self.classifier(x)
          outputs = []
          x = F.interpolate(x, size, mode='bilinear', align_corners=True)
          outputs.append(x)
          if self.aux:
              auxout = self.auxlayer(higher_res_features)
              auxout = F.interpolate(auxout, size, mode='bilinear', align_corners=True)
              outputs.append(auxout)
          return x
          # return tuple(outputs)
  
  
  """print layers and params of network"""
  if __name__ == '__main__':
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
      model = FastSCNNG6(classes=19).to(device)
      summary(model, (3, 512, 1024))
  
      from fvcore.nn.flop_count import flop_count  # https://github.com/facebookresearch/fvcore
      from tools.flops_counter.ptflops import get_model_complexity_info
      from thop import profile  # https://github.com/Lyken17/pytorch-OpCounter
  
      x = torch.randn(2, 3, 512, 1024).to(device)
  
      from fvcore.nn.jit_handles import batchnorm_flop_jit
      from fvcore.nn.jit_handles import generic_activation_jit
  
      supported_ops = {
          "aten::batch_norm": batchnorm_flop_jit,
      }
      flop_dict, _ = flop_count(model, (x,), supported_ops)
  
      flops_count, params_count = get_model_complexity_info(model, (3, 512, 1024),
                                                            as_strings=False,
                                                            print_per_layer_stat=True)
      input = x
      macs, params = profile(model, inputs=(input,))
      print(flop_dict)
      print(flops_count, params_count)
      print(macs, params)
  
  '''
  /home/ethan/anaconda3/envs/py36_cuda101/bin/python /home/ethan/codes/Efficient-Segmentation-Networks/model/FastSCNNG6.py
  ----------------------------------------------------------------
          Layer (type)               Output Shape         Param #
  ================================================================
              Conv2d-1         [-1, 32, 256, 512]             384
         BatchNorm2d-2         [-1, 32, 256, 512]              64
                ReLU-3         [-1, 32, 256, 512]               0
         _ConvBNReLU-4         [-1, 32, 256, 512]               0
              Conv2d-5         [-1, 32, 256, 512]             288
         BatchNorm2d-6         [-1, 32, 256, 512]              64
                ReLU-7         [-1, 32, 256, 512]               0
              Conv2d-8         [-1, 32, 256, 512]           1,024
         BatchNorm2d-9         [-1, 32, 256, 512]              64
               ReLU-10         [-1, 32, 256, 512]               0
            _DSConv-11         [-1, 32, 256, 512]               0
             Conv2d-12         [-1, 32, 128, 256]             128
        BatchNorm2d-13         [-1, 32, 128, 256]              64
               ReLU-14         [-1, 32, 128, 256]               0
             Conv2d-15         [-1, 48, 128, 256]           1,536
        BatchNorm2d-16         [-1, 48, 128, 256]              96
               ReLU-17         [-1, 48, 128, 256]               0
            _DSConv-18         [-1, 48, 128, 256]               0
             Conv2d-19         [-1, 48, 128, 256]             432
        BatchNorm2d-20         [-1, 48, 128, 256]              96
               ReLU-21         [-1, 48, 128, 256]               0
             Conv2d-22         [-1, 48, 128, 256]           2,304
        BatchNorm2d-23         [-1, 48, 128, 256]              96
               ReLU-24         [-1, 48, 128, 256]               0
            _DSConv-25         [-1, 48, 128, 256]               0
             Conv2d-26          [-1, 48, 64, 128]             192
        BatchNorm2d-27          [-1, 48, 64, 128]              96
               ReLU-28          [-1, 48, 64, 128]               0
             Conv2d-29          [-1, 64, 64, 128]           3,072
        BatchNorm2d-30          [-1, 64, 64, 128]             128
               ReLU-31          [-1, 64, 64, 128]               0
            _DSConv-32          [-1, 64, 64, 128]               0
             Conv2d-33          [-1, 64, 64, 128]             576
        BatchNorm2d-34          [-1, 64, 64, 128]             128
               ReLU-35          [-1, 64, 64, 128]               0
             Conv2d-36          [-1, 64, 64, 128]           4,096
        BatchNorm2d-37          [-1, 64, 64, 128]             128
               ReLU-38          [-1, 64, 64, 128]               0
            _DSConv-39          [-1, 64, 64, 128]               0
  LearningToDownsample-40          [-1, 64, 64, 128]               0
             Conv2d-41         [-1, 384, 64, 128]          24,576
        BatchNorm2d-42         [-1, 384, 64, 128]             768
               ReLU-43         [-1, 384, 64, 128]               0
        _ConvBNReLU-44         [-1, 384, 64, 128]               0
             Conv2d-45          [-1, 384, 32, 64]           1,536
        BatchNorm2d-46          [-1, 384, 32, 64]             768
               ReLU-47          [-1, 384, 32, 64]               0
            _DWConv-48          [-1, 384, 32, 64]               0
             Conv2d-49          [-1, 384, 32, 64]           3,456
        BatchNorm2d-50          [-1, 384, 32, 64]             768
               ReLU-51          [-1, 384, 32, 64]               0
            _DWConv-52          [-1, 384, 32, 64]               0
             Conv2d-53           [-1, 64, 32, 64]          24,576
        BatchNorm2d-54           [-1, 64, 32, 64]             128
   LinearBottleneck-55           [-1, 64, 32, 64]               0
             Conv2d-56          [-1, 384, 32, 64]          24,576
        BatchNorm2d-57          [-1, 384, 32, 64]             768
               ReLU-58          [-1, 384, 32, 64]               0
        _ConvBNReLU-59          [-1, 384, 32, 64]               0
             Conv2d-60          [-1, 384, 32, 64]           3,456
        BatchNorm2d-61          [-1, 384, 32, 64]             768
               ReLU-62          [-1, 384, 32, 64]               0
            _DWConv-63          [-1, 384, 32, 64]               0
             Conv2d-64           [-1, 64, 32, 64]          24,576
        BatchNorm2d-65           [-1, 64, 32, 64]             128
   LinearBottleneck-66           [-1, 64, 32, 64]               0
             Conv2d-67          [-1, 384, 32, 64]          24,576
        BatchNorm2d-68          [-1, 384, 32, 64]             768
               ReLU-69          [-1, 384, 32, 64]               0
        _ConvBNReLU-70          [-1, 384, 32, 64]               0
             Conv2d-71          [-1, 384, 32, 64]           3,456
        BatchNorm2d-72          [-1, 384, 32, 64]             768
               ReLU-73          [-1, 384, 32, 64]               0
            _DWConv-74          [-1, 384, 32, 64]               0
             Conv2d-75           [-1, 64, 32, 64]          24,576
        BatchNorm2d-76           [-1, 64, 32, 64]             128
   LinearBottleneck-77           [-1, 64, 32, 64]               0
             Conv2d-78          [-1, 384, 32, 64]          24,576
        BatchNorm2d-79          [-1, 384, 32, 64]             768
               ReLU-80          [-1, 384, 32, 64]               0
        _ConvBNReLU-81          [-1, 384, 32, 64]               0
             Conv2d-82          [-1, 384, 16, 32]           1,536
        BatchNorm2d-83          [-1, 384, 16, 32]             768
               ReLU-84          [-1, 384, 16, 32]               0
            _DWConv-85          [-1, 384, 16, 32]               0
             Conv2d-86          [-1, 384, 16, 32]           3,456
        BatchNorm2d-87          [-1, 384, 16, 32]             768
               ReLU-88          [-1, 384, 16, 32]               0
            _DWConv-89          [-1, 384, 16, 32]               0
             Conv2d-90           [-1, 96, 16, 32]          36,864
        BatchNorm2d-91           [-1, 96, 16, 32]             192
   LinearBottleneck-92           [-1, 96, 16, 32]               0
             Conv2d-93          [-1, 576, 16, 32]          55,296
        BatchNorm2d-94          [-1, 576, 16, 32]           1,152
               ReLU-95          [-1, 576, 16, 32]               0
        _ConvBNReLU-96          [-1, 576, 16, 32]               0
             Conv2d-97          [-1, 576, 16, 32]           5,184
        BatchNorm2d-98          [-1, 576, 16, 32]           1,152
               ReLU-99          [-1, 576, 16, 32]               0
           _DWConv-100          [-1, 576, 16, 32]               0
            Conv2d-101           [-1, 96, 16, 32]          55,296
       BatchNorm2d-102           [-1, 96, 16, 32]             192
  LinearBottleneck-103           [-1, 96, 16, 32]               0
            Conv2d-104          [-1, 576, 16, 32]          55,296
       BatchNorm2d-105          [-1, 576, 16, 32]           1,152
              ReLU-106          [-1, 576, 16, 32]               0
       _ConvBNReLU-107          [-1, 576, 16, 32]               0
            Conv2d-108          [-1, 576, 16, 32]           5,184
       BatchNorm2d-109          [-1, 576, 16, 32]           1,152
              ReLU-110          [-1, 576, 16, 32]               0
           _DWConv-111          [-1, 576, 16, 32]               0
            Conv2d-112           [-1, 96, 16, 32]          55,296
       BatchNorm2d-113           [-1, 96, 16, 32]             192
  LinearBottleneck-114           [-1, 96, 16, 32]               0
            Conv2d-115          [-1, 576, 16, 32]          55,296
       BatchNorm2d-116          [-1, 576, 16, 32]           1,152
              ReLU-117          [-1, 576, 16, 32]               0
       _ConvBNReLU-118          [-1, 576, 16, 32]               0
            Conv2d-119          [-1, 576, 16, 32]           5,184
       BatchNorm2d-120          [-1, 576, 16, 32]           1,152
              ReLU-121          [-1, 576, 16, 32]               0
           _DWConv-122          [-1, 576, 16, 32]               0
            Conv2d-123          [-1, 128, 16, 32]          73,728
       BatchNorm2d-124          [-1, 128, 16, 32]             256
  LinearBottleneck-125          [-1, 128, 16, 32]               0
            Conv2d-126          [-1, 768, 16, 32]          98,304
       BatchNorm2d-127          [-1, 768, 16, 32]           1,536
              ReLU-128          [-1, 768, 16, 32]               0
       _ConvBNReLU-129          [-1, 768, 16, 32]               0
            Conv2d-130          [-1, 768, 16, 32]           6,912
       BatchNorm2d-131          [-1, 768, 16, 32]           1,536
              ReLU-132          [-1, 768, 16, 32]               0
           _DWConv-133          [-1, 768, 16, 32]               0
            Conv2d-134          [-1, 128, 16, 32]          98,304
       BatchNorm2d-135          [-1, 128, 16, 32]             256
  LinearBottleneck-136          [-1, 128, 16, 32]               0
            Conv2d-137          [-1, 768, 16, 32]          98,304
       BatchNorm2d-138          [-1, 768, 16, 32]           1,536
              ReLU-139          [-1, 768, 16, 32]               0
       _ConvBNReLU-140          [-1, 768, 16, 32]               0
            Conv2d-141          [-1, 768, 16, 32]           6,912
       BatchNorm2d-142          [-1, 768, 16, 32]           1,536
              ReLU-143          [-1, 768, 16, 32]               0
           _DWConv-144          [-1, 768, 16, 32]               0
            Conv2d-145          [-1, 128, 16, 32]          98,304
       BatchNorm2d-146          [-1, 128, 16, 32]             256
  LinearBottleneck-147          [-1, 128, 16, 32]               0
            Conv2d-148             [-1, 32, 1, 1]           4,096
       BatchNorm2d-149             [-1, 32, 1, 1]              64
              ReLU-150             [-1, 32, 1, 1]               0
       _ConvBNReLU-151             [-1, 32, 1, 1]               0
            Conv2d-152             [-1, 32, 2, 2]           4,096
       BatchNorm2d-153             [-1, 32, 2, 2]              64
              ReLU-154             [-1, 32, 2, 2]               0
       _ConvBNReLU-155             [-1, 32, 2, 2]               0
            Conv2d-156             [-1, 32, 3, 3]           4,096
       BatchNorm2d-157             [-1, 32, 3, 3]              64
              ReLU-158             [-1, 32, 3, 3]               0
       _ConvBNReLU-159             [-1, 32, 3, 3]               0
            Conv2d-160             [-1, 32, 6, 6]           4,096
       BatchNorm2d-161             [-1, 32, 6, 6]              64
              ReLU-162             [-1, 32, 6, 6]               0
       _ConvBNReLU-163             [-1, 32, 6, 6]               0
            Conv2d-164          [-1, 128, 16, 32]          32,768
       BatchNorm2d-165          [-1, 128, 16, 32]             256
              ReLU-166          [-1, 128, 16, 32]               0
       _ConvBNReLU-167          [-1, 128, 16, 32]               0
    PyramidPooling-168          [-1, 128, 16, 32]               0
  GlobalFeatureExtractor-169          [-1, 128, 16, 32]               0
            Conv2d-170         [-1, 128, 64, 128]           1,152
       BatchNorm2d-171         [-1, 128, 64, 128]             256
              ReLU-172         [-1, 128, 64, 128]               0
           _DWConv-173         [-1, 128, 64, 128]               0
            Conv2d-174         [-1, 128, 64, 128]          16,512
       BatchNorm2d-175         [-1, 128, 64, 128]             256
            Conv2d-176         [-1, 128, 64, 128]           8,320
       BatchNorm2d-177         [-1, 128, 64, 128]             256
              ReLU-178         [-1, 128, 64, 128]               0
  FeatureFusionModule-179         [-1, 128, 64, 128]               0
            Conv2d-180         [-1, 128, 64, 128]           1,152
       BatchNorm2d-181         [-1, 128, 64, 128]             256
              ReLU-182         [-1, 128, 64, 128]               0
            Conv2d-183         [-1, 128, 64, 128]          16,384
       BatchNorm2d-184         [-1, 128, 64, 128]             256
              ReLU-185         [-1, 128, 64, 128]               0
           _DSConv-186         [-1, 128, 64, 128]               0
            Conv2d-187         [-1, 128, 64, 128]           1,152
       BatchNorm2d-188         [-1, 128, 64, 128]             256
              ReLU-189         [-1, 128, 64, 128]               0
            Conv2d-190         [-1, 128, 64, 128]          16,384
       BatchNorm2d-191         [-1, 128, 64, 128]             256
              ReLU-192         [-1, 128, 64, 128]               0
           _DSConv-193         [-1, 128, 64, 128]               0
           Dropout-194         [-1, 128, 64, 128]               0
            Conv2d-195          [-1, 19, 64, 128]           2,451
         Classifer-196          [-1, 19, 64, 128]               0
  ================================================================
  Total params: 1,151,075
  Trainable params: 1,151,075
  Non-trainable params: 0
  ----------------------------------------------------------------
  Input size (MB): 6.00
  Forward/backward pass size (MB): 1165.30
  Params size (MB): 4.39
  Estimated Total Size (MB): 1175.69
  ----------------------------------------------------------------
  Skipped operation aten::relu_ 42 time(s)
  Skipped operation aten::add 7 time(s)
  Skipped operation aten::adaptive_avg_pool2d 4 time(s)
  Skipped operation aten::upsample_bilinear2d 6 time(s)
  Skipped operation aten::dropout 1 time(s)
  FastSCNNG6(
    2.034 GMac, 100.000% MACs, 
    (learning_to_downsample): LearningToDownsample(
      0.492 GMac, 24.207% MACs, 
      (conv): _ConvBNReLU(
        0.063 GMac, 3.093% MACs, 
        (conv): Sequential(
          0.063 GMac, 3.093% MACs, 
          (0): Conv2d(0.05 GMac, 2.474% MACs, 3, 32, kernel_size=(2, 2), stride=(2, 2), bias=False)
          (1): BatchNorm2d(0.008 GMac, 0.412% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.004 GMac, 0.206% MACs, inplace=True)
        )
      )
      (conv1): _DSConv(
        0.197 GMac, 9.691% MACs, 
        (conv): Sequential(
          0.197 GMac, 9.691% MACs, 
          (0): Conv2d(0.038 GMac, 1.856% MACs, 32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=32, bias=False)
          (1): BatchNorm2d(0.008 GMac, 0.412% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.004 GMac, 0.206% MACs, inplace=True)
          (3): Conv2d(0.134 GMac, 6.598% MACs, 32, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.008 GMac, 0.412% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.004 GMac, 0.206% MACs, inplace=True)
        )
      )
      (dsconv1): _DSConv(
        0.062 GMac, 3.067% MACs, 
        (conv): Sequential(
          0.062 GMac, 3.067% MACs, 
          (0): Conv2d(0.004 GMac, 0.206% MACs, 32, 32, kernel_size=(2, 2), stride=(2, 2), groups=32, bias=False)
          (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
          (3): Conv2d(0.05 GMac, 2.474% MACs, 32, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.003 GMac, 0.155% MACs, 48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.002 GMac, 0.077% MACs, inplace=True)
        )
      )
      (dsconv1_1): _DSConv(
        0.099 GMac, 4.871% MACs, 
        (conv): Sequential(
          0.099 GMac, 4.871% MACs, 
          (0): Conv2d(0.014 GMac, 0.696% MACs, 48, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=48, bias=False)
          (1): BatchNorm2d(0.003 GMac, 0.155% MACs, 48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.002 GMac, 0.077% MACs, inplace=True)
          (3): Conv2d(0.075 GMac, 3.711% MACs, 48, 48, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.003 GMac, 0.155% MACs, 48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.002 GMac, 0.077% MACs, inplace=True)
        )
      )
      (dsconv2): _DSConv(
        0.029 GMac, 1.450% MACs, 
        (conv): Sequential(
          0.029 GMac, 1.450% MACs, 
          (0): Conv2d(0.002 GMac, 0.077% MACs, 48, 48, kernel_size=(2, 2), stride=(2, 2), groups=48, bias=False)
          (1): BatchNorm2d(0.001 GMac, 0.039% MACs, 48, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.0 GMac, 0.019% MACs, inplace=True)
          (3): Conv2d(0.025 GMac, 1.237% MACs, 48, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.001 GMac, 0.052% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.001 GMac, 0.026% MACs, inplace=True)
        )
      )
      (dsconv2_1): _DSConv(
        0.041 GMac, 2.036% MACs, 
        (conv): Sequential(
          0.041 GMac, 2.036% MACs, 
          (0): Conv2d(0.005 GMac, 0.232% MACs, 64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=64, bias=False)
          (1): BatchNorm2d(0.001 GMac, 0.052% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.001 GMac, 0.026% MACs, inplace=True)
          (3): Conv2d(0.034 GMac, 1.649% MACs, 64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.001 GMac, 0.052% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.001 GMac, 0.026% MACs, inplace=True)
        )
      )
    )
    (global_feature_extractor): GlobalFeatureExtractor(
      1.001 GMac, 49.188% MACs, 
      (bottleneck1): Sequential(
        0.502 GMac, 24.664% MACs, 
        (0): LinearBottleneck(
          0.276 GMac, 13.582% MACs, 
          (block): Sequential(
            0.276 GMac, 13.582% MACs, 
            (0): _ConvBNReLU(
              0.211 GMac, 10.361% MACs, 
              (conv): Sequential(
                0.211 GMac, 10.361% MACs, 
                (0): Conv2d(0.201 GMac, 9.897% MACs, 64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.006 GMac, 0.309% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.003 GMac, 0.155% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.006 GMac, 0.271% MACs, 
              (conv): Sequential(
                0.006 GMac, 0.271% MACs, 
                (0): Conv2d(0.003 GMac, 0.155% MACs, 384, 384, kernel_size=(2, 2), stride=(2, 2), groups=384, bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (2): _DWConv(
              0.009 GMac, 0.464% MACs, 
              (conv): Sequential(
                0.009 GMac, 0.464% MACs, 
                (0): Conv2d(0.007 GMac, 0.348% MACs, 384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (3): Conv2d(0.05 GMac, 2.474% MACs, 384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (4): BatchNorm2d(0.0 GMac, 0.013% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): LinearBottleneck(
          0.113 GMac, 5.541% MACs, 
          (block): Sequential(
            0.113 GMac, 5.541% MACs, 
            (0): _ConvBNReLU(
              0.053 GMac, 2.590% MACs, 
              (conv): Sequential(
                0.053 GMac, 2.590% MACs, 
                (0): Conv2d(0.05 GMac, 2.474% MACs, 64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.009 GMac, 0.464% MACs, 
              (conv): Sequential(
                0.009 GMac, 0.464% MACs, 
                (0): Conv2d(0.007 GMac, 0.348% MACs, 384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.05 GMac, 2.474% MACs, 384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.013% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (2): LinearBottleneck(
          0.113 GMac, 5.541% MACs, 
          (block): Sequential(
            0.113 GMac, 5.541% MACs, 
            (0): _ConvBNReLU(
              0.053 GMac, 2.590% MACs, 
              (conv): Sequential(
                0.053 GMac, 2.590% MACs, 
                (0): Conv2d(0.05 GMac, 2.474% MACs, 64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.009 GMac, 0.464% MACs, 
              (conv): Sequential(
                0.009 GMac, 0.464% MACs, 
                (0): Conv2d(0.007 GMac, 0.348% MACs, 384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.05 GMac, 2.474% MACs, 384, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.013% MACs, 64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
      )
      (bottleneck2): Sequential(
        0.198 GMac, 9.718% MACs, 
        (0): LinearBottleneck(
          0.075 GMac, 3.706% MACs, 
          (block): Sequential(
            0.075 GMac, 3.706% MACs, 
            (0): _ConvBNReLU(
              0.053 GMac, 2.590% MACs, 
              (conv): Sequential(
                0.053 GMac, 2.590% MACs, 
                (0): Conv2d(0.05 GMac, 2.474% MACs, 64, 384, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.002 GMac, 0.077% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.001 GMac, 0.039% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.001 GMac, 0.068% MACs, 
              (conv): Sequential(
                0.001 GMac, 0.068% MACs, 
                (0): Conv2d(0.001 GMac, 0.039% MACs, 384, 384, kernel_size=(2, 2), stride=(2, 2), groups=384, bias=False)
                (1): BatchNorm2d(0.0 GMac, 0.019% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.010% MACs, inplace=True)
              )
            )
            (2): _DWConv(
              0.002 GMac, 0.116% MACs, 
              (conv): Sequential(
                0.002 GMac, 0.116% MACs, 
                (0): Conv2d(0.002 GMac, 0.087% MACs, 384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=384, bias=False)
                (1): BatchNorm2d(0.0 GMac, 0.019% MACs, 384, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.010% MACs, inplace=True)
              )
            )
            (3): Conv2d(0.019 GMac, 0.928% MACs, 384, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (4): BatchNorm2d(0.0 GMac, 0.005% MACs, 96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): LinearBottleneck(
          0.061 GMac, 3.006% MACs, 
          (block): Sequential(
            0.061 GMac, 3.006% MACs, 
            (0): _ConvBNReLU(
              0.029 GMac, 1.435% MACs, 
              (conv): Sequential(
                0.029 GMac, 1.435% MACs, 
                (0): Conv2d(0.028 GMac, 1.392% MACs, 96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.004 GMac, 0.174% MACs, 
              (conv): Sequential(
                0.004 GMac, 0.174% MACs, 
                (0): Conv2d(0.003 GMac, 0.130% MACs, 576, 576, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=576, bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.028 GMac, 1.392% MACs, 576, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.005% MACs, 96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (2): LinearBottleneck(
          0.061 GMac, 3.006% MACs, 
          (block): Sequential(
            0.061 GMac, 3.006% MACs, 
            (0): _ConvBNReLU(
              0.029 GMac, 1.435% MACs, 
              (conv): Sequential(
                0.029 GMac, 1.435% MACs, 
                (0): Conv2d(0.028 GMac, 1.392% MACs, 96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.004 GMac, 0.174% MACs, 
              (conv): Sequential(
                0.004 GMac, 0.174% MACs, 
                (0): Conv2d(0.003 GMac, 0.130% MACs, 576, 576, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=576, bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.028 GMac, 1.392% MACs, 576, 96, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.005% MACs, 96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
      )
      (bottleneck3): Sequential(
        0.284 GMac, 13.961% MACs, 
        (0): LinearBottleneck(
          0.071 GMac, 3.471% MACs, 
          (block): Sequential(
            0.071 GMac, 3.471% MACs, 
            (0): _ConvBNReLU(
              0.029 GMac, 1.435% MACs, 
              (conv): Sequential(
                0.029 GMac, 1.435% MACs, 
                (0): Conv2d(0.028 GMac, 1.392% MACs, 96, 576, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.004 GMac, 0.174% MACs, 
              (conv): Sequential(
                0.004 GMac, 0.174% MACs, 
                (0): Conv2d(0.003 GMac, 0.130% MACs, 576, 576, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=576, bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.029% MACs, 576, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.014% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.038 GMac, 1.856% MACs, 576, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.006% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): LinearBottleneck(
          0.107 GMac, 5.245% MACs, 
          (block): Sequential(
            0.107 GMac, 5.245% MACs, 
            (0): _ConvBNReLU(
              0.052 GMac, 2.532% MACs, 
              (conv): Sequential(
                0.052 GMac, 2.532% MACs, 
                (0): Conv2d(0.05 GMac, 2.474% MACs, 128, 768, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.039% MACs, 768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.019% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.005 GMac, 0.232% MACs, 
              (conv): Sequential(
                0.005 GMac, 0.232% MACs, 
                (0): Conv2d(0.004 GMac, 0.174% MACs, 768, 768, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=768, bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.039% MACs, 768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.019% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.05 GMac, 2.474% MACs, 768, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.006% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (2): LinearBottleneck(
          0.107 GMac, 5.245% MACs, 
          (block): Sequential(
            0.107 GMac, 5.245% MACs, 
            (0): _ConvBNReLU(
              0.052 GMac, 2.532% MACs, 
              (conv): Sequential(
                0.052 GMac, 2.532% MACs, 
                (0): Conv2d(0.05 GMac, 2.474% MACs, 128, 768, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.039% MACs, 768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.019% MACs, inplace=True)
              )
            )
            (1): _DWConv(
              0.005 GMac, 0.232% MACs, 
              (conv): Sequential(
                0.005 GMac, 0.232% MACs, 
                (0): Conv2d(0.004 GMac, 0.174% MACs, 768, 768, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=768, bias=False)
                (1): BatchNorm2d(0.001 GMac, 0.039% MACs, 768, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
                (2): ReLU(0.0 GMac, 0.019% MACs, inplace=True)
              )
            )
            (2): Conv2d(0.05 GMac, 2.474% MACs, 768, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (3): BatchNorm2d(0.0 GMac, 0.006% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
      )
      (ppm): PyramidPooling(
        0.017 GMac, 0.845% MACs, 
        (conv1): _ConvBNReLU(
          0.0 GMac, 0.000% MACs, 
          (conv): Sequential(
            0.0 GMac, 0.000% MACs, 
            (0): Conv2d(0.0 GMac, 0.000% MACs, 128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (1): BatchNorm2d(0.0 GMac, 0.000% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (2): ReLU(0.0 GMac, 0.000% MACs, inplace=True)
          )
        )
        (conv2): _ConvBNReLU(
          0.0 GMac, 0.001% MACs, 
          (conv): Sequential(
            0.0 GMac, 0.001% MACs, 
            (0): Conv2d(0.0 GMac, 0.001% MACs, 128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (1): BatchNorm2d(0.0 GMac, 0.000% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (2): ReLU(0.0 GMac, 0.000% MACs, inplace=True)
          )
        )
        (conv3): _ConvBNReLU(
          0.0 GMac, 0.002% MACs, 
          (conv): Sequential(
            0.0 GMac, 0.002% MACs, 
            (0): Conv2d(0.0 GMac, 0.002% MACs, 128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (1): BatchNorm2d(0.0 GMac, 0.000% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (2): ReLU(0.0 GMac, 0.000% MACs, inplace=True)
          )
        )
        (conv4): _ConvBNReLU(
          0.0 GMac, 0.007% MACs, 
          (conv): Sequential(
            0.0 GMac, 0.007% MACs, 
            (0): Conv2d(0.0 GMac, 0.007% MACs, 128, 32, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (1): BatchNorm2d(0.0 GMac, 0.000% MACs, 32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (2): ReLU(0.0 GMac, 0.000% MACs, inplace=True)
          )
        )
        (out): _ConvBNReLU(
          0.017 GMac, 0.834% MACs, 
          (conv): Sequential(
            0.017 GMac, 0.834% MACs, 
            (0): Conv2d(0.017 GMac, 0.825% MACs, 256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (1): BatchNorm2d(0.0 GMac, 0.006% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (2): ReLU(0.0 GMac, 0.003% MACs, inplace=True)
          )
        )
      )
    )
    (feature_fusion): FeatureFusionModule(
      0.221 GMac, 10.876% MACs, 
      (dwconv): _DWConv(
        0.013 GMac, 0.619% MACs, 
        (conv): Sequential(
          0.013 GMac, 0.619% MACs, 
          (0): Conv2d(0.009 GMac, 0.464% MACs, 128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128, bias=False)
          (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
        )
      )
      (conv_lower_res): Sequential(
        0.137 GMac, 6.752% MACs, 
        (0): Conv2d(0.135 GMac, 6.649% MACs, 128, 128, kernel_size=(1, 1), stride=(1, 1))
        (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (conv_higher_res): Sequential(
        0.07 GMac, 3.454% MACs, 
        (0): Conv2d(0.068 GMac, 3.350% MACs, 64, 128, kernel_size=(1, 1), stride=(1, 1))
        (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (relu): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
    )
    (classifier): Classifer(
      0.32 GMac, 15.729% MACs, 
      (dsconv1): _DSConv(
        0.15 GMac, 7.371% MACs, 
        (conv): Sequential(
          0.15 GMac, 7.371% MACs, 
          (0): Conv2d(0.009 GMac, 0.464% MACs, 128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128, bias=False)
          (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
          (3): Conv2d(0.134 GMac, 6.598% MACs, 128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
        )
      )
      (dsconv2): _DSConv(
        0.15 GMac, 7.371% MACs, 
        (conv): Sequential(
          0.15 GMac, 7.371% MACs, 
          (0): Conv2d(0.009 GMac, 0.464% MACs, 128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128, bias=False)
          (1): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (2): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
          (3): Conv2d(0.134 GMac, 6.598% MACs, 128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (4): BatchNorm2d(0.002 GMac, 0.103% MACs, 128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (5): ReLU(0.001 GMac, 0.052% MACs, inplace=True)
        )
      )
      (conv): Sequential(
        0.02 GMac, 0.987% MACs, 
        (0): Dropout(0.0 GMac, 0.000% MACs, p=0.1, inplace=False)
        (1): Conv2d(0.02 GMac, 0.987% MACs, 128, 19, kernel_size=(1, 1), stride=(1, 1))
      )
    )
  )
  [INFO] Register count_convNd() for <class 'torch.nn.modules.conv.Conv2d'>.
  [INFO] Register count_bn() for <class 'torch.nn.modules.batchnorm.BatchNorm2d'>.
  [INFO] Register zero_ops() for <class 'torch.nn.modules.activation.ReLU'>.
  [WARN] Cannot find rule for <class 'torch.nn.modules.container.Sequential'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__._ConvBNReLU'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__._DSConv'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.LearningToDownsample'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__._DWConv'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.LinearBottleneck'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.PyramidPooling'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.GlobalFeatureExtractor'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.FeatureFusionModule'>. Treat it as zero Macs and zero Params.
  [INFO] Register zero_ops() for <class 'torch.nn.modules.dropout.Dropout'>.
  [WARN] Cannot find rule for <class '__main__.Classifer'>. Treat it as zero Macs and zero Params.
  [WARN] Cannot find rule for <class '__main__.FastSCNNG6'>. Treat it as zero Macs and zero Params.
  defaultdict(<class 'float'>, {'conv': 3.822534656, 'batchnorm': 0.326775296})
  2034275008.0 1151075
  3990427904.0 1151075.0
  
  Process finished with exit code 0
  
  
  
  conv2*2 cin cout conv3 cout cout
  conv+ds
  ds+ds
  '''
  