国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

yolov5改進(jìn)之加入CBAM,SE,ECA,CA,SimAM,ShuffleAttention,Criss-CrossAttention,CrissCrossAttention多種注意力機(jī)制

這篇具有很好參考價值的文章主要介紹了yolov5改進(jìn)之加入CBAM,SE,ECA,CA,SimAM,ShuffleAttention,Criss-CrossAttention,CrissCrossAttention多種注意力機(jī)制。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

本文所涉及到的yolov5網(wǎng)絡(luò)為6.1版本(6.0-6.2均適用)

yolov5加入注意力機(jī)制模塊的三個標(biāo)準(zhǔn)步驟(適用于本文中的任何注意力機(jī)制)

1.common.py中加入注意力機(jī)制模塊

2.yolo.py中增加對應(yīng)的注意力機(jī)制關(guān)鍵字

3.yaml文件中添加相應(yīng)模塊

注:所有注意力機(jī)制的添加方法都是一致的,加入注意力機(jī)制是否有效的關(guān)鍵在于注意力機(jī)制添加的位置,本文提供兩種常用常用方法。

注:需要下列所有注意力機(jī)制已經(jīng)改好的代碼版本及yaml文件(到手即用),請私聊我(免費(fèi))

目錄

1.CBAM注意力機(jī)制

2.SE注意力機(jī)制

3.ECA注意力注意力機(jī)制

4.CA注意力注意力機(jī)制

5.SimAM注意力機(jī)制

6.ShuffleAttention注意力機(jī)制

7.CrissCrossAttention注意力機(jī)制


1.CBAM注意力機(jī)制

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)
 
        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):
        avg_out = self.f2(self.relu(self.f1(self.avg_pool(x))))
        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):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv(x)
        return self.sigmoid(x)
 
 
class CBAM(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, ratio=16, kernel_size=7):  # ch_in, ch_out, number, shortcut, groups, expansion
        super(CBAM, self).__init__()
        # c_ = int(c2 * e)  # hidden channels
        # self.cv1 = Conv(c1, c_, 1, 1)
        # self.cv2 = Conv(c1, c_, 1, 1)
        # self.cv3 = Conv(2 * c_, c2, 1)
        # self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
        self.channel_attention = ChannelAttention(c1, ratio)
        self.spatial_attention = SpatialAttention(kernel_size)
 
        # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])
 
    def forward(self, x):
        out = self.channel_attention(x) * x
        # print('outchannels:{}'.format(out.shape))
        out = self.spatial_attention(out) * out
        return out

以上代碼需要添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

第二步,需要更改models文件夾下的yolo.py文件??梢灾苯觕trl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加CBAM即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, CBAM):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x, CBAM]:
                args.insert(2, n)  # number of repeats
                n = 1

第三步,就是最為關(guān)鍵的改動yaml文件了,我們以yolov5s.yaml為例進(jìn)行改進(jìn),這里僅截取關(guān)鍵部分,未截取部分則不做改動。

第一個版本是將CBAM放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, CBAM, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將CBAM放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, CBAM, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, CBAM, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, CBAM, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, CBAM, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

2.SE注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

class SE(nn.Module):
    def __init__(self, c1, c2, r=16):
        super(SE, self).__init__()
        self.avgpool = nn.AdaptiveAvgPool2d(1)
        self.l1 = nn.Linear(c1, c1 // r, bias=False)
        self.relu = nn.ReLU(inplace=True)
        self.l2 = nn.Linear(c1 // r, c1, bias=False)
        self.sig = nn.Sigmoid()
    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avgpool(x).view(b, c)
        y = self.l1(y)
        y = self.relu(y)
        y = self.l2(y)
        y = self.sig(y)
        y = y.view(b, c, 1, 1)
        return x * y.expand_as(x)

第二步,需要更改models文件夾下的yolo.py文件。可以直接ctrl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加SE即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, SE):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x, SE]:
                args.insert(2, n)  # number of repeats
                n = 1

第三步,就是最為關(guān)鍵的改動yaml文件了,我們以yolov5s.yaml為例進(jìn)行改進(jìn),這里僅截取關(guān)鍵部分,未截取部分則不做改動。

第一個版本是將SE放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, SE, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將SE放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, SE, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, SE, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, SE, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, SE, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

3.ECA注意力注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

class h_sigmoid(nn.Module):
    def __init__(self, inplace=True):
        super(h_sigmoid, self).__init__()
        self.relu = nn.ReLU6(inplace=inplace)

    def forward(self, x):
        return self.relu(x + 3) / 6


