秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
专栏目录: 《YOLOv5入门 + 改进涨点》专栏介绍 & 专栏目录 |目前已有70+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进
一个高效且有效的解码机制在医学图像分割中至关重要。然而,这些解码机制通常伴随着高昂的计算成本。本文将介绍Efficient Multi-Scale Conv,这是一个新的高效多尺度卷积注意力解码器,旨在优化性能和计算效率。利用独特的多尺度深度卷积块,通过多尺度卷积显著增强特征图。还采用了通道、空间和分组(大核)门控注意力机制,这些机制在捕捉复杂空间关系的同时,能够聚焦于显著区域。通过使用分组和深度卷积,非常高效,并且具有良好的可扩展性。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址: YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转
目录
1.原理
2. 将C3_EMSC添加到yolov5网络中
2.1 C3_EMSC代码实现
2.2 新增yaml文件
2.3 注册模块
2.4 执行程序
3. 完整代码分享
4. GFLOPs
5. 进阶
6. 总结
1.原理
论文地址:EMCAD: Efficient Multi-scale Convolutional Attention Decoding for Medical Image Segmentation——点击即可跳转
官方代码: 官方代码仓库——点击即可跳转
高效多尺度卷积,如论文“EMCAD:用于医学图像分割的高效多尺度卷积注意力解码”中所述,围绕着提高卷积神经网络 (CNN) 用于医学图像分割的效率和有效性的想法。核心创新是在基于注意力的解码框架中使用多尺度深度卷积块,旨在优化特征图的处理以实现高分辨率分割,同时降低计算开销。
关键组件和原理:
多尺度卷积注意力模块 (MSCAM):
-
MSCAM 通过结合三种类型的注意力来细化特征图:
-
通道注意力:专注于选择信息量最大的通道。
-
空间注意力:通过强调最相关的空间区域来捕获局部上下文信息。
-
多尺度卷积块 (MSCB):通过使用深度卷积以不同尺度处理特征来增强特征。与传统卷积层相比,这使模型能够以更低的计算成本捕获各种尺度和分辨率的细节。
深度卷积:
-
使用深度卷积代替标准卷积在每个通道上独立执行操作,这大大减少了所需的参数和计算量。
-
通过在多个尺度上执行这些卷积,模型可以同时有效地捕获精细细节和更广泛的上下文,这对于准确的医学图像分割至关重要。
大核分组注意力门 (LGAG):
-
此组件旨在通过将特征图与网络中较早层的跳过连接相结合来细化特征图。它使用大核(例如 3x3)组卷积,允许以较少的计算成本捕获更大的空间上下文,有助于在减少所需操作数的同时保持高精度。
效率提升:
-
整体架构设计为计算高效且高效。例如,当与标准分层视觉编码器集成时,与最先进的方法相比,EMCAD 可以显著减少参数和浮点运算 (FLOP) 的数量,同时保持或提高分割精度。
高效多尺度卷积 方法利用这些原理来解决平衡计算效率和分割性能的挑战,特别是在医学成像领域,高精度至关重要,但计算资源可能有限。
2. 将C3_EMSC添加到yolov5网络中
2.1 C3_EMSC代码实现
关键步骤一: 将下面的代码粘贴到\yolov5\models\common.py中
from einops import rearrange
class EMSConv(nn.Module):
# Efficient Multi-Scale Conv
def __init__(self, channel=256, kernels=[3, 5]):
super().__init__()
self.groups = len(kernels)
min_ch = channel // 4
assert min_ch >= 16, f'channel must Greater than {64}, but {channel}'
self.convs = nn.ModuleList([])
for ks in kernels:
self.convs.append(Conv(c1=min_ch, c2=min_ch, k=ks))
self.conv_1x1 = Conv(channel, channel, k=1)
def forward(self, x):
_, c, _, _ = x.size()
x_cheap, x_group = torch.split(x, [c // 2, c // 2], dim=1)
x_group = rearrange(x_group, 'bs (g ch) h w -> bs ch h w g', g=self.groups)
x_group = torch.stack([self.convs[i](x_group[..., i]) for i in range(len(self.convs))])
x_group = rearrange(x_group, 'g bs ch h w -> bs (g ch) h w')
x = torch.cat([x_cheap, x_group], dim=1)
x = self.conv_1x1(x)
return x
class EMSConvP(nn.Module):
# Efficient Multi-Scale Conv Plus
def __init__(self, channel=256, kernels=[1, 3, 5, 7]):
super().__init__()
self.groups = len(kernels)
min_ch = channel // self.groups
assert min_ch >= 16, f'channel must Greater than {16 * self.groups}, but {channel}'
self.convs = nn.ModuleList([])
for ks in kernels:
self.convs.append(Conv(c1=min_ch, c2=min_ch, k=ks))
self.conv_1x1 = Conv(channel, channel, k=1)
def forward(self, x):
x_group = rearrange(x, 'bs (g ch) h w -> bs ch h w g', g=self.groups)
x_convs = torch.stack([self.convs[i](x_group[..., i]) for i in range(len(self.convs))])
x_convs = rearrange(x_convs, 'g bs ch h w -> bs (g ch) h w')
x_convs = self.conv_1x1(x_convs)
return x_convs
class Bottleneck_EMSC(Bottleneck):
def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
super().__init__(c1, c2, shortcut, g, k, e)
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, k[0], 1)
self.cv2 = EMSConv(c2)
class C3_EMSC(C3):
def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*(Bottleneck_EMSC(c_, c_, shortcut, g, k=((1, 1), (3, 3)), e=1.0) for _ in range(n)))
EMSC(Efficient Multi-scale Convolutional Attention Decoding)在处理图像时,通过多步骤的流程来进行高效的医疗图像分割。以下是其主要流程的详细说明:
1. 特征提取(Feature Extraction)
-
输入的医疗图像首先通过预训练的分层视觉编码器(例如,CNN或Transformer架构)进行处理,提取出多阶段的特征图。编码器将图像分解为不同层次的特征表示,通常包括四个主要阶段的特征图(X1, X2, X3, X4)。
2. 多尺度卷积注意模块(MSCAM)
-
每个阶段提取的特征图首先进入多尺度卷积注意模块(MSCAM)。MSCAM使用通道注意力、空间注意力和多尺度卷积块来细化这些特征图:
-
通道注意力(Channel Attention)增强那些对任务最有贡献的通道。
-
空间注意力(Spatial Attention)聚焦在图像中最相关的空间区域。
-
多尺度卷积块(MSCB)使用多尺度的深度卷积来捕获不同尺度和分辨率的特征,保证细节与全局信息的兼顾。
-
3. 大核分组注意力门(LGAG)
-
经过MSCAM处理后的特征图会通过大核分组注意力门(LGAG)进行进一步优化。LGAG融合了当前特征图与来自跳跃连接(skip connection)的特征,利用大核分组卷积在更大的局部上下文中捕获重要特征,同时减少计算负担。
4. 上采样与特征增强(Upsampling and Feature Enhancement)
-
优化后的特征图通过高效上卷积块(EUCB)进行上采样,使其分辨率逐步恢复到原始输入图像的大小。在上采样的过程中,EUCB进一步增强特征图,以确保最终的分割结果具有高分辨率和准确性。
5. 分割输出(Segmentation Output)
-
在每个特征提取阶段的末端,通过分割头(Segmentation Head)生成阶段性的分割图。这些分割图会在最后累加,得到最终的分割输出图。
6. 多阶段集成与输出
-
EMSC通过集成来自多个阶段的分割图,结合细化后的特征,最终生成精准的医疗图像分割结果。这个过程确保了分割输出既具有细节分辨能力,又能捕捉全局信息,适应不同分辨率和尺度的需求。
这种处理流程使得EMSC在保持高精度的同时,极大地降低了计算开销和参数数量,适用于资源受限的医疗图像处理任务。
2.2 新增yaml文件
关键步骤二:在下/yolov5/models下新建文件 yolov5_C3_EMSC.yaml并将下面代码复制进去
- 目标检测yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license
# Parameters
nc: 80 # 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]
[
[-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_EMSC, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3_EMSC, [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_EMSC, [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_EMSC, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3_EMSC, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3_EMSC, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
- 语义分割yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license
# Parameters
nc: 80 # 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]
[
[-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_EMSC, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3_EMSC, [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_EMSC, [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_EMSC, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3_EMSC, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3_EMSC, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]], # Detect(P3, P4, P5)
]
温馨提示:本文只是对yolov5基础上添加模块,如果要对yolov5n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。
# YOLOv5n
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.25 # layer channel multiple
# YOLOv5s
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# YOLOv5l
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
# YOLOv5m
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
# YOLOv5x
depth_multiple: 1.33 # model depth multiple
width_multiple: 1.25 # layer channel multiple
2.3 注册模块
关键步骤三:在yolo.py的parse_model函数替换添加C3_EMSC
2.4 执行程序
在train.py中,将cfg的参数路径设置为yolov5_C3_EMSC.yaml的路径
建议大家写绝对路径,确保一定能找到
🚀运行程序,如果出现下面的内容则说明添加成功🚀
from n params module arguments
0 -1 1 7040 models.common.Conv [3, 64, 6, 2, 2]
1 -1 1 73984 models.common.Conv [64, 128, 3, 2]
2 -1 3 156928 models.common.C3 [128, 128, 3]
3 -1 1 295424 models.common.Conv [128, 256, 3, 2]
4 -1 6 1118208 models.common.C3 [256, 256, 6]
5 -1 1 1180672 models.common.Conv [256, 512, 3, 2]
6 -1 9 2970880 models.common.C3_EMSC [512, 512, 9]
7 -1 1 4720640 models.common.Conv [512, 1024, 3, 2]
8 -1 3 5352960 models.common.C3_EMSC [1024, 1024, 3]
9 -1 1 2624512 models.common.SPPF [1024, 1024, 5]
10 -1 1 525312 models.common.Conv [1024, 512, 1, 1]
11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
12 [-1, 6] 1 0 models.common.Concat [1]
13 -1 3 1603328 models.common.C3_EMSC [1024, 512, 3, False]
14 -1 1 131584 models.common.Conv [512, 256, 1, 1]
15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
16 [-1, 4] 1 0 models.common.Concat [1]
17 -1 3 402304 models.common.C3_EMSC [512, 256, 3, False]
18 -1 1 590336 models.common.Conv [256, 256, 3, 2]
19 [-1, 14] 1 0 models.common.Concat [1]
20 -1 3 1341184 models.common.C3_EMSC [512, 512, 3, False]
21 -1 1 2360320 models.common.Conv [512, 512, 3, 2]
22 [-1, 10] 1 0 models.common.Concat [1]
23 -1 3 5352960 models.common.C3_EMSC [1024, 1024, 3, False]
24 [17, 20, 23] 1 457725 Detect [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [256, 512, 1024]]
YOLOv5_C3_EMSC summary: 560 layers, 31266301 parameters, 31266301 gradients, 80.1 GFLOPs
3. 完整代码分享
https://pan.baidu.com/s/1BBgzIrn3-t7S7SjCavDa2w?pwd=qnht
提取码: qnht
4. GFLOPs
关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution
未改进的GFLOPs
改进后的GFLOPs
5. 进阶
可以结合损失函数或者卷积模块进行多重改进
YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转
6. 总结
Efficient Multi-Scale Convolution (EMCAD)通过引入多尺度深度卷积块和注意力机制,优化了医疗图像分割中的解码过程。EMCAD利用多尺度卷积捕捉不同尺度和分辨率的特征,结合通道注意力和空间注意力机制,有效增强了特征图的表达能力。通过使用深度卷积和大核分组注意力门,EMCAD在减少计算量的同时,保持了对复杂空间关系和重要区域的准确捕捉。最终,这种设计大幅降低了模型的参数量和计算复杂度,在提高分割精度的同时实现了计算资源的高效利用。