赞
踩
1.添加CBAM
1)修改commom.py
在代码最后添加
- #CBAM
- class ChannelAttention(nn.Module):
- def __init__(self, in_planes, ratio=16):
- super(ChannelAttention, self).__init__()
- self.avg_pool = nn.AdaptiveAvgPool2d(1)
- self.max_pool = nn.AdaptiveMaxPool2d(1)
- # in_planes // ratio 这里会出现如下警告:
- # UserWarning: __floordiv__ is deprecated(被舍弃了), and its behavior will change in a future version of pytorch.
- # It currently rounds toward 0 (like the 'trunc' function NOT 'floor').
- # This results in incorrect rounding for negative values.
- # To keep the current behavior, use torch.div(a, b, rounding_mode='trunc'),
- # or for actual floor division, use torch.div(a, b, rounding_mode='floor').
- # kernel = torch.DoubleTensor([*(x[0].shape[2:])]) // torch.DoubleTensor(list((m.output_size,))).squeeze()
- self.f1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)
- self.relu = nn.ReLU()
- self.f2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)
-
-
- self.sigmoid = nn.Sigmoid()
-
- def forward(self, x):
- # 全局平均池化—>MLP两层卷积
- avg_out = self.f2(self.relu(self.f1(self.avg_pool(x))))
- # 全局最大池化—>MLP两层卷积
- max_out = self.f2(self.relu(self.f1(self.max_pool(x))))
- out = self.sigmoid(avg_out + max_out)
- return out
-
-
- class SpatialAttention(nn.Module):
- def __init__(self, kernel_size=7):
- super(SpatialAttention, self).__init__()
-
- assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
- padding = 3 if kernel_size == 7 else 1
-
- self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
- self.sigmoid = nn.Sigmoid()
-
- def forward(self, x):
- # 基于channel的全局平均池化(channel=1)
- avg_out = torch.mean(x, dim=1, keepdim=True)
- # 基于channel的全局最大池化(channel=1)
- max_out, _ = torch.max(x, dim=1, keepdim=True)
- # channel拼接(channel=2)
- x = torch.cat([avg_out, max_out], dim=1)
- # channel=1
- x = self.conv(x)
- return self.sigmoid(x)
-
-
- class CBAMBottleneck(nn.Module):
- # ch_in, ch_out, shortcut, groups, expansion, ratio, kernel_size
- def __init__(self, c1, c2, shortcut=True, g=1, e=0.5, ratio=16, kernel_size=7):
- super(CBAMBottleneck, self).__init__()
- c_ = int(c2 * e) # hidden channels
- self.cv1 = Conv(c1, c_, 1, 1)
- self.cv2 = Conv(c_, c2, 3, 1, g=g)
- self.add = shortcut and c1 == c2
- # 加入CBAM模块
- self.channel_attention = ChannelAttention(c2, ratio)
- self.spatial_attention = SpatialAttention(kernel_size)
-
- def forward(self, x):
- # 考虑加入CBAM模块的位置:bottleneck模块刚开始时、bottleneck模块中shortcut之前,这里选择在shortcut之前
- x2 = self.cv2(self.cv1(x)) # x和x2的channel数相同
- # 在bottleneck模块中shortcut之前加入CBAM模块
- out = self.channel_attention(x2) * x2
- # print('outchannels:{}'.format(out.shape))
- out = self.spatial_attention(out) * out
- return x + out if self.add else out
-
-
- class C3CBAM(C3):
- # C3 module with CBAMBottleneck()
- def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
- super().__init__(c1, c2, n, shortcut, g, e) # 引入C3(父类)的属性
- c_ = int(c2 * e) # hidden channels
- self.m = nn.Sequential(*(CBAMBottleneck(c_, c_, shortcut) for _ in range(n)))
-
-
-
2)修改yolo.py
原代码为:
- if m in {
- Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
- BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x}:
- c1, c2 = ch[f], args[0]
在后面添加 CBAMBottleneck, C3CBAM
修改后为:
- if m in {
- Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
- BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,CBAMBottleneck, C3CBAM}:
- c1, c2 = ch[f], args[0]
3)在models文件夹下创建yaml文件,命名为yolov5-cbam.yaml
内容为
- # YOLOv5 声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/290979推荐阅读
相关标签
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。