class h_swish(nn.Module):
    def __init__(self, inplace=True):
        super(h_swish, self).__init__()
        self.sigmoid = h_sigmoid(inplace=inplace)

    def forward(self, x):
        return x * self.sigmoid(x)
 
 
class CA(nn.Module):
    def __init__(self, inp, oup, reduction=32):
        super(CA, self).__init__()
        self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
        self.pool_w = nn.AdaptiveAvgPool2d((1, None))

        mip = max(8, inp // reduction)

        self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0)
        self.bn1 = nn.BatchNorm2d(mip)
        self.act = h_swish()

        self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)
        self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)

    def forward(self, x):
        identity = x

        n, c, h, w = x.size()
        x_h = self.pool_h(x)
        x_w = self.pool_w(x).permute(0, 1, 3, 2)

        y = torch.cat([x_h, x_w], dim=2)
        y = self.conv1(y)
        y = self.bn1(y)
        y = self.act(y)

        x_h, x_w = torch.split(y, [h, w], dim=2)
        x_w = x_w.permute(0, 1, 3, 2)

        a_h = self.conv_h(x_h).sigmoid()
        a_w = self.conv_w(x_w).sigmoid()

        out = identity * a_w * a_h

        return out

ECA注意力機(jī)制比較特殊,不需要改動models文件夾下的yolo.py文件,可直接使用。

第三步,就是最為關(guān)鍵的改動yaml文件了,我們以yolov5s.yaml為例進(jìn)行改進(jìn),這里僅截取關(guān)鍵部分,未截取部分則不做改動。

第一個版本是將ECA放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, SE, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將ECA放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, SE, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, SE, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, SE, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, SE, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

4.CA注意力注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

class ECA(nn.Module):
    """Constructs a ECA module.
    Args:
        channel: Number of channels of the input feature map
        k_size: Adaptive selection of kernel size
    """
    def __init__(self, channel, k_size=3):
        super(ECA, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # feature descriptor on the global spatial information
        y = self.avg_pool(x)

        # Two different branches of ECA module
        y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)

        # Multi-scale information fusion
        y = self.sigmoid(y)
        x= x*y.expand_as(x)

        return x * y.expand_as(x)

第二步,需要更改models文件夾下的yolo.py文件??梢灾苯觕trl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加SE即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, SE):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x, SE]:
                args.insert(2, n)  # number of repeats
                n = 1

第一個版本是將CA放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, CA, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將CA放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, CA, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, CA, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, CA, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, CA, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

5.SimAM注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

class SimAM(torch.nn.Module):
    def __init__(self, channels = None,out_channels = None, e_lambda = 1e-4):
        super(SimAM, self).__init__()

        self.activaton = nn.Sigmoid()
        self.e_lambda = e_lambda

    def forward(self, x):

        b, c, h, w = x.size()
        
        n = w * h - 1

        x_minus_mu_square = (x - x.mean(dim=[2,3], keepdim=True)).pow(2)
        y = x_minus_mu_square / (4 * (x_minus_mu_square.sum(dim=[2,3], keepdim=True) / n + self.e_lambda)) + 0.5

        return x * self.activaton(y)  

第二步,需要更改models文件夾下的yolo.py文件。可以直接ctrl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加SimAM即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, SimAM):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x, SimAM]:
                args.insert(2, n)  # number of repeats
                n = 1

第一個版本是將SimAM放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, SimAM, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將SimAM放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, SimAM, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, SimAM, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, SimAM, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, SimAM, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

6.ShuffleAttention注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

