赞
踩
修改骨干网络主要需要添加模块到models/common.py文件中,在models/yolo.py文件夹中进行注册,修改models下面的yaml文件中的网络结构。
(yolov5-7.0的models/hu/yolov5s-ghost已经包含整体替换):
- class C3Ghost(C3):
-
- # C3 module with GhostBottleneck()
-
- def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
-
- super().__init__(c1, c2, n, shortcut, g, e)
-
- c_ = int(c2 * e) # hidden channels
-
- self.m = nn.Sequential(*(GhostBottleneck(c_, c_) for _ in range(n)))
-
-
-
- class GhostConv(nn.Module):
-
- # Ghost Convolution https://github.com/huawei-noah/ghostnet
-
- def __init__(self, c1, c2, k=1, s=1, g=1, act=True): # ch_in, ch_out, kernel, stride, groups
-
- super().__init__()
-
- c_ = c2 // 2 # hidden channels
-
- self.cv1 = Conv(c1, c_, k, s, None, g, act=act)
-
- self.cv2 = Conv(c_, c_, 5, 1, None, c_, act=act)
-
-
-
- def forward(self, x):
-
- y = self.cv1(x)
-
- return torch.cat((y, self.cv2(y)), 1)
- class GhostBottleneck(nn.Module):
-
- # Ghost Bottleneck https://github.com/huawei-noah/ghostnet
-
- def __init__(self, c1, c2, k=3, s=1): # ch_in, ch_out, kernel, stride
-
- super().__init__()
-
- c_ = c2 // 2
-
- self.conv = nn.Sequential(
-
- GhostConv(c1, c_, 1, 1), # pw
-
- DWConv(c_, c_, k, s, act=False) if s == 2 else nn.Identity(), # dw
-
- GhostConv(c_, c2, 1, 1, act=False)) # pw-linear
-
- self.shortcut = nn.Sequential(DWConv(c1, c1, k, s, act=False), Conv(c1, c2, 1, 1,
-
- act=False)) if s == 2 else nn.Identity()
-
-
-
- def forward(self, x):
-
- return self.conv(x) + self.shortcut(x)
修改步骤:
1. common.py与yolo.py文件已经包含ghost相关模块的配置和引用;
2.yolov5s_Ghost_backnone.yaml文件配置
- # YOLOv5 ��� by Ultralytics, AGPL-3.0 license
-
-
-
- # Parameters
-
- nc: 80 # number of classes
-
- depth_multiple: 0.33 # model depth multiple
-
- width_multiple: 0.50 # layer channel multiple
-
- anchors:
-
- - [10,13, 16,30, 33,23] # P3/8
-
- - [30,61, 62,45, 59,119] # P4/16
-
- - [116,90, 156,198, 373,326] # P5/32
-
-
-
- # YOLOv5 v6.0 backbone
-
- backbone:
-
- # [from, number, module, args]
-
- [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
-
- [-1, 1, GhostConv, [128, 3, 2]], # 1-P2/4
-
- [-1, 3, C3Ghost, [128]],
-
- [-1, 1, GhostConv, [256, 3, 2]], # 3-P3/8
-
- [-1, 6, C3Ghost, [256]],
-
- [-1, 1, GhostConv, [512, 3, 2]], # 5-P4/16
-
- [-1, 9, C3Ghost, [512]],
-
- [-1, 1, GhostConv, [1024, 3, 2]], # 7-P5/32
-
- [-1, 3, C3Ghost, [1024]],
-
- [-1, 1, SPPF, [1024, 5]], # 9
-
- ]
-
-
-
- # YOLOv5 v6.0 head
-
- head:
-
- [[-1, 1, Conv, [512, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 6], 1, Concat, [1]], # cat backbone P4
-
- [-1, 3, C3, [512, False]], # 13
-
-
-
- [-1, 1, Conv, [256, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 4], 1, Concat, [1]], # cat backbone P3
-
- [-1, 3, C3, [256, False]], # 17 (P3/8-small)
-
-
-
- [-1, 1, Conv, [256, 3, 2]],
-
- [[-1, 14], 1, Concat, [1]], # cat head P4
-
- [-1, 3, C3, [512, False]], # 20 (P4/16-medium)
-
-
-
- [-1, 1, Conv, [512, 3, 2]],
-
- [[-1, 10], 1, Concat, [1]], # cat head P5
-
- [-1, 3, C3, [1024, False]], # 23 (P5/32-large)
-
-
-
- [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
-
- ]
修改步骤:
- # ---------------------------- efficientnet_b0 start -------------------------------
-
-
-
- class effb0(nn.Module):
-
- def __init__(self, *args) -> None:
-
- super().__init__()
-
- model = models.efficientnet_b0(pretrained=True)
-
- modules = list(model.children())
-
- modules = modules[0][args[1]:args[2]]
-
- self.model = nn.Sequential(*modules)
-
- def forward(self, x):
-
- return self.model(x)
-
-
-
- # ---------------------------- efficientnet_b0 end ---------------------------------
parse_model函数中添加
- elif m is effb0:
-
- c2 = args[0]
- # YOLOv5 ��� by Ultralytics, GPL-3.0 license
-
-
-
- # Parameters
-
- nc: 80 # number of classes
-
- depth_multiple: 0.33 # model depth multiple
-
- width_multiple: 0.25 # layer channel multiple
-
- anchors:
-
- - [10,13, 16,30, 33,23] # P3/8
-
- - [30,61, 62,45, 59,119] # P4/16
-
- - [116,90, 156,198, 373,326] # P5/32
-
-
-
- # YOLOv5 v6.0 backbone
-
- backbone:
-
- # [from, number, module, args]
-
- [[-1, 1, effb0, [40,0,4]], # 0
-
- [-1, 1, effb0, [112,4,6]], # 1
-
- [-1, 1, effb0, [1280,6,9]], # 2
-
- [-1, 1, SPPF, [1024, 5]], # 3
-
- ]
-
-
-
- # YOLOv5 v6.0 head
-
- head:
-
- [[-1, 1, Conv, [512, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 1], 1, Concat, [1]], # cat backbone P4
-
- [-1, 3, C3, [512, False]], # 7
-
-
-
- [-1, 1, Conv, [256, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 0], 1, Concat, [1]], # cat backbone P3
-
- [-1, 3, C3, [256, False]], # 11 (P3/8-small)
-
-
-
- [-1, 1, Conv, [256, 3, 2]],
-
- [[-1, 7], 1, Concat, [1]], # cat head P4
-
- [-1, 3, C3, [512, False]], # 14 (P4/16-medium)
-
-
-
- [-1, 1, Conv, [512, 3, 2]],
-
- [[-1, 3], 1, Concat, [1]], # cat head P5
-
- [-1, 3, C3, [1024, False]], # 17 (P5/32-large)
-
-
-
- [[11, 14, 17], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
-
- ]
修改步骤:
- # ---------------------------- MobileBlock small start -------------------------------
-
- # Mobilenetv3Small
-
- class SeBlock(nn.Module):
-
- def __init__(self, in_channel, reduction=4):
-
- super().__init__()
-
- self.Squeeze = nn.AdaptiveAvgPool2d(1)
-
-
-
- self.Excitation = nn.Sequential()
-
- self.Excitation.add_module('FC1', nn.Conv2d(in_channel, in_channel // reduction, kernel_size=1)) # 1*1卷积与此效果相同
-
- self.Excitation.add_module('ReLU', nn.ReLU())
-
- self.Excitation.add_module('FC2', nn.Conv2d(in_channel // reduction, in_channel, kernel_size=1))
-
- self.Excitation.add_module('Sigmoid', nn.Sigmoid())
-
-
-
- def forward(self, x):
-
- y = self.Squeeze(x)
-
- ouput = self.Excitation(y)
-
- return x * (ouput.expand_as(x))
-
-
-
-
-
- class Conv_BN_HSwish(nn.Module):
-
- """
- This equals to
- def conv_3x3_bn(inp, oup, stride):
- return nn.Sequential(
- nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
- nn.BatchNorm2d(oup),
- h_swish()
- )
- """
-
-
-
- def __init__(self, c1, c2, stride):
-
- super(Conv_BN_HSwish, self).__init__()
-
- self.conv = nn.Conv2d(c1, c2, 3, stride, 1, bias=False)
-
- self.bn = nn.BatchNorm2d(c2)
-
- self.act = nn.Hardswish()
-
-
-
- def forward(self, x):
-
- return self.act(self.bn(self.conv(x)))
-
-
-
-
-
- class MobileNetV3_InvertedResidual(nn.Module):
-
- def __init__(self, inp, oup, hidden_dim, kernel_size, stride, use_se, use_hs):
-
- super(MobileNetV3_InvertedResidual, self).__init__()
-
- assert stride in [1, 2]
-
-
-
- self.identity = stride == 1 and inp == oup
-
-
-
- if inp == hidden_dim:
-
- self.conv = nn.Sequential(
-
- # dw
-
- nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
-
- bias=False),
-
- nn.BatchNorm2d(hidden_dim),
-
- nn.Hardswish() if use_hs else nn.ReLU(),
-
- # Squeeze-and-Excite
-
- SeBlock(hidden_dim) if use_se else nn.Sequential(),
-
- # pw-linear
-
- nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
-
- nn.BatchNorm2d(oup),
-
- )
-
- else:
-
- self.conv = nn.Sequential(
-
- # pw
-
- nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
-
- nn.BatchNorm2d(hidden_dim),
-
- nn.Hardswish() if use_hs else nn.ReLU(),
-
- # dw
-
- nn.Conv2d(hidden_dim, hidden_dim, kernel_size, stride, (kernel_size - 1) // 2, groups=hidden_dim,
-
- bias=False),
-
- nn.BatchNorm2d(hidden_dim),
-
- # Squeeze-and-Excite
-
- SeBlock(hidden_dim) if use_se else nn.Sequential(),
-
- nn.Hardswish() if use_hs else nn.ReLU(),
-
- # pw-linear
-
- nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
-
- nn.BatchNorm2d(oup),
-
- )
-
-
-
- def forward(self, x):
-
- y = self.conv(x)
-
- if self.identity:
-
- return x + y
-
- else:
-
- return y
-
-
-
- # ---------------------------- MobileBlock end ---------------------------------
在parse_model函数中引入 Conv_BN_HSwish, MobileNetV3_InvertedResidual模块
- if m in {
-
- Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv, #cyz
-
- BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,
-
- Conv_BN_HSwish, MobileNetV3_InvertedResidual,conv_bn_relu_maxpool, Shuffle_Block}
- # YOLOv5 ��� by Ultralytics, GPL-3.0 license
-
-
-
- # Parameters
-
- nc: 1 # number of classes
-
- depth_multiple: 1.0 # model depth multiple
-
- width_multiple: 1.0 # layer channel multiple
-
- anchors:
-
- - [10,13, 16,30, 33,23] # P3/8
-
- - [30,61, 62,45, 59,119] # P4/16
-
- - [116,90, 156,198, 373,326] # P5/32
-
-
-
- # Mobilenetv3-small backbone
-
- # MobileNetV3_InvertedResidual [out_ch, hid_ch, k_s, stride, SE, HardSwish]
-
- backbone:
-
- # [from, number, module, args]
-
- [[-1, 1, Conv_BN_HSwish, [16, 2]], # 0-p1/2
-
- [-1, 1, MobileNetV3_InvertedResidual, [16, 16, 3, 2, 1, 0]], # 1-p2/4
-
- [-1, 1, MobileNetV3_InvertedResidual, [24, 72, 3, 2, 0, 0]], # 2-p3/8
-
- [-1, 1, MobileNetV3_InvertedResidual, [24, 88, 3, 1, 0, 0]], # 3
-
- [-1, 1, MobileNetV3_InvertedResidual, [40, 96, 5, 2, 1, 1]], # 4-p4/16
-
- [-1, 1, MobileNetV3_InvertedResidual, [40, 240, 5, 1, 1, 1]], # 5
-
- [-1, 1, MobileNetV3_InvertedResidual, [40, 240, 5, 1, 1, 1]], # 6
-
- [-1, 1, MobileNetV3_InvertedResidual, [48, 120, 5, 1, 1, 1]], # 7
-
- [-1, 1, MobileNetV3_InvertedResidual, [48, 144, 5, 1, 1, 1]], # 8
-
- [-1, 1, MobileNetV3_InvertedResidual, [96, 288, 5, 2, 1, 1]], # 9-p5/32
-
- [-1, 1, MobileNetV3_InvertedResidual, [96, 576, 5, 1, 1, 1]], # 10
-
- [-1, 1, MobileNetV3_InvertedResidual, [96, 576, 5, 1, 1, 1]], # 11
-
- ]
-
-
-
- # YOLOv5 v6.0 head
-
- head:
-
- [[-1, 1, Conv, [96, 1, 1]], # 12
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 8], 1, Concat, [1]], # cat backbone P4
-
- [-1, 3, C3, [144, False]], # 15
-
-
-
- [-1, 1, Conv, [144, 1, 1]], # 16
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 3], 1, Concat, [1]], # cat backbone P3
-
- [-1, 3, C3, [168, False]], # 19 (P3/8-small)
-
-
-
- [-1, 1, Conv, [168, 3, 2]],
-
- [[-1, 16], 1, Concat, [1]], # cat head P4
-
- [-1, 3, C3, [312, False]], # 22 (P4/16-medium)
-
-
-
- [-1, 1, Conv, [312, 3, 2]],
-
- [[-1, 12], 1, Concat, [1]], # cat head P5
-
- [-1, 3, C3, [408, False]], # 25 (P5/32-large)
-
-
-
- [[19, 22, 25], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
-
- ]
修改步骤:
- # ---------------------------- ShuffleBlock start -------------------------------
-
-
-
- # 通道重排,跨group信息交流
-
- def channel_shuffle(x, groups):
-
- batchsize, num_channels, height, width = x.data.size()
-
- channels_per_group = num_channels // groups
-
-
-
- # reshape
-
- x = x.view(batchsize, groups,
-
- channels_per_group, height, width)
-
-
-
- x = torch.transpose(x, 1, 2).contiguous()
-
-
-
- # flatten
-
- x = x.view(batchsize, -1, height, width)
-
-
-
- return x
-
-
-
-
-
- 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))
-
-
-
-
-
- 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
-
- assert (self.stride != 1) or (inp == branch_features << 1)
-
-
-
- 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),
-
- )
-
-
-
- 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):
-
- if self.stride == 1:
-
- x1, x2 = x.chunk(2, dim=1) # 按照维度1进行split
-
- 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
-
-
-
-
-
- # ---------------------------- ShuffleBlock end --------------------------------
在parse_model函数中引入 conv_bn_relu_maxpool, Shuffle_Block模块:
- if m in {
-
- Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv, #cyz
-
- BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,
-
- Conv_BN_HSwish, MobileNetV3_InvertedResidual,conv_bn_relu_maxpool, Shuffle_Block}:
-
- c1, c2 = ch[f], args[0]
-
-
-
- # YOLOv5 ��� by Ultralytics, GPL-3.0 license
-
-
-
- # Parameters
-
- nc: 20 # number of classes
-
- depth_multiple: 1.0 # model depth multiple
-
- width_multiple: 1.0 # layer channel multiple
-
- anchors:
-
- - [10,13, 16,30, 33,23] # P3/8
-
- - [30,61, 62,45, 59,119] # P4/16
-
- - [116,90, 156,198, 373,326] # P5/32
-
-
-
- # YOLOv5 v6.0 backbone
-
- backbone:
-
- # [from, number, module, args]
-
- # Shuffle_Block: [out, stride]
-
- [[ -1, 1, conv_bn_relu_maxpool, [ 32 ] ], # 0-P2/4
-
- [ -1, 1, Shuffle_Block, [ 128, 2 ] ], # 1-P3/8
-
- [ -1, 3, Shuffle_Block, [ 128, 1 ] ], # 2
-
- [ -1, 1, Shuffle_Block, [ 256, 2 ] ], # 3-P4/16
-
- [ -1, 7, Shuffle_Block, [ 256, 1 ] ], # 4
-
- [ -1, 1, Shuffle_Block, [ 512, 2 ] ], # 5-P5/32
-
- [ -1, 3, Shuffle_Block, [ 512, 1 ] ], # 6
-
- ]
-
-
-
- # YOLOv5 v6.0 head
-
- head:
-
- [[-1, 1, Conv, [256, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 4], 1, Concat, [1]], # cat backbone P4
-
- [-1, 1, C3, [256, False]], # 10
-
-
-
- [-1, 1, Conv, [128, 1, 1]],
-
- [-1, 1, nn.Upsample, [None, 2, 'nearest']],
-
- [[-1, 2], 1, Concat, [1]], # cat backbone P3
-
- [-1, 1, C3, [128, False]], # 14 (P3/8-small)
-
-
-
- [-1, 1, Conv, [128, 3, 2]],
-
- [[-1, 11], 1, Concat, [1]], # cat head P4
-
- [-1, 1, C3, [256, False]], # 17 (P4/16-medium)
-
-
-
- [-1, 1, Conv, [256, 3, 2]],
-
- [[-1, 7], 1, Concat, [1]], # cat head P5
-
- [-1, 1, C3, [512, False]], # 20 (P5/32-large)
-
-
-
- [[14, 17, 20], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
-
- ]
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。