💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
注意力机制是计算机视觉中最广泛使用的组件之一,它可以帮助神经网络强调重要元素并抑制不相关的元素。然而,绝大多数的通道注意力机制只包含通道特征信息而忽略了空间特征信息,这导致了模型表征效果或对象检测性能不佳,而且空间注意力模块通常复杂且成本高昂。为了在性能和复杂性之间取得平衡,研究人员一种轻量级的混合局部通道注意力(MLCA)模块,以提高对象检测网络的性能,并且它能够同时整合通道信息与空间信息,以及局部信息和全局信息,以提高网络的表达效果。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址:YOLOv8改进——更新各种有效涨点方法——点击即可跳转
1. 原理
目标检测的"混合局部通道注意力"(MLCA)机制,解决了传统注意力机制的几个不足。以下是MLCA的主要原理和创新:
融入空间信息: 传统的通道注意力机制,如Squeeze-and-Excitation(SE)和Efficient Channel Attention(ECA),将整个通道特征图压缩为单个值,忽略了每个通道内的空间信息。当只有通道的一部分重要时,这可能导致重要特征信息的丢失。
Local SE(LSE)方法: 为了引入空间信息,将特征图划分为多个斑块。然后对这些斑块应用注意力机制,类似于应用局部SE机制。这确保了每个斑块内的重要空间特征得以保留。然而,如果使用过多斑块,这种方法可能导致参数数量过多。
平衡参数和性能: MLCA旨在平衡检测效果、速度和模型参数数量。它同时整合了通道信息、空间信息、局部通道信息和全局通道信息。这种全面的方法增强了模型的表征能力,而不会过度增加计算复杂性。
不同配置的比较: 对SE和LSE方法的各种配置进行了参数和GFLOPs(每秒十亿浮点运算)的比较。MLCA配置(例如,2x2、3x3、5x5、7x7)在参数数量和计算负载之间展示了平衡,提供了在可控复杂性下的高效性能。
在目标检测网络中的实现: MLCA机制被整合到一种新的目标检测网络中。这种整合在几个数据集上进行了测试和验证,与传统注意力机制相比,展示了改进的准确性和性能。
总之,MLCA通过解决传统注意力机制的局限性,融入关键的空间信息,并在模型复杂性与性能增益之间取得平衡,从而增强了目标检测。
2. MLCA代码实现
2.1 将MLCA添加到YOLOv8代码中
关键步骤一: 将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/conv.py中,并在该文件的all中添加“MLCA”
class MLCA(nn.Module):
def __init__(self, in_size, local_size=5, gamma=2, b=1, local_weight=0.5):
super(MLCA, self).__init__()
# ECA 计算方法
self.local_size = local_size
self.gamma = gamma
self.b = b
t = int(abs(math.log(in_size, 2) + self.b) / self.gamma) # eca gamma=2
k = t if t % 2 else t + 1
self.conv = nn.Conv1d(1, 1, kernel_size=k, padding=(k - 1) // 2, bias=False)
self.conv_local = nn.Conv1d(1, 1, kernel_size=k, padding=(k - 1) // 2, bias=False)
self.local_weight = local_weight
self.local_arv_pool = nn.AdaptiveAvgPool2d(local_size)
self.global_arv_pool = nn.AdaptiveAvgPool2d(1)
def forward(self, x):
local_arv = self.local_arv_pool(x)
global_arv = self.global_arv_pool(local_arv)
b, c, m, n = x.shape
b_local, c_local, m_local, n_local = local_arv.shape
# (b,c,local_size,local_size) -> (b,c,local_size*local_size) -> (b,local_size*local_size,c) -> (b,1,local_size*local_size*c)
temp_local = local_arv.view(b, c_local, -1).transpose(-1, -2).reshape(b, 1, -1)
# (b,c,1,1) -> (b,c,1) -> (b,1,c)
temp_global = global_arv.view(b, c, -1).transpose(-1, -2)
y_local = self.conv_local(temp_local)
y_global = self.conv(temp_global)
# (b,c,local_size,local_size) <- (b,c,local_size*local_size)<-(b,local_size*local_size,c) <- (b,1,local_size*local_size*c)
y_local_transpose = y_local.reshape(b, self.local_size * self.local_size, c).transpose(-1, -2).view(b, c,