class ShuffleAttention(nn.Module):

    def __init__(self, channel=512,reduction=16,G=8):
        super().__init__()
        self.G=G
        self.channel=channel
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.gn = nn.GroupNorm(channel // (2 * G), channel // (2 * G))
        self.cweight = torch.ones(1, channel // (2 * G), 1, 1)
        self.cbias = torch.ones(1, channel // (2 * G), 1, 1)
        self.sweight = torch.ones(1, channel // (2 * G), 1, 1)
        self.sbias = torch.ones(1, channel // (2 * G), 1, 1)
        self.sigmoid=nn.Sigmoid()

    @staticmethod
    def channel_shuffle(x, groups):
        b, c, h, w = x.shape
        x = x.reshape(b, groups, -1, h, w)
        x = x.permute(0, 2, 1, 3, 4)

        # flatten
        x = x.reshape(b, -1, h, w)

        return x

    def forward(self, x):
        b, c, h, w = x.size()
        
        #group into subfeatures
        x=x.view(b*self.G,-1,h,w) #bs*G,c//G,h,w

        #channel_split
        x_0,x_1=x.chunk(2,dim=1) #bs*G,c//(2*G),h,w

        #channel attention
        x_channel=self.avg_pool(x_0) #bs*G,c//(2*G),1,1
        x_channel=self.cweight*x_channel+self.cbias #bs*G,c//(2*G),1,1
        x_channel=x_0*self.sigmoid(x_channel)

        #spatial attention
        x_spatial=self.gn(x_1) #bs*G,c//(2*G),h,w
        x_spatial=self.sweight*x_spatial+self.sbias #bs*G,c//(2*G),h,w
        x_spatial=x_1*self.sigmoid(x_spatial) #bs*G,c//(2*G),h,w

        # concatenate along channel axis
        out=torch.cat([x_channel,x_spatial],dim=1)  #bs*G,c//G,h,w
        out=out.contiguous().view(b,-1,h,w)

        # channel shuffle
        out = self.channel_shuffle(out, 2)
        return out

第二步,需要更改models文件夾下的yolo.py文件??梢灾苯觕trl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加ShuffleAttention即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, ShuffleAttention):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x, ShuffleAttention]:
                args.insert(2, n)  # number of repeats
                n = 1

第一個版本是將ShuffleAttention放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, ShuffleAttention, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將ShuffleAttention放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, ShuffleAttention, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, ShuffleAttention, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, ShuffleAttention, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, ShuffleAttention, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

7.CrissCrossAttention注意力機(jī)制

同理,首先將下方代碼添加在models文件夾下的common.py文件中,具體添加位置如果找不準(zhǔn)可以選擇common.py文件的最底端(最穩(wěn)妥的做法,肯定不會錯),或者C3模塊后面(方便查找)。

def INF(B,H,W):
     return -torch.diag(torch.tensor(float("inf")).repeat(H),0).unsqueeze(0).repeat(B*W,1,1).cuda()


class CrissCrossAttention(nn.Module):
    """ Criss-Cross Attention Module"""
    def __init__(self, in_dim, out_channels, none):
        super(CrissCrossAttention,self).__init__()
        self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim//8, kernel_size=1)
        self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim//8, kernel_size=1)
        self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)
        self.softmax = nn.Softmax(dim=3)
        self.INF = INF
        self.gamma = nn.Parameter(torch.zeros(1))

    def forward(self, x):
        m_batchsize, _, height, width = x.size()
        proj_query = self.query_conv(x)
        proj_query_H = proj_query.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height).permute(0, 2, 1)
        proj_query_W = proj_query.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width).permute(0, 2, 1)
        proj_key = self.key_conv(x)
        proj_key_H = proj_key.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height)
        proj_key_W = proj_key.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width)
        proj_value = self.value_conv(x)
        proj_value_H = proj_value.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height)
        proj_value_W = proj_value.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width)
        energy_H = (torch.bmm(proj_query_H, proj_key_H)+self.INF(m_batchsize, height, width)).view(m_batchsize,width,height,height).permute(0,2,1,3)
        energy_W = torch.bmm(proj_query_W, proj_key_W).view(m_batchsize,height,width,width)
        concate = self.softmax(torch.cat([energy_H, energy_W], 3))

        att_H = concate[:,:,:,0:height].permute(0,2,1,3).contiguous().view(m_batchsize*width,height,height)
        #print(concate)
        #print(att_H) 
        att_W = concate[:,:,:,height:height+width].contiguous().view(m_batchsize*height,width,width)
        out_H = torch.bmm(proj_value_H, att_H.permute(0, 2, 1)).view(m_batchsize,width,-1,height).permute(0,2,3,1)
        out_W = torch.bmm(proj_value_W, att_W.permute(0, 2, 1)).view(m_batchsize,height,-1,width).permute(0,2,1,3)
        #print(out_H.size(),out_W.size())
        return self.gamma*(out_H + out_W) + x

第二步,需要更改models文件夾下的yolo.py文件。可以直接ctrl+F 然后查找parse_model關(guān)鍵字,定位到parse_model函數(shù),你會發(fā)現(xiàn)有一段這樣的代碼

 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]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3TR, C3Ghost, C3x]:
                args.insert(2, n)  # number of repeats
                n = 1

我們僅需在第1行和第8行末尾添加CrissCrossAttention即可,具體做法如下

if m in (Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                 BottleneckCSP, C3, C3new, C3new2, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, CrissCrossAttention):
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [BottleneckCSP, C3, C3new, C3new2, C3TR, C3Ghost, C3x, CrissCrossAttention]:
                args.insert(2, n)  # number of repeats
                n = 1

