当前位置:   article > 正文

yolov5-7.0修改骨干网络Ghostnet\efficientnet_b0\MobileNetv3_small\ShuffleNetV2_yolov7 更换骨干网

yolov7 更换骨干网

修改骨干网络主要需要添加模块到models/common.py文件中,在models/yolo.py文件夹中进行注册,修改models下面的yaml文件中的网络结构。

一、添加Ghostnet网络,替换Backbone

(yolov5-7.0的models/hu/yolov5s-ghost已经包含整体替换):

  1. class C3Ghost(C3):
  2.     # C3 module with GhostBottleneck()
  3.     def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
  4.         super().__init__(c1, c2, n, shortcut, g, e)
  5.         c_ = int(c2 * e)  # hidden channels
  6.         self.m = nn.Sequential(*(GhostBottleneck(c_, c_) for _ in range(n)))

  1. class GhostConv(nn.Module):
  2.     # Ghost Convolution https://github.com/huawei-noah/ghostnet
  3.     def __init__(self, c1, c2, k=1, s=1, g=1, act=True):  # ch_in, ch_out, kernel, stride, groups
  4.         super().__init__()
  5.         c_ = c2 // 2  # hidden channels
  6.         self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
  7.         self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)
  8.     def forward(self, x):
  9.         y = self.cv1(x)
  10.         return torch.cat((y, self.cv2(y)), 1)

  1. class GhostBottleneck(nn.Module):
  2.     # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
  3.     def __init__(self, c1, c2, k=3, s=1):  # ch_in, ch_out, kernel, stride
  4.         super().__init__()
  5.         c_ = c2 // 2
  6.         self.conv = nn.Sequential(
  7.             GhostConv(c1, c_, 1, 1),  # pw
  8.             DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(),  # dw
  9.             GhostConv(c_, c2, 1, 1, act=False))  # pw-linear
  10.         self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False), Conv(c1, c2, 1, 1,
  11.                                                                             act=False)) if s == 2 else nn.Identity()
  12.     def forward(self, x):
  13.         return self.conv(x) + self.shortcut(x)

修改步骤:

1. common.py与yolo.py文件已经包含ghost相关模块的配置和引用;

