当前位置:网站首页>YOLOv5s-ShuffleNetV2

YOLOv5s-ShuffleNetV2

2022-07-04 19:56:00 Master Ma

Yes YOLOV5 Lightweight :
One 、backbone part
yaml The configuration file :

backbone:
  # [from, number, module, args]
  [[-1, 1, conv_bn_relu_maxpool, [32]],    # 0-P2/4
   [-1, 1, Shuffle_Block, [116, 2]], # 1-P3/8
   [-1, 3, Shuffle_Block, [116, 1]], # 2
   [-1, 1, Shuffle_Block, [232, 2]], # 3-P4/16
   [-1, 7, Shuffle_Block, [232, 1]], # 4
   [-1, 1, Shuffle_Block, [464, 2]], # 5-P5/32
   [-1, 1, Shuffle_Block, [464, 1]], # 6
  ]

1.1、Focus Replace
The original YOLOv5s-5.0 Of stem It's a Focus Slicing operation , and v6 It's a 6x6Conv, Here is a copy v6 Yes Focus Improvement , Change it to 1 individual 3x3 Convolution ( Because my task itself is not complicated , Change it to 3x3 The parameters can be reduced after )

class conv_bn_relu_maxpool(nn.Module):
    def __init__(self, c1, c2):  # ch_in, ch_out
        super(conv_bn_relu_maxpool, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(c1, c2, kernel_size=3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(c2),
            nn.ReLU(inplace=True),
        )
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)

    def forward(self, x):
        return self.maxpool(self.conv(x))

1.2、 all Conv+C3 Replace with Shuffle_Block
 Insert picture description here

def channel_shuffle(x, groups):
    batchsize, num_channels, height, width = x.data.size()  # bs c h w
    channels_per_group = num_channels // groups

    # reshape
    x = x.view(batchsize, groups, channels_per_group, height, width)  # [bs,c,h,w] to [bs,group,channels_per_group,h,w]

    x = torch.transpose(x, 1, 2).contiguous()  # channel shuffle [bs,channels_per_group,group,h,w]

    # flatten
    x = x.view(batchsize, -1, height, width)  # [bs,c,h,w]

    return x

 Insert picture description here

class Shuffle_Block(nn.Module):
    def __init__(self, inp, oup, stride):
        super(Shuffle_Block, self).__init__()

        if not (1 <= stride <= 3):
            raise ValueError('illegal stride value')
        self.stride = stride

        branch_features = oup // 2 # channel split to 2 feature map
        assert (self.stride != 1) or (inp == branch_features << 1)

        # stride=2  chart d  The left branch =3x3DW Conv + 1x1Conv
        if self.stride > 1:
            self.branch1 = nn.Sequential(
                self.depthwise_conv(inp, inp, kernel_size=3, stride=self.stride, padding=1),
                nn.BatchNorm2d(inp),
                nn.Conv2d(inp, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
                nn.BatchNorm2d(branch_features),
                nn.ReLU(inplace=True),
            )

        #  Right branch =1x1Conv + 3x3DW Conv + 1x1Conv
        self.branch2 = nn.Sequential(
            nn.Conv2d(inp if (self.stride > 1) else branch_features,
                      branch_features, kernel_size=1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(branch_features),
            nn.ReLU(inplace=True),
            self.depthwise_conv(branch_features, branch_features, kernel_size=3, stride=self.stride, padding=1),
            nn.BatchNorm2d(branch_features),
            nn.Conv2d(branch_features, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(branch_features),
            nn.ReLU(inplace=True),
        )

    @staticmethod
    def depthwise_conv(i, o, kernel_size, stride=1, padding=0, bias=False):
        return nn.Conv2d(i, o, kernel_size, stride, padding, bias=bias, groups=i)

    def forward(self, x):
        # x/out: [bs, c, h, w]
        if self.stride == 1:
            x1, x2 = x.chunk(2, dim=1)  # channel split to 2 feature map
            out = torch.cat((x1, self.branch2(x2)), dim=1)
        else:
            out = torch.cat((self.branch1(x), self.branch2(x)), dim=1)

        out = channel_shuffle(out, 2)

        return out

1.3、 Cut off SPP
Cut off SPP Structure and the one behind C3 structure , because SPP Parallel operation will affect the speed .

Two 、head part

head:
  [[-1, 1, Conv, [96, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[ -1, 4 ], 1, Concat, [1]],  # cat backbone P4
   [-1, 1, DWConvblock, [96, 3, 1]],  # 10

   [-1, 1, Conv, [96, 1, 1 ]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 2], 1, Concat, [1]],  # cat backbone P3
   [-1, 1, DWConvblock, [96, 3, 1]],  # 14 (P3/8-small)

   [-1, 1, DWConvblock, [96, 3, 2]],
   [[-1, 11], 1, ADD, [1]],  # cat head P4
   [-1, 1, DWConvblock, [96, 3, 1]],  # 17 (P4/16-medium)

   [-1, 1, DWConvblock, [ 96, 3, 2]],
   [[-1, 7], 1, ADD, [1]],  # cat head P5
   [-1, 1, DWConvblock, [96, 3, 1]],  # 20 (P5/32-large)

   [[14, 17, 20], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

2.1、 All layer structure inputs and outputs channel equal
2.2、 all C3 Replace all structures with DWConv

2.3、PAN Of the two Concat Change it to ADD

3、 ... and 、、 summary
ShuffleNeckV2 Four criteria for designing lightweight networks are proposed :
G1、 Input characteristics of convolution layer channel And output characteristics channel Try to be equal ;
G2、 Try not to use group convolution , Or convolution group g As small as possible ;
G3、 Network branches should be as few as possible , Avoid parallel structures ;
G4、 Element-Wise The operation should be as few as possible , Such as :ReLU、ADD、 Point by point convolution, etc ;

YOLOv5s-ShuffleNetV2 Summary of improvement points :

backbone Of Focus Replace with a 3x3Conv(c=32), because v5-6.0 Just replace it with a 6x6Conv, Here, in order to further reduce the amount of parameters , Replace with 3x3Conv;
backbone all Conv and C3 Replace with Shuffle Block;
Cut off SPP And the one behind C3 structure ,SPP There are too many parallel operations (G3)
head Input and output of all layers channel=96(G1)
head all C3 Change it to DWConv
PAN Of the two Concat Change it to ADD(channel Too big , Too much computation , Although it violates G4, But the amount of calculation is smaller )

Four 、 experimental result
GFLOPs= value /10^9
Parameter quantity (M)= value *4/1024/1024
 Insert picture description here
Parameter quantity 、 Amount of computation 、 The weight file size is compressed to YOLOv5s Of 1/10, precision [email protected] It fell off 1% about (96.7%->95.5%),[email protected]~0.95 It fell off 5 A p.m. (88.5%->84%).

reference :https://blog.csdn.net/qq_38253797/article/details/124803531

原网站

版权声明
本文为[Master Ma]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/185/202207041753494856.html