第一個版本是將CrissCrossAttention放在backbone部分的最末端,這樣可以使注意力機(jī)制看到整個backbone部分的特征圖,將具有全局視野,類似于一個小transformer結(jié)構(gòu)。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
   [-1, 3, CrissCrossAttention, [1024]], # 10
  ]

# 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]],  # 14

   [-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]],  # 18 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 15], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 11], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 24 (P5/32-large)

   [[18, 21, 24], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

第二個版本是將CrissCrossAttention放在backbone部分每個C3模塊的后面,這樣可以使注意力機(jī)制看到局部的特征,每層進(jìn)行一次注意力,可以分擔(dān)學(xué)習(xí)壓力。

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 3, CrissCrossAttention, [128]], # 3
   [-1, 1, Conv, [256, 3, 2]],  # 4-P3/8
   [-1, 6, C3, [256]], 
   [-1, 3, CrissCrossAttention, [256]], 
   [-1, 1, Conv, [512, 3, 2]],  # 7-P4/16
   [-1, 9, C3, [512]],
   [-1, 3, CrissCrossAttention, [512]], 
   [-1, 1, Conv, [1024, 3, 2]],  #  10 -P5/32
   [-1, 3, C3, [1024]],
   [-1, 3, CrissCrossAttention, [1024]], 
   [-1, 1, SPPF, [1024, 5]],  # 13
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 9], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 17

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 21 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 18], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 24 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 27 (P5/32-large)

   [[21, 24, 27], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

如需單獨(dú)輔導(dǎo)改進(jìn)(有償) 可添加博主vx:Wansit99文章來源地址http://www.zghlxwxcb.cn/news/detail-400182.html

到了這里,關(guān)于yolov5改進(jìn)之加入CBAM,SE,ECA,CA,SimAM,ShuffleAttention,Criss-CrossAttention,CrissCrossAttention多種注意力機(jī)制的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力機(jī)制

    YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力機(jī)制

    記錄在YOLOv5添加注意力機(jī)制,方便自己查閱。 由于本人水平有限,難免出現(xiàn)錯漏,敬請批評改正。 更多精彩內(nèi)容,可點(diǎn)擊進(jìn)入YOLO系列專欄或我的個人主頁查看 YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU https://blog.csdn.net/FriendshipTang/article/details/129969044 YOLOv7訓(xùn)練自己的數(shù)據(jù)集(口罩檢測)

    2024年02月03日
    瀏覽(22)
  • Yolov8改進(jìn)---注意力機(jī)制: SimAM(無參Attention)和NAM(基于標(biāo)準(zhǔn)化的注意力模塊),效果秒殺CBAM、SE

    Yolov8改進(jìn)---注意力機(jī)制: SimAM(無參Attention)和NAM(基于標(biāo)準(zhǔn)化的注意力模塊),效果秒殺CBAM、SE

    論文:?http://proceedings.mlr.press/v139/yang21o/yang21o.pdf ????????SimAM(Simple Attenti

    2024年02月09日
    瀏覽(21)
  • 注意力機(jī)制SE、CBAM、ECA、CA的優(yōu)缺點(diǎn)

    注意力機(jī)制是一種 機(jī)器學(xué)習(xí)技術(shù) ,通常用于處理序列數(shù)據(jù)(如文本或音頻)或圖像數(shù)據(jù)中的信息篩選和集成。 注意力機(jī)制模塊可以幫助神經(jīng)網(wǎng)絡(luò)更好地處理序列數(shù)據(jù)和圖像數(shù)據(jù),從而 提高模型的性能和精度 。 優(yōu)點(diǎn): 可以通過學(xué)習(xí) 自適應(yīng)的通道權(quán)重 ,使得模型更加關(guān)注有

    2024年02月03日
    瀏覽(22)
  • 【魔改YOLOv5-6.x(中)】加入ACON激活函數(shù)、CBAM和CA注意力機(jī)制、加權(quán)雙向特征金字塔BiFPN

    【魔改YOLOv5-6.x(中)】加入ACON激活函數(shù)、CBAM和CA注意力機(jī)制、加權(quán)雙向特征金字塔BiFPN

    【魔改YOLOv5-6.x(上)】:結(jié)合輕量化網(wǎng)絡(luò)Shufflenetv2、Mobilenetv3和Ghostnet 本文使用的YOLOv5版本為v6.1,對YOLOv5-6.x網(wǎng)絡(luò)結(jié)構(gòu)還不熟悉的同學(xué)們,可以移步至:【YOLOv5-6.x】網(wǎng)絡(luò)模型源碼解析 另外,本文所使用的實(shí)驗(yàn)環(huán)境為1個GTX 1080 GPU,數(shù)據(jù)集為VOC2007,超參數(shù)為hyp.scratch-low.yaml,訓(xùn)

    2024年02月02日
    瀏覽(22)
  • YOLOv8/v7/v5全網(wǎng)首發(fā)獨(dú)家創(chuàng)新,內(nèi)涵CBAM注意力改進(jìn)、ECA改進(jìn),SPPF改進(jìn)等

    YOLOv8/v7/v5全網(wǎng)首發(fā)獨(dú)家創(chuàng)新,內(nèi)涵CBAM注意力改進(jìn)、ECA改進(jìn),SPPF改進(jìn)等

    ?????? 全網(wǎng)獨(dú)家首發(fā)創(chuàng)新(原創(chuàng)),純自研模塊,適合paper ?。。??????? 內(nèi)涵CBAM注意力改進(jìn)、ECA改進(jìn),SPPF改進(jìn)等?。?! 重新設(shè)計全局平均池化層和全局最大池化層,增強(qiáng)全局視角信息和不同尺度大小的特征 分析SPPF的問題點(diǎn),只關(guān)注邊緣信息而忽略背景信息 如何改進(jìn)

    2024年01月23日
    瀏覽(41)
  • (超詳細(xì))4-YOLOV5改進(jìn)-添加ShuffleAttention注意力機(jī)制

    (超詳細(xì))4-YOLOV5改進(jìn)-添加ShuffleAttention注意力機(jī)制

    1、在yolov5/models下面新建一個ShuffleAttention.py文件,在里面放入下面的代碼 代碼如下: 2、找到y(tǒng)olo.py文件,進(jìn)行更改內(nèi)容 在28行加一個 from models.ShuffleAttention import ShuffleAttention , 保存即可 3、找到自己想要更改的yaml文件,我選擇的yolov5s.yaml文件(你可以根據(jù)自己需求進(jìn)行選擇),

    2024年01月23日
    瀏覽(32)
  • Yolov8改進(jìn)---注意力機(jī)制:CoTAttention,效果秒殺CBAM、SE

    Yolov8改進(jìn)---注意力機(jī)制:CoTAttention,效果秒殺CBAM、SE

    ?論文:https://arxiv.org/pdf/2107.12292.pdf ?????????CoTAttention網(wǎng)絡(luò)是一種用于多模態(tài)場景下的視覺問答(Visual Question Answering,VQA)任務(wù)的神經(jīng)網(wǎng)絡(luò)模型。它是在經(jīng)典的注意力機(jī)制(Attention Mechanism)上進(jìn)行了改進(jìn),能夠自適應(yīng)地對不同的視覺和語言輸入進(jìn)行注意力分配,從而更

    2024年02月03日
    瀏覽(27)
  • Yolov8改進(jìn)---注意力機(jī)制:CoordAttention,效果秒殺CBAM、SE

    目錄 1.CoordAttention 2.?基于Yolov8的CoordAttention實(shí)現(xiàn) 2.1加入yolov8?modules.py中 2.2 加入tasks.py中: 2.3??yolov8_coordAtt.yaml

    2024年02月04日
    瀏覽(23)
  • (超詳細(xì))2-YOLOV5改進(jìn)-添加SimAM注意力機(jī)制

    (超詳細(xì))2-YOLOV5改進(jìn)-添加SimAM注意力機(jī)制

    1、在yolov5/models下面新建一個SimAM.py文件,在里面放入下面的代碼 代碼如下: 2、找到y(tǒng)olo.py文件,進(jìn)行更改內(nèi)容 在26行加一個 from models SimAM import SimAM , 保存即可 3、找到自己想要更改的yaml文件,我選擇的yolov5s.yaml文件(你可以根據(jù)自己需求進(jìn)行選擇),將剛剛寫好的模塊SimAM加

    2024年01月17日
    瀏覽(69)
  • [YOLOv7/YOLOv5系列算法改進(jìn)NO.4]添加ECA通道注意力機(jī)制

    [YOLOv7/YOLOv5系列算法改進(jìn)NO.4]添加ECA通道注意力機(jī)制

    ?前? ? ? 言 作為當(dāng)前先進(jìn)的深度學(xué)習(xí)目標(biāo)檢測算法YOLOv5,已經(jīng)集合了大量的trick,但是在處理一些復(fù)雜背景問題的時候,還是容易出現(xiàn)錯漏檢的問題。此后的系列文章,將重點(diǎn)對YOLOv5的如何改進(jìn)進(jìn)行詳細(xì)的介紹,目的是為了給那些搞科研的同學(xué)需要創(chuàng)新點(diǎn)或者搞工程項(xiàng)目的

    2024年02月05日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包