CSPNet:Cross Stage Partial Network,跨阶段局部网络
作用:从网络设计角度来缓解以前推理时需要很大计算量的问题
推理计算过高的原因:由于网络优化中的梯度信息重复导致的!
cspnet解决方式:通过将梯度的变化从头到尾地集成到特征图中,在减少了计算量的同时可以保证准确率。CSPNet是一种处理的思想,可以和ResNet、ResNeXt和DenseNet结合。
图是cspnet对不同backbone结合后的效果,可以看出计算量大幅下降,准确率保持不变或者略有提升(ps: 分类的提升确实不多)
下图是CSPNet用于目标检测的结果:
AlexeyAB版本的darknet的首页就是这张图,使用CSPNet做backbone可以极大提升模型的准确率,在同等FPS的情况下,CSPNet准确率更有竞争力。
CSPNet的提出主要是为了解决三个问题:
问题1:增强CNN的学习能力,能够轻量化的同时保持准确性
神经网络推理过程中计算量过高是网络优化中的梯度信息重复所导致的。CSPNet将梯度的变化从头到尾集成到特征图中,这样就可以在减少了计算量的同时可以保证准确率。
问题2:降低计算瓶颈
过高的计算瓶颈会导致更多的周期来完成神经网络的推理过程,或者一些算术单元经常处于空闲状态。因此,如果能在CNN的每一层上均匀地分配计算量,就能有效地提高每个计算单元的利用率,从而减少不必要的能耗。
问题3:降低内存成本
在特征金字塔生成过程中采用跨通道池来压缩特征映射,可以减少内存使用。
CSPNet不单单是一个网络,更是一种可移植的思想方法,可以与多种网络结构结合
比如:可以和ResNet、ResNeXt和DenseNet结合:CSPResNet、CSPDenseNet-201。
(1)将之前所有层的输出特征连接起来,作为下一层的输入,最大化cardinality(分支路径的数量);
(2)由梯度信息结合的思想,让高cardinality和稀疏性连接来提升网络的学习能力。
作者给出了几种设计思路:
注:上图中的Transition Layer代表过渡层,主要包含瓶颈层(1x1卷积)和池化层(可选)
其中(a)图是原始的DenseNet的特征融合方式,(b)图是CSPDenseNet的特征融合方式
(c)图是Fusion First的特征融合方式 (d)图是Fusion Last的特征融合方式。
DenseNet网络简介:其每一阶段包含一个dense block和一个transition layers(放在两个Dense Block中间,是因为每个Dense Block结束后的输出通道数很多,要使用1*1的卷积核来降维),
每个dense block由多个dense layer组成。(优点:特征重复使用)
Fusion First :将两个分支的特征映射连接起来(concat),然后进行转换操作(Transition)。
如果采用这种策略,将会重用大量的梯度信息。
Fusion Last :对比(a),本方式是对稠密块(Dense Block)所在的分支先进行转移操作(Transition),然后再进行concatenation,梯度信息将被截断,因此不会重复性使用梯度信息。
上图是对Fusion First、Fusion Last和CSP最终结构进行实验对比,我们可以得到如下结论:
(1)使用Fusion First有助于降低计算代价,但是准确率有显著下降。
(2)使用Fusion Last也是极大降低了计算代价,top-1 accuracy仅仅下降了0.1个百分点。
(3)同时使用Fusion First和Fusion Last相结合的CSP所采用的融合方式可以在降低计算代价的同时,提升准确率。
下图是DenseNet的示意图和CSPDenseNet的改进示意图:
注意:输入端的粉红色块分成了两半part1和part2,第一半边part1不进行处理,只用于最后与part2经过(Partial Dense Block)处理完后,在Partial Transition Layer(局部转移层)中进行二个分支的堆叠concat。
CSPDenseNet相对于DenseNet的改进点在于:CSPNet将浅层特征映射为两个部分,一部分经过Dense模块(图中的Partial Dense Block),另一部分直接与Partial Dense Block输出进concat。
CSP思想也可以应用到ResNet或者ResNeXt中:
(1)CSPNet和PRN都是一个思想,将feature map拆成两个部分,一部分进行卷积操作,另一部分和上一部分卷积操作的结果进行concat。
从实验结果来看,分类问题中,使用CSPNet可以降低计算量,但是准确率提升很小;在目标检测问题中,使用CSPNet作为Backbone带来的提升比较大,可以有效增强CNN的学习能力,同时也降低了计算量。
一半的特征进入dense layer,通过通道拆分来减少计算量,是一种网络优化的方法,但是对分类问题中的精度的提升好像帮助并不大。
总体来说,CSPNet还是非常强的,也得到了AlexeyAB大神的认可,darknet中也提供了具体的实现:
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
# 1-1
[route]
layers = -1
group_id=0
groups=2
# 1-2
[route]
layers = -2
group_id=1
groups=2
或者
# 1-1
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -2
# 1-2
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
作者也在Github中公开了部分的cfg文件实现,可以配合AlexeyAB版的Darknet进行使用,Github链接如下:
GitHub - WongKinYiu/CrossStagePartialNetworks: Cross Stage Partial Networks
Partial Dense Block(局部稠密块)
(1)增加了渐变路径:采用拆分合并的思想,拆成两部分,让渐变路径的数目翻倍
(2)均衡各层的计算:因为在局部密集块中参与密层操作的基层通道只有原来数量的一半,因此可以减少近一半的计算瓶颈
(3)减少内存流量:假设DenseNet中一个密集块的基本特征图大小为,增长率为,总共有个密集层。 那么,那个密集块的CIO为,部分密集块的CIO为。 虽然m和d通常远小于c,但部分密集的块最多可以节省网络一半的内存流量开销。
注:
Partial Transition Layer
它是一种层次化的特征融合机制,采用了截断梯度流的策略(就是对半拆)来防止不同的层学习重复的梯度信息,最大化梯度组合的差异。
shortcut:截断
(2)CSPNet的主要思想还是Partial Dense Block(局部稠密块),设计Partial Dense Block的目的是:
增加梯度路径:通过分裂合并策略,可以使梯度路径的数目翻倍。由于采用了跨阶段的策略,可以减轻使用显式特征映射复制进行连接的缺点;
平衡各层的计算:通常情况下,DenseNet底层的信道数远远大于增长率。由于部分dense block中的dense layer操作所涉及的底层信道只占原始信道的一半,因此可以有效地解决近一半的计算瓶颈;
class CSPResStage(nn.Layer):
def __init__(self, block_fn, ch_in, ch_out, n, stride, act='relu', attn='eca'):
super(CSPResStage, self).__init__()
ch_mid = (ch_in + ch_out) // 2
if stride == 2:
self.conv_down = ConvBNLayer(ch_in, ch_mid, 3, stride=2, padding=1, act=act)
else:
self.conv_down = None
self.conv1 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
self.conv2 = ConvBNLayer(ch_mid, ch_mid // 2, 1, act=act)
self.blocks = nn.Sequential(* [block_fn(ch_mid // 2, ch_mid // 2, act=act, shortcut=True) for i in range(n)])
if attn:
self.attn = EffectiveSELayer(ch_mid, act='hardsigmoid')
else:
self.attn = None
self.conv3 = ConvBNLayer(ch_mid, ch_out, 1, act=act)
def forward(self, x):
if self.conv_down is not None:
x = self.conv_down(x)
y1 = self.conv1(x)
y2 = self.blocks(self.conv2(x))
y = paddle.concat([y1, y2], axis=1)
if self.attn is not None:
y = self.attn(y)
y = self.conv3(y)
return y
reference
YOLOv4之CSPNet - 知乎 (zhihu.com)
增强CNN学习能力的Backbone:CSPNet - 知乎 (zhihu.com)
深度学习之CSPNet分析_tt丫的博客-CSDN博客_csp结构
深度学习_经典网络_CSPNet网络详解_【WeThinkIn】的主理人的博客-CSDN博客_csp网络
CNN模型合集 | 26 HarDNet - 知乎 (zhihu.com)
PP-YoLoE | PP-YoLov2全面升级Anchor-Free,速度精度完美超越YoLoX和YoLov5 (qq.com)