1.摘要
论文名称:RepVGG: Making VGG-style ConvNets Great Again
论文下载地址:https://arxiv.org/abs/2101.03697
本文提出了一种简单但功能强大的卷积神经网络结构,它具有一个由3 × 3卷积和ReLU组成的类似VGG的推理时间体,而训练时间模型具有多分支拓扑结构。这种训练时间和推理时间结构的解耦是通过结构重新参数化
技术实现的,因此该模型被命名为RepVGG
2. 引言
经典卷积神经网络在图像识别上取得巨大的成功,其简单的结构由conv,relu和pooling构成,但随着ResNet,Inception和DenseNet的出现,人们逐渐将兴趣转到设计良好的架构上,从而使模型越来越复杂,虽然这些网络比普通网络在精度上有明显的提升,但是缺点也很明显,比如:
- 基于多分支结构设计,如残差网络add,Inception系列中的concat操作。多分支结构带来的问题是难以自定义,增加推理时间,增加显存消耗(因为需要保存各个分支的结果,直到add操作后,显存才会减少,后续会分析)
- 一些网络结构组件,比如为轻量化网络设计的DepthwiseConv和ShuffleNet中的channel shuffle。这些操作会提高访存消耗,FLOPS看起来很低,但并不能反应实际推理速度。
这就说明新颖的组件固然能提高精度,但是复杂的结构也影响推理结构,所以本篇论文通过结构重参数化
思想,让训练网络
的多路结构(多分支模型训练时的优势——性能高)转换为推理网络
的单路结构(模型推理时的好处——速度快、省内存)
2.1 VGG网络作为Backbone的优势
-
速度快
:VGG网络几乎都是由3✖️3卷机构成,现有的计算库(如CuDNN,Intel MKL)和硬件针对3x3卷积有深度的优化,相比其他卷积核,3x3卷积计算密度更高,更加有效。
-
节省内存
:VGG网络是一个单路结构,分支结构很消耗显存的,因为各个分支的结果需要保存,直到最后一步融合(比如add),才能把各分支显存释放掉,由上述分析可知,单路结构会占有更少的内存,因为不需要保存其中间结果,同时,单路架构非常快,因为并行度高。同样的计算量,大而整的运算效率远超小而碎的运算。
上图可以看出,以残差块结构为例子,它有2个分支,其中主分支经过卷积层,假设前后张量维度相同,我们认为是一份显存消耗,另外一个旁路分支需要保存初始的输入结果,同样也是一份显存消耗,这样在运行的时候是占用了两份显存,直到最后一步将两个分支结果Add,显存才恢复成一份。而Plain结构只有一个主分支,所以其显存占用一直是一份。
灵活
:单路架构灵活性更好,容易改变各层的宽度(如剪枝),RepVGG主体部分只有一种算子:3x3卷积接ReLU。在设计专用芯片时,给定芯片尺寸或造价,我们可以集成海量的3x3卷积-ReLU计算单元来达到很高的效率。别忘了,单路架构省内存的特性也可以帮我们少做存储单元。
虽然VGG网络有诸多好处,但是还是性能上有所不足,尤其在训练时的表现不好,性能低,所以作者受ResNet的启发,由于ResNet的多分支结构适合训练但不适合推理, 所以要想要使网络具有高性能,又要有高效推理速度,作者提出结构重参数化思想,也即训练时尽量用多分支结构来提升网络性能,而推理时,采用利用结构重参数化思想,将其变为单路结构,这样,显存占用少,推理速度又快,所以提出了RepVGG网络如下图
上图实现方式是在训练时
,为每一个3x3卷积层添加平行的1x1卷积分支和恒等映射分支,构成一个RepVGG Block。这种设计是借鉴ResNet的做法,区别在于ResNet是每隔两层或三层加一分支,这里是每层都加。后续的消融实验了证明了这两个分支对性能提升的重要性
3.结构重参数化(struc-tural re-parameterization)
网络在训练完毕后,怎样将多路模型转化为单路模型,最终部署到终端,这应该是本文的核心,如下图所示
3.1 卷积+BN融合
RepVGG里面大量使用卷积层和BN层,这里首先将两者合并起来,能提高推理速度,融合是在网络训练完之后做的,所以现在讲的默认都是推理模式,注意BN在训练以及推理时计算方式是不同的。
卷积层公式为:
c
o
n
v
(
x
)
=
W
(
x
)
+
b
conv(x) = W(x) + b
conv(x)=W(x)+b
BN层公式为:
B
N
(
x
)
=
γ
∗
x
−
m
e
a
n
v
a
r
+
β
BN(x) = \gamma *\frac{x-mean}{\sqrt{var}} +\beta
BN(x)=γ∗varx−mean+β
将卷积公式代入BN公式:
B
N
(
c
o
n
v
(
x
)
)
=
γ
∗
W
(
x
)
+
b
−
m
e
a
n
v
a
r
+
β
BN(conv(x)) = \gamma *\frac{W(x) + b -mean}{\sqrt{var}} +\beta
BN(conv(x))=γ∗varW(x)+b−mean+β
进一步简化:
B
N
(
c
o
n
v
(
x
)
)
=
γ
∗
W
(
x
)
v
a
r
+
(
γ
∗
(
b
−
m
e
a
n
)
v
a
r
+
β
)
BN(conv(x)) = \frac{\gamma*W(x)}{\sqrt{var}} +(\frac{\gamma*(b -mean)}{\sqrt{var}} +\beta )
BN(conv(x))=varγ∗W(x)+(varγ∗(b−mean)+β)
这里就可以看出上式就是一个卷积层,只不过权重考虑了BN的参数,不妨将上式令:
W
f
u
s
e
d
=
γ
∗
W
v
a
r
W_{fused} = \frac{\gamma*W}{\sqrt{var}}
Wfused=varγ∗W
B
f
u
s
e
d
=
(
γ
∗
(
b
−
m
e
a
n
)
v
a
r
+
β
)
B_{fused} = (\frac{\gamma*(b -mean)}{\sqrt{var}} +\beta )
Bfused=(varγ∗(b−mean)+β)
最终融合为
B
N
(
c
o
n
v
(
x
)
)
=
W
f
u
s
e
d
(
x
)
+
B
f
u
s
e
d
BN(conv(x)) = W_{fused}(x) + B_{fused}
BN(conv(x))=Wfused(x)+Bfused
3.2 Conv_3x3和Conv_1x1合并
为了方便理解,这里仅考虑stride=1且卷积前后特征图大小不变的情况
这部分参考知乎文章:https://zhuanlan.zhihu.com/p/352239591
首先我们看下1x1卷积
这里1x1卷积不需要padding,就能保证特征图大小前后一致,下面我们再看看3x3卷积
为了保证特征图大小不变,我们需要在原特征图上padding一圈(图中灰色部分表示padding)
我们观察下3x3卷积核中间的那个核,会惊奇的发现它卷积的路径就是前面1x1卷积的路径
一个很自然的想法是,把1x1卷积核加在3x3卷积核中间,就能完成卷积分支融合
下面是融合之后的示例图
3.3 BN层转换为 3*3卷积层
参考博文太阳花的小绿豆:https://blog.csdn.net/qq_37541097
对于只有BN的分支由于没有卷积层,所以我们可以先自己构建出一个卷积层来。如下图所示,构建了一个3x3的卷积层,该卷积层只做了恒等映射,即输入输出特征图不变。既然有了卷积层,那么又可以按照上述讲的内容将卷积层和BN层进行融合
3.4 多分支融合
这一步就是利用卷积可加性原理,将三个分支的卷积层和bias对应相加组成最终一个conv3x3的形式即可。
4. 实验
作者提出了A和B系列两种模型,其区别是卷积块堆叠设置,并设立了两个参数a,b来控制通道数,根据表2可以看出RepVGG-B比RepVGG-A要更深,更加详细的模型配置可以看表3. 其中a代表模型stage2~4的宽度缩放因子,b代表模型最后一个stage的宽度缩放因子。
在论文中对模型进一步细分有RepVGG-A、RepVGG-B以及RepVGG-Bxgy三种配置。