2.yolov5s_Ghost_backnone.yaml文件配置

  1. # YOLOv5 ��� by Ultralytics, AGPL-3.0 license
  2. # Parameters
  3. nc: 80  # number of classes
  4. depth_multiple: 0.33  # model depth multiple
  5. width_multiple: 0.50  # layer channel multiple
  6. anchors:
  7.   - [10,13, 16,30, 33,23]  # P3/8
  8.   - [30,61, 62,45, 59,119]  # P4/16
  9.   - [116,90, 156,198, 373,326]  # P5/32
  10. # YOLOv5 v6.0 backbone
  11. backbone:
  12.   # [from, number, module, args]
  13.   [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
  14.    [-1, 1, GhostConv, [128, 3, 2]],  # 1-P2/4
  15.    [-1, 3, C3Ghost, [128]],
  16.    [-1, 1, GhostConv, [256, 3, 2]],  # 3-P3/8
  17.    [-1, 6, C3Ghost, [256]],
  18.    [-1, 1, GhostConv, [512, 3, 2]],  # 5-P4/16
  19.    [-1, 9, C3Ghost, [512]],
  20.    [-1, 1, GhostConv, [1024, 3, 2]],  # 7-P5/32
  21.    [-1, 3, C3Ghost, [1024]],
  22.    [-1, 1, SPPF, [1024, 5]],  # 9
  23.   ]
  24. # YOLOv5 v6.0 head
  25. head:
  26.   [[-1, 1, Conv, [512, 1, 1]],
  27.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  28.    [[-1, 6], 1, Concat, [1]],  # cat backbone P4
  29.    [-1, 3, C3, [512, False]],  # 13
  30.    [-1, 1, Conv, [256, 1, 1]],
  31.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  32.    [[-1, 4], 1, Concat, [1]],  # cat backbone P3
  33.    [-1, 3, C3, [256, False]],  # 17 (P3/8-small)
  34.    [-1, 1, Conv, [256, 3, 2]],
  35.    [[-1, 14], 1, Concat, [1]],  # cat head P4
  36.    [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)
  37.    [-1, 1, Conv, [512, 3, 2]],
  38.    [[-1, 10], 1, Concat, [1]],  # cat head P5
  39.    [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)
  40.    [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  41.   ]

二、添加efficientnet_b0网络

修改步骤:

1. common.py

  1. # ---------------------------- efficientnet_b0 start -------------------------------
  2. class effb0(nn.Module):
  3.     def __init__(self, *args) -> None:
  4.         super().__init__()
  5.         model = models.efficientnet_b0(pretrained=True)
  6.         modules = list(model.children())
  7.         modules = modules[0][args[1]:args[2]]
  8.         self.model = nn.Sequential(*modules)
  9.     def forward(self, x):
  10.         return self.model(x)
  11. # ---------------------------- efficientnet_b0 end ---------------------------------

2. yolo.py文件

parse_model函数中添加

  1.  elif m is effb0:    
  2.               
  3.             c2 = args[0]

3. yolov5s_efficientnet_b0.yaml文件配置

  1. # YOLOv5 ��� by Ultralytics, GPL-3.0 license
  2. # Parameters
  3. nc: 80  # number of classes
  4. depth_multiple: 0.33  # model depth multiple
  5. width_multiple: 0.25  # layer channel multiple
  6. anchors:
  7.   - [10,13, 16,30, 33,23]  # P3/8
  8.   - [30,61, 62,45, 59,119]  # P4/16
  9.   - [116,90, 156,198, 373,326]  # P5/32
  10. # YOLOv5 v6.0 backbone
  11. backbone:
  12.   # [from, number, module, args]
  13.   [[-1, 1, effb0, [40,0,4]],  # 0
  14.    [-1, 1, effb0, [112,4,6]],  # 1
  15.    [-1, 1, effb0, [1280,6,9]],  # 2
  16.    [-1, 1, SPPF, [1024, 5]],  # 3
  17.   ]
  18. # YOLOv5 v6.0 head
  19. head:
  20.   [[-1, 1, Conv, [512, 1, 1]],
  21.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  22.    [[-1, 1], 1, Concat, [1]],  # cat backbone P4
  23.    [-1, 3, C3, [512, False]],  # 7
  24.    [-1, 1, Conv, [256, 1, 1]],
  25.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  26.    [[-1, 0], 1, Concat, [1]],  # cat backbone P3
  27.    [-1, 3, C3, [256, False]],  # 11 (P3/8-small)
  28.    [-1, 1, Conv, [256, 3, 2]],
  29.    [[-1, 7], 1, Concat, [1]],  # cat head P4
  30.    [-1, 3, C3, [512, False]],  # 14 (P4/16-medium)
  31.    [-1, 1, Conv, [512, 3, 2]],
  32.    [[-1, 3], 1, Concat, [1]],  # cat head P5
  33.    [-1, 3, C3, [1024, False]],  # 17 (P5/32-large)
  34.    [[11, 14, 17], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  35.   ]

三、添加MobileNetv3_small网络

修改步骤:

1. common.py

  1. # ---------------------------- MobileBlock small start -------------------------------
  2. # Mobilenetv3Small
  3. class SeBlock(nn.Module):
  4.     def __init__(self, in_channel, reduction=4):
  5.         super().__init__()
  6.         self.Squeeze = nn.AdaptiveAvgPool2d(1)
  7.         self.Excitation = nn.Sequential()
  8.         self.Excitation.add_module('FC1', nn.Conv2d(in_channel, in_channel // reduction, kernel_size=1))  # 1*1卷积与此效果相同
  9.         self.Excitation.add_module('ReLU', nn.ReLU())
  10.         self.Excitation.add_module('FC2', nn.Conv2d(in_channel // reduction, in_channel, kernel_size=1))
  11.         self.Excitation.add_module('Sigmoid', nn.Sigmoid())
  12.     def forward(self, x):
  13.         y = self.Squeeze(x)
  14.         ouput = self.Excitation(y)
  15.         return x * (ouput.expand_as(x))
  16. class Conv_BN_HSwish(nn.Module):
  17.     """
  18.     This equals to
  19.     def conv_3x3_bn(inp, oup, stride):
  20.         return nn.Sequential(
  21.             nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
  22.             nn.BatchNorm2d(oup),
  23.             h_swish()
  24.         )
  25.     """
  26.     def __init__(self, c1, c2, stride):
  27.         super(Conv_BN_HSwish, self).__init__()
  28.         self.conv = nn.Conv2d(c1, c2, 3, stride, 1, bias=False)
  29.         self.bn = nn.BatchNorm2d(c2)
  30.         self.act = nn.Hardswish()
  31.     def forward(self, x):
  32.         return self.act(self.bn(self.conv(x)))
  33. class MobileNetV3_InvertedResidual(nn.Module):
  34.     def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):
  35.         super(MobileNetV3_InvertedResidual, self).__init__()
  36.         assert stride in [1, 2]
  37.         self.identity = stride == 1 and inp == oup
  38.         if inp == hidden_dim:
  39.             self.conv = nn.Sequential(
  40.                 # dw
  41.                 nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
  42.                           bias=False),
  43.                 nn.BatchNorm2d(hidden_dim),
  44.                 nn.Hardswish() if use_hs else nn.ReLU(),
  45.                 # Squeeze-and-Excite
  46.                 SeBlock(hidden_dim) if use_se else nn.Sequential(),
  47.                 # pw-linear
  48.                 nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
  49.                 nn.BatchNorm2d(oup),
  50.             )
  51.         else:
  52.             self.conv = nn.Sequential(
  53.                 # pw
  54.                 nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
  55.                 nn.BatchNorm2d(hidden_dim),
  56.                 nn.Hardswish() if use_hs else nn.ReLU(),
  57.                 # dw
  58.                 nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
  59.                           bias=False),
  60.                 nn.BatchNorm2d(hidden_dim),
  61.                 # Squeeze-and-Excite
  62.                 SeBlock(hidden_dim) if use_se else nn.Sequential(),
  63.                 nn.Hardswish() if use_hs else nn.ReLU(),
  64.                 # pw-linear
  65.                 nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
  66.                 nn.BatchNorm2d(oup),
  67.             )
  68.     def forward(self, x):
  69.         y = self.conv(x)
  70.         if self.identity:
  71.             return x + y
  72.         else:
  73.             return y
  74. # ---------------------------- MobileBlock end ---------------------------------

2. yolo.py文件

在parse_model函数中引入 Conv_BN_HSwish, MobileNetV3_InvertedResidual模块   

  1. if m in {
  2.                 Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,     #cyz
  3.                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,
  4.                 Conv_BN_HSwish, MobileNetV3_InvertedResidual,conv_bn_relu_maxpool, Shuffle_Block}

 3.  yolov5s_MobileNetv3_small.yaml文件配置

  1. # YOLOv5 ��� by Ultralytics, GPL-3.0 license
  2. # Parameters
  3. nc: 1  # number of classes
  4. depth_multiple: 1.0  # model depth multiple
  5. width_multiple: 1.0  # layer channel multiple
  6. anchors:
  7.   - [10,13, 16,30, 33,23]  # P3/8
  8.   - [30,61, 62,45, 59,119]  # P4/16
  9.   - [116,90, 156,198, 373,326]  # P5/32
  10.    # Mobilenetv3-small backbone
  11.    # MobileNetV3_InvertedResidual [out_ch, hid_ch, k_s, stride, SE, HardSwish]
  12. backbone:
  13.   # [from, number, module, args]
  14.   [[-1, 1, Conv_BN_HSwish, [16, 2]],                              # 0-p1/2
  15.    [-1, 1, MobileNetV3_InvertedResidual, [16,  16, 3, 2, 1, 0]],  # 1-p2/4
  16.    [-1, 1, MobileNetV3_InvertedResidual, [24,  72, 3, 2, 0, 0]],  # 2-p3/8
  17.    [-1, 1, MobileNetV3_InvertedResidual, [24,  88, 3, 1, 0, 0]],  # 3
  18.    [-1, 1, MobileNetV3_InvertedResidual, [40,  96, 5, 2, 1, 1]],  # 4-p4/16
  19.    [-1, 1, MobileNetV3_InvertedResidual, [40, 240, 5, 1, 1, 1]],  # 5
  20.    [-1, 1, MobileNetV3_InvertedResidual, [40, 240, 5, 1, 1, 1]],  # 6
  21.    [-1, 1, MobileNetV3_InvertedResidual, [48, 120, 5, 1, 1, 1]],  # 7
  22.    [-1, 1, MobileNetV3_InvertedResidual, [48, 144, 5, 1, 1, 1]],  # 8
  23.    [-1, 1, MobileNetV3_InvertedResidual, [96, 288, 5, 2, 1, 1]],  # 9-p5/32
  24.    [-1, 1, MobileNetV3_InvertedResidual, [96, 576, 5, 1, 1, 1]],  # 10
  25.    [-1, 1, MobileNetV3_InvertedResidual, [96, 576, 5, 1, 1, 1]],  # 11
  26.   ]
  27. # YOLOv5 v6.0 head
  28. head:
  29.   [[-1, 1, Conv, [96, 1, 1]],  # 12
  30.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  31.    [[-1, 8], 1, Concat, [1]],  # cat backbone P4
  32.    [-1, 3, C3, [144, False]],  # 15
  33.    [-1, 1, Conv, [144, 1, 1]], # 16
  34.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  35.    [[-1, 3], 1, Concat, [1]],  # cat backbone P3
  36.    [-1, 3, C3, [168, False]],  # 19 (P3/8-small)
  37.    [-1, 1, Conv, [168, 3, 2]],
  38.    [[-1, 16], 1, Concat, [1]], # cat head P4
  39.    [-1, 3, C3, [312, False]],  # 22 (P4/16-medium)
  40.    [-1, 1, Conv, [312, 3, 2]],
  41.    [[-1, 12], 1, Concat, [1]], # cat head P5
  42.    [-1, 3, C3, [408, False]],  # 25 (P5/32-large)
  43.    [[19, 22, 25], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  44.   ]

四、添加ShuffleNetV2网络

修改步骤:

1.common.py

  1. # ---------------------------- ShuffleBlock start -------------------------------
  2. # 通道重排,跨group信息交流
  3. def channel_shuffle(x, groups):
  4.     batchsize, num_channels, height, width = x.data.size()
  5.     channels_per_group = num_channels // groups
  6.     # reshape
  7.     x = x.view(batchsize, groups,
  8.                channels_per_group, height, width)
  9.     x = torch.transpose(x, 1, 2).contiguous()
  10.     # flatten
  11.     x = x.view(batchsize, -1, height, width)
  12.     return x
  13. class conv_bn_relu_maxpool(nn.Module):
  14.     def __init__(self, c1, c2):  # ch_in, ch_out
  15.         super(conv_bn_relu_maxpool, self).__init__()
  16.         self.conv = nn.Sequential(
  17.             nn.Conv2d(c1, c2, kernel_size=3, stride=2, padding=1, bias=False),
  18.             nn.BatchNorm2d(c2),
  19.             nn.ReLU(inplace=True),
  20.         )
  21.         self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  22.     def forward(self, x):
  23.         return self.maxpool(self.conv(x))
  24. class Shuffle_Block(nn.Module):
  25.     def __init__(self, inp, oup, stride):
  26.         super(Shuffle_Block, self).__init__()
  27.         if not (1 <= stride <= 3):
  28.             raise ValueError('illegal stride value')
  29.         self.stride = stride
  30.         branch_features = oup // 2
  31.         assert (self.stride != 1) or (inp == branch_features << 1)
  32.         if self.stride > 1:
  33.             self.branch1 = nn.Sequential(
  34.                 self.depthwise_conv(inp, inp, kernel_size=3, stride=self.stride, padding=1),
  35.                 nn.BatchNorm2d(inp),
  36.                 nn.Conv2d(inp, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
  37.                 nn.BatchNorm2d(branch_features),
  38.                 nn.ReLU(inplace=True),
  39.             )
  40.         self.branch2 = nn.Sequential(
  41.             nn.Conv2d(inp if (self.stride > 1) else branch_features,
  42.                       branch_features, kernel_size=1, stride=1, padding=0, bias=False),
  43.             nn.BatchNorm2d(branch_features),
  44.             nn.ReLU(inplace=True),
  45.             self.depthwise_conv(branch_features, branch_features, kernel_size=3, stride=self.stride, padding=1),
  46.             nn.BatchNorm2d(branch_features),
  47.             nn.Conv2d(branch_features, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
  48.             nn.BatchNorm2d(branch_features),
  49.             nn.ReLU(inplace=True),
  50.         )
  51.     @staticmethod
  52.     def depthwise_conv(i, o, kernel_size, stride=1, padding=0, bias=False):
  53.         return nn.Conv2d(i, o, kernel_size, stride, padding, bias=bias, groups=i)
  54.     def forward(self, x):
  55.         if self.stride == 1:
  56.             x1, x2 = x.chunk(2, dim=1)  # 按照维度1进行split
  57.             out = torch.cat((x1, self.branch2(x2)), dim=1)
  58.         else:
  59.             out = torch.cat((self.branch1(x), self.branch2(x)), dim=1)
  60.         out = channel_shuffle(out, 2)
  61.         return out
  62. # ---------------------------- ShuffleBlock end --------------------------------

2. yolo.py文件

在parse_model函数中引入 conv_bn_relu_maxpool, Shuffle_Block模块:

  1.  if m in {
  2.                 Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,     #cyz
  3.                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,
  4.                 Conv_BN_HSwish, MobileNetV3_InvertedResidual,conv_bn_relu_maxpool, Shuffle_Block}:
  5.             c1, c2 = ch[f], args[0]

3. yolov5s_ShuffleNetV2.yaml文件配置

  1. # YOLOv5 ��� by Ultralytics, GPL-3.0 license
  2. # Parameters
  3. nc: 20  # number of classes
  4. depth_multiple: 1.0  # model depth multiple
  5. width_multiple: 1.0  # layer channel multiple
  6. anchors:
  7.   - [10,13, 16,30, 33,23]  # P3/8
  8.   - [30,61, 62,45, 59,119]  # P4/16
  9.   - [116,90, 156,198, 373,326]  # P5/32
  10. # YOLOv5 v6.0 backbone
  11. backbone:
  12.   # [from, number, module, args]
  13.   # Shuffle_Block: [out, stride]
  14.   [[ -1, 1, conv_bn_relu_maxpool, [ 32 ] ], # 0-P2/4
  15.    [ -1, 1, Shuffle_Block, [ 128, 2 ] ],  # 1-P3/8
  16.    [ -1, 3, Shuffle_Block, [ 128, 1 ] ],  # 2
  17.    [ -1, 1, Shuffle_Block, [ 256, 2 ] ],  # 3-P4/16
  18.    [ -1, 7, Shuffle_Block, [ 256, 1 ] ],  # 4
  19.    [ -1, 1, Shuffle_Block, [ 512, 2 ] ],  # 5-P5/32
  20.    [ -1, 3, Shuffle_Block, [ 512, 1 ] ],  # 6
  21.   ]
  22. # YOLOv5 v6.0 head
  23. head:
  24.   [[-1, 1, Conv, [256, 1, 1]],
  25.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  26.    [[-1, 4], 1, Concat, [1]],  # cat backbone P4
  27.    [-1, 1, C3, [256, False]],  # 10
  28.    [-1, 1, Conv, [128, 1, 1]],
  29.    [-1, 1, nn.Upsample, [None, 2, 'nearest']],
  30.    [[-1, 2], 1, Concat, [1]],  # cat backbone P3
  31.    [-1, 1, C3, [128, False]],  # 14 (P3/8-small)
  32.    [-1, 1, Conv, [128, 3, 2]],
  33.    [[-1, 11], 1, Concat, [1]],  # cat head P4
  34.    [-1, 1, C3, [256, False]],  # 17 (P4/16-medium)
  35.    [-1, 1, Conv, [256, 3, 2]],
  36.    [[-1, 7], 1, Concat, [1]],  # cat head P5
  37.    [-1, 1, C3, [512, False]],  # 20 (P5/32-large)
  38.    [[14, 17, 20], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  39.   ]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/402506
推荐阅读
相关标签
  

闽ICP备14008679号