一、论文理论
论文地址:ConvMixer:Patches Are All You Need?
1.理论思想
背景
尽管多年来卷积网络一直是视觉任务的主要架构,但最近的实验表明,基于 Transformer 的模型,尤其是 Vision Transformer (ViT),在某些设置下可能会超过卷积的性能。然而,由于 transformer中自注意层的 quadratic runtime,ViT 需要使用 patch embeddings,将图像中的小区域组合成单个输入特征,以便应用于更大的图像尺寸。这就提出了一个问题: ViT 的性能是由于固有的更强大的Transformer架构,还是至少部分是因为使用补丁作为输入表示?
方法
本文为后者提供了一些证据:具体来说,提出了 ConvMixer,这是一个非常简单的模型,受到类似于 ViT 启发和更基本的 MLP-Mixer,ConvMixer 直接对输入的 patch 进行操作,分离空间和通道维度的混合,并在整个网络中保持相同的大小和分辨率。然而,相比之下,ConvMixer 只使用标准的卷积来实现混合步骤。
结果
尽管它很简单,本文证明了 ConvMixer 在类似参数计数和数据集大小的情况下优于 ViT、MLP-Mixer 及其一些变体,此外还优于 ResNet 等经典视觉模型。
2.创新点
操作过程:
“ 本文进而探讨了这样一个问题:即 vision transformers 的强大性能可能更多地来自于这种基于 patch 的表示,而不是 Transformer 架构本身。本文开发了一个非常简单的卷积架构,将其命名为 “ConvMixer”,因为它与最近提出的 MLP-Mixer 相似。这个架构在很多方面与 Vision Transformer (和 MLP-Mixer ) 相似:1) 它直接对 patches 进行操作,2) 在所有层中保持相同分辨率和大小的表示,3) 它在连续层不对表示进行下采样,4) 它将信息的 “channel-wise mixing” 与 “spatial mixing” 分离。但与 Vision Transformer 和 MLP-Mixer 不同的是,ConvMixer 架构只通过标准的卷积来完成所有这些操作。”
ConvMixer 取决于四个参数的实例化:(1) 宽度或隐藏维度 h (即 patch embeddings 的维数),(2) 深度 d,即 ConvMixer 层重复的次数,(3) patch 的大小 p,其控制模型的内部分辨率,(4) depthwise 卷积层卷积核的大小 k。本文以其隐藏维度和深度来命名 ConvMixers,比如ConvMixer-h/d。将原始输入大小 n 除以 patch 大小 p 作为内部分辨率;但是请注意,ConvMixers支持可变大小的输入。
二、代码部署
1.代码
def autopad(k, p=None): # kernel, padding
# Pad to 'same'
if p is None:
p = k // 2 if isinstance(k, int) else [x // 2 for x in k] # auto-pad
return p
class Conv(nn.Module):
# Standard convolution
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super().__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def forward_fuse(self, x):
return self.act(self.conv(x))
class ConvMix(nn.Module):
def __init__(self, dim, dim1, kernel_size=9):
super().__init__()
self.Resnet = nn.Sequential(
nn.Conv2d(dim,dim, kernel_size=kernel_size, groups=dim, padding='same'),
nn.GELU(),
nn.BatchNorm2d(dim)
)
self.Conv_1x1 = nn.Sequential(
nn.Conv2d(dim,dim,kernel_size=1),
nn.GELU(),
nn.BatchNorm2d(dim)
)
def forward(self,x):
x = x +self.Resnet(x)
x = self.Conv_1x1(x)
return x
class CSPCM(nn.Module):
#
def __init__(self, c1, c2, n=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion
super().__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) # act=FReLU(c2)
self.m = nn.Sequential(*(ConvMix(c_, c_) for _ in range(n)))
def forward(self, x):
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))
2.配置教程
(1)在models/cmmon.py中添加上述代码,将与初始代码中重复类删除
(2)在./models/yolo.py文件下里的parse_model函数,将类名加入进去
for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']):内部
elif m in [ConvMix, CSPCM]:
c1, c2 = ch[f], args[0]
if c2 != no: # if not outputss
c2 = make_divisible(c2 * gw, 8)
args = [c1, c2, *args[1:]]
3.yaml文件
# Parameters
nc: 2 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors:
- [19,27, 44,40, 38,94] # P3/8
- [96,68, 86,152, 180,137] # P4/16
- [140,301, 303,264, 238,542] # P5/32
- [436,615, 739,380, 925,792] # P6/64
# 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, CSPCM, [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, [ 128, 1, 1 ] ],
[ -1, 1, nn.Upsample, [ None, 2, 'nearest' ] ],
[ [ -1, 2 ], 1, Concat, [ 1 ] ], # cat backbone P2
[ -1, 2, C3, [ 128] ], # 21 (P2/4-xsmall)
[ -1, 1, Conv, [ 128, 3, 2 ] ],
[ [ -1, 18, 4], 1, Concat, [ 1 ] ], # cat head P3
[ -1, 2, C3, [ 256] ], # 24 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14, 6], 1, Concat, [1]], # cat head P4
[-1, 2, C3, [512]], # 27 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 2, CSPCM, [1024]], # 30 (P5/32-large)
[[21, 24, 27, 30], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
三、总结
本文主要工作包括ConvMixer介绍及改进代码策略,该模块为即插即用模块,部署位置可根据实际针对任务需求,自行调整
本专栏持续更新中,订阅本栏,关注更新~
标签:dim,YOLOv5,涨点,nn,Conv,self,ConvMixer,c2 From: https://blog.csdn.net/ZzzzzKnight/article/details/137175141