text: import torch.nn as nn
  
  '''
  https://github.com/qiulinzhang/SPConv.pytorch
  '''
  
  class SPConv_3x3(nn.Module):
      def __init__(self, inplanes, outplanes, stride=1, ratio=0.5, reduction=16):
          super(SPConv_3x3, self).__init__()
          self.inplanes_3x3 = int(inplanes*ratio)
          self.inplanes_1x1 = inplanes - self.inplanes_3x3
          self.outplanes_3x3 = int(outplanes*ratio)
          self.outplanes_1x1 = outplanes - self.outplanes_3x3
          self.outplanes = outplanes
          self.stride = stride
  
          self.gwc = nn.Conv2d(self.inplanes_3x3, self.outplanes, kernel_size=3, stride=self.stride,
                               padding=1, groups=2, bias=False)
          self.pwc = nn.Conv2d(self.inplanes_3x3, self.outplanes, kernel_size=1, bias=False)
  
          self.conv1x1 = nn.Conv2d(self.inplanes_1x1, self.outplanes,kernel_size=1)
          self.avgpool_s2_1 = nn.AvgPool2d(kernel_size=2,stride=2)
          self.avgpool_s2_3 = nn.AvgPool2d(kernel_size=2, stride=2)
          self.avgpool_add_1 = nn.AdaptiveAvgPool2d(1)
          self.avgpool_add_3 = nn.AdaptiveAvgPool2d(1)
          self.bn1 = nn.BatchNorm2d(self.outplanes)
          self.bn2 = nn.BatchNorm2d(self.outplanes)
          self.ratio = ratio
          self.groups = int(1/self.ratio)
      def forward(self, x):
          b, c, _, _ = x.size()
  
  
          x_3x3 = x[:,:int(c*self.ratio),:,:]
          x_1x1 = x[:,int(c*self.ratio):,:,:]
          out_3x3_gwc = self.gwc(x_3x3)
          if self.stride ==2:
              x_3x3 = self.avgpool_s2_3(x_3x3)
          out_3x3_pwc = self.pwc(x_3x3)
          out_3x3 = out_3x3_gwc + out_3x3_pwc
          out_3x3 = self.bn1(out_3x3)
          out_3x3_ratio = self.avgpool_add_3(out_3x3).squeeze()
  
          # use avgpool first to reduce information lost
          if self.stride == 2:
              x_1x1_se = self.avgpool_s2_1(x_1x1_se)
  
          out_1x1 = self.conv1x1(x_1x1)
          out_1x1 = self.bn2(out_1x1)
          out_1x1_ratio = self.avgpool_add_1(out_1x1).squeeze()
  
          out_31_ratio = torch.stack((out_3x3_ratio, out_1x1_ratio), 2)
          out_31_ratio = nn.Softmax(dim=2)(out_31_ratio)
          out = out_1x1 * (out_31_ratio[:,:,1].view(b, self.outplanes, 1, 1).expand_as(out_1x1))\
                + out_3x3 * (out_31_ratio[:,:,0].view(b, self.outplanes, 1, 1).expand_as(out_3x3))
  
          return out